📄 mov.c
字号:
a.offset += a.size; total_size += a.size; } if (!err && total_size < atom.size && atom.size < 0x7ffff) { //av_log(NULL, AV_LOG_DEBUG, "RESET %Ld %Ld err:%d\n", atom.size, total_size, err); url_fskip(pb, atom.size - total_size); }#ifdef DEBUG debug_indent--;#endif return err;}static int mov_read_ctab(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ unsigned int len; MOV_ctab_t *t; //url_fskip(pb, atom.size); // for now c->ctab = av_realloc(c->ctab, ++c->ctab_size); t = c->ctab[c->ctab_size]; t->seed = get_be32(pb); t->flags = get_be16(pb); t->size = get_be16(pb) + 1; len = 2 * t->size * 4; if (len > 0) { t->clrs = av_malloc(len); // 16bit A R G B if (t->clrs) get_buffer(pb, t->clrs, len); } return 0;}static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ AVStream *st = c->fc->streams[c->fc->nb_streams-1]; int len = 0; uint32_t type; uint32_t ctype; print_atom("hdlr", atom); 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 av_log(NULL, AV_LOG_DEBUG, "ctype= %c%c%c%c (0x%08lx)\n", *((char *)&ctype), ((char *)&ctype)[1], ((char *)&ctype)[2], ((char *)&ctype)[3], (long) ctype); av_log(NULL, AV_LOG_DEBUG, "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 */#ifdef DEBUG char* buf;#endif len = get_byte(pb);#ifdef DEBUG buf = (uint8_t*) av_malloc(len+1); if (buf) { get_buffer(pb, buf, len); buf[len] = '\0'; av_log(NULL, AV_LOG_DEBUG, "**buf='%s'\n", buf); av_free(buf); } else#endif url_fskip(pb, len); } url_fskip(pb, atom.size - (url_ftell(pb) - atom.offset)); return 0;}static int mov_mp4_read_descr_len(ByteIOContext *pb){ int len = 0; int count = 4; while (count--) { int c = get_byte(pb); len = (len << 7) | (c & 0x7f); if (!(c & 0x80)) break; } return len;}static int mov_mp4_read_descr(ByteIOContext *pb, int *tag){ int len; *tag = get_byte(pb); len = mov_mp4_read_descr_len(pb);#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "MPEG4 description: tag=0x%02x len=%d\n", *tag, len);#endif return len;}static inline unsigned int get_be24(ByteIOContext *s){ unsigned int val; val = get_byte(s) << 16; val |= get_byte(s) << 8; val |= get_byte(s); return val;}static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ AVStream *st = c->fc->streams[c->fc->nb_streams-1]; MOVStreamContext *sc = (MOVStreamContext *)st->priv_data; int64_t start_pos = url_ftell(pb); int tag, len; print_atom("esds", atom); /* Well, broken but suffisant for some MP4 streams */ get_be32(pb); /* version + flags */ len = mov_mp4_read_descr(pb, &tag); if (tag == MP4ESDescrTag) { get_be16(pb); /* ID */ get_byte(pb); /* priority */ } else get_be16(pb); /* ID */ len = mov_mp4_read_descr(pb, &tag); if (tag == MP4DecConfigDescrTag) { sc->esds.object_type_id = get_byte(pb); sc->esds.stream_type = get_byte(pb); sc->esds.buffer_size_db = get_be24(pb); sc->esds.max_bitrate = get_be32(pb); sc->esds.avg_bitrate = get_be32(pb); len = mov_mp4_read_descr(pb, &tag); //av_log(NULL, AV_LOG_DEBUG, "LEN %d TAG %d m:%d a:%d\n", len, tag, sc->esds.max_bitrate, sc->esds.avg_bitrate); if (tag == MP4DecSpecificDescrTag) {#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "Specific MPEG4 header len=%d\n", len);#endif st->codec.extradata = (uint8_t*) av_mallocz(len); if (st->codec.extradata) { get_buffer(pb, st->codec.extradata, len); st->codec.extradata_size = len; } } } /* in any case, skip garbage */ url_fskip(pb, atom.size - ((url_ftell(pb) - start_pos))); return 0;}/* this atom contains actual media data */static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ print_atom("mdat", atom); if(atom.size == 0) /* wrong one (MP4) */ return 0; c->found_mdat=1; c->mdat_offset = atom.offset; c->mdat_size = atom.size; if(c->found_moov) return 1; /* found both, just go */ url_fskip(pb, atom.size); return 0; /* now go for moov */}/* this atom should contain all header atoms */static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ int err; print_atom("moov", atom); err = mov_read_default(c, pb, atom); /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */ /* so we don't parse the whole file if over a network */ c->found_moov=1; if(c->found_mdat) return 1; /* found both, just go */ return 0; /* now go for mdat */}static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ print_atom("mdhd", atom); 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->fc->nb_streams-1]->time_scale = get_be32(pb);#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "track[%i].time_scale = %i\n", c->fc->nb_streams-1, c->streams[c->fc->nb_streams-1]->time_scale); /* time scale */#endif get_be32(pb); /* duration */ get_be16(pb); /* language */ get_be16(pb); /* quality */ return 0;}static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ print_atom("mvhd", atom); 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->time_scale = get_be32(pb); /* time scale */#ifdef DEBUG av_log(NULL, AV_LOG_DEBUG, "time scale = %i\n", c->time_scale);#endif c->duration = get_be32(pb); /* duration */ get_be32(pb); /* preferred scale */ get_be16(pb); /* preferred volume */ url_fskip(pb, 10); /* reserved */ url_fskip(pb, 36); /* display matrix */ get_be32(pb); /* preview time */ get_be32(pb); /* preview duration */ get_be32(pb); /* poster time */ get_be32(pb); /* selection time */ get_be32(pb); /* selection duration */ get_be32(pb); /* current time */ get_be32(pb); /* next track ID */ return 0;}static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ AVStream *st = c->fc->streams[c->fc->nb_streams-1]; // currently SVQ3 decoder expect full STSD header - so let's fake it // this should be fixed and just SMI header should be passed av_free(st->codec.extradata); st->codec.extradata_size = 0x5a + atom.size; st->codec.extradata = (uint8_t*) av_mallocz(st->codec.extradata_size); if (st->codec.extradata) { strcpy(st->codec.extradata, "SVQ3"); // fake get_buffer(pb, st->codec.extradata + 0x5a, atom.size); //av_log(NULL, AV_LOG_DEBUG, "Reading SMI %Ld %s\n", atom.size, (char*)st->codec.extradata + 0x5a); } else url_fskip(pb, atom.size); return 0;}static int mov_read_stco(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("stco", atom); 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 = (int64_t*) av_malloc(entries * sizeof(int64_t)); if (!sc->chunk_offsets) return -1; 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++) { av_log(NULL, AV_LOG_DEBUG, "chunk offset=0x%Lx\n", sc->chunk_offsets[i]); }*/#endif return 0;}static int mov_read_stsd(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, frames_per_sample; uint32_t format; /* for palette traversal */ int color_depth; int color_start; int color_count; int color_end; int color_index; int color_dec; int color_greyscale; unsigned char *color_table; int j; unsigned char r, g, b; print_atom("stsd", atom); get_byte(pb); /* version */ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ entries = get_be32(pb); while(entries--) { //Parsing Sample description table enum CodecID id; int size = get_be32(pb); /* size */ format = get_le32(pb); /* data format */ get_be32(pb); /* reserved */ get_be16(pb); /* reserved */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -