实际上是一种流媒体 是由很多细小部分构成的
...NAL header | RBSP | NAL header | RBSP | NAL herder | RBSP... |
流媒体是近乎于无限可分的文件格式
NALU 使用 00 00 00 01 或者 00 00 01分隔开
一个文件中有很短的数据是图片压缩时两张相差不多的图片第二张可以基于第一张 就不用多少数据
代码实现:
MideaFile::MideaFile()
:m_file(NULL),m_type(-1)
{
}
MideaFile::~MideaFile()
{
Close();
}
int MideaFile::Open(const ZBuffer& path, int nType)
{
m_file = fopen(path, "rb");
if (m_file == NULL) {
//TODO 错误提示
return -1;
}
m_type = nType;
fseek(m_file, 0, SEEK_END);//移到尾部
m_size = ftell(m_file);//获取尾部位置
Reset();
return 0;
}
ZBuffer MideaFile::ReadOneFrame()
{
switch (m_type)
{
case 96:
return ReadH264Frame();
break;
default:
break;
}
return ZBuffer();
}
void MideaFile::Close()
{
m_type = -1;
if (m_file != NULL) {
FILE* file = m_file;
m_file = NULL;
fclose(file);
}
}
void MideaFile::Reset()
{
if (m_file) {
fseek(m_file, 0, SEEK_SET);
}
}
long MideaFile::FindH264Head()
{
while (!feof(m_file)) {
char c = 0x7F;
while (!feof(m_file)) {//是否到文件尾部
c = fgetc(m_file);//一个字节一个字节移动
if (c == 0)break;
}
if (!feof(m_file)) {
c = fgetc(m_file);
if (c == 0) {
c = fgetc(m_file);
if (c == 1) {//找到了一个头
return ftell(m_file)-3;
}
else if (c == 0) {
c = fgetc(m_file);
if (c == 1) {//找到了一个头
return ftell(m_file)-4;
}
}
}
}
}
return -1;
}
ZBuffer MideaFile::ReadH264Frame()
{
if (m_file) {
long off = FindH264Head();
if (off == -1)return ZBuffer();
fseek(m_file, off+3, SEEK_SET);
long tail = FindH264Head();
if (tail == -1) tail = m_size;
long size = m_size - off;
fseek(m_file, off + 3, SEEK_SET);
ZBuffer result(size);
fread(result, 1, size, m_file);
return result;
}
return ZBuffer();
}