FilterGraph *fg = filtergraphs[i];
avfilter_graph_free(&fg->graph);
for (j = 0; j < fg->nb_inputs; j++) {
+ while (av_fifo_size(fg->inputs[j]->frame_queue)) {
+ AVFrame *frame;
+ av_fifo_generic_read(fg->inputs[j]->frame_queue, &frame,
+ sizeof(frame), NULL);
+ av_frame_free(&frame);
+ }
+ av_fifo_free(fg->inputs[j]->frame_queue);
av_buffer_unref(&fg->inputs[j]->hw_frames_ctx);
av_freep(&fg->inputs[j]->name);
av_freep(&fg->inputs[j]);
avcodec_free_context(&ost->enc_ctx);
- while (av_fifo_size(ost->muxing_queue)) {
- AVPacket pkt;
- av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL);
- av_packet_unref(&pkt);
+ if (ost->muxing_queue) {
+ while (av_fifo_size(ost->muxing_queue)) {
+ AVPacket pkt;
+ av_log(NULL, AV_LOG_INFO, "after av_fifo_size()\n");
+ av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL);
+ av_packet_unref(&pkt);
+ }
+ av_fifo_free(ost->muxing_queue);
}
- av_fifo_free(ost->muxing_queue);
-
av_freep(&output_streams[i]);
}
for (i = 0; i < nb_input_files; i++) {
}
}
+static int init_output_stream(OutputStream *ost, char *error, int error_len);
+
/*
* Read one frame for lavfi output for ost and encode it.
*/
}
filtered_frame = ost->filtered_frame;
+ if (!ost->initialized) {
+ char error[1024];
+ ret = init_output_stream(ost, error, sizeof(error));
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error initializing output stream %d:%d -- %s\n",
+ ost->file_index, ost->index, error);
+ exit_program(1);
+ }
+ }
+
if (ost->enc->type == AVMEDIA_TYPE_AUDIO &&
!(ost->enc->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE))
ret = av_buffersink_get_samples(ost->filter->filter, filtered_frame,
for (i = 0; i < nb_output_streams; i++) {
int64_t pts = output_streams[i]->sync_opts;
- if (!output_streams[i]->filter || output_streams[i]->finished)
+ if (output_streams[i]->filter && !output_streams[i]->filter->graph->graph &&
+ !output_streams[i]->filter->graph->nb_inputs) {
+ ret = configure_filtergraph(output_streams[i]->filter->graph);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n");
+ return ret;
+ }
+ }
+
+ if (!output_streams[i]->filter || output_streams[i]->finished ||
+ !output_streams[i]->filter->graph->graph)
continue;
pts = av_rescale_q(pts, output_streams[i]->enc_ctx->time_base,
output_packet(of, &opkt, ost);
}
+static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame)
+{
+ FilterGraph *fg = ifilter->graph;
+ int need_reinit, ret, i;
+
+ /* determine if the parameters for this input changed */
+ need_reinit = ifilter->format != frame->format;
+ if (!!ifilter->hw_frames_ctx != !!frame->hw_frames_ctx ||
+ (ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data))
+ need_reinit = 1;
+
+ switch (ifilter->ist->st->codecpar->codec_type) {
+ case AVMEDIA_TYPE_AUDIO:
+ need_reinit |= ifilter->sample_rate != frame->sample_rate ||
+ ifilter->channel_layout != frame->channel_layout;
+ break;
+ case AVMEDIA_TYPE_VIDEO:
+ need_reinit |= ifilter->width != frame->width ||
+ ifilter->height != frame->height;
+ break;
+ }
+
+ if (need_reinit) {
+ ret = ifilter_parameters_from_frame(ifilter, frame);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* (re)init the graph if possible, otherwise buffer the frame and return */
+ if (need_reinit || !fg->graph) {
+ for (i = 0; i < fg->nb_inputs; i++) {
+ if (fg->inputs[i]->format < 0) {
+ AVFrame *tmp = av_frame_clone(frame);
+ if (!tmp)
+ return AVERROR(ENOMEM);
+ av_frame_unref(frame);
+
+ if (!av_fifo_space(ifilter->frame_queue)) {
+ ret = av_fifo_realloc2(ifilter->frame_queue, 2 * av_fifo_size(ifilter->frame_queue));
+ if (ret < 0)
+ return ret;
+ }
+ av_fifo_generic_write(ifilter->frame_queue, &tmp, sizeof(tmp), NULL);
+ return 0;
+ }
+ }
+
+ ret = poll_filters();
+ if (ret < 0 && ret != AVERROR_EOF) {
+ char errbuf[128];
+ av_strerror(ret, errbuf, sizeof(errbuf));
+
+ av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", errbuf);
+ return ret;
+ }
+
+ ret = configure_filtergraph(fg);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error reinitializing filters!\n");
+ return ret;
+ }
+ }
+
+ ret = av_buffersrc_add_frame(ifilter->filter, frame);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Error while filtering\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ifilter_send_eof(InputFilter *ifilter)
+{
+ int i, j, ret;
+
+ ifilter->eof = 1;
+
+ if (ifilter->filter) {
+ ret = av_buffersrc_add_frame(ifilter->filter, NULL);
+ if (ret < 0)
+ return ret;
+ } else {
+ // the filtergraph was never configured
+ FilterGraph *fg = ifilter->graph;
+ for (i = 0; i < fg->nb_inputs; i++)
+ if (!fg->inputs[i]->eof)
+ break;
+ if (i == fg->nb_inputs) {
+ // All the input streams have finished without the filtergraph
+ // ever being configured.
+ // Mark the output streams as finished.
+ for (j = 0; j < fg->nb_outputs; j++)
+ finish_output_stream(fg->outputs[j]->ost);
+ }
+ }
+
+ return 0;
+}
+
// This does not quite work like avcodec_decode_audio4/avcodec_decode_video2.
// There is the following difference: if you got a frame, you must call
// it again with pkt=NULL. pkt==NULL is treated differently from pkt.size==0
{
AVFrame *decoded_frame, *f;
AVCodecContext *avctx = ist->dec_ctx;
- int i, ret, err = 0, resample_changed;
+ int i, ret, err = 0;
if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc()))
return AVERROR(ENOMEM);
decoded_frame->pts = pkt->pts;
}
- resample_changed = ist->resample_sample_fmt != decoded_frame->format ||
- ist->resample_channels != avctx->channels ||
- ist->resample_channel_layout != decoded_frame->channel_layout ||
- ist->resample_sample_rate != decoded_frame->sample_rate;
- if (resample_changed) {
- char layout1[64], layout2[64];
-
- if (!guess_input_channel_layout(ist)) {
- av_log(NULL, AV_LOG_FATAL, "Unable to find default channel "
- "layout for Input Stream #%d.%d\n", ist->file_index,
- ist->st->index);
- exit_program(1);
- }
- decoded_frame->channel_layout = avctx->channel_layout;
-
- av_get_channel_layout_string(layout1, sizeof(layout1), ist->resample_channels,
- ist->resample_channel_layout);
- av_get_channel_layout_string(layout2, sizeof(layout2), avctx->channels,
- decoded_frame->channel_layout);
-
- av_log(NULL, AV_LOG_INFO,
- "Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d chl:%s to rate:%d fmt:%s ch:%d chl:%s\n",
- ist->file_index, ist->st->index,
- ist->resample_sample_rate, av_get_sample_fmt_name(ist->resample_sample_fmt),
- ist->resample_channels, layout1,
- decoded_frame->sample_rate, av_get_sample_fmt_name(decoded_frame->format),
- avctx->channels, layout2);
-
- ist->resample_sample_fmt = decoded_frame->format;
- ist->resample_sample_rate = decoded_frame->sample_rate;
- ist->resample_channel_layout = decoded_frame->channel_layout;
- ist->resample_channels = avctx->channels;
-
- for (i = 0; i < ist->nb_filters; i++) {
- err = ifilter_parameters_from_frame(ist->filters[i], decoded_frame);
- if (err < 0) {
- av_log(NULL, AV_LOG_ERROR,
- "Error reconfiguring input stream %d:%d filter %d\n",
- ist->file_index, ist->st->index, i);
- goto fail;
- }
- }
-
- for (i = 0; i < nb_filtergraphs; i++)
- if (ist_in_filtergraph(filtergraphs[i], ist) &&
- configure_filtergraph(filtergraphs[i]) < 0) {
- av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n");
- exit_program(1);
- }
- }
-
if (decoded_frame->pts != AV_NOPTS_VALUE)
decoded_frame->pts = av_rescale_q(decoded_frame->pts,
ist->st->time_base,
} else
f = decoded_frame;
- err = av_buffersrc_add_frame(ist->filters[i]->filter, f);
+ err = ifilter_send_frame(ist->filters[i], f);
if (err < 0)
break;
}
-fail:
av_frame_unref(ist->filter_frame);
av_frame_unref(decoded_frame);
return err < 0 ? err : ret;
static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
{
AVFrame *decoded_frame, *f;
- int i, ret = 0, err = 0, resample_changed;
+ int i, ret = 0, err = 0;
if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc()))
return AVERROR(ENOMEM);
decoded_frame->pts = guess_correct_pts(&ist->pts_ctx, decoded_frame->pts,
decoded_frame->pkt_dts);
+ if (ist->framerate.num)
+ decoded_frame->pts = ist->cfr_next_pts++;
if (ist->st->sample_aspect_ratio.num)
decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
- resample_changed = ist->resample_width != decoded_frame->width ||
- ist->resample_height != decoded_frame->height ||
- ist->resample_pix_fmt != decoded_frame->format;
- if (resample_changed) {
- av_log(NULL, AV_LOG_INFO,
- "Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n",
- ist->file_index, ist->st->index,
- ist->resample_width, ist->resample_height, av_get_pix_fmt_name(ist->resample_pix_fmt),
- decoded_frame->width, decoded_frame->height, av_get_pix_fmt_name(decoded_frame->format));
-
- ret = poll_filters();
- if (ret < 0 && ret != AVERROR_EOF) {
- char errbuf[128];
- av_strerror(ret, errbuf, sizeof(errbuf));
-
- av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", errbuf);
- }
-
- ist->resample_width = decoded_frame->width;
- ist->resample_height = decoded_frame->height;
- ist->resample_pix_fmt = decoded_frame->format;
-
- for (i = 0; i < ist->nb_filters; i++) {
- err = ifilter_parameters_from_frame(ist->filters[i], decoded_frame);
- if (err < 0) {
- av_log(NULL, AV_LOG_ERROR,
- "Error reconfiguring input stream %d:%d filter %d\n",
- ist->file_index, ist->st->index, i);
- goto fail;
- }
- }
-
- for (i = 0; i < nb_filtergraphs; i++)
- if (ist_in_filtergraph(filtergraphs[i], ist) &&
- configure_filtergraph(filtergraphs[i]) < 0) {
- av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n");
- exit_program(1);
- }
- }
-
for (i = 0; i < ist->nb_filters; i++) {
if (i < ist->nb_filters - 1) {
f = ist->filter_frame;
} else
f = decoded_frame;
- err = av_buffersrc_add_frame(ist->filters[i]->filter, f);
+ err = ifilter_send_frame(ist->filters[i], f);
if (err < 0)
break;
}
{
int i, ret;
for (i = 0; i < ist->nb_filters; i++) {
- ret = av_buffersrc_add_frame(ist->filters[i]->filter, NULL);
+ ret = ifilter_send_eof(ist->filters[i]);
if (ret < 0)
return ret;
}
}
continue;
}
+
+ if (ist->hw_frames_ctx) {
+ s->hw_frames_ctx = av_buffer_ref(ist->hw_frames_ctx);
+ if (!s->hw_frames_ctx)
+ return AV_PIX_FMT_NONE;
+ }
+
ist->active_hwaccel_id = hwaccel->id;
ist->hwaccel_pix_fmt = *p;
break;
static int init_input_stream(int ist_index, char *error, int error_len)
{
- int i, ret;
+ int ret;
InputStream *ist = input_streams[ist_index];
- for (i = 0; i < ist->nb_filters; i++) {
- ret = ifilter_parameters_from_decoder(ist->filters[i], ist->dec_ctx);
- if (ret < 0) {
- av_log(NULL, AV_LOG_FATAL, "Error initializing filter input\n");
- return ret;
- }
- }
-
if (ist->decoding_needed) {
AVCodec *codec = ist->dec;
if (!codec) {
AVCodecParameters *par_dst = ost->st->codecpar;
AVCodecParameters *par_src = ist->st->codecpar;
AVRational sar;
- int i;
- uint64_t extra_size;
-
- extra_size = (uint64_t)par_src->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE;
- if (extra_size > INT_MAX) {
- return AVERROR(EINVAL);
- }
-
- ost->st->disposition = ist->st->disposition;
-
- /* if stream_copy is selected, no need to decode or encode */
- par_dst->codec_id = par_src->codec_id;
- par_dst->codec_type = par_src->codec_type;
+ uint32_t codec_tag = par_dst->codec_tag;
+ int i, ret;
- if (!par_dst->codec_tag) {
+ if (!codec_tag) {
if (!of->ctx->oformat->codec_tag ||
- av_codec_get_id (of->ctx->oformat->codec_tag, par_src->codec_tag) == par_dst->codec_id ||
+ av_codec_get_id (of->ctx->oformat->codec_tag, par_src->codec_tag) == par_src->codec_id ||
av_codec_get_tag(of->ctx->oformat->codec_tag, par_src->codec_id) <= 0)
- par_dst->codec_tag = par_src->codec_tag;
+ codec_tag = par_src->codec_tag;
}
- par_dst->bit_rate = par_src->bit_rate;
- par_dst->field_order = par_src->field_order;
- par_dst->chroma_location = par_src->chroma_location;
+ ret = avcodec_parameters_copy(par_dst, par_src);
+ if (ret < 0)
+ return ret;
- if (par_src->extradata) {
- par_dst->extradata = av_mallocz(extra_size);
- if (!par_dst->extradata) {
- return AVERROR(ENOMEM);
- }
- memcpy(par_dst->extradata, par_src->extradata, par_src->extradata_size);
- par_dst->extradata_size = par_src->extradata_size;
- }
+ par_dst->codec_tag = codec_tag;
+
+ ost->st->disposition = ist->st->disposition;
ost->st->time_base = ist->st->time_base;
if (!ost->parser_avctx)
return AVERROR(ENOMEM);
- switch (par_dst->codec_type) {
- case AVMEDIA_TYPE_AUDIO:
- if (audio_volume != 256) {
- av_log(NULL, AV_LOG_FATAL, "-acodec copy and -vol are incompatible (frames are not decoded)\n");
- exit_program(1);
- }
- par_dst->channel_layout = par_src->channel_layout;
- par_dst->sample_rate = par_src->sample_rate;
- par_dst->channels = par_src->channels;
- par_dst->block_align = par_src->block_align;
- break;
- case AVMEDIA_TYPE_VIDEO:
- par_dst->format = par_src->format;
- par_dst->width = par_src->width;
- par_dst->height = par_src->height;
+ if (par_dst->codec_type == AVMEDIA_TYPE_VIDEO) {
if (ost->frame_aspect_ratio)
sar = av_d2q(ost->frame_aspect_ratio * par_dst->height / par_dst->width, 255);
else if (ist->st->sample_aspect_ratio.num)
else
sar = par_src->sample_aspect_ratio;
ost->st->sample_aspect_ratio = par_dst->sample_aspect_ratio = sar;
- break;
- case AVMEDIA_TYPE_SUBTITLE:
- par_dst->width = par_src->width;
- par_dst->height = par_src->height;
- break;
- case AVMEDIA_TYPE_DATA:
- case AVMEDIA_TYPE_ATTACHMENT:
- break;
- default:
- abort();
}
return 0;
enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location;
}
- if ((enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||
- enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO) &&
- filtergraph_is_simple(ost->filter->graph)) {
- FilterGraph *fg = ost->filter->graph;
-
- if (configure_filtergraph(fg)) {
- av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
- exit_program(1);
- }
- }
-
switch (enc_ctx->codec_type) {
case AVMEDIA_TYPE_AUDIO:
enc_ctx->sample_fmt = ost->filter->filter->inputs[0]->format;
/* open each encoder */
for (i = 0; i < nb_output_streams; i++) {
+ // skip streams fed from filtergraphs until we have a frame for them
+ if (output_streams[i]->filter)
+ continue;
+
ret = init_output_stream(output_streams[i], error, sizeof(error));
if (ret < 0)
goto dump_format;