📄 mov.c
字号:
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 = qt_default_palette_4; else if (color_depth == 4) color_table = qt_default_palette_16; else color_table = 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 printf("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(size>=(16+20)) {//16 bytes read, reading atleast 20 more#ifdef DEBUG printf("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)); //printf("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 printf("version =%d mp4=%d\n",version,c->mp4); printf("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 printf("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) printf("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 printf("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 DEBUGprintf("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/* printf("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 } return 0;}static int mov_read_stsz(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("stsz", atom); get_byte(pb); /* version */ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ sc->sample_size = get_be32(pb); entries = get_be32(pb); sc->sample_count = entries;#ifdef DEBUG printf("sample_size = %ld sample_count = %ld\n", sc->sample_size, sc->sample_count);#endif if(sc->sample_size) return 0; /* there isn't any table following */ sc->sample_sizes = (long*) av_malloc(entries * sizeof(long)); if (!sc->sample_sizes) return -1; for(i=0; i<entries; i++) { sc->sample_sizes[i] = get_be32(pb);#ifdef DEBUG/* printf("sample_sizes[]=%ld\n", sc->sample_sizes[i]); */#endif } return 0;}static int mov_read_stts(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; int duration=0; int total_sample_count=0; print_atom("stts", atom); get_byte(pb); /* version */ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ entries = get_be32(pb);#ifdef DEBUGprintf("track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);#endif for(i=0; i<entries; i++) { int sample_duration; int sample_count; sample_count=get_be32(pb); sample_duration = get_be32(pb);#ifdef DEBUG printf("sample_count=%d, sample_duration=%d\n",sample_count,sample_duration);#endif duration+=sample_duration*sample_count; total_sample_count+=sample_count;#if 0 //We calculate an average instead, needed by .mp4-files created with nec e606 3g phone if (!i && st->codec.codec_type==CODEC_TYPE_VIDEO) { st->codec.frame_rate_base = sample_duration ? sample_duration : 1; st->codec.frame_rate = c->streams[c->total_streams]->time_scale;#ifdef DEBUG printf("VIDEO FRAME RATE= %i (sd= %i)\n", st->codec.frame_rate, sample_duration);#endif }#endif }#define MAX(a,b) a>b?a:b#define MIN(a,b) a>b?b:a /*The stsd atom which contain codec type sometimes comes after the stts so we cannot check for codec_type*/ if(duration>0) { //Find greatest common divisor to avoid overflow using the Euclidean Algorithm... uint32_t max=MAX(duration,total_sample_count); uint32_t min=MIN(duration,total_sample_count); uint32_t spare=max%min; while(spare!=0) { max=min; min=spare; spare=max%min; } duration/=min; total_sample_count/=min; //Only support constant frame rate. But lets calculate the average. Needed by .mp4-files created with nec e606 3g phone. //To get better precision, we use the duration as frame_rate_base st->codec.frame_rate_base=duration; st->codec.frame_rate = c->streams[c->total_streams]->time_scale * total_sample_count;#ifdef DEBUG printf("FRAME RATE average (video or audio)= %f (tot sample count= %i ,tot dur= %i timescale=%d)\n", (float)st->codec.frame_rate/st->codec.frame_rate_base,total_sample_count,duration,c->streams[c->total_streams]->time_scale);#endif } else { st->codec.frame_rate_base = 1; st->codec.frame_rate = c->streams[c->total_streams]->time_scale; }#undef MAX#undef MIN return 0;}static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ AVStream *st; MOVStreamContext *sc; print_atom("trak", atom); st = av_new_stream(c->fc, c->fc->nb_streams); if (!st) return -2; sc = (MOVStreamContext*) av_mallocz(sizeof(MOVStreamContext)); if (!sc) { av_free(st); return -1; } sc->sample_to_chunk_index = -1; st->priv_data = sc; st->codec.codec_type = CODEC_TYPE_MOV_OTHER; st->start_time = 0; /* XXX: check */ st->duration = (c->duration * (int64_t)AV_TIME_BASE) / c->time_scale; c->streams[c->fc->nb_streams-1] = sc; return mov_read_default(c, pb, atom);}static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ AVStream *st; print_atom("tkhd", atom); st = c->fc->streams[c->fc->nb_streams-1]; get_byte(pb); /* version */ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ /* MOV_TRACK_ENABLED 0x0001 MOV_TRACK_IN_MOVIE 0x0002 MOV_TRACK_IN_PREVIEW 0x0004 MOV_TRACK_IN_POSTER 0x0008 */ get_be32(pb); /* creation time */ get_be32(pb); /* modification time */ st->id = (int)get_be32(pb); /* track id (NOT 0 !)*/ get_be32(pb); /* reserved */ st->start_time = 0; /* check */ st->duration = (get_be32(pb) * (int64_t)AV_TIME_BASE) / c->time_scale; /* duration */ get_be32(pb); /* reserved */ get_be32(pb); /* reserved */ get_be16(pb); /* layer */ get_be16(pb); /* alternate group */ get_be16(pb); /* volume */ get_be16(pb); /* reserved */ url_fskip(pb, 36); /* display matrix */ /* those are fixed-point */ st->codec.width = get_be32(pb) >> 16; /* track width */ st->codec.height = get_be32(pb) >> 16; /* track height */ return 0;}/* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... *//* like the files created with Adobe Premiere 5.0, for samples see *//* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ int err;#ifdef DEBUG print_atom("wide", atom); debug_indent++;#endif if (atom.size < 8) return 0; /* continue */ if (get_be32(pb) != 0) { /* 0 sized mdat atom... use the 'wide' atom size */ url_fskip(pb, atom.size - 4); return 0; } atom.type = get_le32(pb); atom.offset += 8; atom.size -= 8; if (atom.type != MKTAG('m', 'd', 'a', 't')) { url_fskip(pb, atom.size); return 0; } err = mov_read_mdat(c, pb, atom);#ifdef DEBUG debug_indent--;#endif return err;}#ifdef CONFIG_ZLIBstatic int null_read_packet(void *opaque, uint8_t *buf, int buf_size){ return -1;}static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ ByteIOContext ctx; uint8_t *cmov_data; uint8_t *moov_data; /* uncompressed data */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -