demux_mov.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,854 行 · 第 1/5 页
C
1,854 行
sh->format=char2int(trak->stdata,52+8); mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found little endian PCM data, reversed fourcc:%04x\n", sh->format); } break; default: if (len > 8 && len + 44 <= trak->stdata_len) { sh->codecdata_len = len-8; sh->codecdata = trak->stdata+44+8; } } } else { if (len > 8 && len + 44 <= trak->stdata_len) { sh->codecdata_len = len-8; sh->codecdata = trak->stdata+44+8; } } } } switch (version) { case 0: adjust = 0; break; case 1: adjust = 48; break; case 2: adjust = 68; break; default: mp_msg(MSGT_DEMUX, MSGL_WARN, "MOV: unknown sound atom version (%d); may not work!\n", version); adjust = 68; } if (trak->stdata_len >= 36 + adjust) { int atom_len = char2int(trak->stdata,28+adjust); switch(char2int(trak->stdata,32+adjust)) { // atom type case MOV_FOURCC('e','s','d','s'): { mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found MPEG4 audio Elementary Stream Descriptor atom (%d)!\n", atom_len); if(atom_len > 8) { esds_t esds; if(!mp4_parse_esds(&trak->stdata[36+adjust], atom_len-8, &esds)) { /* 0xdd is a "user private" id, not an official allocated id (see http://www.mp4ra.org/object.html), so perform some extra checks to be sure that this is really vorbis audio */ if(esds.objectTypeId==0xdd && esds.streamType==0x15 && sh->format==0x6134706D && esds.decoderConfigLen > 8) { //vorbis audio unsigned char *buf[3]; unsigned short sizes[3]; int offset, len, k; unsigned char *ptr = esds.decoderConfig; if(ptr[0] != 0 || ptr[1] != 30) goto quit_vorbis_block; //wrong extradata layout offset = len = 0; for(k = 0; k < 3; k++) { sizes[k] = (ptr[offset]<<8) | ptr[offset+1]; len += sizes[k]; offset += 2; if(offset + sizes[k] > esds.decoderConfigLen) { mp_msg(MSGT_DEMUX, MSGL_FATAL, "MOV: ERROR!, not enough vorbis extradata to read: offset = %d, k=%d, size=%d, len: %d\n", offset, k, sizes[k], esds.decoderConfigLen); goto quit_vorbis_block; } buf[k] = malloc(sizes[k]); if(!buf[k]) goto quit_vorbis_block; memcpy(buf[k], &ptr[offset], sizes[k]); offset += sizes[k]; } sh->codecdata_len = len + len/255 + 64; sh->codecdata = malloc(sh->codecdata_len); sh->codecdatatype = 1; ptr = sh->codecdata; ptr[0] = 2; offset = 1; offset += store_ughvlc(&ptr[offset], sizes[0]); offset += store_ughvlc(&ptr[offset], sizes[1]); for(k = 0; k < 3; k++) { memcpy(&ptr[offset], buf[k], sizes[k]); offset += sizes[k]; } sh->codecdata_len = offset; sh->codecdata = realloc(sh->codecdata, offset); mp_msg(MSGT_DEMUX,MSGL_V, "demux_mov, vorbis extradata size: %d\n", offset); is_vorbis = 1;quit_vorbis_block: sh->format = mmioFOURCC('v', 'r', 'b', 's'); } sh->i_bps = esds.avgBitrate/8; // printf("######## audio format = %d ########\n",esds.objectTypeId); if(esds.objectTypeId==MP4OTI_MPEG1Audio || esds.objectTypeId==MP4OTI_MPEG2AudioPart3) sh->format=0x55; // .mp3 if(esds.objectTypeId==MP4OTI_13kVoice) { // 13K Voice, defined by 3GPP2 sh->format=mmioFOURCC('Q', 'c', 'l', 'p'); trak->nchannels=sh->channels=1; trak->samplebytes=sh->samplesize=1; } // dump away the codec specific configuration for the AAC decoder if(esds.decoderConfigLen){ if( (esds.decoderConfig[0]>>3) == 29 ) sh->format = 0x1d61346d; // request multi-channel mp3 decoder if(!is_vorbis) { sh->codecdata_len = esds.decoderConfigLen; sh->codecdata = malloc(sh->codecdata_len); sh->codecdatatype = 1; memcpy(sh->codecdata, esds.decoderConfig, sh->codecdata_len); } } } mp4_free_esds(&esds); // freeup esds mem#if 0 { FILE* f=fopen("esds.dat","wb"); fwrite(&trak->stdata[36],atom_len-8,1,f); fclose(f); }#endif } } break; case MOV_FOURCC('a','l','a','c'): { mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found alac atom (%d)!\n", atom_len); if(atom_len > 8) { // copy all the atom (not only payload) for lavc alac decoder sh->codecdata_len = atom_len; sh->codecdata = malloc(sh->codecdata_len); sh->codecdatatype = 1; memcpy(sh->codecdata, &trak->stdata[28], sh->codecdata_len); } } break; case MOV_FOURCC('d','a','m','r'): mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found AMR audio atom %c%c%c%c (%d)!\n", trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], atom_len); if (atom_len>14) { mp_msg(MSGT_DEMUX, MSGL_V, "mov: vendor: %c%c%c%c Version: %d\n",trak->stdata[36+adjust],trak->stdata[37+adjust],trak->stdata[38+adjust], trak->stdata[39+adjust],trak->stdata[40+adjust]); mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Modes set: %02x%02x\n",trak->stdata[41+adjust],trak->stdata[42+adjust]); mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Mode change period: %d Frames per sample: %d\n",trak->stdata[43+adjust],trak->stdata[44+adjust]); } break; default: mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unknown audio atom %c%c%c%c (%d)!\n", trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], atom_len); } } mp_msg(MSGT_DEMUX, MSGL_V, "Fourcc: %.4s\n",(char *)&trak->fourcc);#if 0 { FILE* f=fopen("stdata.dat","wb"); fwrite(trak->stdata,trak->stdata_len,1,f); fclose(f); } { FILE* f=fopen("tkdata.dat","wb"); fwrite(trak->tkdata,trak->tkdata_len,1,f); fclose(f); }#endif // Emulate WAVEFORMATEX struct: sh->wf=malloc(sizeof(WAVEFORMATEX) + (is_vorbis ? sh->codecdata_len : 0)); memset(sh->wf,0,sizeof(WAVEFORMATEX)); sh->wf->nChannels=sh->channels; sh->wf->wBitsPerSample=(trak->stdata[18]<<8)+trak->stdata[19]; // sh->wf->nSamplesPerSec=trak->timescale; sh->wf->nSamplesPerSec=sh->samplerate; if(trak->stdata_len >= 44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){ //Audio header: samp/pack=4096 bytes/pack=743 bytes/frame=1486 bytes/samp=2 sh->wf->nAvgBytesPerSec=(sh->wf->nChannels*sh->wf->nSamplesPerSec* char2int(trak->stdata,32)+char2int(trak->stdata,28)/2) /char2int(trak->stdata,28); sh->wf->nBlockAlign=char2int(trak->stdata,36); } else { sh->wf->nAvgBytesPerSec=sh->wf->nChannels*sh->wf->wBitsPerSample*sh->wf->nSamplesPerSec/8; // workaround for ms11 ima4 if (sh->format == 0x1100736d && trak->stdata_len >= 36) sh->wf->nBlockAlign=char2int(trak->stdata,36); } if(is_vorbis && sh->codecdata_len) { memcpy(sh->wf+1, sh->codecdata, sh->codecdata_len); sh->wf->cbSize = sh->codecdata_len; } // Selection:// if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){// // (auto)selected audio track:// demuxer->audio->id=priv->track_db;// demuxer->audio->sh=sh; sh->ds=demuxer->audio;// } return 1;}static int gen_sh_video(sh_video_t* sh, mov_track_t* trak, int timescale) { int depth, i, entry; int flag, start, count_flag, end, palette_count, gray; int hdr_ptr = 76; // the byte just after depth unsigned char *palette_map; sh->format=trak->fourcc; // crude video delay from editlist0 hack ::atm if(trak->editlist_size>=1) { if(trak->editlist[0].pos == -1) { sh->stream_delay = (float)trak->editlist[0].dur/(float)timescale; mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Initial Video-Delay: %.3f sec\n", sh->stream_delay); } } if (trak->stdata_len < 78) { mp_msg(MSGT_DEMUXER, MSGL_WARN, "MOV: Invalid (%d bytes instead of >= 78) video trak desc\n", trak->stdata_len); return 0; } depth = trak->stdata[75] | (trak->stdata[74] << 8);// stdata[]:// 8 short version// 10 short revision// 12 int vendor_id// 16 int temporal_quality// 20 int spatial_quality// 24 short width// 26 short height// 28 int h_dpi// 32 int v_dpi// 36 int 0// 40 short frames_per_sample// 42 char[4] compressor_name// 74 short depth// 76 short color_table_id// additional atoms may follow,// eg esds atom from .MP4 files// 78 int atom size// 82 char[4] atom type// 86 ... atom data { ImageDescription* id=malloc(8+trak->stdata_len); // safe trak->desc=id; id->idSize=8+trak->stdata_len;// id->cType=bswap_32(trak->fourcc); id->cType=le2me_32(trak->fourcc); id->version=char2short(trak->stdata,8); id->revisionLevel=char2short(trak->stdata,10); id->vendor=char2int(trak->stdata,12); id->temporalQuality=char2int(trak->stdata,16); id->spatialQuality=char2int(trak->stdata,20); id->width=char2short(trak->stdata,24); id->height=char2short(trak->stdata,26); id->hRes=char2int(trak->stdata,28); id->vRes=char2int(trak->stdata,32); id->dataSize=char2int(trak->stdata,36); id->frameCount=char2short(trak->stdata,40); memcpy(&id->name,trak->stdata+42,32); id->depth=char2short(trak->stdata,74); id->clutID=char2short(trak->stdata,76); if(trak->stdata_len>78) memcpy(((char*)&id->clutID)+2,trak->stdata+78,trak->stdata_len-78); sh->ImageDesc=id;#if 0 { FILE *f=fopen("ImageDescription","wb"); fwrite(id,id->idSize,1,f); fclose(f); }#endif } if(trak->stdata_len >= 86) { // extra atoms found int pos=78; int atom_len; while(pos+8<=trak->stdata_len && (pos+(atom_len=char2int(trak->stdata,pos)))<=trak->stdata_len){ switch(char2int(trak->stdata,pos+4)) { // switch atom type case MOV_FOURCC('g','a','m','a'): // intfp with gamma value at which movie was captured // can be used to gamma correct movie display mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unsupported Gamma-Correction movie atom (%d)!\n", atom_len); break; case MOV_FOURCC('f','i','e','l'): // 2 char-values (8bit int) that specify field handling // see the Apple's QuickTime Fileformat PDF for more info mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found unsupported Field-Handling movie atom (%d)!\n", atom_len); break; case MOV_FOURCC('m','j','q','t'): // Motion-JPEG default quantization table mp_msg(MSGT_DEMUX, MSGL_V, "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_V, "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_V, "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 = 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_V, "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 = malloc(trak->stream_header_len); memcpy(trak->stream_header, trak->stdata+pos+8, trak->stream_header_len); } break; case MOV_FOURCC('d','2','6','3'): mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Found H.263 decoder 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>10) mp_msg(MSGT_DEMUX, MSGL_V, "MOV: Vendor: %c%c%c%c H.263 level: %d H.263 profile: %d \n", trak->stdata[pos+8],trak->stdata[pos+9],trak->stdata[pos+10],trak->stdata[pos+11],trak->stdata[pos+12],trak->stdata[pos+13]); break; case 0: break; default: mp_msg(MSGT_DEMUX, MSGL_V, "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);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?