📄 demux_mov.c
字号:
mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: Found unsupported MJPEG-Quantization movie atom (%d)!\n", atom_len); break; case MOV_FOURCC('m','j','h','t'): // Motion-JPEG default huffman table mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: Found unsupported MJPEG-Huffman movie atom (%d)!\n", atom_len); break; case MOV_FOURCC('e','s','d','s'): // MPEG4 Elementary Stream Descriptor header mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: Found MPEG4 movie Elementary Stream Descriptor atom (%d)!\n", atom_len); // add code here to save esds header of length atom_len-8 // beginning at stdata[86] to some variable to pass it // on to the decoder ::atmos if(atom_len > 8) { esds_t esds; if(!mp4_parse_esds(trak->stdata+pos+8, atom_len-8, &esds)) { if(esds.objectTypeId==MP4OTI_MPEG2VisualSimple || esds.objectTypeId==MP4OTI_MPEG2VisualMain || esds.objectTypeId==MP4OTI_MPEG2VisualSNR || esds.objectTypeId==MP4OTI_MPEG2VisualSpatial || esds.objectTypeId==MP4OTI_MPEG2VisualHigh || esds.objectTypeId==MP4OTI_MPEG2Visual422) sh->format=mmioFOURCC('m', 'p', 'g', '2'); else if(esds.objectTypeId==MP4OTI_MPEG1Visual) sh->format=mmioFOURCC('m', 'p', 'g', '1'); // dump away the codec specific configuration for the AAC decoder trak->stream_header_len = esds.decoderConfigLen; trak->stream_header = (unsigned char *)malloc(trak->stream_header_len); memcpy(trak->stream_header, esds.decoderConfig, trak->stream_header_len); } mp4_free_esds(&esds); // freeup esds mem } break; case MOV_FOURCC('a','v','c','C'): // AVC decoder configuration record mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: AVC decoder configuration record atom (%d)!\n", atom_len); if(atom_len > 8) { int i, poffs, cnt; // Parse some parts of avcC, just for fun :) // real parsing is done by avc1 decoder mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC version: %d\n", *(trak->stdata+pos+8)); if (*(trak->stdata+pos+8) != 1) mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: unknown avcC version (%d). Expexct problems.\n", *(trak->stdata+pos+9)); mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC profile: %d\n", *(trak->stdata+pos+9)); mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC profile compatibility: %d\n", *(trak->stdata+pos+10)); mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC level: %d\n", *(trak->stdata+pos+11)); mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC nal length size: %d\n", ((*(trak->stdata+pos+12))&0x03)+1); mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC number of sequence param sets: %d\n", cnt = (*(trak->stdata+pos+13) & 0x1f)); poffs = pos + 14; for (i = 0; i < cnt; i++) { mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC sps %d have length %d\n", i, BE_16(trak->stdata+poffs)); poffs += BE_16(trak->stdata+poffs) + 2; } mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC number of picture param sets: %d\n", *(trak->stdata+poffs)); poffs++; for (i = 0; i < cnt; i++) { mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC pps %d have length %d\n", i, BE_16(trak->stdata+poffs)); poffs += BE_16(trak->stdata+poffs) + 2; } // Copy avcC for the AVC decoder // This data will be put in extradata below, where BITMAPINFOHEADER is created trak->stream_header_len = atom_len-8; trak->stream_header = (unsigned char *)malloc(trak->stream_header_len); memcpy(trak->stream_header, trak->stdata+pos+8, trak->stream_header_len); } break; case 0: break; default: mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: Found unknown movie atom %c%c%c%c (%d)!\n", trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7], atom_len); } if(atom_len<8) break; pos+=atom_len;// printf("pos=%d max=%d\n",pos,trak->stdata_len); } } sh->fps=trak->timescale/ ((trak->durmap_size>=1)?(float)trak->durmap[0].dur:1); sh->frametime=1.0f/sh->fps; sh->disp_w=trak->stdata[25]|(trak->stdata[24]<<8); sh->disp_h=trak->stdata[27]|(trak->stdata[26]<<8); // if image size is zero, fallback to display size if(!sh->disp_w && !sh->disp_h) { sh->disp_w=trak->tkdata[77]|(trak->tkdata[76]<<8); sh->disp_h=trak->tkdata[81]|(trak->tkdata[80]<<8); } else if(sh->disp_w!=(trak->tkdata[77]|(trak->tkdata[76]<<8))){ // codec and display width differ... use display one for aspect sh->aspect=trak->tkdata[77]|(trak->tkdata[76]<<8); sh->aspect/=trak->tkdata[81]|(trak->tkdata[80]<<8); } if(depth>32+8) printf("*** depth = 0x%X\n",depth); // palettized? gray = 0; if (depth > 32) { depth&=31; gray = 1; } // depth > 32 means grayscale if ((depth == 2) || (depth == 4) || (depth == 8)) palette_count = (1 << depth); else palette_count = 0; // emulate BITMAPINFOHEADER: if (palette_count) { sh->bih=malloc(sizeof(BITMAPINFOHEADER) + palette_count * 4); memset(sh->bih,0,sizeof(BITMAPINFOHEADER) + palette_count * 4); sh->bih->biSize=40 + palette_count * 4; // fetch the relevant fields flag = BE_16(&trak->stdata[hdr_ptr]); hdr_ptr += 2; start = BE_32(&trak->stdata[hdr_ptr]); hdr_ptr += 4; count_flag = BE_16(&trak->stdata[hdr_ptr]); hdr_ptr += 2; end = BE_16(&trak->stdata[hdr_ptr]); hdr_ptr += 2; palette_map = (unsigned char *)sh->bih + 40; mp_msg(MSGT_DEMUX, MSGL_INFO, "Allocated %d entries for palette\n", palette_count); mp_msg(MSGT_DEMUX, MSGL_DBG2, "QT palette: start: %x, end: %x, count flag: %d, flags: %x\n", start, end, count_flag, flag); /* XXX: problems with sample (statunit6.mov) with flag&0x4 set! - alex*/ // load default palette if (flag & 0x08) { if (gray) { mp_msg(MSGT_DEMUX, MSGL_INFO, "Using default QT grayscale palette\n"); if (palette_count == 16) memcpy(palette_map, qt_default_grayscale_palette_16, 16 * 4); else if (palette_count == 256) { memcpy(palette_map, qt_default_grayscale_palette_256, 256 * 4); if (trak->fourcc == mmioFOURCC('c','v','i','d')) { int i; // Hack for grayscale CVID, negative palette // If you have samples where this is not required contact me (rxt) mp_msg(MSGT_DEMUX, MSGL_INFO, "MOV: greyscale cvid with default palette," " enabling negative palette hack.\n"); for (i = 0; i < 256 * 4; i++) palette_map[i] = palette_map[i] ^ 0xff; } } } else { mp_msg(MSGT_DEMUX, MSGL_INFO, "Using default QT colour palette\n"); if (palette_count == 4) memcpy(palette_map, qt_default_palette_4, 4 * 4); else if (palette_count == 16) memcpy(palette_map, qt_default_palette_16, 16 * 4); else if (palette_count == 256) memcpy(palette_map, qt_default_palette_256, 256 * 4); } } // load palette from file else { mp_msg(MSGT_DEMUX, MSGL_INFO, "Loading palette from file\n"); for (i = start; i <= end; i++) { entry = BE_16(&trak->stdata[hdr_ptr]); hdr_ptr += 2; // apparently, if count_flag is set, entry is same as i if (count_flag & 0x8000) entry = i; // only care about top 8 bits of 16-bit R, G, or B value if (entry <= palette_count && entry >= 0) { palette_map[entry * 4 + 2] = trak->stdata[hdr_ptr + 0]; palette_map[entry * 4 + 1] = trak->stdata[hdr_ptr + 2]; palette_map[entry * 4 + 0] = trak->stdata[hdr_ptr + 4]; mp_dbg(MSGT_DEMUX, MSGL_DBG2, "QT palette: added entry: %d of %d (colors: R:%x G:%x B:%x)\n", entry, palette_count, palette_map[entry * 4 + 2], palette_map[entry * 4 + 1], palette_map[entry * 4 + 0]); } else mp_msg(MSGT_DEMUX, MSGL_V, "QT palette: skipped entry (out of count): %d of %d\n", entry, palette_count); hdr_ptr += 6; } } } else { if (trak->fourcc == mmioFOURCC('a','v','c','1')) { sh->bih=malloc(sizeof(BITMAPINFOHEADER) + trak->stream_header_len); memset(sh->bih,0,sizeof(BITMAPINFOHEADER) + trak->stream_header_len); sh->bih->biSize=40 + trak->stream_header_len; memcpy(((unsigned char *)sh->bih)+40, trak->stream_header, trak->stream_header_len); free (trak->stream_header); trak->stream_header_len = 0; trak->stream_header = NULL; } else { sh->bih=malloc(sizeof(BITMAPINFOHEADER)); memset(sh->bih,0,sizeof(BITMAPINFOHEADER)); sh->bih->biSize=40; } } sh->bih->biWidth=sh->disp_w; sh->bih->biHeight=sh->disp_h; sh->bih->biPlanes=0; sh->bih->biBitCount=depth; sh->bih->biCompression=trak->fourcc; sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight; mp_msg(MSGT_DEMUX, MSGL_INFO, "Image size: %d x %d (%d bpp)\n",sh->disp_w,sh->disp_h,sh->bih->biBitCount); if(trak->tkdata_len>81) mp_msg(MSGT_DEMUX, MSGL_INFO, "Display size: %d x %d\n", trak->tkdata[77]|(trak->tkdata[76]<<8), trak->tkdata[81]|(trak->tkdata[80]<<8)); mp_msg(MSGT_DEMUX, MSGL_INFO, "Fourcc: %.4s Codec: '%.*s'\n",&trak->fourcc,trak->stdata[42]&31,trak->stdata+43); // if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){// // (auto)selected video track:// demuxer->video->id=priv->track_db;// demuxer->video->sh=sh; sh->ds=demuxer->video;// } break; } case MOV_TRAK_GENERIC: mp_msg(MSGT_DEMUX, MSGL_INFO, "Generic track - not completely understood! (id: %d)\n", trak->id); /* XXX: Also this contains the FLASH data */#if 0 { int pos = stream_tell(demuxer->stream); int i; int fd; char name[20]; for (i=0; i<trak->samples_size; i++) { char buf[trak->samples[i].size]; stream_seek(demuxer->stream, trak->samples[i].pos); snprintf((char *)&name[0], 20, "samp%d", i); fd = open((char *)&name[0], O_CREAT|O_WRONLY); stream_read(demuxer->stream, &buf[0], trak->samples[i].size); write(fd, &buf[0], trak->samples[i].size); close(fd); } for (i=0; i<trak->chunks_size; i++) { char buf[trak->length]; stream_seek(demuxer->stream, trak->chunks[i].pos); snprintf((char *)&name[0], 20, "chunk%d", i); fd = open((char *)&name[0], O_CREAT|O_WRONLY); stream_read(demuxer->stream, &buf[0], trak->length); write(fd, &buf[0], trak->length); close(fd); } if (trak->samplesize > 0) { char *buf; buf = malloc(trak->samplesize); stream_seek(demuxer->stream, trak->chunks[0].pos); snprintf((char *)&name[0], 20, "trak%d", trak->id); fd = open((char *)&name[0], O_CREAT|O_WRONLY); stream_read(demuxer->stream, buf, trak->samplesize); write(fd, buf, trak->samplesize); close(fd); } stream_seek(demuxer->stream, pos); } #endif break; default: mp_msg(MSGT_DEMUX, MSGL_INFO, "Unknown track type found (type: %d)\n", trak->type); break; } mp_msg(MSGT_DEMUX, MSGL_INFO, "--------------\n"); priv->track_db++; trak=NULL; break; }#ifndef HAVE_ZLIB case MOV_FOURCC('c','m','o','v'): { mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_MOVcomprhdr); return; }#else case MOV_FOURCC('m','o','o','v'): case MOV_FOURCC('c','m','o','v'): {// mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_MOVcomprhdr); lschunks(demuxer,level+1,pos+len,NULL); break; } case MOV_FOURCC('d','c','o','m'): {// int temp=stream_read_dword(demuxer->stream); unsigned int algo=be2me_32(stream_read_dword(demuxer->stream)); mp_msg(MSGT_DEMUX, MSGL_INFO, "Compressed header uses %.4s algo!\n",&algo); break; } case MOV_FOURCC('c','m','v','d'): {// int temp=stream_read_dword(demuxer->stream); unsigned int moov_sz=stream_read_dword(demuxer->stream); unsigned int cmov_sz=len-4; unsigned char* cmov_buf=malloc(cmov_sz); unsigned char* moov_buf=malloc(moov_sz+16); int zret; z_stream zstrm; stream_t* backup; mp_msg(MSGT_DEMUX, MSGL_INFO, "Compressed header size: %d / %d\n",cmov_sz,moov_sz); stream_read(demuxer->stream,cmov_buf,cmov_sz); zstrm.zalloc = (alloc_func)0; zstrm.zfree = (free_func)0; zstrm.opaque = (voidpf)0; zstrm.next_in = cmov_buf; zstrm.avail_in = cmov_sz; zstrm.next_out = moov_buf; zstrm.avail_out = moov_sz; zret = inflateInit(&zstrm); if (zret != Z_OK) { mp_msg(MSGT_DEMUX, MSGL_ERR, "QT cmov: inflateInit err %d\n",zret); return; } zret = inflate(&zstrm, Z_NO_FLUSH); if ((zret != Z_OK) && (zret != Z_STREAM_END)) { mp_msg(MSGT_DEMUX, MSGL_ERR, "QT cmov inflate: ERR %d\n",zret); return; }#if 0 else { FILE *DecOut; DecOut = fopen("Out.bin", "w"); fwrite(moov_buf, 1, moov_sz, DecOut); fclose(DecOut); }#endif if(moov_sz != zstrm.total_out) mp_msg(MSGT_DEMUX, MSGL_WARN, "Warning! moov size differs cmov: %d zlib: %d\n",moov_sz,zstrm.total_out); zret = inflateEnd(&zstrm); backup=demuxer->stream; demuxer->stream=new_memory_stream(moov_buf,moov_sz); stream_skip(demuxer->stream,8); lschunks(demuxer,level+1,moov_sz,NULL); // parse uncompr. 'moov' //free_stream(demuxer->stream); demuxer->stream=backup; free(cmov_buf); free(moov_buf); break; }#endif case MOV_FOURCC('u','d','t','a'): { unsigned int udta_id; off_t udta_len; off_t udta_size = len; mp_msg(MSGT_DEMUX, MSGL_DBG2, "mov: user data record found\n"); mp_msg(MSGT_DEMUX, MSGL_V, "Quicktime Clip Info:\n"); while((len > 8) && (udta_size > 8)) { udta_len = stream_read_dword(demuxer->stream); udta_id = stream_read_dword(demuxer->stream); udta_size -= 8; mp_msg(MSGT_DEMUX, MSGL_DBG2, "udta_id: %.4s (len: %d)\n", &udta_id, udta_len); switch (udta_id) { case MOV_FOURCC(0xa9,'c','p','y'): case MOV_FOURCC(0xa9,'d','a','y'): case MOV_FOURCC(0xa9,'d','i','r'): /* 0xa9,'e','d','1' - '9' : edit timestamps */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -