?? mov.c.svn-base
字號:
if ((uint64_t)entries+sc->ctts_count >= UINT_MAX/sizeof(*sc->ctts_data)) return -1; sc->ctts_data = av_realloc(sc->ctts_data, (entries+sc->ctts_count)*sizeof(*sc->ctts_data)); if (!sc->ctts_data) return AVERROR(ENOMEM); } dts = st->duration; offset = frag->base_data_offset + data_offset; distance = 0; dprintf(c->fc, "first sample flags 0x%x\n", first_sample_flags); for (i = 0; i < entries; i++) { unsigned sample_size = frag->size; int sample_flags = i ? frag->flags : first_sample_flags; unsigned sample_duration = frag->duration; int keyframe; if (flags & 0x100) sample_duration = get_be32(pb); if (flags & 0x200) sample_size = get_be32(pb); if (flags & 0x400) sample_flags = get_be32(pb); if (flags & 0x800) { sc->ctts_data[sc->ctts_count].count = 1; sc->ctts_data[sc->ctts_count].duration = get_be32(pb); sc->ctts_count++; } if ((keyframe = st->codec->codec_type == CODEC_TYPE_AUDIO || (flags & 0x004 && !i && !sample_flags) || sample_flags & 0x2000000)) distance = 0; av_add_index_entry(st, offset, dts, sample_size, distance, keyframe ? AVINDEX_KEYFRAME : 0); dprintf(c->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", " "size %d, distance %d, keyframe %d\n", st->index, sc->sample_count+i, offset, dts, sample_size, distance, keyframe); distance++; assert(sample_duration % sc->time_rate == 0); dts += sample_duration / sc->time_rate; offset += sample_size; } frag->moof_offset = offset; sc->sample_count = st->nb_index_entries; st->duration = dts; 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; 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); return err;}static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){#ifdef CONFIG_ZLIB ByteIOContext ctx; uint8_t *cmov_data; uint8_t *moov_data; /* uncompressed data */ long cmov_len, moov_len; int ret = -1; get_be32(pb); /* dcom atom */ if (get_le32(pb) != MKTAG('d','c','o','m')) return -1; if (get_le32(pb) != MKTAG('z','l','i','b')) { av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !"); return -1; } get_be32(pb); /* cmvd atom */ if (get_le32(pb) != MKTAG('c','m','v','d')) return -1; moov_len = get_be32(pb); /* uncompressed size */ cmov_len = atom.size - 6 * 4; cmov_data = av_malloc(cmov_len); if (!cmov_data) return -1; moov_data = av_malloc(moov_len); if (!moov_data) { av_free(cmov_data); return -1; } get_buffer(pb, cmov_data, cmov_len); if(uncompress (moov_data, (uLongf *) &moov_len, (const Bytef *)cmov_data, cmov_len) != Z_OK) goto free_and_return; if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0) goto free_and_return; atom.type = MKTAG('m','o','o','v'); atom.offset = 0; atom.size = moov_len;#ifdef DEBUG// { int fd = open("/tmp/uncompheader.mov", O_WRONLY | O_CREAT); write(fd, moov_data, moov_len); close(fd); }#endif ret = mov_read_default(c, &ctx, atom);free_and_return: av_free(moov_data); av_free(cmov_data); return ret;#else av_log(c->fc, AV_LOG_ERROR, "this file requires zlib support compiled in\n"); return -1;#endif}/* edit list atom */static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom){ MOVStreamContext *sc = c->fc->streams[c->fc->nb_streams-1]->priv_data; int i, edit_count; get_byte(pb); /* version */ get_be24(pb); /* flags */ edit_count= sc->edit_count = get_be32(pb); /* entries */ for(i=0; i<edit_count; i++){ int time; get_be32(pb); /* Track duration */ time = get_be32(pb); /* Media time */ get_be32(pb); /* Media rate */ if (time != 0) av_log(c->fc, AV_LOG_WARNING, "edit list not starting at 0, " "a/v desync might occur, patch welcome\n"); } dprintf(c->fc, "track[%i].edit_count = %i\n", c->fc->nb_streams-1, sc->edit_count); return 0;}static const MOVParseTableEntry mov_default_parse_table[] = {{ MKTAG('a','v','s','s'), mov_read_extradata },{ MKTAG('c','o','6','4'), mov_read_stco },{ MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */{ MKTAG('d','i','n','f'), mov_read_default },{ MKTAG('d','r','e','f'), mov_read_dref },{ MKTAG('e','d','t','s'), mov_read_default },{ MKTAG('e','l','s','t'), mov_read_elst },{ MKTAG('e','n','d','a'), mov_read_enda },{ MKTAG('f','i','e','l'), mov_read_extradata },{ MKTAG('f','t','y','p'), mov_read_ftyp },{ MKTAG('g','l','b','l'), mov_read_glbl },{ MKTAG('h','d','l','r'), mov_read_hdlr },{ MKTAG('j','p','2','h'), mov_read_extradata },{ MKTAG('m','d','a','t'), mov_read_mdat },{ MKTAG('m','d','h','d'), mov_read_mdhd },{ MKTAG('m','d','i','a'), mov_read_default },{ MKTAG('m','i','n','f'), mov_read_default },{ MKTAG('m','o','o','f'), mov_read_moof },{ MKTAG('m','o','o','v'), mov_read_moov },{ MKTAG('m','v','e','x'), mov_read_default },{ MKTAG('m','v','h','d'), mov_read_mvhd },{ MKTAG('S','M','I',' '), mov_read_smi }, /* Sorenson extension ??? */{ MKTAG('a','l','a','c'), mov_read_extradata }, /* alac specific atom */{ MKTAG('a','v','c','C'), mov_read_glbl },{ MKTAG('s','t','b','l'), mov_read_default },{ MKTAG('s','t','c','o'), mov_read_stco },{ MKTAG('s','t','s','c'), mov_read_stsc },{ MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */{ MKTAG('s','t','s','s'), mov_read_stss }, /* sync sample */{ MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */{ MKTAG('s','t','t','s'), mov_read_stts },{ MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */{ MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */{ MKTAG('t','r','a','k'), mov_read_trak },{ MKTAG('t','r','a','f'), mov_read_default },{ MKTAG('t','r','e','x'), mov_read_trex },{ MKTAG('t','r','u','n'), mov_read_trun },{ MKTAG('u','d','t','a'), mov_read_udta },{ MKTAG('w','a','v','e'), mov_read_wave },{ MKTAG('e','s','d','s'), mov_read_esds },{ MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */{ MKTAG('c','m','o','v'), mov_read_cmov },{ 0, NULL }};static int mov_probe(AVProbeData *p){ unsigned int offset; uint32_t tag; int score = 0; /* check file header */ offset = 0; for(;;) { /* ignore invalid offset */ if ((offset + 8) > (unsigned int)p->buf_size) return score; tag = AV_RL32(p->buf + offset + 4); switch(tag) { /* check for obvious tags */ case MKTAG('j','P',' ',' '): /* jpeg 2000 signature */ case MKTAG('m','o','o','v'): case MKTAG('m','d','a','t'): case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */ case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */ return AVPROBE_SCORE_MAX; /* those are more common words, so rate then a bit less */ case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */ case MKTAG('w','i','d','e'): case MKTAG('f','r','e','e'): case MKTAG('j','u','n','k'): case MKTAG('p','i','c','t'): return AVPROBE_SCORE_MAX - 5; case MKTAG(0x82,0x82,0x7f,0x7d ): case MKTAG('f','t','y','p'): case MKTAG('s','k','i','p'): case MKTAG('u','u','i','d'): case MKTAG('p','r','f','l'): offset = AV_RB32(p->buf+offset) + offset; /* if we only find those cause probedata is too small at least rate them */ score = AVPROBE_SCORE_MAX - 50; break; default: /* unrecognized tag */ return score; } } return score;}static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap){ MOVContext *mov = s->priv_data; ByteIOContext *pb = s->pb; int err; MOV_atom_t atom = { 0, 0, 0 }; mov->fc = s; /* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */ if(!url_is_streamed(pb)) atom.size = url_fsize(pb); else atom.size = INT64_MAX; /* check MOV header */ if ((err = mov_read_default(mov, pb, atom)) < 0) { av_log(s, AV_LOG_ERROR, "error reading header: %d\n", err); return err; } if (!mov->found_moov) { av_log(s, AV_LOG_ERROR, "moov atom not found\n"); return -1; } dprintf(mov->fc, "on_parse_exit_offset=%lld\n", url_ftell(pb)); return 0;}static int mov_read_packet(AVFormatContext *s, AVPacket *pkt){ MOVContext *mov = s->priv_data; MOVStreamContext *sc = 0; AVIndexEntry *sample = 0; int64_t best_dts = INT64_MAX; int i; retry: for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; MOVStreamContext *msc = st->priv_data; if (st->discard != AVDISCARD_ALL && msc->pb && msc->current_sample < msc->sample_count) { AVIndexEntry *current_sample = &st->index_entries[msc->current_sample]; int64_t dts = av_rescale(current_sample->timestamp * (int64_t)msc->time_rate, AV_TIME_BASE, msc->time_scale); dprintf(s, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts); if (!sample || (url_is_streamed(s->pb) && current_sample->pos < sample->pos) || (!url_is_streamed(s->pb) && ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb && ((FFABS(best_dts - dts) <= AV_TIME_BASE && current_sample->pos < sample->pos) || (FFABS(best_dts - dts) > AV_TIME_BASE && dts < best_dts)))))) { sample = current_sample; best_dts = dts; sc = msc; } } } if (!sample) { mov->found_mdat = 0; if (!url_is_streamed(s->pb) || mov_read_default(mov, s->pb, (MOV_atom_t){ 0, 0, INT64_MAX }) < 0 || url_feof(s->pb)) return -1; dprintf(s, "read fragments, offset 0x%llx\n", url_ftell(s->pb)); goto retry; } /* must be done just before reading, to avoid infinite loop on sample */ sc->current_sample++; if (url_fseek(sc->pb, sample->pos, SEEK_SET) != sample->pos) { av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n", sc->ffindex, sample->pos); return -1; } av_get_packet(sc->pb, pkt, sample->size);#ifdef CONFIG_DV_DEMUXER if (mov->dv_demux && sc->dv_audio_container) { dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size); av_free(pkt->data); pkt->size = 0; if (dv_get_packet(mov->dv_demux, pkt) < 0) return -1; }#endif pkt->stream_index = sc->ffindex; pkt->dts = sample->timestamp; if (sc->ctts_data) { assert(sc->ctts_data[sc->sample_to_ctime_index].duration % sc->time_rate == 0); pkt->pts = pkt->dts + sc->ctts_data[sc->sample_to_ctime_index].duration / sc->time_rate; /* update ctts context */ sc->sample_to_ctime_sample++; if (sc->sample_to_ctime_index < sc->ctts_count && sc->ctts_data[sc->sample_to_ctime_index].count == sc->sample_to_ctime_sample) { sc->sample_to_ctime_index++; sc->sample_to_ctime_sample = 0; } } else { AVStream *st = s->streams[sc->ffindex]; int64_t next_dts = (sc->current_sample < sc->sample_count) ? st->index_entries[sc->current_sample].timestamp : st->duration; pkt->duration = next_dts - pkt->dts; pkt->pts = pkt->dts; } pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? PKT_FLAG_KEY : 0; pkt->pos = sample->pos; dprintf(s, "stream %d, pts %"PRId64", dts %"PRId64", pos 0x%"PRIx64", duration %d\n", pkt->stream_index, pkt->pts, pkt->dts, pkt->pos, pkt->duration); return 0;}static int mov_seek_stream(AVStream *st, int64_t timestamp, int flags){ MOVStreamContext *sc = st->priv_data; int sample, time_sample; int i; sample = av_index_search_timestamp(st, timestamp, flags); dprintf(st->codec, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample); if (sample < 0) /* not sure what to do */ return -1; sc->current_sample = sample; dprintf(st->codec, "stream %d, found sample %d\n", st->index, sc->current_sample); /* adjust ctts index */ if (sc->ctts_data) { time_sample = 0; for (i = 0; i < sc->ctts_count; i++) { int next = time_sample + sc->ctts_data[i].count; if (next > sc->current_sample) { sc->sample_to_ctime_index = i; sc->sample_to_ctime_sample = sc->current_sample - time_sample; break; } time_sample = next; } } return sample;}static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -