[FFmpeg-devel] [PATCH 7/7] ffmpeg: stop decoding and filtering frames for finished streams.
Nicolas George
nicolas.george at normalesup.org
Mon Aug 20 23:28:15 CEST 2012
Add a finished field to InputFilter.
If filtering fails with AVERROR_EOF, set the finished field
and decrement the needs_decoding counter.
For non-filtered streams (subtitles), decrement needs_decoding
directly.
Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
ffmpeg.c | 69 +++++++++++++++++++++++++++++++++++++++++++++-----------------
ffmpeg.h | 1 +
2 files changed, 51 insertions(+), 19 deletions(-)
diff --git a/ffmpeg.c b/ffmpeg.c
index 4e8d32d..de17a96 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -572,15 +572,33 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
}
}
+static void close_input_to_filter(InputStream *ist, int index)
+{
+ ist->filters[index]->finished = 1;
+ ist->decoding_needed--;
+}
+
static void close_output_stream(OutputStream *ost)
{
OutputFile *of = output_files[ost->file_index];
+ int ost_min = of->ost_index + ost->index, ost_max = ost_min, i;
- ost->finished = 1;
if (of->shortest) {
- int i;
- for (i = 0; i < of->ctx->nb_streams; i++)
- output_streams[of->ost_index + i]->finished = 1;
+ ost_min = of->ost_index;
+ ost_max = of->ost_index + of->ctx->nb_streams - 1;
+ }
+ for (i = ost_min; i <= ost_max; i++) {
+ ost = output_streams[i];
+ if (ost->finished)
+ continue;
+ ost->finished = 1;
+ if (ost->filter) {
+ avfilter_link_set_closed(ost->filter->filter->inputs[0], 1);
+ } else {
+ av_assert0(ost->source_index >= 0);
+ if (ost->encoding_needed)
+ input_streams[ost->source_index]->decoding_needed--;
+ }
}
}
@@ -1411,7 +1429,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
{
AVFrame *decoded_frame;
AVCodecContext *avctx = ist->st->codec;
- int i, ret, resample_changed;
+ int i, ret, ret_filter, resample_changed;
AVRational decoded_frame_tb;
if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame()))
@@ -1520,9 +1538,14 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
decoded_frame->pts = av_rescale_q(decoded_frame->pts,
decoded_frame_tb,
(AVRational){1, ist->st->codec->sample_rate});
- for (i = 0; i < ist->nb_filters; i++)
- av_buffersrc_add_frame(ist->filters[i]->filter, decoded_frame,
- AV_BUFFERSRC_FLAG_PUSH);
+ for (i = 0; i < ist->nb_filters; i++) {
+ if (ist->filters[i]->finished)
+ continue;
+ ret_filter = av_buffersrc_add_frame(ist->filters[i]->filter, decoded_frame,
+ AV_BUFFERSRC_FLAG_PUSH);
+ if (ret_filter == AVERROR_EOF)
+ close_input_to_filter(ist, i);
+ }
decoded_frame->pts = AV_NOPTS_VALUE;
@@ -1533,7 +1556,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
{
AVFrame *decoded_frame;
void *buffer_to_free = NULL;
- int i, ret = 0, resample_changed;
+ int i, ret = 0, ret_filter, resample_changed;
int64_t best_effort_timestamp;
AVRational *frame_sample_aspect;
float quality;
@@ -1611,6 +1634,9 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
int changed = ist->st->codec->width != ist->filters[i]->filter->outputs[0]->w
|| ist->st->codec->height != ist->filters[i]->filter->outputs[0]->h
|| ist->st->codec->pix_fmt != ist->filters[i]->filter->outputs[0]->format;
+ if (ist->filters[i]->finished)
+ continue;
+
// XXX what an ugly hack
if (ist->filters[i]->graph->nb_outputs == 1)
ist->filters[i]->graph->outputs[0]->ost->last_quality = quality;
@@ -1631,12 +1657,16 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
av_assert0(buf->refcount>0);
buf->refcount++;
- av_buffersrc_add_ref(ist->filters[i]->filter, fb,
- AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT |
- AV_BUFFERSRC_FLAG_NO_COPY |
- AV_BUFFERSRC_FLAG_PUSH);
- } else
- if(av_buffersrc_add_frame(ist->filters[i]->filter, decoded_frame, AV_BUFFERSRC_FLAG_PUSH)<0) {
+ ret_filter = av_buffersrc_add_ref(ist->filters[i]->filter, fb,
+ AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT |
+ AV_BUFFERSRC_FLAG_NO_COPY |
+ AV_BUFFERSRC_FLAG_PUSH);
+ } else {
+ ret_filter = av_buffersrc_add_frame(ist->filters[i]->filter, decoded_frame, AV_BUFFERSRC_FLAG_PUSH);
+ }
+ if (ret_filter == AVERROR_EOF) {
+ close_input_to_filter(ist, i--);
+ } else if (ret_filter < 0) {
av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n");
exit_program(1);
}
@@ -1701,12 +1731,13 @@ static int output_packet(InputStream *ist, const AVPacket *pkt)
{
int ret = 0, i;
int got_output;
+ int decoding_needed = ist->decoding_needed;
AVPacket avpkt;
if (!ist->saw_first_ts) {
ist->dts = ist->st->avg_frame_rate.num ? - ist->st->codec->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;
ist->pts = 0;
- if (pkt != NULL && pkt->pts != AV_NOPTS_VALUE && !ist->decoding_needed) {
+ if (pkt != NULL && pkt->pts != AV_NOPTS_VALUE && !decoding_needed) {
ist->dts += av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q);
ist->pts = ist->dts; //unused but better to set it to a value thats not totally wrong
}
@@ -1730,12 +1761,12 @@ static int output_packet(InputStream *ist, const AVPacket *pkt)
if (pkt->dts != AV_NOPTS_VALUE) {
ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
- if (ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || !ist->decoding_needed)
+ if (ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || !decoding_needed)
ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
}
// while we have more to decode or while the decoder did output something on EOF
- while (ist->decoding_needed && (avpkt.size > 0 || (!pkt && got_output))) {
+ while (decoding_needed && (avpkt.size > 0 || (!pkt && got_output))) {
int duration;
handle_eof:
@@ -1798,7 +1829,7 @@ static int output_packet(InputStream *ist, const AVPacket *pkt)
}
/* handle stream copy */
- if (!ist->decoding_needed) {
+ if (!decoding_needed) {
rate_emu_sleep(ist);
ist->dts = ist->next_dts;
switch (ist->st->codec->codec_type) {
diff --git a/ffmpeg.h b/ffmpeg.h
index a2ba198..593280f 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -168,6 +168,7 @@ typedef struct InputFilter {
struct InputStream *ist;
struct FilterGraph *graph;
uint8_t *name;
+ int finished;
} InputFilter;
typedef struct OutputFilter {
--
1.7.10.4
More information about the ffmpeg-devel
mailing list