我正在尝试从 isobmff 格式的电影框中提取“moof”框。
// It is assumed that the movie box contains fragment data.
ISOMovie moov;
MP4MovieFragmentAtomPtr moof;
FILE *fp;
fp = fopen("test_moof_mdat.m4v","w");
movie = (MP4PrivateMovieRecordPtr)moov;
if((movie->moovAtomPtr)->type ==MP4MovieFragmentAtomType)
{
// movie fragment box
moof = (MP4MovieFragmentAtomPtr)movie->moovAtomPtr;
// calculate `moof` box size
movie->moovAtomPtr->calculateSize(movie->moovAtomPtr);
}
fwrite(moof,moof->size,1,fp2);
如您所见,ASCII 码是颠倒过来的。
mp4 盒子的 ASCII 码和大小是大端格式吗?
(*参考:我的电脑 CPU:Intel(R) Xeon(R) Gold 6238R CPU @ 2.20GHz。)
“MP4盒子的ASCII码和大小是用big-endian格式写的吗?”
是的。 MP4 结构的所有数据(原子、值等)均应以 Big Endian 格式写入。
通过快速研究,您使用的库似乎确实为 MP4 输出编写了 Big-Endian。它还允许将 PCM 音频添加到 MP4,这是它处理 Little-Endian 代码的唯一一次。
问题可能在于 fwrite() 本身如何工作。
图书馆可能没有做错任何事。
可能的解决方案:
1.尝试将
fopen
输出设置为二进制模式“wb”(不仅仅是“w”)。 fp = fopen("test_moof_mdat.m4v","wb");
2. 您可能需要创建一个自定义函数来转换每个 16 位、24 位或 32 位整数的字节序。如果您不知道如何操作,请查看这篇文章作为起点:
https://developer.ibm.com/articles/au-endianc/
(特别是这部分:“清单 4. 强制字节顺序”)。
PS:尚不清楚(代码的)
moof =
部分是否为您提供了字节值数组(eg:uint32_t
)。我的意思是,您是否处于可以轻松手动反转整数的阶段?
3. 最终的解决方案是自己从文件(或字节流)中手动提取原子。如果您需要一些帮助,我可以稍后扩展这部分(这里没有 C++ 来测试),但这个概念的简短版本是:
将 MOOV 字节获取到可以使用 While 循环逐一读取它们的程度。
通过递增
idx
向前搜索uint_8数组的槽(例如:读取单个字节)。
如果槽有一个字节与匹配的起始值,则检查其他接下来的 3 个字节是否也匹配。
如果全部匹配,您现在已经在
moof
原子中找到了“moof”文本的起始位置。
从新的
pos_moof
向后移动 -4 个字节,然后将 size
读取为 32 位 Big-Endian uint。
从输入字节中提取一个新数组(从
pos_moof
开始,长度为(size + 4)
等)。
下面是一个使用伪代码的快速 “搜索字节序列”示例...
//### about the required vars...
byte[] my_MOOV_Bytes_Array //# provides input byte values (could be an Array or FileStream, etc)
int pos_idx = 0; //# for the index (pos) within the bytes
//### search process is simple with a While loop...
while (true)
{
//# end While loop if reached end of bytes Array
if( pos_idx >= my_MOOV_Bytes_Array.length ) { break; }
//# find "m"
if( my_MOOV_Bytes_Array[ pos_idx ] == 0x6D )
{
if(
( my_MOOV_Bytes_Array[ pos_idx + 1 ] == 0x6F ) && //# find "o"
( my_MOOV_Bytes_Array[ pos_idx + 2 ] == 0x6F ) && //# find "o"
( my_MOOV_Bytes_Array[ pos_idx + 3 ] == 0x66 ) //# find "f"
)
{
cout << "MOOF atom found at : " << pos_idx << endl;
break; //# or can Return pos_idx if used inside a search function
}
}
pos_idx++; //# just keep incrementing...
}