📄 mov.c
字号:
get_be16(pb); /* index */ /* for MPEG4: set codec type by looking for it */ id = codec_get_id(mov_video_tags, format); if (id >= 0) { AVCodec *codec; codec = avcodec_find_decoder(id); if (codec) st->codec.codec_type = codec->type; }#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "size=%d 4CC= %c%c%c%c codec_type=%d\n", size, (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, (format >> 24) & 0xff, st->codec.codec_type);#endif st->codec.codec_tag = format; if(st->codec.codec_type==CODEC_TYPE_VIDEO) { MOV_atom_t a = { 0, 0, 0 }; st->codec.codec_id = id; get_be16(pb); /* version */ get_be16(pb); /* revision level */ get_be32(pb); /* vendor */ get_be32(pb); /* temporal quality */ get_be32(pb); /* spacial quality */ st->codec.width = get_be16(pb); /* width */ st->codec.height = get_be16(pb); /* height */#if 1 if (st->codec.codec_id == CODEC_ID_MPEG4) { /* in some MPEG4 the width/height are not correct, so we ignore this info */ st->codec.width = 0; st->codec.height = 0; }#endif get_be32(pb); /* horiz resolution */ get_be32(pb); /* vert resolution */ get_be32(pb); /* data size, always 0 */ frames_per_sample = get_be16(pb); /* frames per samples */#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "frames/samples = %d\n", frames_per_sample);#endif get_buffer(pb, (uint8_t *)st->codec.codec_name, 32); /* codec name */ st->codec.bits_per_sample = get_be16(pb); /* depth */ st->codec.color_table_id = get_be16(pb); /* colortable id *//* These are set in mov_read_stts and might already be set! st->codec.frame_rate = 25; st->codec.frame_rate_base = 1;*/ size -= (16+8*4+2+32+2*2);#if 0 while (size >= 8) { MOV_atom_t a; int64_t start_pos; a.size = get_be32(pb); a.type = get_le32(pb); size -= 8;#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "VIDEO: atom_type=%c%c%c%c atom.size=%Ld size_left=%d\n", (a.type >> 0) & 0xff, (a.type >> 8) & 0xff, (a.type >> 16) & 0xff, (a.type >> 24) & 0xff, a.size, size);#endif start_pos = url_ftell(pb); switch(a.type) { case MKTAG('e', 's', 'd', 's'): { int tag, len; /* Well, broken but suffisant for some MP4 streams */ get_be32(pb); /* version + flags */ len = mov_mp4_read_descr(pb, &tag); if (tag == 0x03) { /* MP4ESDescrTag */ get_be16(pb); /* ID */ get_byte(pb); /* priority */ len = mov_mp4_read_descr(pb, &tag); if (tag != 0x04) goto fail; /* MP4DecConfigDescrTag */ get_byte(pb); /* objectTypeId */ get_be32(pb); /* streamType + buffer size */ get_be32(pb); /* max bit rate */ get_be32(pb); /* avg bit rate */ len = mov_mp4_read_descr(pb, &tag); if (tag != 0x05) goto fail; /* MP4DecSpecificDescrTag */#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "Specific MPEG4 header len=%d\n", len);#endif sc->header_data = av_mallocz(len); if (sc->header_data) { get_buffer(pb, sc->header_data, len); sc->header_len = len; } } /* in any case, skip garbage */ } break; default: break; } fail: av_log(NULL, AV_LOG_DEBUG, "ATOMENEWSIZE %Ld %d\n", atom.size, url_ftell(pb) - start_pos); if (atom.size > 8) { url_fskip(pb, (atom.size - 8) - ((url_ftell(pb) - start_pos))); size -= atom.size - 8; } } if (size > 0) { /* unknown extension */ url_fskip(pb, size); }#else /* figure out the palette situation */ color_depth = st->codec.bits_per_sample & 0x1F; color_greyscale = st->codec.bits_per_sample & 0x20; /* if the depth is 2, 4, or 8 bpp, file is palettized */ if ((color_depth == 2) || (color_depth == 4) || (color_depth == 8)) { if (color_greyscale) { /* compute the greyscale palette */ color_count = 1 << color_depth; color_index = 255; color_dec = 256 / (color_count - 1); for (j = 0; j < color_count; j++) { r = g = b = color_index; c->palette_control.palette[j] = (r << 16) | (g << 8) | (b); color_index -= color_dec; if (color_index < 0) color_index = 0; } } else if (st->codec.color_table_id & 0x08) { /* if flag bit 3 is set, use the default palette */ color_count = 1 << color_depth; if (color_depth == 2) color_table = ff_qt_default_palette_4; else if (color_depth == 4) color_table = ff_qt_default_palette_16; else color_table = ff_qt_default_palette_256; for (j = 0; j < color_count; j++) { r = color_table[j * 4 + 0]; g = color_table[j * 4 + 1]; b = color_table[j * 4 + 2]; c->palette_control.palette[j] = (r << 16) | (g << 8) | (b); } } else { /* load the palette from the file */ color_start = get_be32(pb); color_count = get_be16(pb); color_end = get_be16(pb); for (j = color_start; j <= color_end; j++) { /* each R, G, or B component is 16 bits; * only use the top 8 bits; skip alpha bytes * up front */ get_byte(pb); get_byte(pb); r = get_byte(pb); get_byte(pb); g = get_byte(pb); get_byte(pb); b = get_byte(pb); get_byte(pb); c->palette_control.palette[j] = (r << 16) | (g << 8) | (b); } } st->codec.palctrl = &c->palette_control; st->codec.palctrl->palette_changed = 1; } else st->codec.palctrl = NULL; a.size = size; mov_read_default(c, pb, a);#endif } else { st->codec.codec_id = codec_get_id(mov_audio_tags, format); if(st->codec.codec_id==CODEC_ID_AMR_NB || st->codec.codec_id==CODEC_ID_AMR_WB) //from TS26.244 {#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "AMR-NB or AMR-WB audio identified!!\n");#endif get_be32(pb);get_be32(pb); //Reserved_8 get_be16(pb);//Reserved_2 get_be16(pb);//Reserved_2 get_be32(pb);//Reserved_4 get_be16(pb);//TimeScale get_be16(pb);//Reserved_2 //AMRSpecificBox.(10 bytes) get_be32(pb); //size get_be32(pb); //type=='damr' get_be32(pb); //vendor get_byte(pb); //decoder version get_be16(pb); //mode_set get_byte(pb); //mode_change_period get_byte(pb); //frames_per_sample st->duration = AV_NOPTS_VALUE;//Not possible to get from this info, must count number of AMR frames if(st->codec.codec_id==CODEC_ID_AMR_NB) { st->codec.sample_rate=8000; st->codec.channels=1; } else //AMR-WB { st->codec.sample_rate=16000; st->codec.channels=1; } st->codec.bits_per_sample=16; st->codec.bit_rate=0; /*It is not possible to tell this before we have an audio frame and even then every frame can be different*/ } else if( st->codec.codec_tag == MKTAG( 'm', 'p', '4', 's' )) { //This is some stuff for the hint track, lets ignore it! //Do some mp4 auto detect. c->mp4=1; size-=(16); url_fskip(pb, size); /* The mp4s atom also contians a esds atom that we can skip*/ } else if( st->codec.codec_tag == MKTAG( 'm', 'p', '4', 'a' )) { /* Handle mp4 audio tag */ get_be32(pb); /* version */ get_be32(pb); st->codec.channels = get_be16(pb); /* channels */ st->codec.bits_per_sample = get_be16(pb); /* bits per sample */ get_be32(pb); st->codec.sample_rate = get_be16(pb); /* sample rate, not always correct */ get_be16(pb); c->mp4=1; { MOV_atom_t a = { format, url_ftell(pb), size - (20 + 20 + 8) }; mov_read_default(c, pb, a); } /* Get correct sample rate from extradata */ if(st->codec.extradata_size) { const int samplerate_table[] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, 0 }; unsigned char *px = st->codec.extradata; // 5 bits objectTypeIndex, 4 bits sampleRateIndex, 4 bits channels int samplerate_index = ((px[0] & 7) << 1) + ((px[1] >> 7) & 1); st->codec.sample_rate = samplerate_table[samplerate_index]; } } else if(size>=(16+20)) {//16 bytes read, reading atleast 20 more#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "audio size=0x%X\n",size);#endif uint16_t version = get_be16(pb); /* version */ get_be16(pb); /* revision level */ get_be32(pb); /* vendor */ st->codec.channels = get_be16(pb); /* channel count */ st->codec.bits_per_sample = get_be16(pb); /* sample size */ /* handle specific s8 codec */ get_be16(pb); /* compression id = 0*/ get_be16(pb); /* packet size = 0 */ st->codec.sample_rate = ((get_be32(pb) >> 16)); //av_log(NULL, AV_LOG_DEBUG, "CODECID %d %d %.4s\n", st->codec.codec_id, CODEC_ID_PCM_S16BE, (char*)&format); switch (st->codec.codec_id) { case CODEC_ID_PCM_S16BE: if (st->codec.bits_per_sample == 8) st->codec.codec_id = CODEC_ID_PCM_S8; /* fall */ case CODEC_ID_PCM_U8: st->codec.bit_rate = st->codec.sample_rate * 8; break; default: ; } //Read QT version 1 fields. In version 0 theese dont exist#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "version =%d mp4=%d\n",version,c->mp4); av_log(NULL, AV_LOG_DEBUG, "size-(16+20+16)=%d\n",size-(16+20+16));#endif if((version==1) && size>=(16+20+16)) { get_be32(pb); /* samples per packet */ get_be32(pb); /* bytes per packet */ get_be32(pb); /* bytes per frame */ get_be32(pb); /* bytes per sample */ if(size>(16+20+16)) { //Optional, additional atom-based fields#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "offest=0x%X, sizeleft=%d=0x%x,format=%c%c%c%c\n",(int)url_ftell(pb),size - (16 + 20 + 16 ),size - (16 + 20 + 16 ), (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff, (format >> 24) & 0xff);#endif MOV_atom_t a = { format, url_ftell(pb), size - (16 + 20 + 16 + 8) }; mov_read_default(c, pb, a); } } else { //We should be down to 0 bytes here, but lets make sure. size-=(16+20);#ifdef DEBUG if(size>0) av_log(NULL, AV_LOG_DEBUG, "skipping 0x%X bytes\n",size-(16+20));#endif url_fskip(pb, size); } } else { size-=16; //Unknown size, but lets do our best and skip the rest.#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "Strange size, skipping 0x%X bytes\n",size);#endif url_fskip(pb, size); } } } return 0;}static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ AVStream *st = c->fc->streams[c->fc->nb_streams-1]; MOVStreamContext *sc = (MOVStreamContext *)st->priv_data; int entries, i; print_atom("stsc", atom); get_byte(pb); /* version */ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ entries = get_be32(pb);#ifdef DEBUGav_log(NULL, AV_LOG_DEBUG, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);#endif sc->sample_to_chunk_sz = entries; sc->sample_to_chunk = (MOV_sample_to_chunk_tbl*) av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl)); if (!sc->sample_to_chunk) return -1; for(i=0; i<entries; i++) { sc->sample_to_chunk[i].first = get_be32(pb); sc->sample_to_chunk[i].count = get_be32(pb); sc->sample_to_chunk[i].id = get_be32(pb);#ifdef DEBUG/* av_log(NULL, AV_LOG_DEBUG, "sample_to_chunk first=%ld count=%ld, id=%ld\n", sc->sample_to_chunk[i].first, sc->sample_to_chunk[i].count, sc->sample_to_chunk[i].id); */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -