📄 mov.c
字号:
MOVContext *c; AVStream *st;#ifdef DEBUG print_atom("mdhd", atom_type, atom_offset, atom_size);#endif c = (MOVContext *)param; st = c->fc->streams[c->fc->nb_streams-1]; get_byte(pb); /* version */ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ get_be32(pb); /* creation time */ get_be32(pb); /* modification time */ c->streams[c->total_streams]->time_scale = get_be32(pb);#ifdef DEBUG printf("track[%i].time_scale = %li\n", c->fc->nb_streams-1, c->streams[c->total_streams]->time_scale); /* time scale */#endif get_be32(pb); /* duration */ get_be16(pb); /* language */ get_be16(pb); /* quality */ return 0;}static int parse_hdlr(const MOVParseTableEntry *parse_table, ByteIOContext *pb, UINT32 atom_type, INT64 atom_offset, INT64 atom_size, void *param){ MOVContext *c; int len = 0; char *buf; UINT32 type; AVStream *st; UINT32 ctype;#ifdef DEBUG print_atom("hdlr", atom_type, atom_offset, atom_size);#endif c = (MOVContext *)param; st = c->fc->streams[c->fc->nb_streams-1]; get_byte(pb); /* version */ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ /* component type */ ctype = get_le32(pb); type = get_le32(pb); /* component subtype */#ifdef DEBUG printf("ctype= %c%c%c%c (0x%08lx)\n", *((char *)&ctype), ((char *)&ctype)[1], ((char *)&ctype)[2], ((char *)&ctype)[3], (long) ctype); printf("stype= %c%c%c%c\n", *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]);#endif#ifdef DEBUG/* XXX: yeah this is ugly... */ if(ctype == MKTAG('m', 'h', 'l', 'r')) { /* MOV */ if(type == MKTAG('v', 'i', 'd', 'e')) puts("hdlr: vide"); else if(type == MKTAG('s', 'o', 'u', 'n')) puts("hdlr: soun"); } else if(ctype == 0) { /* MP4 */ if(type == MKTAG('v', 'i', 'd', 'e')) puts("hdlr: vide"); else if(type == MKTAG('s', 'o', 'u', 'n')) puts("hdlr: soun"); else if(type == MKTAG('o', 'd', 's', 'm')) puts("hdlr: odsm"); else if(type == MKTAG('s', 'd', 's', 'm')) puts("hdlr: sdsm"); } else puts("hdlr: meta");#endif if(ctype == MKTAG('m', 'h', 'l', 'r')) { /* MOV */ /* helps parsing the string hereafter... */ c->mp4 = 0; if(type == MKTAG('v', 'i', 'd', 'e')) st->codec.codec_type = CODEC_TYPE_VIDEO; else if(type == MKTAG('s', 'o', 'u', 'n')) st->codec.codec_type = CODEC_TYPE_AUDIO; } else if(ctype == 0) { /* MP4 */ /* helps parsing the string hereafter... */ c->mp4 = 1; if(type == MKTAG('v', 'i', 'd', 'e')) st->codec.codec_type = CODEC_TYPE_VIDEO; else if(type == MKTAG('s', 'o', 'u', 'n')) st->codec.codec_type = CODEC_TYPE_AUDIO; } get_be32(pb); /* component manufacture */ get_be32(pb); /* component flags */ get_be32(pb); /* component flags mask */ if(atom_size <= 24) return 0; /* nothing left to read */ /* XXX: MP4 uses a C string, not a pascal one */ /* component name */ if(c->mp4) { /* .mp4: C string */ while(get_byte(pb) && (++len < (atom_size - 24))); } else { /* .mov: PASCAL string */ len = get_byte(pb); buf = av_malloc(len+1); get_buffer(pb, buf, len); buf[len] = '\0';#ifdef DEBUG printf("**buf='%s'\n", buf);#endif av_free(buf); }#if 0 len = get_byte(pb); /* XXX: use a better heuristic */ if(len < 32) { /* assume that it is a Pascal like string */ buf = av_malloc(len+1); get_buffer(pb, buf, len); buf[len] = '\0';#ifdef DEBUG printf("**buf='%s'\n", buf);#endif av_free(buf); } else { /* MP4 string */ for(;;) { if (len == 0) break; len = get_byte(pb); } }#endif return 0;}static int mp4_read_descr_len(ByteIOContext *pb){ int c, len, count; len = 0; count = 0; for(;;) { c = get_byte(pb); len = (len << 7) | (c & 0x7f); if ((c & 0x80) == 0) break; if (++count == 4) break; } return len;}static int mp4_read_descr(ByteIOContext *pb, int *tag){ int len; *tag = get_byte(pb); len = mp4_read_descr_len(pb);#ifdef DEBUG printf("MPEG4 description: tag=0x%02x len=%d\n", *tag, len);#endif return len;}static int parse_stsd(const MOVParseTableEntry *parse_table, ByteIOContext *pb, UINT32 atom_type, INT64 atom_offset, INT64 atom_size, void *param){ MOVContext *c; int entries, size, samp_sz, frames_per_sample, id; UINT32 format; AVStream *st; MOVStreamContext *sc;#ifdef DEBUG print_atom("stsd", atom_type, atom_offset, atom_size);#endif c = (MOVContext *)param; st = c->fc->streams[c->fc->nb_streams-1]; sc = (MOVStreamContext *)st->priv_data; get_byte(pb); /* version */ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ entries = get_be32(pb); while(entries--) { size = get_be32(pb); /* size */ format = get_le32(pb); /* data format */ get_be32(pb); /* reserved */ get_be16(pb); /* reserved */ 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 printf("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 if(st->codec.codec_type==CODEC_TYPE_VIDEO) { st->codec.codec_tag = format; st->codec.codec_id = codec_get_id(mov_video_tags, format); 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); /* frame per samples */#ifdef DEBUG printf("frames/samples = %d\n", frames_per_sample);#endif url_fskip(pb, 32); /* codec name */ get_be16(pb); /* depth */ get_be16(pb); /* colortable id */ st->codec.frame_rate = 25 * FRAME_RATE_BASE; size -= (16+8*4+2+32+2*2); while (size >= 8) { int atom_size, atom_type; INT64 start_pos; atom_size = get_be32(pb); atom_type = get_le32(pb); size -= 8;#ifdef DEBUG printf("VIDEO: atom_type=%c%c%c%c atom_size=%d size_left=%d\n", (atom_type >> 0) & 0xff, (atom_type >> 8) & 0xff, (atom_type >> 16) & 0xff, (atom_type >> 24) & 0xff, atom_size, size);#endif start_pos = url_ftell(pb); switch(atom_type) { case MKTAG('e', 's', 'd', 's'): { int tag, len; /* Well, broken but suffisant for some MP4 streams */ get_be32(pb); /* version + flags */ len = mp4_read_descr(pb, &tag); if (tag == 0x03) { /* MP4ESDescrTag */ get_be16(pb); /* ID */ get_byte(pb); /* priority */ len = 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 = mp4_read_descr(pb, &tag); if (tag != 0x05) goto fail; /* MP4DecSpecificDescrTag */#ifdef DEBUG printf("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: 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 { st->codec.codec_tag = format; get_be16(pb); /* version */ get_be16(pb); /* revision level */ get_be32(pb); /* vendor */ st->codec.channels = get_be16(pb);/* channel count */ samp_sz = get_be16(pb); /* sample size */#ifdef DEBUG if(samp_sz != 16) puts("!!! stsd: audio sample size is not 16 bit !");#endif st->codec.codec_id = codec_get_id(mov_audio_tags, format); /* handle specific s8 codec */ if (st->codec.codec_id == CODEC_ID_PCM_S16BE && samp_sz == 8) st->codec.codec_id = CODEC_ID_PCM_S8; get_be16(pb); /* compression id = 0*/ get_be16(pb); /* packet size = 0 */ st->codec.sample_rate = ((get_be32(pb) >> 16)); st->codec.bit_rate = 0;#if 0 get_be16(pb); get_be16(pb); /* */ get_be16(pb); /* */ get_be16(pb); /* */ get_be16(pb); /* */ get_be16(pb); /* */#endif if(size > 16) url_fskip(pb, size-(16+20)); } }/* if(len) { buf = av_malloc(len+1); get_buffer(pb, buf, len); buf[len] = '\0'; puts(buf); av_free(buf); }*/ return 0;}static int parse_stco(const MOVParseTableEntry *parse_table, ByteIOContext *pb, UINT32 atom_type, INT64 atom_offset, INT64 atom_size, void *param){ MOVContext *c; int entries, i; AVStream *st; MOVStreamContext *sc;#ifdef DEBUG print_atom("stco", atom_type, atom_offset, atom_size);#endif c = (MOVContext *)param; st = c->fc->streams[c->fc->nb_streams-1]; sc = (MOVStreamContext *)st->priv_data; get_byte(pb); /* version */ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ entries = get_be32(pb); sc->chunk_count = entries; sc->chunk_offsets = av_malloc(entries * sizeof(INT64)); if(atom_type == MKTAG('s', 't', 'c', 'o')) { for(i=0; i<entries; i++) { sc->chunk_offsets[i] = get_be32(pb); } } else if(atom_type == MKTAG('c', 'o', '6', '4')) { for(i=0; i<entries; i++) { sc->chunk_offsets[i] = get_be64(pb); } } else return -1;#ifdef DEBUG/* for(i=0; i<entries; i++) { printf("chunk offset=0x%Lx\n", sc->chunk_offsets[i]); }*/#endif return 0;}static int parse_stsc(const MOVParseTableEntry *parse_table, ByteIOContext *pb, UINT32 atom_type, INT64 atom_offset, INT64 atom_size, void *param){ MOVContext *c; int entries, i; AVStream *st; MOVStreamContext *sc;#ifdef DEBUG print_atom("stsc", atom_type, atom_offset, atom_size);#endif c = (MOVContext *)param; st = c->fc->streams[c->fc->nb_streams-1]; sc = (MOVStreamContext *)st->priv_data; 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 = av_malloc(entries * sizeof(MOV_sample_to_chunk_tbl)); 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 parse_stsz(const MOVParseTableEntry *parse_table, ByteIOContext *pb, UINT32 atom_type, INT64 atom_offset, INT64 atom_size, void *param){ MOVContext *c; int entries, i; AVStream *st; MOVStreamContext *sc;#ifdef DEBUG print_atom("stsz", atom_type, atom_offset, atom_size);#endif c = (MOVContext *)param; st = c->fc->streams[c->fc->nb_streams-1]; sc = (MOVStreamContext *)st->priv_data; 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 = av_malloc(entries * sizeof(long));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -