64,282
社区成员
发帖
与我相关
我的任务
分享
/**
* @brief 从内存进行文件duration判定
* TODO: 暂时还是模拟文件读取的方式,是copy的
*/
int GetMP4DurationInMem(const unsigned char *apBuf, const int anBufLen)
{
if(!anBufLen) {
fprintf(stderr, "filesize is zero\n");
return -1;
}
int file_ptr = 0;
unsigned long filesize = anBufLen;
// init the atom size stack
top = 0;
size_stack[top] = filesize;
unsigned long duration = 0;
char buf[5];
unsigned long offset = 0;
int deep = 0; // TODO: 这里小心深度太深。不过这个应用里面是安全的。
while(1) {
if(++deep > 100) {
//printf("reach max depth, abort\n");
break;
}
if(offset >= size_stack[top]) {
if(--top < 0) {
break;
}
}
#ifdef DEBUG_MEM_ALLOC
if(file_ptr != offset) {
FILE *fp = fopen("c:\\cm_mp4_debug.txt", "a+");
if(fp) {
int filesize = 0;
fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
rewind(fp);
if(filesize < 1024*1024*10) {
fprintf(fp, "file_ptr %d, offset %d\r\n");
fprintf(fp, "start\r\n");
fwrite(apBuf, anBufLen, 1, fp);
fprintf(fp, "end\r\n");
} else {
fprintf(fp, "the log file is too large, not write stream data\r\n");
}
fclose(fp);
}
break; // 错误了
}
#endif
//printf("\noffset: %d\n", offset);
if(file_ptr >= anBufLen-4) return -1;
memcpy(buf, apBuf+file_ptr, 4); // ========== (1)
file_ptr += 4;
unsigned long atom_size = GetLong((unsigned char*)buf); buf[4] = 0;
//printf("%X %X %X %X \n", buf[0], buf[1], buf[2], buf[3]);
if(file_ptr >= anBufLen-4) return -1;
memcpy(buf, apBuf+file_ptr, 4);
file_ptr += 4;
//printf("Atom size: %d, name: %c%c%c%c\n", atom_size, buf[0], buf[1], buf[2], buf[3]);
if(!strncmp("moov", buf, 4)) {
//printf(">> Find moov\n");
GoIntoAtomInMem(atom_size, &offset);
continue;
}
// get mvhd, then we go back to the moov atom
if(!strncmp("mvhd", buf, 4)) {
//printf(">> Find mvhd\n");
// get mvhd version
if(file_ptr >= anBufLen-4) return -1;
memcpy(buf, apBuf+file_ptr, 4);
file_ptr += 4;
if( 0 != GetLong((unsigned char *)buf) ) {
fprintf(stderr, "We only accept movie that mvhd version == 0, abort\n");
break;
}
file_ptr += 8; // skip the creation an monification time
if(file_ptr >= anBufLen-4) return -1;
memcpy(buf, apBuf+file_ptr, 4);
file_ptr += 4; // get timescale
unsigned long timescale = GetLong((unsigned char *)buf);
if(file_ptr >= anBufLen-4) return -1;
memcpy(buf, apBuf+file_ptr, 4);
file_ptr += 4; // get duration
duration = GetLong((unsigned char *)buf);
duration /= timescale;
// we break here because this time we only need the duration from mvhd, but not track->mdhd
return duration * 1000; // in millisecond
// seek back to the beginning of this atom in order ot let the SkipAtom work correctly
file_ptr -= 20;
file_ptr += SkipAtomInMem(apBuf, atom_size, &offset);
continue;
}
// default skip
file_ptr += SkipAtomInMem(apBuf, atom_size, &offset);
}
return -1;
}
//printf("\noffset: %d\n", offset);
if(file_ptr >= anBufLen-4) return -1;
00414338 add eax,0FFFFFFFCh
0041433B cmp edi,eax
0041433D jge GetMP4DurationInMem+25Ah (41450Ah)
memcpy(buf, apBuf+file_ptr, 4);
00414343 mov edx,dword ptr [ebx+edi]
00414346 mov dword ptr [esp+10h],edx
// 内存进去atom
void GoIntoAtomInMem(unsigned long atom_size, unsigned long *offset)
{
*offset += 8; // len( size + 4cc )
size_stack[++top] = atom_size;
}
// 内存跳过当前atom
int SkipAtomInMem(const unsigned char *apBuf, unsigned long atom_size, unsigned long *offset)
{
*offset += atom_size;
return atom_size - 8; // 返回file_ptr的增量,模拟fseek
}
unsigned long size_stack[100];
int top;
unsigned long GetLong(const unsigned char *buf)
{
int ret = 0;
for(int i=0;i<4;++i) {
ret *= 256;
ret += buf[i];
}
return ret;
}
void GoIntoAtom(FILE *fp, unsigned long atom_size, unsigned long *offset)
{
// no seek , already in
// unused fp
*offset += 8; // len( size + 4cc )
size_stack[++top] = atom_size;
}
void SkipAtom(FILE *fp, unsigned long atom_size, unsigned long *offset)
{
fseek(fp, atom_size - 8, SEEK_CUR);
*offset += atom_size;
}
/**
* @brief 根据fp来获取mp4文件的duration
*/
// TODO: considering get duration from track->mdhd
int GetMP4Duration(FILE *fp)
{
if(!fp) {
fprintf(stderr, "the file fp is invalid\n");
return -1;
}
unsigned long filesize = 0;
fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
//printf("filesize: %d\n", filesize);
rewind(fp);
// init the atom size stack
top = 0;
size_stack[top] = filesize;
unsigned long duration = 0;
char buf[5];
unsigned long offset = 0;
int deep = 0; // TODO: 这里小心深度太深。不过这个应用里面是安全的。
while(1) {
if(++deep > 100) {
//printf("reach max depth, abort\n");
break;
}
if(offset >= size_stack[top]) {
if(--top < 0) {
break;
}
}
//printf("\noffset: %d\n", offset);
fread(buf, 1, 4, fp);
unsigned long atom_size = GetLong((unsigned char*)buf); buf[4] = 0;
//printf("%X %X %X %X \n", buf[0], buf[1], buf[2], buf[3]);
fread(buf, 1, 4, fp);
//printf("Atom size: %d, name: %c%c%c%c\n", atom_size, buf[0], buf[1], buf[2], buf[3]);
if(!strncmp("moov", buf, 4)) {
//printf(">> Find moov\n");
GoIntoAtom(fp, atom_size, &offset);
continue;
}
// get mvhd, then we go back to the moov atom
if(!strncmp("mvhd", buf, 4)) {
//printf(">> Find mvhd\n");
// get mvhd version
fread(buf, 1, 4, fp);
if( 0 != GetLong((unsigned char *)buf) ) {
fprintf(stderr, "We only accept movie that mvhd version == 0, abort\n");
break;
}
fseek(fp, 8, SEEK_CUR); // skip the creation an monification time
fread(buf, 1, 4, fp); // get timescale
unsigned long timescale = GetLong((unsigned char *)buf);
fread(buf, 1, 4, fp); // get duration
duration = GetLong((unsigned char *)buf);
duration /= timescale;
// we break here because this time we only need the duration from mvhd, but not track->mdhd
rewind(fp);
return duration * 1000; // in millisecond
// seek back to the beginning of this atom in order ot let the SkipAtom work correctly
fseek(fp, -20, SEEK_CUR);
SkipAtom(fp, atom_size, &offset);
continue;
}
// default skip
SkipAtom(fp, atom_size, &offset);
}
rewind(fp);
return -1;
}