diff options
author | Michael Niedermayer | 2012-03-06 03:56:25 +0100 |
---|---|---|
committer | Michael Niedermayer | 2012-03-06 06:03:32 +0100 |
commit | f095391a140ed3f379e1fb16605fac821c3e6660 (patch) | |
tree | 6b0be38bffb002457cba26183c57e56d5d464551 /libavformat | |
parent | 01606d10e600c4794d89490e731c321fb73a5141 (diff) | |
parent | 632eb1bbae473f7105e0ec6556cb040ea6d30910 (diff) |
Merge remote-tracking branch 'qatar/master'
* qatar/master: (31 commits)
cdxl demux: do not create packets with uninitialized data at EOF.
Replace computations of remaining bits with calls to get_bits_left().
amrnb/amrwb: Remove get_bits usage.
cosmetics: reindent
avformat: do not require a pixel/sample format if there is no decoder
avformat: do not fill-in audio packet duration in compute_pkt_fields()
lavf: Use av_get_audio_frame_duration() in get_audio_frame_size()
dca_parser: parse the sample rate and frame durations
libspeexdec: do not set AVCodecContext.frame_size
libopencore-amr: do not set AVCodecContext.frame_size
alsdec: do not set AVCodecContext.frame_size
siff: do not set AVCodecContext.frame_size
amr demuxer: do not set AVCodecContext.frame_size.
aiffdec: do not set AVCodecContext.frame_size
mov: do not set AVCodecContext.frame_size
ape: do not set AVCodecContext.frame_size.
rdt: remove workaround for infinite loop with aac
avformat: do not require frame_size in avformat_find_stream_info() for CELT
avformat: do not require frame_size in avformat_find_stream_info() for MP1/2/3
avformat: do not require frame_size in avformat_find_stream_info() for AAC
...
Conflicts:
doc/APIchanges
libavcodec/Makefile
libavcodec/avcodec.h
libavcodec/h264.c
libavcodec/h264_ps.c
libavcodec/utils.c
libavcodec/version.h
libavcodec/x86/dsputil_mmx.c
libavformat/utils.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/aiffdec.c | 30 | ||||
-rw-r--r-- | libavformat/amr.c | 2 | ||||
-rw-r--r-- | libavformat/ape.c | 1 | ||||
-rw-r--r-- | libavformat/avformat.h | 13 | ||||
-rw-r--r-- | libavformat/dv.c | 8 | ||||
-rw-r--r-- | libavformat/mov.c | 13 | ||||
-rw-r--r-- | libavformat/rdt.c | 3 | ||||
-rw-r--r-- | libavformat/riff.c | 28 | ||||
-rw-r--r-- | libavformat/rtpenc.c | 11 | ||||
-rw-r--r-- | libavformat/seek.c | 17 | ||||
-rw-r--r-- | libavformat/seek.h | 5 | ||||
-rw-r--r-- | libavformat/siff.c | 8 | ||||
-rw-r--r-- | libavformat/swfenc.c | 6 | ||||
-rw-r--r-- | libavformat/utils.c | 538 |
14 files changed, 362 insertions, 321 deletions
diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index 239fca3452..d57ba005ff 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -32,6 +32,7 @@ typedef struct { int64_t data_end; + int block_duration; } AIFFInputContext; static enum CodecID aiff_codec_get_id(int bps) @@ -87,9 +88,12 @@ static void get_meta(AVFormatContext *s, const char *key, int size) } /* Returns the number of sound data frames or negative on error */ -static unsigned int get_aiff_header(AVIOContext *pb, AVCodecContext *codec, - int size, unsigned version) +static unsigned int get_aiff_header(AVFormatContext *s, int size, + unsigned version) { + AVIOContext *pb = s->pb; + AVCodecContext *codec = s->streams[0]->codec; + AIFFInputContext *aiff = s->priv_data; int exp; uint64_t val; double sample_rate; @@ -117,26 +121,27 @@ static unsigned int get_aiff_header(AVIOContext *pb, AVCodecContext *codec, case CODEC_ID_PCM_S16BE: codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample); codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id); + aiff->block_duration = 1; break; case CODEC_ID_ADPCM_IMA_QT: codec->block_align = 34*codec->channels; - codec->frame_size = 64; + aiff->block_duration = 64; break; case CODEC_ID_MACE3: codec->block_align = 2*codec->channels; - codec->frame_size = 6; + aiff->block_duration = 6; break; case CODEC_ID_MACE6: codec->block_align = 1*codec->channels; - codec->frame_size = 6; + aiff->block_duration = 6; break; case CODEC_ID_GSM: codec->block_align = 33; - codec->frame_size = 160; + aiff->block_duration = 160; break; case CODEC_ID_QCELP: codec->block_align = 35; - codec->frame_size= 160; + aiff->block_duration = 160; break; default: break; @@ -146,6 +151,7 @@ static unsigned int get_aiff_header(AVIOContext *pb, AVCodecContext *codec, /* Need the codec type */ codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample); codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id); + aiff->block_duration = 1; } /* Block align needs to be computed in all cases, as the definition @@ -153,8 +159,8 @@ static unsigned int get_aiff_header(AVIOContext *pb, AVCodecContext *codec, if (!codec->block_align) codec->block_align = (codec->bits_per_coded_sample * codec->channels) >> 3; - codec->bit_rate = (codec->frame_size ? codec->sample_rate/codec->frame_size : - codec->sample_rate) * (codec->block_align << 3); + codec->bit_rate = codec->sample_rate * (codec->block_align << 3) / + aiff->block_duration; /* Chunk is over */ if (size) @@ -215,7 +221,7 @@ static int aiff_read_header(AVFormatContext *s) switch (tag) { case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */ /* Then for the complete header info */ - st->nb_frames = get_aiff_header(pb, st->codec, size, version); + st->nb_frames = get_aiff_header(s, size, version); if (st->nb_frames < 0) return st->nb_frames; if (offset > 0) // COMM is after SSND @@ -279,8 +285,7 @@ got_sound: /* Now positioned, get the sound data start and end */ avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); st->start_time = 0; - st->duration = st->codec->frame_size ? - st->nb_frames * st->codec->frame_size : st->nb_frames; + st->duration = st->nb_frames * aiff->block_duration; /* Position the stream at the first block */ avio_seek(pb, offset, SEEK_SET); @@ -315,6 +320,7 @@ static int aiff_read_packet(AVFormatContext *s, /* Only one stream in an AIFF file */ pkt->stream_index = 0; + pkt->duration = (res / st->codec->block_align) * aiff->block_duration; return 0; } diff --git a/libavformat/amr.c b/libavformat/amr.c index 84dbd5a78b..e2705e9a97 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -100,14 +100,12 @@ static int amr_read_header(AVFormatContext *s) st->codec->codec_tag = MKTAG('s', 'a', 'w', 'b'); st->codec->codec_id = CODEC_ID_AMR_WB; st->codec->sample_rate = 16000; - st->codec->frame_size = 320; } else { st->codec->codec_tag = MKTAG('s', 'a', 'm', 'r'); st->codec->codec_id = CODEC_ID_AMR_NB; st->codec->sample_rate = 8000; - st->codec->frame_size = 160; } st->codec->channels = 1; st->codec->codec_type = AVMEDIA_TYPE_AUDIO; diff --git a/libavformat/ape.c b/libavformat/ape.c index 549330d4aa..df39e37532 100644 --- a/libavformat/ape.c +++ b/libavformat/ape.c @@ -335,7 +335,6 @@ static int ape_read_header(AVFormatContext * s) st->codec->channels = ape->channels; st->codec->sample_rate = ape->samplerate; st->codec->bits_per_coded_sample = ape->bps; - st->codec->frame_size = MAC_SUBFRAME_SIZE; st->nb_frames = ape->totalframes; st->start_time = 0; diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 1dc74fc9ff..434f355a17 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -650,12 +650,9 @@ typedef struct AVStream { double duration_error[2][2][MAX_STD_TIMEBASES]; int64_t codec_info_duration; int nb_decoded_frames; + int found_decoder; } *info; - AVPacket cur_pkt; - const uint8_t *cur_ptr; - int cur_len; - int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */ // Timestamp generation support: @@ -990,9 +987,6 @@ typedef struct AVFormatContext { struct AVPacketList *packet_buffer; struct AVPacketList *packet_buffer_end; - /* av_read_frame() support */ - AVStream *cur_st; - /* av_seek_frame() support */ int64_t data_offset; /**< offset of the first packet */ @@ -1005,6 +999,11 @@ typedef struct AVFormatContext { struct AVPacketList *raw_packet_buffer; struct AVPacketList *raw_packet_buffer_end; /** + * Packets split by the parser get queued here. + */ + struct AVPacketList *parse_queue; + struct AVPacketList *parse_queue_end; + /** * Remaining size available for raw_packet_buffer, in bytes. */ #define RAW_PACKET_BUFFER_SIZE 2500000 diff --git a/libavformat/dv.c b/libavformat/dv.c index 752475a3b6..1200dda45c 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -323,13 +323,7 @@ DVDemuxContext* avpriv_dv_init_demux(AVFormatContext *s) return NULL; } - c->sys = NULL; - c->fctx = s; - memset(c->ast, 0, sizeof(c->ast)); - c->ach = 0; - c->frames = 0; - c->abytes = 0; - + c->fctx = s; c->vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; c->vst->codec->codec_id = CODEC_ID_DVVIDEO; c->vst->codec->bit_rate = 25000000; diff --git a/libavformat/mov.c b/libavformat/mov.c index 4ad2051efc..3ca1f97658 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1464,20 +1464,16 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) // force sample rate for qcelp when not stored in mov if (st->codec->codec_tag != MKTAG('Q','c','l','p')) st->codec->sample_rate = 8000; - st->codec->frame_size= 160; st->codec->channels= 1; /* really needed */ break; case CODEC_ID_AMR_NB: st->codec->channels= 1; /* really needed */ /* force sample rate for amr, stsd in 3gp does not store sample rate */ st->codec->sample_rate = 8000; - /* force frame_size, too, samples_per_frame isn't always set properly */ - st->codec->frame_size = 160; break; case CODEC_ID_AMR_WB: st->codec->channels = 1; st->codec->sample_rate = 16000; - st->codec->frame_size = 320; break; case CODEC_ID_MP2: case CODEC_ID_MP3: @@ -1487,12 +1483,10 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) case CODEC_ID_GSM: case CODEC_ID_ADPCM_MS: case CODEC_ID_ADPCM_IMA_WAV: - st->codec->frame_size = sc->samples_per_frame; st->codec->block_align = sc->bytes_per_frame; break; case CODEC_ID_ALAC: if (st->codec->extradata_size == 36) { - st->codec->frame_size = AV_RB32(st->codec->extradata+12); st->codec->channels = AV_RB8 (st->codec->extradata+21); st->codec->sample_rate = AV_RB32(st->codec->extradata+32); } @@ -2058,13 +2052,6 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) avpriv_set_pts_info(st, 64, 1, sc->time_scale); - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && - !st->codec->frame_size && sc->stts_count == 1) { - st->codec->frame_size = av_rescale(sc->stts_data[0].duration, - st->codec->sample_rate, sc->time_scale); - av_dlog(c->fc, "frame size %d\n", st->codec->frame_size); - } - mov_build_index(c, st); if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) { diff --git a/libavformat/rdt.c b/libavformat/rdt.c index d153028ac4..d2437ee73f 100644 --- a/libavformat/rdt.c +++ b/libavformat/rdt.c @@ -432,9 +432,6 @@ rdt_parse_sdp_line (AVFormatContext *s, int st_index, } rdt->rmst[s->streams[n]->index] = ff_rm_alloc_rmstream(); rdt_load_mdpr(rdt, s->streams[n], (n - first) * 2); - - if (s->streams[n]->codec->codec_id == CODEC_ID_AAC) - s->streams[n]->codec->frame_size = 1; // FIXME } } diff --git a/libavformat/riff.c b/libavformat/riff.c index 70134276f0..774a02f82d 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -414,7 +414,7 @@ void ff_end_tag(AVIOContext *pb, int64_t start) /* returns the size or -1 on error */ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) { - int bps, blkalign, bytespersec; + int bps, blkalign, bytespersec, frame_size; int hdrsize = 18; int waveformatextensible; uint8_t temp[256]; @@ -423,6 +423,14 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) if(!enc->codec_tag || enc->codec_tag > 0xffff) return -1; + + /* We use the known constant frame size for the codec if known, otherwise + fallback to using AVCodecContext.frame_size, which is not as reliable + for indicating packet duration */ + frame_size = av_get_audio_frame_duration(enc, 0); + if (!frame_size) + frame_size = enc->frame_size; + waveformatextensible = (enc->channels > 2 && enc->channel_layout) || enc->sample_rate > 48000 || av_get_bits_per_sample(enc->codec_id) > 16; @@ -449,7 +457,9 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) } if (enc->codec_id == CODEC_ID_MP2 || enc->codec_id == CODEC_ID_MP3) { - blkalign = enc->frame_size; //this is wrong, but it seems many demuxers do not work if this is set correctly + /* this is wrong, but it seems many demuxers do not work if this is set + correctly */ + blkalign = frame_size; //blkalign = 144 * enc->bit_rate/enc->sample_rate; } else if (enc->codec_id == CODEC_ID_AC3) { blkalign = 3840; //maximum bytes per frame @@ -489,7 +499,7 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) bytestream_put_le32(&riff_extradata, 0); /* dwPTSHigh */ } else if (enc->codec_id == CODEC_ID_GSM_MS || enc->codec_id == CODEC_ID_ADPCM_IMA_WAV) { hdrsize += 2; - bytestream_put_le16(&riff_extradata, enc->frame_size); /* wSamplesPerBlock */ + bytestream_put_le16(&riff_extradata, frame_size); /* wSamplesPerBlock */ } else if(enc->extradata_size){ riff_extradata_start= enc->extradata; riff_extradata= enc->extradata + enc->extradata_size; @@ -657,10 +667,18 @@ int ff_get_bmp_header(AVIOContext *pb, AVStream *st) void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, int *au_ssize, int *au_scale) { int gcd; + int audio_frame_size; + + /* We use the known constant frame size for the codec if known, otherwise + fallback to using AVCodecContext.frame_size, which is not as reliable + for indicating packet duration */ + audio_frame_size = av_get_audio_frame_duration(stream, 0); + if (!audio_frame_size) + audio_frame_size = stream->frame_size; *au_ssize= stream->block_align; - if(stream->frame_size && stream->sample_rate){ - *au_scale=stream->frame_size; + if (audio_frame_size && stream->sample_rate) { + *au_scale = audio_frame_size; *au_rate= stream->sample_rate; }else if(stream->codec_type == AVMEDIA_TYPE_VIDEO || stream->codec_type == AVMEDIA_TYPE_DATA || diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index 9f3fd08a55..1e1dac5ef0 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -129,10 +129,17 @@ static int rtp_write_header(AVFormatContext *s1) s->max_frames_per_packet = 0; if (s1->max_delay) { if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - if (st->codec->frame_size == 0) { + int frame_size = av_get_audio_frame_duration(st->codec, 0); + if (!frame_size) + frame_size = st->codec->frame_size; + if (frame_size == 0) { av_log(s1, AV_LOG_ERROR, "Cannot respect max delay: frame size = 0\n"); } else { - s->max_frames_per_packet = av_rescale_rnd(s1->max_delay, st->codec->sample_rate, AV_TIME_BASE * (int64_t)st->codec->frame_size, AV_ROUND_DOWN); + s->max_frames_per_packet = + av_rescale_q_rnd(s1->max_delay, + AV_TIME_BASE_Q, + (AVRational){ frame_size / st->codec->sample_rate }, + AV_ROUND_DOWN); } } if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { diff --git a/libavformat/seek.c b/libavformat/seek.c index 3ffcde4664..0ae99eb211 100644 --- a/libavformat/seek.c +++ b/libavformat/seek.c @@ -409,13 +409,13 @@ AVParserState *ff_store_parser_state(AVFormatContext *s) state->fpos = avio_tell(s->pb); // copy context structures - state->cur_st = s->cur_st; state->packet_buffer = s->packet_buffer; + state->parse_queue = s->parse_queue; state->raw_packet_buffer = s->raw_packet_buffer; state->raw_packet_buffer_remaining_size = s->raw_packet_buffer_remaining_size; - s->cur_st = NULL; s->packet_buffer = NULL; + s->parse_queue = NULL; s->raw_packet_buffer = NULL; s->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; @@ -429,19 +429,13 @@ AVParserState *ff_store_parser_state(AVFormatContext *s) ss->last_IP_pts = st->last_IP_pts; ss->cur_dts = st->cur_dts; ss->reference_dts = st->reference_dts; - ss->cur_ptr = st->cur_ptr; - ss->cur_len = st->cur_len; ss->probe_packets = st->probe_packets; - ss->cur_pkt = st->cur_pkt; st->parser = NULL; st->last_IP_pts = AV_NOPTS_VALUE; st->cur_dts = AV_NOPTS_VALUE; st->reference_dts = AV_NOPTS_VALUE; - st->cur_ptr = NULL; - st->cur_len = 0; st->probe_packets = MAX_PROBE_PACKETS; - av_init_packet(&st->cur_pkt); } return state; @@ -460,8 +454,8 @@ void ff_restore_parser_state(AVFormatContext *s, AVParserState *state) avio_seek(s->pb, state->fpos, SEEK_SET); // copy context structures - s->cur_st = state->cur_st; s->packet_buffer = state->packet_buffer; + s->parse_queue = state->parse_queue; s->raw_packet_buffer = state->raw_packet_buffer; s->raw_packet_buffer_remaining_size = state->raw_packet_buffer_remaining_size; @@ -474,10 +468,7 @@ void ff_restore_parser_state(AVFormatContext *s, AVParserState *state) st->last_IP_pts = ss->last_IP_pts; st->cur_dts = ss->cur_dts; st->reference_dts = ss->reference_dts; - st->cur_ptr = ss->cur_ptr; - st->cur_len = ss->cur_len; st->probe_packets = ss->probe_packets; - st->cur_pkt = ss->cur_pkt; } av_free(state->stream_states); @@ -507,10 +498,10 @@ void ff_free_parser_state(AVFormatContext *s, AVParserState *state) ss = &state->stream_states[i]; if (ss->parser) av_parser_close(ss->parser); - av_free_packet(&ss->cur_pkt); } free_packet_list(state->packet_buffer); + free_packet_list(state->parse_queue); free_packet_list(state->raw_packet_buffer); av_free(state->stream_states); diff --git a/libavformat/seek.h b/libavformat/seek.h index 408f7d6ac7..b27cb42a9d 100644 --- a/libavformat/seek.h +++ b/libavformat/seek.h @@ -31,12 +31,9 @@ typedef struct AVParserStreamState { // saved members of AVStream AVCodecParserContext *parser; - AVPacket cur_pkt; int64_t last_IP_pts; int64_t cur_dts; int64_t reference_dts; - const uint8_t *cur_ptr; - int cur_len; int probe_packets; } AVParserStreamState; @@ -47,8 +44,8 @@ typedef struct AVParserState { int64_t fpos; ///< file position at the time of call // saved members of AVFormatContext - AVStream *cur_st; ///< current stream. AVPacketList *packet_buffer; ///< packet buffer of original state + AVPacketList *parse_queue; ///< parse queue of original state AVPacketList *raw_packet_buffer; ///< raw packet buffer of original state int raw_packet_buffer_remaining_size; ///< remaining space in raw_packet_buffer diff --git a/libavformat/siff.c b/libavformat/siff.c index e0f21f3f4b..5809067903 100644 --- a/libavformat/siff.c +++ b/libavformat/siff.c @@ -79,10 +79,10 @@ static int create_audio_stream(AVFormatContext *s, SIFFContext *c) ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; ast->codec->codec_id = CODEC_ID_PCM_U8; ast->codec->channels = 1; - ast->codec->bits_per_coded_sample = c->bits; + ast->codec->bits_per_coded_sample = 8; ast->codec->sample_rate = c->rate; - ast->codec->frame_size = c->block_align; avpriv_set_pts_info(ast, 16, 1, c->rate); + ast->start_time = 0; return 0; } @@ -215,9 +215,10 @@ static int siff_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->stream_index = 0; c->curstrm = -1; }else{ - if (av_get_packet(s->pb, pkt, c->sndsize - 4) < 0) + if ((size = av_get_packet(s->pb, pkt, c->sndsize - 4)) < 0) return AVERROR(EIO); pkt->stream_index = 1; + pkt->duration = size; c->curstrm = 0; } if(!c->cur_frame || c->curstrm) @@ -228,6 +229,7 @@ static int siff_read_packet(AVFormatContext *s, AVPacket *pkt) size = av_get_packet(s->pb, pkt, c->block_align); if(size <= 0) return AVERROR(EIO); + pkt->duration = size; } return pkt->size; } diff --git a/libavformat/swfenc.c b/libavformat/swfenc.c index af812d09eb..d4c6d0b50a 100644 --- a/libavformat/swfenc.c +++ b/libavformat/swfenc.c @@ -187,10 +187,6 @@ static int swf_write_header(AVFormatContext *s) AVCodecContext *enc = s->streams[i]->codec; if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { if (enc->codec_id == CODEC_ID_MP3) { - if (!enc->frame_size) { - av_log(s, AV_LOG_ERROR, "audio frame size not set\n"); - return -1; - } swf->audio_enc = enc; swf->audio_fifo= av_fifo_alloc(AUDIO_FIFO_SIZE); if (!swf->audio_fifo) @@ -452,7 +448,7 @@ static int swf_write_audio(AVFormatContext *s, } av_fifo_generic_write(swf->audio_fifo, buf, size, NULL); - swf->sound_samples += enc->frame_size; + swf->sound_samples += av_get_audio_frame_duration(enc, size); /* if audio only stream make sure we add swf frames */ if (!swf->video_enc) diff --git a/libavformat/utils.c b/libavformat/utils.c index 42dbae3a48..9d1a761b8e 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -754,11 +754,11 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt) static int determinable_frame_size(AVCodecContext *avctx) { - if (avctx->codec_id == CODEC_ID_AAC || + if (/*avctx->codec_id == CODEC_ID_AAC || avctx->codec_id == CODEC_ID_MP1 || - avctx->codec_id == CODEC_ID_MP2 || - avctx->codec_id == CODEC_ID_MP3 || - avctx->codec_id == CODEC_ID_CELT) + avctx->codec_id == CODEC_ID_MP2 ||*/ + avctx->codec_id == CODEC_ID_MP3/* || + avctx->codec_id == CODEC_ID_CELT*/) return 1; return 0; } @@ -766,27 +766,22 @@ static int determinable_frame_size(AVCodecContext *avctx) /** * Get the number of samples of an audio frame. Return -1 on error. */ -static int get_audio_frame_size(AVCodecContext *enc, int size) +static int get_audio_frame_size(AVCodecContext *enc, int size, int mux) { int frame_size; - if (enc->frame_size <= 1) { - int bits_per_sample = av_get_bits_per_sample(enc->codec_id); + /* give frame_size priority if demuxing */ + if (!mux && enc->frame_size > 1) + return enc->frame_size; - if (bits_per_sample) { - if (enc->channels == 0) - return -1; - frame_size = (size << 3) / (bits_per_sample * enc->channels); - } else { - /* used for example by ADPCM codecs */ - if (enc->bit_rate == 0 || determinable_frame_size(enc)) - return -1; - frame_size = ((int64_t)size * 8 * enc->sample_rate) / enc->bit_rate; - } - } else { - frame_size = enc->frame_size; - } - return frame_size; + if ((frame_size = av_get_audio_frame_duration(enc, size)) > 0) + return frame_size; + + /* fallback to using frame_size if muxing */ + if (enc->frame_size > 1) + return enc->frame_size; + + return -1; } @@ -822,7 +817,7 @@ static void compute_frame_duration(int *pnum, int *pden, AVStream *st, } break; case AVMEDIA_TYPE_AUDIO: - frame_size = get_audio_frame_size(st->codec, pkt->size); + frame_size = get_audio_frame_size(st->codec, pkt->size, 0); if (frame_size <= 0 || st->codec->sample_rate <= 0) break; *pnum = frame_size; @@ -860,11 +855,20 @@ static int is_intra_only(AVCodecContext *enc){ return 0; } +static AVPacketList *get_next_pkt(AVFormatContext *s, AVStream *st, AVPacketList *pktl) +{ + if (pktl->next) + return pktl->next; + if (pktl == s->parse_queue_end) + return s->packet_buffer; + return NULL; +} + static void update_initial_timestamps(AVFormatContext *s, int stream_index, int64_t dts, int64_t pts) { AVStream *st= s->streams[stream_index]; - AVPacketList *pktl= s->packet_buffer; + AVPacketList *pktl= s->parse_queue ? s->parse_queue : s->packet_buffer; if(st->first_dts != AV_NOPTS_VALUE || dts == AV_NOPTS_VALUE || st->cur_dts == AV_NOPTS_VALUE) return; @@ -872,7 +876,7 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, st->first_dts= dts - st->cur_dts; st->cur_dts= dts; - for(; pktl; pktl= pktl->next){ + for(; pktl; pktl= get_next_pkt(s, st, pktl)){ if(pktl->pkt.stream_index != stream_index) continue; //FIXME think more about this check @@ -889,34 +893,36 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, st->start_time = pts; } -static void update_initial_durations(AVFormatContext *s, AVStream *st, AVPacket *pkt) +static void update_initial_durations(AVFormatContext *s, AVStream *st, + int stream_index, int duration) { - AVPacketList *pktl= s->packet_buffer; + AVPacketList *pktl= s->parse_queue ? s->parse_queue : s->packet_buffer; int64_t cur_dts= 0; if(st->first_dts != AV_NOPTS_VALUE){ cur_dts= st->first_dts; - for(; pktl; pktl= pktl->next){ - if(pktl->pkt.stream_index == pkt->stream_index){ + for(; pktl; pktl= get_next_pkt(s, st, pktl)){ + if(pktl->pkt.stream_index == stream_index){ if(pktl->pkt.pts != pktl->pkt.dts || pktl->pkt.dts != AV_NOPTS_VALUE || pktl->pkt.duration) break; - cur_dts -= pkt->duration; + cur_dts -= duration; } } - pktl= s->packet_buffer; + pktl= s->parse_queue ? s->parse_queue : s->packet_buffer; st->first_dts = cur_dts; }else if(st->cur_dts) return; - for(; pktl; pktl= pktl->next){ - if(pktl->pkt.stream_index != pkt->stream_index) + for(; pktl; pktl= get_next_pkt(s, st, pktl)){ + if(pktl->pkt.stream_index != stream_index) continue; if(pktl->pkt.pts == pktl->pkt.dts && (pktl->pkt.dts == AV_NOPTS_VALUE || pktl->pkt.dts == st->first_dts) && !pktl->pkt.duration){ pktl->pkt.dts= cur_dts; if(!st->codec->has_b_frames) pktl->pkt.pts= cur_dts; - pktl->pkt.duration= pkt->duration; +// if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) + pktl->pkt.duration = duration; }else break; cur_dts = pktl->pkt.dts + pktl->pkt.duration; @@ -969,8 +975,8 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, pkt->duration = av_rescale_rnd(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num, AV_ROUND_DOWN); } } - if(pkt->duration != 0 && s->packet_buffer) - update_initial_durations(s, st, pkt); + if(pkt->duration != 0 && (s->packet_buffer || s->parse_queue)) + update_initial_durations(s, st, pkt->stream_index, pkt->duration); /* correct timestamps with byte offset if demuxers only have timestamps on packet boundaries */ @@ -1029,12 +1035,16 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, st->last_IP_pts= pkt->pts; /* cannot compute PTS if not present (we can compute it only by knowing the future */ - } else if(pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE || pkt->duration){ - if(pkt->pts != AV_NOPTS_VALUE && pkt->duration){ - int64_t old_diff= FFABS(st->cur_dts - pkt->duration - pkt->pts); + } else if (pkt->pts != AV_NOPTS_VALUE || + pkt->dts != AV_NOPTS_VALUE || + pkt->duration ) { + int duration = pkt->duration; + + if(pkt->pts != AV_NOPTS_VALUE && duration){ + int64_t old_diff= FFABS(st->cur_dts - duration - pkt->pts); int64_t new_diff= FFABS(st->cur_dts - pkt->pts); - if(old_diff < new_diff && old_diff < (pkt->duration>>3)){ - pkt->pts += pkt->duration; + if(old_diff < new_diff && old_diff < (duration>>3)){ + pkt->pts += duration; // av_log(NULL, AV_LOG_DEBUG, "id:%d old:%"PRId64" new:%"PRId64" dur:%d cur:%"PRId64" size:%d\n", pkt->stream_index, old_diff, new_diff, pkt->duration, st->cur_dts, pkt->size); } } @@ -1047,7 +1057,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, pkt->pts = st->cur_dts; pkt->dts = pkt->pts; if(pkt->pts != AV_NOPTS_VALUE) - st->cur_dts = pkt->pts + pkt->duration; + st->cur_dts = pkt->pts + duration; } } @@ -1073,161 +1083,215 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, pkt->convergence_duration = pc->convergence_duration; } +static void free_packet_buffer(AVPacketList **pkt_buf, AVPacketList **pkt_buf_end) +{ + while (*pkt_buf) { + AVPacketList *pktl = *pkt_buf; + *pkt_buf = pktl->next; + av_free_packet(&pktl->pkt); + av_freep(&pktl); + } + *pkt_buf_end = NULL; +} -static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) +/** + * Parse a packet, add all split parts to parse_queue + * + * @param pkt packet to parse, NULL when flushing the parser at end of stream + */ +static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) { - AVStream *st; - int len, ret, i; + AVPacket out_pkt = { 0 }, flush_pkt = { 0 }; + AVStream *st = s->streams[stream_index]; + uint8_t *data = pkt ? pkt->data : NULL; + int size = pkt ? pkt->size : 0; + int ret = 0, got_output = 0; - av_init_packet(pkt); + if (!pkt) { + av_init_packet(&flush_pkt); + pkt = &flush_pkt; + got_output = 1; + } - for(;;) { - /* select current input stream component */ - st = s->cur_st; - if (st) { - if (!st->need_parsing || !st->parser) { - /* no parsing needed: we just output the packet as is */ - /* raw data support */ - *pkt = st->cur_pkt; - st->cur_pkt.data= NULL; - st->cur_pkt.side_data_elems = 0; - st->cur_pkt.side_data = NULL; - compute_pkt_fields(s, st, NULL, pkt); - s->cur_st = NULL; - if ((s->iformat->flags & AVFMT_GENERIC_INDEX) && - (pkt->flags & AV_PKT_FLAG_KEY) && pkt->dts != AV_NOPTS_VALUE) { - ff_reduce_index(s, st->index); - av_add_index_entry(st, pkt->pos, pkt->dts, 0, 0, AVINDEX_KEYFRAME); - } - break; - } else if (st->cur_len > 0 && st->discard < AVDISCARD_ALL) { - len = av_parser_parse2(st->parser, st->codec, &pkt->data, &pkt->size, - st->cur_ptr, st->cur_len, - st->cur_pkt.pts, st->cur_pkt.dts, - st->cur_pkt.pos); - st->cur_pkt.pts = AV_NOPTS_VALUE; - st->cur_pkt.dts = AV_NOPTS_VALUE; - /* increment read pointer */ - st->cur_ptr += len; - st->cur_len -= len; - - /* return packet if any */ - if (pkt->size) { - got_packet: - pkt->duration = 0; - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - if (st->codec->sample_rate > 0) { - pkt->duration = av_rescale_q_rnd(st->parser->duration, - (AVRational){ 1, st->codec->sample_rate }, - st->time_base, - AV_ROUND_DOWN); - } - } else if (st->codec->time_base.num != 0 && - st->codec->time_base.den != 0) { - pkt->duration = av_rescale_q_rnd(st->parser->duration, - st->codec->time_base, - st->time_base, - AV_ROUND_DOWN); - } - pkt->stream_index = st->index; - pkt->pts = st->parser->pts; - pkt->dts = st->parser->dts; - pkt->pos = st->parser->pos; - if (st->parser->key_frame == 1 || - (st->parser->key_frame == -1 && - st->parser->pict_type == AV_PICTURE_TYPE_I)) - pkt->flags |= AV_PKT_FLAG_KEY; - if(pkt->data == st->cur_pkt.data && pkt->size == st->cur_pkt.size){ - s->cur_st = NULL; - pkt->destruct= st->cur_pkt.destruct; - st->cur_pkt.destruct= NULL; - st->cur_pkt.data = NULL; - assert(st->cur_len == 0); - }else{ - pkt->destruct = NULL; - } - compute_pkt_fields(s, st, st->parser, pkt); + while (size > 0 || (pkt == &flush_pkt && got_output)) { + int len; - if((s->iformat->flags & AVFMT_GENERIC_INDEX) && pkt->flags & AV_PKT_FLAG_KEY){ - int64_t pos= (st->parser->flags & PARSER_FLAG_COMPLETE_FRAMES) ? pkt->pos : st->parser->frame_offset; - ff_reduce_index(s, st->index); - av_add_index_entry(st, pos, pkt->dts, - 0, 0, AVINDEX_KEYFRAME); - } + av_init_packet(&out_pkt); + len = av_parser_parse2(st->parser, st->codec, + &out_pkt.data, &out_pkt.size, data, size, + pkt->pts, pkt->dts, pkt->pos); - break; - } - } else { - /* free packet */ - av_free_packet(&st->cur_pkt); - s->cur_st = NULL; + pkt->pts = pkt->dts = AV_NOPTS_VALUE; + /* increment read pointer */ + data += len; + size -= len; + + got_output = !!out_pkt.size; + + if (!out_pkt.size) + continue; + + /* set the duration */ + out_pkt.duration = 0; + if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st->codec->sample_rate > 0) { + out_pkt.duration = av_rescale_q_rnd(st->parser->duration, + (AVRational){ 1, st->codec->sample_rate }, + st->time_base, + AV_ROUND_DOWN); } - } else { - AVPacket cur_pkt; - /* read next packet */ - ret = av_read_packet(s, &cur_pkt); - if (ret < 0) { - if (ret == AVERROR(EAGAIN)) - return ret; - /* return the last frames, if any */ - for(i = 0; i < s->nb_streams; i++) { - st = s->streams[i]; - if (st->parser && st->need_parsing) { - av_parser_parse2(st->parser, st->codec, - &pkt->data, &pkt->size, - NULL, 0, - AV_NOPTS_VALUE, AV_NOPTS_VALUE, - AV_NOPTS_VALUE); - if (pkt->size) - goto got_packet; - } - } - /* no more packets: really terminate parsing */ + } else if (st->codec->time_base.num != 0 && + st->codec->time_base.den != 0) { + out_pkt.duration = av_rescale_q_rnd(st->parser->duration, + st->codec->time_base, + st->time_base, + AV_ROUND_DOWN); + } + + out_pkt.stream_index = st->index; + out_pkt.pts = st->parser->pts; + out_pkt.dts = st->parser->dts; + out_pkt.pos = st->parser->pos; + + if (st->parser->key_frame == 1 || + (st->parser->key_frame == -1 && + st->parser->pict_type == AV_PICTURE_TYPE_I)) + out_pkt.flags |= AV_PKT_FLAG_KEY; + + compute_pkt_fields(s, st, st->parser, &out_pkt); + + if ((s->iformat->flags & AVFMT_GENERIC_INDEX) && + out_pkt.flags & AV_PKT_FLAG_KEY) { + int64_t pos= (st->parser->flags & PARSER_FLAG_COMPLETE_FRAMES) ? out_pkt.pos : st->parser->frame_offset; + ff_reduce_index(s, st->index); + av_add_index_entry(st, pos, out_pkt.dts, + 0, 0, AVINDEX_KEYFRAME); + } + + if (out_pkt.data == pkt->data && out_pkt.size == pkt->size) { + out_pkt.destruct = pkt->destruct; + pkt->destruct = NULL; + } + if ((ret = av_dup_packet(&out_pkt)) < 0) + goto fail; + + if (!add_to_pktbuf(&s->parse_queue, &out_pkt, &s->parse_queue_end)) { + av_free_packet(&out_pkt); + ret = AVERROR(ENOMEM); + goto fail; + } + } + + + /* end of the stream => close and free the parser */ + if (pkt == &flush_pkt) { + av_parser_close(st->parser); + st->parser = NULL; + } + +fail: + av_free_packet(pkt); + return ret; +} + +static int read_from_packet_buffer(AVPacketList **pkt_buffer, + AVPacketList **pkt_buffer_end, + AVPacket *pkt) +{ + AVPacketList *pktl; + av_assert0(*pkt_buffer); + pktl = *pkt_buffer; + *pkt = pktl->pkt; + *pkt_buffer = pktl->next; + if (!pktl->next) + *pkt_buffer_end = NULL; + av_freep(&pktl); + return 0; +} + +static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) +{ + int ret = 0, i, got_packet = 0; + + av_init_packet(pkt); + + while (!got_packet && !s->parse_queue) { + AVStream *st; + AVPacket cur_pkt; + + /* read next packet */ + ret = av_read_packet(s, &cur_pkt); + if (ret < 0) { + if (ret == AVERROR(EAGAIN)) return ret; + /* flush the parsers */ + for(i = 0; i < s->nb_streams; i++) { + st = s->streams[i]; + if (st->parser && st->need_parsing) + parse_packet(s, NULL, st->index); } - st = s->streams[cur_pkt.stream_index]; - st->cur_pkt= cur_pkt; - - if(st->cur_pkt.pts != AV_NOPTS_VALUE && - st->cur_pkt.dts != AV_NOPTS_VALUE && - st->cur_pkt.pts < st->cur_pkt.dts){ - av_log(s, AV_LOG_WARNING, "Invalid timestamps stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d\n", - st->cur_pkt.stream_index, - st->cur_pkt.pts, - st->cur_pkt.dts, - st->cur_pkt.size); -// av_free_packet(&st->cur_pkt); -// return -1; + /* all remaining packets are now in parse_queue => + * really terminate parsing */ + break; + } + ret = 0; + st = s->streams[cur_pkt.stream_index]; + + if (cur_pkt.pts != AV_NOPTS_VALUE && + cur_pkt.dts != AV_NOPTS_VALUE && + cur_pkt.pts < cur_pkt.dts) { + av_log(s, AV_LOG_WARNING, "Invalid timestamps stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d\n", + cur_pkt.stream_index, + cur_pkt.pts, + cur_pkt.dts, + cur_pkt.size); + } + if (s->debug & FF_FDEBUG_TS) + av_log(s, AV_LOG_DEBUG, "av_read_packet stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, duration=%d, flags=%d\n", + cur_pkt.stream_index, + cur_pkt.pts, + cur_pkt.dts, + cur_pkt.size, + cur_pkt.duration, + cur_pkt.flags); + + if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE)) { + st->parser = av_parser_init(st->codec->codec_id); + if (!st->parser) { + av_log(s, AV_LOG_VERBOSE, "parser not found for codec " + "%s, packets or times may be invalid.\n", + avcodec_get_name(st->codec->codec_id)); + /* no parser available: just output the raw packets */ + st->need_parsing = AVSTREAM_PARSE_NONE; + } else if(st->need_parsing == AVSTREAM_PARSE_HEADERS) { + st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; + } else if(st->need_parsing == AVSTREAM_PARSE_FULL_ONCE) { + st->parser->flags |= PARSER_FLAG_ONCE; } + } - if(s->debug & FF_FDEBUG_TS) - av_log(s, AV_LOG_DEBUG, "av_read_packet stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, duration=%d, flags=%d\n", - st->cur_pkt.stream_index, - st->cur_pkt.pts, - st->cur_pkt.dts, - st->cur_pkt.size, - st->cur_pkt.duration, - st->cur_pkt.flags); - - s->cur_st = st; - st->cur_ptr = st->cur_pkt.data; - st->cur_len = st->cur_pkt.size; - if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE)) { - st->parser = av_parser_init(st->codec->codec_id); - if (!st->parser) { - av_log(s, AV_LOG_VERBOSE, "parser not found for codec " - "%s, packets or times may be invalid.\n", - avcodec_get_name(st->codec->codec_id)); - /* no parser available: just output the raw packets */ - st->need_parsing = AVSTREAM_PARSE_NONE; - }else if(st->need_parsing == AVSTREAM_PARSE_HEADERS){ - st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; - }else if(st->need_parsing == AVSTREAM_PARSE_FULL_ONCE){ - st->parser->flags |= PARSER_FLAG_ONCE; - } + if (!st->need_parsing || !st->parser) { + /* no parsing needed: we just output the packet as is */ + *pkt = cur_pkt; + compute_pkt_fields(s, st, NULL, pkt); + if ((s->iformat->flags & AVFMT_GENERIC_INDEX) && + (pkt->flags & AV_PKT_FLAG_KEY) && pkt->dts != AV_NOPTS_VALUE) { + ff_reduce_index(s, st->index); + av_add_index_entry(st, pkt->pos, pkt->dts, 0, 0, AVINDEX_KEYFRAME); } + got_packet = 1; + } else if (st->discard < AVDISCARD_ALL) { + if ((ret = parse_packet(s, &cur_pkt, cur_pkt.stream_index)) < 0) + return ret; + } else { + /* free packet */ + av_free_packet(&cur_pkt); } } + + if (!got_packet && s->parse_queue) + ret = read_from_packet_buffer(&s->parse_queue, &s->parse_queue_end, pkt); + if(s->debug & FF_FDEBUG_TS) av_log(s, AV_LOG_DEBUG, "read_frame_internal stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, duration=%d, flags=%d\n", pkt->stream_index, @@ -1237,17 +1301,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) pkt->duration, pkt->flags); - return 0; -} - -static int read_from_packet_buffer(AVFormatContext *s, AVPacket *pkt) -{ - AVPacketList *pktl = s->packet_buffer; - av_assert0(pktl); - *pkt = pktl->pkt; - s->packet_buffer = pktl->next; - av_freep(&pktl); - return 0; + return ret; } int av_read_frame(AVFormatContext *s, AVPacket *pkt) @@ -1256,7 +1310,9 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) int eof = 0; if (!genpts) - return s->packet_buffer ? read_from_packet_buffer(s, pkt) : + return s->packet_buffer ? read_from_packet_buffer(&s->packet_buffer, + &s->packet_buffer_end, + pkt) : read_frame_internal(s, pkt); for (;;) { @@ -1282,7 +1338,8 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) /* read packet from packet buffer, if there is data */ if (!(next_pkt->pts == AV_NOPTS_VALUE && next_pkt->dts != AV_NOPTS_VALUE && !eof)) - return read_from_packet_buffer(s, pkt); + return read_from_packet_buffer(&s->packet_buffer, + &s->packet_buffer_end, pkt); } ret = read_frame_internal(s, pkt); @@ -1303,24 +1360,10 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) /* XXX: suppress the packet queue */ static void flush_packet_queue(AVFormatContext *s) { - AVPacketList *pktl; + free_packet_buffer(&s->parse_queue, &s->parse_queue_end); + free_packet_buffer(&s->packet_buffer, &s->packet_buffer_end); + free_packet_buffer(&s->raw_packet_buffer, &s->raw_packet_buffer_end); - for(;;) { - pktl = s->packet_buffer; - if (!pktl) - break; - s->packet_buffer = pktl->next; - av_free_packet(&pktl->pkt); - av_free(pktl); - } - while(s->raw_packet_buffer){ - pktl = s->raw_packet_buffer; - s->raw_packet_buffer = pktl->next; - av_free_packet(&pktl->pkt); - av_free(pktl); - } - s->packet_buffer_end= - s->raw_packet_buffer_end= NULL; s->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; } @@ -1356,8 +1399,6 @@ void ff_read_frame_flush(AVFormatContext *s) flush_packet_queue(s); - s->cur_st = NULL; - /* for each stream, reset read state */ for(i = 0; i < s->nb_streams; i++) { st = s->streams[i]; @@ -1365,15 +1406,11 @@ void ff_read_frame_flush(AVFormatContext *s) if (st->parser) { av_parser_close(st->parser); st->parser = NULL; - av_free_packet(&st->cur_pkt); } st->last_IP_pts = AV_NOPTS_VALUE; if(st->first_dts == AV_NOPTS_VALUE) st->cur_dts = 0; else st->cur_dts = AV_NOPTS_VALUE; /* we set the current DTS to an unspecified origin */ st->reference_dts = AV_NOPTS_VALUE; - /* fail safe */ - st->cur_ptr = NULL; - st->cur_len = 0; st->probe_packets = MAX_PROBE_PACKETS; @@ -1992,8 +2029,6 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) int64_t filesize, offset, duration; int retry=0; - ic->cur_st = NULL; - /* flush packet queue */ flush_packet_queue(ic); @@ -2005,7 +2040,6 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) if (st->parser) { av_parser_close(st->parser); st->parser= NULL; - av_free_packet(&st->cur_pkt); } } @@ -2107,17 +2141,22 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset) } } -static int has_codec_parameters(AVCodecContext *avctx) +static int has_codec_parameters(AVStream *st) { + AVCodecContext *avctx = st->codec; int val; switch (avctx->codec_type) { case AVMEDIA_TYPE_AUDIO: - val = avctx->sample_rate && avctx->channels && avctx->sample_fmt != AV_SAMPLE_FMT_NONE; + val = avctx->sample_rate && avctx->channels; if (!avctx->frame_size && determinable_frame_size(avctx)) return 0; + if (st->info->found_decoder >= 0 && avctx->sample_fmt == AV_SAMPLE_FMT_NONE) + return 0; break; case AVMEDIA_TYPE_VIDEO: - val = avctx->width && avctx->pix_fmt != PIX_FMT_NONE; + val = avctx->width; + if (st->info->found_decoder >= 0 && avctx->pix_fmt == PIX_FMT_NONE) + return 0; break; case AVMEDIA_TYPE_DATA: if(avctx->codec_id == CODEC_ID_NONE) return 1; @@ -2142,14 +2181,16 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option AVFrame picture; AVPacket pkt = *avpkt; - if (!avcodec_is_open(st->codec)) { + if (!avcodec_is_open(st->codec) && !st->info->found_decoder) { AVDictionary *thread_opt = NULL; codec = st->codec->codec ? st->codec->codec : avcodec_find_decoder(st->codec->codec_id); - if (!codec) + if (!codec) { + st->info->found_decoder = -1; return -1; + } /* force thread count to 1 since the h264 decoder will not extract SPS * and PPS to extradata during multi-threaded decoding */ @@ -2157,13 +2198,20 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option ret = avcodec_open2(st->codec, codec, options ? options : &thread_opt); if (!options) av_dict_free(&thread_opt); - if (ret < 0) + if (ret < 0) { + st->info->found_decoder = -1; return ret; - } + } + st->info->found_decoder = 1; + } else if (!st->info->found_decoder) + st->info->found_decoder = 1; + + if (st->info->found_decoder < 0) + return -1; while ((pkt.size > 0 || (!pkt.data && got_picture)) && ret >= 0 && - (!has_codec_parameters(st->codec) || + (!has_codec_parameters(st) || !has_decode_delay_been_guessed(st) || (!st->codec_info_nb_frames && st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF))) { got_picture = 0; @@ -2331,7 +2379,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) : &thread_opt); //try to just open decoders, in case this is enough to get parameters - if(!has_codec_parameters(st->codec)){ + if (!has_codec_parameters(st)) { if (codec && !st->codec->codec) avcodec_open2(st->codec, codec, options ? &options[i] : &thread_opt); @@ -2358,7 +2406,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) int fps_analyze_framecount = 20; st = ic->streams[i]; - if (!has_codec_parameters(st->codec)) + if (!has_codec_parameters(st)) break; /* if the timebase is coarse (like the usual millisecond precision of mkv), we need to analyze more frames to reliably arrive at @@ -2483,7 +2531,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (flush_codecs) { AVPacket empty_pkt = { 0 }; - int err; + int err = 0; av_init_packet(&empty_pkt); ret = -1; /* we could not have all the codec parameters before EOF */ @@ -2491,17 +2539,20 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) st = ic->streams[i]; /* flush the decoders */ - do { - err = try_decode_frame(st, &empty_pkt, - (options && i < orig_nb_streams) ? - &options[i] : NULL); - } while (err > 0 && !has_codec_parameters(st->codec)); - - if (err < 0) { - av_log(ic, AV_LOG_INFO, - "decoding for stream %d failed\n", st->index); + if (st->info->found_decoder == 1) { + do { + err = try_decode_frame(st, &empty_pkt, + (options && i < orig_nb_streams) ? + &options[i] : NULL); + } while (err > 0 && !has_codec_parameters(st)); + + if (err < 0) { + av_log(ic, AV_LOG_INFO, + "decoding for stream %d failed\n", st->index); + } } - if (!has_codec_parameters(st->codec)){ + + if (!has_codec_parameters(st)){ char buf[256]; avcodec_string(buf, sizeof(buf), st->codec, 0); av_log(ic, AV_LOG_WARNING, @@ -2738,7 +2789,6 @@ void avformat_free_context(AVFormatContext *s) st = s->streams[i]; if (st->parser) { av_parser_close(st->parser); - av_free_packet(&st->cur_pkt); } if (st->attached_pic.data) av_free_packet(&st->attached_pic); @@ -3193,7 +3243,7 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt){ /* update pts */ switch (st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: - frame_size = get_audio_frame_size(st->codec, pkt->size); + frame_size = get_audio_frame_size(st->codec, pkt->size, 1); /* HACK/FIXME, we skip the initial 0 size packets as they are most likely equal to the encoder delay, but it would be better if we |