From 7204ec1a88ab286023cf9e1e096dac983c198a37 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 21 Nov 2011 13:48:45 +0100 Subject: [PATCH] avconv: split off streamcopy handling into a separate loop. This is easier to understand and is less likely to break horribly when a stream is to be both decoded and copied. --- avconv.c | 162 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 90 insertions(+), 72 deletions(-) diff --git a/avconv.c b/avconv.c index c962b2bb33..0537e8cdc2 100644 --- a/avconv.c +++ b/avconv.c @@ -1528,6 +1528,83 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams) } } +/* + * Check whether a packet from ist should be written into ost at this time + */ +static int check_output_constraints(InputStream *ist, OutputStream *ost) +{ + OutputFile *of = &output_files[ost->file_index]; + int ist_index = ist - input_streams; + + if (ost->source_index != ist_index) + return 0; + + if (of->start_time && ist->pts < of->start_time) + return 0; + + if (of->recording_time != INT64_MAX && + av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time, + (AVRational){1, 1000000}) >= 0) { + ost->is_past_recording_time = 1; + return 0; + } + + return 1; +} + +static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt) +{ + OutputFile *of = &output_files[ost->file_index]; + int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); + AVPacket opkt; + + av_init_packet(&opkt); + + if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && + !ost->copy_initial_nonkeyframes) + return; + + /* force the input stream PTS */ + if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) + audio_size += pkt->size; + else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + video_size += pkt->size; + ost->sync_opts++; + } + + opkt.stream_index = ost->index; + if (pkt->pts != AV_NOPTS_VALUE) + opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time; + else + opkt.pts = AV_NOPTS_VALUE; + + if (pkt->dts == AV_NOPTS_VALUE) + opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base); + else + opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base); + opkt.dts -= ost_tb_start_time; + + opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base); + opkt.flags = pkt->flags; + + //FIXME remove the following 2 lines they shall be replaced by the bitstream filters + if( ost->st->codec->codec_id != CODEC_ID_H264 + && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO + && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO + ) { + if (av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, pkt->data, pkt->size, pkt->flags & AV_PKT_FLAG_KEY)) + opkt.destruct = av_destruct_packet; + } else { + opkt.data = pkt->data; + opkt.size = pkt->size; + } + + write_frame(of->ctx, &opkt, ost->st->codec, ost->bitstream_filters); + ost->st->codec->frame_number++; + ost->frame_number++; + av_free_packet(&opkt); +} + /* pkt = NULL means EOF (needed to flush decoder buffers) */ static int output_packet(InputStream *ist, int ist_index, OutputStream *ost_table, int nb_ostreams, @@ -1569,8 +1646,8 @@ static int output_packet(InputStream *ist, int ist_index, //while we have more to decode or while the decoder did output something on EOF while (avpkt.size > 0 || (!pkt && got_output)) { - uint8_t *data_buf, *decoded_data_buf; - int data_size, decoded_data_size; + uint8_t *decoded_data_buf; + int decoded_data_size; AVFrame *decoded_frame, *filtered_frame; handle_eof: ist->pts= ist->next_pts; @@ -1584,8 +1661,6 @@ static int output_packet(InputStream *ist, int ist_index, decoded_frame = filtered_frame = NULL; decoded_data_buf = NULL; /* fail safe */ decoded_data_size= 0; - data_buf = avpkt.data; - data_size = avpkt.size; subtitle_to_free = NULL; if (ist->decoding_needed) { switch(ist->st->codec->codec_type) { @@ -1604,7 +1679,6 @@ static int output_packet(InputStream *ist, int ist_index, return ret; avpkt.data += ret; avpkt.size -= ret; - data_size = ret; got_output = decoded_data_size > 0; /* Some bug in mpeg audio decoder gives */ /* decoded_data_size < 0, it seems they are overflows */ @@ -1745,23 +1819,13 @@ static int output_packet(InputStream *ist, int ist_index, /* if output time reached then transcode raw format, encode packets and output them */ for (i = 0; i < nb_ostreams; i++) { - OutputFile *of = &output_files[ost_table[i].file_index]; int frame_size; ost = &ost_table[i]; - if (ost->source_index != ist_index) - continue; - if (of->start_time && ist->pts < of->start_time) + if (!check_output_constraints(ist, ost) || !ost->encoding_needed) continue; - if (of->recording_time != INT64_MAX && - av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time, - (AVRational){1, 1000000}) >= 0) { - ost->is_past_recording_time = 1; - continue; - } - #if CONFIG_AVFILTER if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->input_video_filter) { @@ -1815,64 +1879,8 @@ static int output_packet(InputStream *ist, int ist_index, default: abort(); } - } else { - AVPacket opkt; - int64_t ost_tb_start_time= av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); - - av_init_packet(&opkt); - - if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && - !ost->copy_initial_nonkeyframes) -#if !CONFIG_AVFILTER - continue; -#else - goto cont; -#endif - - /* no reencoding needed : output the packet directly */ - /* force the input stream PTS */ - - if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) - audio_size += data_size; - else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - video_size += data_size; - ost->sync_opts++; - } - - opkt.stream_index= ost->index; - if(pkt->pts != AV_NOPTS_VALUE) - opkt.pts= av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time; - else - opkt.pts= AV_NOPTS_VALUE; - - if (pkt->dts == AV_NOPTS_VALUE) - opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base); - else - opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base); - opkt.dts -= ost_tb_start_time; - - opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base); - opkt.flags= pkt->flags; - - //FIXME remove the following 2 lines they shall be replaced by the bitstream filters - if( ost->st->codec->codec_id != CODEC_ID_H264 - && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO - && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO - ) { - if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & AV_PKT_FLAG_KEY)) - opkt.destruct= av_destruct_packet; - } else { - opkt.data = data_buf; - opkt.size = data_size; - } - - write_frame(os, &opkt, ost->st->codec, ost->bitstream_filters); - ost->st->codec->frame_number++; - ost->frame_number++; - av_free_packet(&opkt); } #if CONFIG_AVFILTER - cont: frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]); if (ost->picref) @@ -1895,6 +1903,16 @@ fail: } discard_packet: + /* handle stream copy */ + for (i = 0; pkt && i < nb_ostreams; i++) { + ost = &ost_table[i]; + + if (!check_output_constraints(ist, ost) || ost->encoding_needed) + continue; + + do_streamcopy(ist, ost, pkt); + } + return 0; }