static int run_as_daemon = 0;
static int nb_frames_dup = 0;
+static unsigned dup_warning = 1000;
static int nb_frames_drop = 0;
static int64_t decode_error_stat[2];
FilterGraph *fg = filtergraphs[i];
avfilter_graph_free(&fg->graph);
for (j = 0; j < fg->nb_inputs; j++) {
+ 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);
avcodec_parameters_free(&ost->ref_par);
+ while (ost->muxing_queue && av_fifo_size(ost->muxing_queue)) {
+ AVPacket pkt;
+ av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL);
+ av_packet_unref(&pkt);
+ }
+ av_fifo_freep(&ost->muxing_queue);
+
av_freep(&output_streams[i]);
}
#if HAVE_PTHREADS
}
}
-static void write_packet(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
+static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
{
+ AVFormatContext *s = of->ctx;
AVStream *st = ost->st;
int ret;
+ if (!of->header_written) {
+ AVPacket tmp_pkt;
+ /* the muxer is not initialized yet, buffer the packet */
+ if (!av_fifo_space(ost->muxing_queue)) {
+ int new_size = FFMIN(2 * av_fifo_size(ost->muxing_queue),
+ ost->max_muxing_queue_size);
+ if (new_size <= av_fifo_size(ost->muxing_queue)) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Too many packets buffered for output stream %d:%d.\n",
+ ost->file_index, ost->st->index);
+ exit_program(1);
+ }
+ ret = av_fifo_realloc2(ost->muxing_queue, new_size);
+ if (ret < 0)
+ exit_program(1);
+ }
+ av_packet_move_ref(&tmp_pkt, pkt);
+ av_fifo_generic_write(ost->muxing_queue, &tmp_pkt, sizeof(tmp_pkt), NULL);
+ return;
+ }
+
if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) ||
(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0))
pkt->pts = pkt->dts = AV_NOPTS_VALUE;
}
}
-static void output_packet(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
+static void output_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost)
{
int ret = 0;
if (ost->nb_bitstream_filters) {
int idx;
+ av_packet_split_side_data(pkt);
ret = av_bsf_send_packet(ost->bsf_ctx[0], pkt);
if (ret < 0)
goto finish;
while (idx) {
/* get a packet from the previous filter up the chain */
ret = av_bsf_receive_packet(ost->bsf_ctx[idx - 1], pkt);
+ if (ret == AVERROR(EAGAIN)) {
+ ret = 0;
+ idx--;
+ continue;
+ } else if (ret < 0)
+ goto finish;
/* HACK! - aac_adtstoasc updates extradata after filtering the first frame when
* the api states this shouldn't happen after init(). Propagate it here to the
* muxer and to the next filters in the chain to workaround this.
goto finish;
ost->bsf_extradata_updated[idx - 1] |= 1;
}
- if (ret == AVERROR(EAGAIN)) {
- ret = 0;
- idx--;
- continue;
- } else if (ret < 0)
- goto finish;
/* send it to the next filter down the chain or to the muxer */
if (idx < ost->nb_bitstream_filters) {
goto finish;
idx++;
} else
- write_packet(s, pkt, ost);
+ write_packet(of, pkt, ost);
}
} else
- write_packet(s, pkt, ost);
+ write_packet(of, pkt, ost);
finish:
if (ret < 0 && ret != AVERROR_EOF) {
return 1;
}
-static void do_audio_out(AVFormatContext *s, OutputStream *ost,
+static void do_audio_out(OutputFile *of, OutputStream *ost,
AVFrame *frame)
{
AVCodecContext *enc = ost->enc_ctx;
av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base));
}
- output_packet(s, &pkt, ost);
+ output_packet(of, &pkt, ost);
}
return;
exit_program(1);
}
-static void do_subtitle_out(AVFormatContext *s,
+static void do_subtitle_out(OutputFile *of,
OutputStream *ost,
- InputStream *ist,
AVSubtitle *sub)
{
int subtitle_out_max_size = 1024 * 1024;
pkt.pts += 90 * sub->end_display_time;
}
pkt.dts = pkt.pts;
- output_packet(s, &pkt, ost);
+ output_packet(of, &pkt, ost);
}
}
-static void do_video_out(AVFormatContext *s,
+static void do_video_out(OutputFile *of,
OutputStream *ost,
AVFrame *next_picture,
double sync_ipts)
format_video_sync = video_sync_method;
if (format_video_sync == VSYNC_AUTO) {
- if(!strcmp(s->oformat->name, "avi")) {
+ if(!strcmp(of->ctx->oformat->name, "avi")) {
format_video_sync = VSYNC_VFR;
} else
- format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? ((s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : VSYNC_VFR) : VSYNC_CFR;
+ format_video_sync = (of->ctx->oformat->flags & AVFMT_VARIABLE_FPS) ? ((of->ctx->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : VSYNC_VFR) : VSYNC_CFR;
if ( ist
&& format_video_sync == VSYNC_CFR
&& input_files[ist->file_index]->ctx->nb_streams == 1
}
nb_frames_dup += nb_frames - (nb0_frames && ost->last_dropped) - (nb_frames > nb0_frames);
av_log(NULL, AV_LOG_VERBOSE, "*** %d dup!\n", nb_frames - 1);
+ if (nb_frames_dup > dup_warning) {
+ av_log(NULL, AV_LOG_WARNING, "More than %d frames duplicated\n", dup_warning);
+ dup_warning *= 10;
+ }
}
ost->last_dropped = nb_frames == nb0_frames && next_picture;
return;
#if FF_API_LAVF_FMT_RAWPICTURE
- if (s->oformat->flags & AVFMT_RAWPICTURE &&
+ if (of->ctx->oformat->flags & AVFMT_RAWPICTURE &&
enc->codec->id == AV_CODEC_ID_RAWVIDEO) {
/* raw pictures are written as AVPicture structure to
avoid any copies. We support temporarily the older
pkt.pts = av_rescale_q(in_picture->pts, enc->time_base, ost->st->time_base);
pkt.flags |= AV_PKT_FLAG_KEY;
- output_packet(s, &pkt, ost);
+ output_packet(of, &pkt, ost);
} else
#endif
{
}
frame_size = pkt.size;
- output_packet(s, &pkt, ost);
+ output_packet(of, &pkt, ost);
/* if two pass, output log */
if (ost->logfile && enc->stats_out) {
"Error in av_buffersink_get_frame_flags(): %s\n", av_err2str(ret));
} else if (flush && ret == AVERROR_EOF) {
if (filter->inputs[0]->type == AVMEDIA_TYPE_VIDEO)
- do_video_out(of->ctx, ost, NULL, AV_NOPTS_VALUE);
+ do_video_out(of, ost, NULL, AV_NOPTS_VALUE);
}
break;
}
enc->time_base.num, enc->time_base.den);
}
- do_video_out(of->ctx, ost, filtered_frame, float_pts);
+ do_video_out(of, ost, filtered_frame, float_pts);
break;
case AVMEDIA_TYPE_AUDIO:
if (!(enc->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) &&
"Audio filter graph output is not normalized and encoder does not support parameter changes\n");
break;
}
- do_audio_out(of->ctx, ost, filtered_frame);
+ do_audio_out(of, ost, filtered_frame);
break;
default:
// TODO support subtitle filters
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
AVCodecContext *enc = ost->enc_ctx;
- AVFormatContext *os = output_files[ost->file_index]->ctx;
+ OutputFile *of = output_files[ost->file_index];
int stop_encoding = 0;
if (!ost->encoding_needed)
if (enc->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <= 1)
continue;
#if FF_API_LAVF_FMT_RAWPICTURE
- if (enc->codec_type == AVMEDIA_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE) && enc->codec->id == AV_CODEC_ID_RAWVIDEO)
+ if (enc->codec_type == AVMEDIA_TYPE_VIDEO && (of->ctx->oformat->flags & AVFMT_RAWPICTURE) && enc->codec->id == AV_CODEC_ID_RAWVIDEO)
continue;
#endif
}
av_packet_rescale_ts(&pkt, enc->time_base, ost->st->time_base);
pkt_size = pkt.size;
- output_packet(os, &pkt, ost);
+ output_packet(of, &pkt, ost);
if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) {
do_video_stats(ost, pkt_size);
}
}
#endif
- output_packet(of->ctx, &opkt, ost);
+ output_packet(of, &opkt, ost);
}
int guess_input_channel_layout(InputStream *ist)
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)) {
FilterGraph *fg = filtergraphs[i];
}
decoded_frame->pts = AV_NOPTS_VALUE;
+fail:
av_frame_unref(ist->filter_frame);
av_frame_unref(decoded_frame);
return err < 0 ? err : ret;
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) && ist->reinit_filters &&
configure_filtergraph(filtergraphs[i]) < 0) {
|| ost->enc->type != AVMEDIA_TYPE_SUBTITLE)
continue;
- do_subtitle_out(output_files[ost->file_index]->ctx, ost, ist, &subtitle);
+ do_subtitle_out(output_files[ost->file_index], ost, &subtitle);
}
out:
if (sdp_filename || want_sdp)
print_sdp();
+ /* flush the muxing queues */
+ for (i = 0; i < of->ctx->nb_streams; i++) {
+ OutputStream *ost = output_streams[of->ost_index + i];
+
+ while (av_fifo_size(ost->muxing_queue)) {
+ AVPacket pkt;
+ av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL);
+ write_packet(of, &pkt, ost);
+ }
+ }
+
return 0;
}
enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO) &&
filtergraph_is_simple(ost->filter->graph)) {
FilterGraph *fg = ost->filter->graph;
+
+ if (dec_ctx) {
+ ret = ifilter_parameters_from_decoder(fg->inputs[0],
+ dec_ctx);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_FATAL, "Error initializing filter input\n");
+ exit_program(1);
+ }
+ }
+
if (configure_filtergraph(fg)) {
av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
exit_program(1);
}
}
+ /* write headers for files with no streams */
+ for (i = 0; i < nb_output_files; i++) {
+ oc = output_files[i]->ctx;
+ if (oc->oformat->flags & AVFMT_NOSTREAMS && oc->nb_streams == 0) {
+ ret = check_init_output_file(output_files[i], i);
+ if (ret < 0)
+ goto dump_format;
+ }
+ }
+
dump_format:
/* dump the stream mapping */
av_log(NULL, AV_LOG_INFO, "Stream mapping:\n");
"+ increase verbosity\n"
"- decrease verbosity\n"
"c Send command to first matching filter supporting it\n"
- "C Send/Que command to all matching filters\n"
+ "C Send/Queue command to all matching filters\n"
"D cycle through available debug modes\n"
"h dump packets/hex press to cycle through the 3 states\n"
"q quit\n"