X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=avconv.c;h=d7ca8bdf8941e39a0f6125cf47aea2260907f06c;hb=b7165426917f91ebcad84bdff366824f03b32bfe;hp=e2cc4b0381249cb6df8b16446ca9bcb3f7a850ca;hpb=999328479305e317d9fdaeae791a60d299986073;p=ffmpeg diff --git a/avconv.c b/avconv.c index e2cc4b03812..d7ca8bdf894 100644 --- a/avconv.c +++ b/avconv.c @@ -168,9 +168,11 @@ typedef struct InputStream { AVFrame *filtered_frame; int64_t start; /* time when read started */ - int64_t next_pts; /* synthetic pts for cases where pkt.pts - is not defined */ - int64_t pts; /* current pts */ + /* predicted dts of the next packet read for this stream or (when there are + * several frames in a packet) of the next frame in current packet */ + int64_t next_dts; + /* dts of the last packet read for this stream */ + int64_t last_dts; PtsCorrectionContext pts_ctx; double ts_scale; int is_start; /* is 1 at the start and after a discontinuity */ @@ -204,6 +206,9 @@ typedef struct OutputStream { // double sync_ipts; /* dts from the AVPacket of the demuxer in second units */ struct InputStream *sync_ist; /* input stream to sync against */ int64_t sync_opts; /* output frame counter, could be changed to some true timestamp */ // FIXME look at frame_number + /* pts of the first frame encoded for this stream, used for limiting + * recording time */ + int64_t first_pts; AVBitStreamFilterContext *bitstream_filters; AVCodec *enc; int64_t max_frames; @@ -421,7 +426,7 @@ static int alloc_buffer(InputStream *ist, FrameBuffer **pbuf) { AVCodecContext *s = ist->st->codec; FrameBuffer *buf = av_mallocz(sizeof(*buf)); - int ret; + int i, ret; const int pixel_size = av_pix_fmt_descriptors[s->pix_fmt].comp[0].step_minus1+1; int h_chroma_shift, v_chroma_shift; int edge = 32; // XXX should be avcodec_get_edge_width(), but that fails on svq1 @@ -444,12 +449,12 @@ static int alloc_buffer(InputStream *ist, FrameBuffer **pbuf) /* XXX this shouldn't be needed, but some tests break without this line * those decoders are buggy and need to be fixed. * the following tests fail: - * bethsoft-vid, cdgraphics, ansi, aasc, fraps-v1, qtrle-1bit + * cdgraphics, ansi, aasc, fraps-v1, qtrle-1bit */ memset(buf->base[0], 128, ret); avcodec_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift); - for (int i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) { + for (i = 0; i < FF_ARRAY_ELEMS(buf->data); i++) { const int h_shift = i==0 ? 0 : h_chroma_shift; const int v_shift = i==0 ? 0 : v_chroma_shift; if (s->flags & CODEC_FLAG_EMU_EDGE) @@ -550,7 +555,7 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost) /** filter graph containing all filters including input & output */ AVCodecContext *codec = ost->st->codec; AVCodecContext *icodec = ist->st->codec; - FFSinkContext ffsink_ctx = { .pix_fmt = codec->pix_fmt }; + SinkContext sink_ctx = { .pix_fmt = codec->pix_fmt }; AVRational sample_aspect_ratio; char args[255]; int ret; @@ -570,8 +575,8 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost) "src", args, NULL, ost->graph); if (ret < 0) return ret; - ret = avfilter_graph_create_filter(&ost->output_video_filter, &ffsink, - "out", NULL, &ffsink_ctx, ost->graph); + ret = avfilter_graph_create_filter(&ost->output_video_filter, &sink, + "out", NULL, &sink_ctx, ost->graph); if (ret < 0) return ret; last_filter = ost->input_video_filter; @@ -862,11 +867,10 @@ static void choose_pixel_fmt(AVStream *st, AVCodec *codec) } static double -get_sync_ipts(const OutputStream *ost) +get_sync_ipts(const OutputStream *ost, int64_t pts) { - const InputStream *ist = ost->sync_ist; OutputFile *of = &output_files[ost->file_index]; - return (double)(ist->pts - of->start_time) / AV_TIME_BASE; + return (double)(pts - of->start_time) / AV_TIME_BASE; } static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) @@ -910,6 +914,7 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) bsfc = bsfc->next; } + pkt->stream_index = ost->index; ret = av_interleaved_write_frame(s, pkt); if (ret < 0) { print_error("av_interleaved_write_frame()", ret); @@ -917,6 +922,19 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) } } +static int check_recording_time(OutputStream *ost) +{ + OutputFile *of = &output_files[ost->file_index]; + + if (of->recording_time != INT64_MAX && + av_compare_ts(ost->sync_opts - ost->first_pts, ost->st->codec->time_base, of->recording_time, + AV_TIME_BASE_Q) >= 0) { + ost->is_past_recording_time = 1; + return 0; + } + return 1; +} + static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_t size) { int fill_char = 0x00; @@ -957,6 +975,11 @@ static int encode_audio_frame(AVFormatContext *s, OutputStream *ost, av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n"); exit_program(1); } + + if (!check_recording_time(ost)) + return 0; + + ost->sync_opts += frame->nb_samples; } got_packet = 0; @@ -966,9 +989,10 @@ static int encode_audio_frame(AVFormatContext *s, OutputStream *ost, } if (got_packet) { - pkt.stream_index = ost->index; if (pkt.pts != AV_NOPTS_VALUE) pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base); + if (pkt.dts != AV_NOPTS_VALUE) + pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base); if (pkt.duration > 0) pkt.duration = av_rescale_q(pkt.duration, enc->time_base, ost->st->time_base); @@ -977,9 +1001,6 @@ static int encode_audio_frame(AVFormatContext *s, OutputStream *ost, audio_size += pkt.size; } - if (frame) - ost->sync_opts += frame->nb_samples; - return pkt.size; } @@ -1075,7 +1096,7 @@ need_realloc: } if (audio_sync_method) { - double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts - + double delta = get_sync_ipts(ost, ist->last_dts) * enc->sample_rate - ost->sync_opts - av_fifo_size(ost->fifo) / (enc->channels * osize); int idelta = delta * dec->sample_rate / enc->sample_rate; int byte_delta = idelta * isize * dec->channels; @@ -1118,7 +1139,7 @@ need_realloc: } } } else - ost->sync_opts = lrintf(get_sync_ipts(ost) * enc->sample_rate) - + ost->sync_opts = lrintf(get_sync_ipts(ost, ist->last_dts) * enc->sample_rate) - av_fifo_size(ost->fifo) / (enc->channels * osize); // FIXME wrong if (ost->audio_resample) { @@ -1241,6 +1262,10 @@ static void do_subtitle_out(AVFormatContext *s, nb = 1; for (i = 0; i < nb; i++) { + ost->sync_opts = av_rescale_q(pts, ist->st->time_base, enc->time_base); + if (!check_recording_time(ost)) + return; + sub->pts = av_rescale_q(pts, ist->st->time_base, AV_TIME_BASE_Q); // start_display_time is required to be 0 sub->pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, AV_TIME_BASE_Q); @@ -1254,7 +1279,6 @@ static void do_subtitle_out(AVFormatContext *s, } av_init_packet(&pkt); - pkt.stream_index = ost->index; pkt.data = subtitle_out; pkt.size = subtitle_out_size; pkt.pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->st->time_base); @@ -1270,9 +1294,6 @@ static void do_subtitle_out(AVFormatContext *s, } } -static int bit_buffer_size = 1024 * 256; -static uint8_t *bit_buffer = NULL; - #if !CONFIG_AVFILTER static void do_video_resample(OutputStream *ost, InputStream *ist, @@ -1339,7 +1360,7 @@ static void do_video_out(AVFormatContext *s, enc = ost->st->codec; - sync_ipts = get_sync_ipts(ost) / av_q2d(enc->time_base); + sync_ipts = get_sync_ipts(ost, in_picture->pts) / av_q2d(enc->time_base); /* by default, we output a single frame */ nb_frames = 1; @@ -1363,7 +1384,6 @@ static void do_video_out(AVFormatContext *s, ost->sync_opts = lrintf(sync_ipts); } else if (vdelta > 1.1) nb_frames = lrintf(vdelta); -//fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, get_sync_ipts(ost), nb_frames); if (nb_frames == 0) { ++nb_frames_drop; av_log(NULL, AV_LOG_VERBOSE, "*** drop!\n"); @@ -1384,11 +1404,18 @@ static void do_video_out(AVFormatContext *s, final_picture = in_picture; #endif + if (!ost->frame_number) + ost->first_pts = ost->sync_opts; + /* duplicates frame if needed */ for (i = 0; i < nb_frames; i++) { AVPacket pkt; av_init_packet(&pkt); - pkt.stream_index = ost->index; + pkt.data = NULL; + pkt.size = 0; + + if (!check_recording_time(ost)) + return; if (s->oformat->flags & AVFMT_RAWPICTURE && enc->codec->id == CODEC_ID_RAWVIDEO) { @@ -1404,6 +1431,7 @@ static void do_video_out(AVFormatContext *s, write_frame(s, &pkt, ost); } else { + int got_packet; AVFrame big_picture; big_picture = *final_picture; @@ -1422,39 +1450,28 @@ static void do_video_out(AVFormatContext *s, big_picture.quality = quality; if (!enc->me_threshold) big_picture.pict_type = 0; -// big_picture.pts = AV_NOPTS_VALUE; big_picture.pts = ost->sync_opts; -// big_picture.pts= av_rescale(ost->sync_opts, AV_TIME_BASE*(int64_t)enc->time_base.num, enc->time_base.den); -// av_log(NULL, AV_LOG_DEBUG, "%"PRId64" -> encoder\n", ost->sync_opts); if (ost->forced_kf_index < ost->forced_kf_count && big_picture.pts >= ost->forced_kf_pts[ost->forced_kf_index]) { big_picture.pict_type = AV_PICTURE_TYPE_I; ost->forced_kf_index++; } - ret = avcodec_encode_video(enc, - bit_buffer, bit_buffer_size, - &big_picture); + ret = avcodec_encode_video2(enc, &pkt, &big_picture, &got_packet); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); exit_program(1); } - if (ret > 0) { - pkt.data = bit_buffer; - pkt.size = ret; - if (enc->coded_frame->pts != AV_NOPTS_VALUE) - pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base); -/*av_log(NULL, AV_LOG_DEBUG, "encoder -> %"PRId64"/%"PRId64"\n", - pkt.pts != AV_NOPTS_VALUE ? av_rescale(pkt.pts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1, - pkt.dts != AV_NOPTS_VALUE ? av_rescale(pkt.dts, enc->time_base.den, AV_TIME_BASE*(int64_t)enc->time_base.num) : -1);*/ - - if (enc->coded_frame->key_frame) - pkt.flags |= AV_PKT_FLAG_KEY; + if (got_packet) { + if (pkt.pts != AV_NOPTS_VALUE) + pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base); + if (pkt.dts != AV_NOPTS_VALUE) + pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base); + write_frame(s, &pkt, ost); *frame_size = ret; video_size += ret; - // fprintf(stderr,"\nFrame: %3d size: %5d type: %d", - // enc->frame_number-1, ret, enc->pict_type); + /* if two pass, output log */ if (ost->logfile && enc->stats_out) { fprintf(ost->logfile, "%s", enc->stats_out); @@ -1656,7 +1673,7 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams) for (;;) { AVPacket pkt; - int fifo_bytes; + int fifo_bytes, got_packet; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; @@ -1689,26 +1706,23 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams) } break; case AVMEDIA_TYPE_VIDEO: - ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL); + ret = avcodec_encode_video2(enc, &pkt, NULL, &got_packet); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); exit_program(1); } video_size += ret; - if (enc->coded_frame && enc->coded_frame->key_frame) - pkt.flags |= AV_PKT_FLAG_KEY; if (ost->logfile && enc->stats_out) { fprintf(ost->logfile, "%s", enc->stats_out); } - if (ret <= 0) { + if (!got_packet) { stop_encoding = 1; break; } - pkt.stream_index = ost->index; - pkt.data = bit_buffer; - pkt.size = ret; - if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE) - pkt.pts = av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base); + if (pkt.pts != AV_NOPTS_VALUE) + pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base); + if (pkt.dts != AV_NOPTS_VALUE) + pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base); write_frame(os, &pkt, ost); break; default: @@ -1731,15 +1745,8 @@ static int check_output_constraints(InputStream *ist, OutputStream *ost) 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; + if (of->start_time && ist->last_dts < of->start_time) return 0; - } return 1; } @@ -1756,6 +1763,12 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p !ost->copy_initial_nonkeyframes) return; + if (of->recording_time != INT64_MAX && + ist->last_dts >= of->recording_time + of->start_time) { + ost->is_past_recording_time = 1; + return; + } + /* force the input stream PTS */ if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) audio_size += pkt->size; @@ -1764,14 +1777,13 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p 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); + opkt.dts = av_rescale_q(ist->last_dts, 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; @@ -1783,6 +1795,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p 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 + && ost->st->codec->codec_id != CODEC_ID_VC1 ) { 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; @@ -1799,7 +1812,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p static void rate_emu_sleep(InputStream *ist) { if (input_files[ist->file_index].rate_emu) { - int64_t pts = av_rescale(ist->pts, 1000000, AV_TIME_BASE); + int64_t pts = av_rescale(ist->last_dts, 1000000, AV_TIME_BASE); int64_t now = av_gettime() - ist->start; if (pts > now) usleep(pts - now); @@ -1832,11 +1845,11 @@ static int transcode_audio(InputStream *ist, AVPacket *pkt, int *got_output) /* if the decoder provides a pts, use it instead of the last packet pts. the decoder could be delaying output by a packet or more. */ if (decoded_frame->pts != AV_NOPTS_VALUE) - ist->next_pts = decoded_frame->pts; + ist->next_dts = decoded_frame->pts; - /* increment next_pts to use for the case where the input stream does not + /* increment next_dts to use for the case where the input stream does not have timestamps or there are multiple frames in the packet */ - ist->next_pts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) / + ist->next_dts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) / avctx->sample_rate; // preprocess audio (volume) @@ -1926,7 +1939,7 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int avcodec_get_frame_defaults(ist->decoded_frame); decoded_frame = ist->decoded_frame; pkt->pts = *pkt_pts; - pkt->dts = ist->pts; + pkt->dts = ist->last_dts; *pkt_pts = AV_NOPTS_VALUE; ret = avcodec_decode_video2(ist->st->codec, @@ -1939,17 +1952,8 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int /* no picture yet */ return ret; } - ist->next_pts = ist->pts = guess_correct_pts(&ist->pts_ctx, decoded_frame->pkt_pts, - decoded_frame->pkt_dts); - if (pkt->duration) - ist->next_pts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q); - else if (ist->st->codec->time_base.num != 0) { - int ticks = ist->st->parser ? ist->st->parser->repeat_pict + 1 : - ist->st->codec->ticks_per_frame; - ist->next_pts += ((int64_t)AV_TIME_BASE * - ist->st->codec->time_base.num * ticks) / - ist->st->codec->time_base.den; - } + decoded_frame->pts = guess_correct_pts(&ist->pts_ctx, decoded_frame->pkt_pts, + decoded_frame->pkt_dts); pkt->size = 0; pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free); @@ -1995,7 +1999,6 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int ist->st->codec->pix_fmt); avfilter_copy_frame_props(fb, decoded_frame); - fb->pts = ist->pts; fb->buf->priv = buf; fb->buf->free = filter_release_buffer; @@ -2003,7 +2006,7 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int av_buffersrc_buffer(ost->input_video_filter, fb); } else av_vsrc_buffer_add_frame(ost->input_video_filter, decoded_frame, - ist->pts, decoded_frame->sample_aspect_ratio); + decoded_frame->pts, decoded_frame->sample_aspect_ratio); if (!ist->filtered_frame && !(ist->filtered_frame = avcodec_alloc_frame())) { av_free(buffer_to_free); @@ -2018,7 +2021,7 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int if (ost->output_video_filter) get_filtered_video_frame(ost->output_video_filter, filtered_frame, &ost->picref, &ist_pts_tb); if (ost->picref) - ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q); + filtered_frame->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q); if (ost->picref->video && !ost->frame_aspect_ratio) ost->st->codec->sample_aspect_ratio = ost->picref->video->pixel_aspect; #else @@ -2076,8 +2079,8 @@ static int output_packet(InputStream *ist, int64_t pkt_pts = AV_NOPTS_VALUE; AVPacket avpkt; - if (ist->next_pts == AV_NOPTS_VALUE) - ist->next_pts = ist->pts; + if (ist->next_dts == AV_NOPTS_VALUE) + ist->next_dts = ist->last_dts; if (pkt == NULL) { /* EOF handling */ @@ -2090,7 +2093,7 @@ static int output_packet(InputStream *ist, } if (pkt->dts != AV_NOPTS_VALUE) - ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); + ist->next_dts = ist->last_dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); if (pkt->pts != AV_NOPTS_VALUE) pkt_pts = av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q); @@ -2099,7 +2102,7 @@ static int output_packet(InputStream *ist, int ret = 0; handle_eof: - ist->pts = ist->next_pts; + ist->last_dts = ist->next_dts; if (avpkt.size && avpkt.size != pkt->size) { av_log(NULL, ist->showed_multi_packet_warning ? AV_LOG_VERBOSE : AV_LOG_WARNING, @@ -2113,6 +2116,17 @@ static int output_packet(InputStream *ist, break; case AVMEDIA_TYPE_VIDEO: ret = transcode_video (ist, &avpkt, &got_output, &pkt_pts); + if (avpkt.duration) + ist->next_dts += av_rescale_q(avpkt.duration, ist->st->time_base, AV_TIME_BASE_Q); + else if (ist->st->r_frame_rate.num) + ist->next_dts += av_rescale_q(1, (AVRational){ist->st->r_frame_rate.den, + ist->st->r_frame_rate.num}, + AV_TIME_BASE_Q); + else if (ist->st->codec->time_base.num != 0) { + int ticks = ist->st->parser ? ist->st->parser->repeat_pict + 1 : + ist->st->codec->ticks_per_frame; + ist->next_dts += av_rescale_q(ticks, ist->st->codec->time_base, AV_TIME_BASE_Q); + } break; case AVMEDIA_TYPE_SUBTITLE: ret = transcode_subtitles(ist, &avpkt, &got_output); @@ -2136,16 +2150,16 @@ static int output_packet(InputStream *ist, /* handle stream copy */ if (!ist->decoding_needed) { rate_emu_sleep(ist); - ist->pts = ist->next_pts; + ist->last_dts = ist->next_dts; switch (ist->st->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: - ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) / + ist->next_dts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) / ist->st->codec->sample_rate; break; case AVMEDIA_TYPE_VIDEO: if (ist->st->codec->time_base.num != 0) { int ticks = ist->st->parser ? ist->st->parser->repeat_pict + 1 : ist->st->codec->ticks_per_frame; - ist->next_pts += ((int64_t)AV_TIME_BASE * + ist->next_dts += ((int64_t)AV_TIME_BASE * ist->st->codec->time_base.num * ticks) / ist->st->codec->time_base.den; } @@ -2210,6 +2224,8 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb ist->st->codec->opaque = ist; } + if (!av_dict_get(ist->opts, "threads", NULL, 0)) + av_dict_set(&ist->opts, "threads", "auto", 0); if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) { snprintf(error, error_len, "Error while opening decoder for input stream #%d:%d", ist->file_index, ist->st->index); @@ -2219,8 +2235,8 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb assert_avoptions(ist->opts); } - ist->pts = ist->st->avg_frame_rate.num ? - ist->st->codec->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; - ist->next_pts = AV_NOPTS_VALUE; + ist->last_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->next_dts = AV_NOPTS_VALUE; init_pts_correction(&ist->pts_ctx); ist->is_start = 1; @@ -2444,6 +2460,7 @@ static int transcode_init(OutputFile *output_files, #endif break; case AVMEDIA_TYPE_SUBTITLE: + codec->time_base = (AVRational){1, 1000}; break; default: abort(); @@ -2477,18 +2494,6 @@ static int transcode_init(OutputFile *output_files, } } } - if (codec->codec_type == AVMEDIA_TYPE_VIDEO) { - int size = codec->width * codec->height; - bit_buffer_size = FFMAX(bit_buffer_size, 6 * size + 200); - } - } - - if (!bit_buffer) - bit_buffer = av_malloc(bit_buffer_size); - if (!bit_buffer) { - av_log(NULL, AV_LOG_ERROR, "Cannot allocate %d bytes output buffer\n", - bit_buffer_size); - return AVERROR(ENOMEM); } /* open each encoder */ @@ -2512,6 +2517,8 @@ static int transcode_init(OutputFile *output_files, memcpy(ost->st->codec->subtitle_header, dec->subtitle_header, dec->subtitle_header_size); ost->st->codec->subtitle_header_size = dec->subtitle_header_size; } + if (!av_dict_get(ost->opts, "threads", NULL, 0)) + av_dict_set(&ost->opts, "threads", "auto", 0); if (avcodec_open2(ost->st->codec, codec, &ost->opts) < 0) { snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d:%d - maybe incorrect parameters such as bit_rate, rate, width or height", ost->file_index, ost->index); @@ -2666,7 +2673,7 @@ static int transcode(OutputFile *output_files, (os->pb && avio_tell(os->pb) >= of->limit_filesize)) continue; opts = ost->st->pts.val * av_q2d(ost->st->time_base); - ipts = ist->pts; + ipts = ist->last_dts; if (!input_files[ist->file_index].eof_reached) { if (ipts < ipts_min) { ipts_min = ipts; @@ -2739,14 +2746,14 @@ static int transcode(OutputFile *output_files, pkt.dts *= ist->ts_scale; //fprintf(stderr, "next:%"PRId64" dts:%"PRId64" off:%"PRId64" %d\n", - // ist->next_pts, + // ist->next_dts, // pkt.dts, input_files[ist->file_index].ts_offset, // ist->st->codec->codec_type); - if (pkt.dts != AV_NOPTS_VALUE && ist->next_pts != AV_NOPTS_VALUE + if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && (is->iformat->flags & AVFMT_TS_DISCONT)) { int64_t pkt_dts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); - int64_t delta = pkt_dts - ist->next_pts; - if ((FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE || pkt_dts + 1 < ist->pts) && !copy_ts) { + int64_t delta = pkt_dts - ist->next_dts; + if ((FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE || pkt_dts + 1 < ist->last_dts) && !copy_ts) { input_files[ist->file_index].ts_offset -= delta; av_log(NULL, AV_LOG_DEBUG, "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", @@ -2819,7 +2826,6 @@ static int transcode(OutputFile *output_files, ret = 0; fail: - av_freep(&bit_buffer); av_freep(&no_packet); if (output_streams) { @@ -3950,6 +3956,8 @@ static void opt_output_file(void *optctx, const char *filename) output_files[nb_output_files - 1].ctx = oc; output_files[nb_output_files - 1].ost_index = nb_output_streams - oc->nb_streams; output_files[nb_output_files - 1].recording_time = o->recording_time; + if (o->recording_time != INT64_MAX) + oc->duration = o->recording_time; output_files[nb_output_files - 1].start_time = o->start_time; output_files[nb_output_files - 1].limit_filesize = o->limit_filesize; av_dict_copy(&output_files[nb_output_files - 1].opts, format_opts, 0); @@ -4367,6 +4375,13 @@ static int opt_vsync(const char *opt, const char *arg) return 0; } +static int opt_deinterlace(const char *opt, const char *arg) +{ + av_log(NULL, AV_LOG_WARNING, "-%s is deprecated, use -filter:v yadif instead\n", opt); + do_deinterlace = 1; + return 0; +} + #define OFFSET(x) offsetof(OptionsContext, x) static const OptionDef options[] = { /* main options */ @@ -4431,8 +4446,8 @@ static const OptionDef options[] = { "use same quantizer as source (implies VBR)" }, { "pass", HAS_ARG | OPT_VIDEO, {(void*)opt_pass}, "select the pass number (1 or 2)", "n" }, { "passlogfile", HAS_ARG | OPT_STRING | OPT_VIDEO, {(void*)&pass_logfilename_prefix}, "select two pass log file name prefix", "prefix" }, - { "deinterlace", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_deinterlace}, - "deinterlace pictures" }, + { "deinterlace", OPT_EXPERT | OPT_VIDEO, {(void*)opt_deinterlace}, + "this option is deprecated, use the yadif filter instead" }, { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" }, { "vstats_file", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_vstats_file}, "dump video coding statistics to file", "file" }, #if CONFIG_AVFILTER