📄 mov.c
字号:
/* empty */; a.size -= 8; if(a.size < 0) break; // av_log(NULL, AV_LOG_DEBUG, " i=%ld\n", i); if (c->parse_table[i].type == 0) { /* skip leaf atoms data */// url_seek(pb, atom.offset+atom.size, SEEK_SET);#ifdef DEBUG print_atom("unknown", a);#endif url_fskip(pb, a.size); } else {#ifdef DEBUG //char b[5] = { type & 0xff, (type >> 8) & 0xff, (type >> 16) & 0xff, (type >> 24) & 0xff, 0 }; //print_atom(b, type, offset, size);#endif err = (c->parse_table[i].func)(c, pb, a); } 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){#if 1 url_fskip(pb, atom.size); // for now#else VERY VERY BROKEN, NEVER execute this, needs rewrite unsigned int len; MOV_ctab_t *t; 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); }#endif 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 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 + FF_INPUT_BUFFER_PADDING_SIZE); 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); av_set_pts_info(c->fc->streams[c->fc->nb_streams-1], 64, 1, c->streams[c->fc->nb_streams-1]->time_scale);#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 c->fc->streams[c->fc->nb_streams-1]->duration= 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]; if((uint64_t)atom.size > (1<<30)) return -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 + FF_INPUT_BUFFER_PADDING_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_avcC(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ AVStream *st = c->fc->streams[c->fc->nb_streams-1]; if((uint64_t)atom.size > (1<<30)) return -1; av_free(st->codec->extradata); st->codec->extradata_size = atom.size; st->codec->extradata = (uint8_t*) av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); if (st->codec->extradata) { get_buffer(pb, st->codec->extradata, atom.size); } 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; unsigned int i, entries; print_atom("stco", atom); get_byte(pb); /* version */ get_byte(pb); get_byte(pb); get_byte(pb); /* flags */ entries = get_be32(pb); if(entries >= UINT_MAX/sizeof(int64_t)) return -1; 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -