关于获取yuv帧数问题

来源:互联网 发布:红场飞机事件知乎 编辑:程序博客网 时间:2024/04/29 01:56

读yuv文件的时候需要获取yuv文件的帧数,以便建立循环一帧一帧读取,这时候要获取yuv的帧数。

方法:首先用fopen函数打开一个yuv文件,接着用fseek(   fYUV,   0L,   SEEK_END   ),再接着用ftell来获取文件的大小size,由于用的是yuv420,因此用size/(WIDTH*HEIGHT*1.5)即获得了yuv文件的总帧数。

需要注意的是:fseek函数已把指向yuv文件的开始的指针改变了位置,即此时的指针已指向文件的结尾处,由于接着要进行文件的读写,这时候应该用rewind()函数把指针直接重新指到文件开始处。

 

ps:获得文件大小的几种方法

 

#include <iostream>
#include 
<io.h>
#include 
<sys/stat.h>
#include 
<afx.h>
#define _AFXDLL
using namespace std;

void main()
{
    
// 此文件在工程打开状态下为不可访问
    char* filepath = "..//test.ncb";

    
// 方法一
    struct _stat info;
    _stat(filepath, 
&info);
    
int size = info.st_size;
    cout
<<size<<endl;

    
// 方法二
    FILE* file = fopen(filepath, "rb");
    
if (file)
    {
        
int size = filelength(fileno(file));
        cout
<<size<<endl;
        fclose(file);
    }

    
// 方法三
    CFile cfile;
    
if (cfile.Open(filepath, CFile::modeRead))
    {
        
int size = cfile.GetLength();
        cout
<<size<<endl;
    }

    
// 方法四
    HANDLE handle = CreateFile(filepath, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 00);
    
if (handle != INVALID_HANDLE_VALUE)
    {
        
int size = GetFileSize(handle, NULL);
        cout
<<size<<endl;
        CloseHandle(handle);
    }
}

 

 

VS2005:若编译链接不通过,需要修改工程设置:

(1) Configuration Properties -> C/C++ -> Code Generation -> Runtime Library, 选择"Multi-threaded Debug(/MTd)"

(2) Configuration Properties -> Linker -> Input -> Ignore Specific Library, 输入"msvcprtd.lib"

 

例子中,由于在工程打开状态下,test.ncb文件无法打开,所以方法二、三无法获取文件大小,因此推荐使用方法一、四。

 

另:文件的随机读写

前面介绍了对文件的顺序读写操作,这些操作都是从文件的第一个有效数据(或某个位置)开始的,依照数据在文件存储设备中的先后次序进行读写,在读写过程中,文件位置指针自动移动。但在实际应用中,往往需要对文件中某个特定位置处的数据进行处理,换言之,就是读完一个字节的内容后,并不一定要读写其后续的字节数据,可能会强制性地将文件位置指针移动到用户所希望的特定位置,读取该位置上的数据,这就是随机读写文件。

C语言提供了对文件的随机读写功能。在随机方式下,系统并不按数据在文件中的物理顺序进行读写,而是可以读取文件任何有效位置上的数据,也可以将数据写入到任意有效的位置。

C语言通过提供文件定位函数来实现随机读写功能。

1. 获取文件位置指针当前值的函数ftell()

ftell()函数的功能是获得并返回文件位置指针的当前值。ftell()函数的原型定义为:

long ftell(FILE * fp);

其中参数fp是文件型指针,指向当前操作的文件。

rewind()函数的返回值为文件位置指针的当前位置。如果rewind()函数执行时出现错误,则返回长整型的-1(即-1L)。

2. 重置文件位置指针的函数rewind()

rewind()函数的功能是使文件的位置指针移到文件的开头处。rewind()函数的原型定义为:

void rewind(FILE * fp);

其中参数fp是文件型指针,指向当前操作的文件。

rewind()函数没有返回值,其作用在于:如果要对文件进行多次读写操作,可以在不关闭文件的情况下,将文件位置指针重新设置到文件开头,从而能够重新读写此文件。如果没有rewind()函数,每次重新操作文件之前,需要将该文件关闭后再重新打开,这种方式不仅效率低下,而且操作也不方便。使用rewind()函数便能克服这一缺陷。

 

【例11.7  有一个文本文件file1.dat,两次读写它的内容,第一次将它的内容显示在屏幕上,第二次将它的内容复制到另一个文件fiel2.dat上。以下为实现该功能的程序代码。

 

#include "stdio.h"

void main()

{

FILE *fp1,*fp2;

fp1=fopen("file1.dat","r");

fp2=fopen("fiel2.dat","w");

while(!feof(fp1))

putchar(getc(fp1));

rewind(fp1);

while(!feof(fp1))

putc(getc(fp1),fp2);

fclose(fp1);

fclose(fp2);

}

3. 移动文件位置指针的函数fseek()

函数fseek()可以实现改变文件位置指针到指定位置的操作。fseek()函数的原型定义为:

int fseek(FILE * fp,long offset,int origin);

即:int fseek(文件类型指针,位移量,起始点);

其中fp为打开的文件指针,参数offset为文件位置指针移动的位移量(单位为字节),参数origin指示出文件位置指针移动的起始点(或称基点)位置。当执行fseek()函数后,文件位置指针新的位置是以起始点为基准,向后(offset为正值)/或向前(offset为负值)移动offset个字节。文件位置指针的新位置可以用公式“origin+offset”来计算得出。

二进制文件的基点origin 可以取以下三个常量值之一:

⑴SEEK_SET(也可直接用数字0表示):此时文件位置指针从文件的开始位置进行移动;

⑵SEEK_CUP(对应值为1): 此时文件位置指针从文件的当前位置进行移动;

⑶SEEK_END(对应值为2): 此时文件位置指针从文件的结束位置进行移动。

文本文件的基点origin只能取SEEK_SET常量值(或取0值),而origin的值应为0。

fseek()函数常用于二进制文件中,对于文本文件则不常使用,因为文本文件要进行字符的转换,这会为文件位置指针的计算带来混乱。fseek()函数的调用形式为:

fseek()函数返回一个整形值。如果函数执行成功,返回0值;否则,返回一个非0值。

下面给出fseek()函数调用的两个例子:

①fseek(fp,50L,1),将fp指向的文件的位置指针向后移动到离当前位置50个字节处;

②fseek(fp,-100L,2),将fp指向的文件的位置指针从文件末尾处向前回退100个字节。

4. 应用实例

【例11.8 在当前目录下有一二进制文件information.dat,文件中存储有学生信息数据。编程实现按指定位置读取该文件中的数据,显示到屏幕上,并统计文件的总字节数目,也显示到屏幕上。

以下为实现该功能的程序代码。

 

#include "stdio.h"

struct student

{

char name[20];int num;

};

/*主函数*/

main()

{

int i=0;

long n=0;

FILE *fp=NULL;

struct  student a = {0};

fp = fopen("information.dat","rb");

if(fp==NULL)

{

printf("Can't open!/n");

exit(0);

}

printf("Record in file information.dat:/n");

for(i=1;i<5;i+=2)

{

fseek(fp,i*sizeof(struct student),SEEK_SET);  /*定位文件位置指针*/

n=ftell(fp);   /*获取文件位置指针当前值*/

fread(&a,sizeof(struct student),1,fp);   /*读取数据块*/

printf("current:%ldth byte,%dth record:%s  %d/n",n,i+1,a.name,a.num);

fseek(fp,-3l*sizeof(struct student),2);  /*重新定位文件位置指针*/

n=ftell(fp);   /*重新读取数据块*/

fread(&a,sizeof(struct student),1,fp);

printf("current:%ldth btype,record is:%s  %d/n",n,a.name,a.num);

rewind(fp);   /*重置文件位置指针到文件开始*/

n=ftell(fp);  /*获取文件位置指针当前值*/

fread(&a,sizeof(struct student),1,fp);

printf("current:%ldth btype,frist record :%s  %d/n",n,a.name,a.num);

/*重新定位文件位置指针到文件尾部*/

fseek(fp,-0l*sizeof(struct student),2);

n=ftell(fp);    /*计算文件总字节数目*/

printf("total bytes:%ld/n",n);   /*显示文件总字节数目*/

fclose(fp);

}

getch();

}

http://blog.csdn.net/cherry_xidian/article/details/6229151

原创粉丝点击