From patchwork Fri Mar 5 16:33:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 26136 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 277CC44B9E2 for ; Fri, 5 Mar 2021 18:36:30 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 0CB0668ADE9; Fri, 5 Mar 2021 18:36:30 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qk1-f180.google.com (mail-qk1-f180.google.com [209.85.222.180]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3AABC68ADF3 for ; Fri, 5 Mar 2021 18:36:28 +0200 (EET) Received: by mail-qk1-f180.google.com with SMTP id f124so2553598qkj.5 for ; Fri, 05 Mar 2021 08:36:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=+AHwJpr6FbFgJtXe62HQRvcHPD6Xj4T70GCn8PkdFRw=; b=BvYnRC6a3w9PLGa9adtsVxoUrzm5LomYBS7d4VCC6Jt2Efp34xfIwq7spwzXJ/M9VG iKJEp7wOrL8rnmWK6jNX+PO7nSOkuK7yPG82HBDfWN50DKpVwCG5nhrcFFpk9fbV7M4b OuMRh0hOhCdyOnDi9x7lFRmUrigK3rryU8adqy9f1c5BnsuNDpQjzw4ToW/SOWlRsYVQ kELF/3StSEDPDoDaVuBJy2I09LI8IXHrBmc59RcVCfKKzTwS89snUEAUu37v/R6SQyC/ IjCbwPp9YUvFVVkD4clhV/M4ieQxZWPgMWLzBVZYZumNYr7VqAvLfGs/cG0elP6+EUYL 25qg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+AHwJpr6FbFgJtXe62HQRvcHPD6Xj4T70GCn8PkdFRw=; b=XmJTY2J+S/u78xXm4qFUmY5EXWax523p5XzQek7mKWJ0KRjSqE0GHB/Mr3LoAoL5Cj X2cI2lpO/1kuk1czqFKAlx5TzmqvzsZDm4je/G1WI/9YBkqKJjUydITlxmUF0o3zbm3k xmSRk/uUlkVDScEuk3pXvnB+uXzGrV0NoIBwsDfoLIwEiehaJhRIL3SzVI9LrO+JWGJp rXqPJHoNJ1wr6sJi/qe3jFEIdDlJh7tExc8JszO9LhYYuKKm2lk4BIf7dAraDu+eSjTr 1tRAW774NFUFltlohSdd7rF8WJAu4Ioq55XdnYjl5O4iHikBPOiFg80Jxprf0nwhVolG gAFg== X-Gm-Message-State: AOAM532MJqv8K4CIfCRKhS47znlfny2egRnoazAwWKq+WjZNVzS7BHAo kPDDMRToz68BPw0MYFE5Vu6Sb0fxWE8+RA== X-Google-Smtp-Source: ABdhPJzZp6oHww0Et9L00LWP3wslgzd3q8q9X4YMxKCRgejo9dKI7SavfNioXq4erd8xd3sNX/+ftQ== X-Received: by 2002:a05:620a:7ec:: with SMTP id k12mr10059240qkk.185.1614962186215; Fri, 05 Mar 2021 08:36:26 -0800 (PST) Received: from localhost.localdomain ([181.23.89.132]) by smtp.gmail.com with ESMTPSA id b10sm2168494qtt.23.2021.03.05.08.36.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Mar 2021 08:36:25 -0800 (PST) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Fri, 5 Mar 2021 13:33:39 -0300 Message-Id: <20210305163339.63164-49-jamrial@gmail.com> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210305163339.63164-1-jamrial@gmail.com> References: <20210305163339.63164-1-jamrial@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 48/48] fftools/ffmpeg: use av_packet_alloc() to allocate packets X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: James Almer --- fftools/ffmpeg.c | 318 +++++++++++++++++++++++-------------------- fftools/ffmpeg.h | 4 + fftools/ffmpeg_opt.c | 5 +- 3 files changed, 177 insertions(+), 150 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 2abbc0ff29..46bb014de8 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -592,6 +592,7 @@ static void ffmpeg_cleanup(int ret) av_frame_free(&ost->filtered_frame); av_frame_free(&ost->last_frame); + av_packet_free(&ost->pkt); av_dict_free(&ost->encoder_opts); av_freep(&ost->forced_keyframes); @@ -610,9 +611,9 @@ static void ffmpeg_cleanup(int ret) if (ost->muxing_queue) { while (av_fifo_size(ost->muxing_queue)) { - AVPacket pkt; + AVPacket *pkt; av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL); - av_packet_unref(&pkt); + av_packet_free(&pkt); } av_fifo_freep(&ost->muxing_queue); } @@ -624,6 +625,7 @@ static void ffmpeg_cleanup(int ret) #endif for (i = 0; i < nb_input_files; i++) { avformat_close_input(&input_files[i]->ctx); + av_packet_free(&input_files[i]->pkt); av_freep(&input_files[i]); } for (i = 0; i < nb_input_streams; i++) { @@ -631,6 +633,7 @@ static void ffmpeg_cleanup(int ret) av_frame_free(&ist->decoded_frame); av_frame_free(&ist->filter_frame); + av_packet_free(&ist->pkt); av_dict_free(&ist->decoder_opts); avsubtitle_free(&ist->prev_sub.subtitle); av_frame_free(&ist->sub2video.frame); @@ -746,7 +749,7 @@ static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int u } if (!of->header_written) { - AVPacket tmp_pkt = {0}; + AVPacket *tmp_pkt; /* the muxer is not initialized yet, buffer the packet */ if (!av_fifo_space(ost->muxing_queue)) { unsigned int are_we_over_size = @@ -769,8 +772,11 @@ static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int u ret = av_packet_make_refcounted(pkt); if (ret < 0) exit_program(1); - av_packet_move_ref(&tmp_pkt, pkt); - ost->muxing_queue_data_size += tmp_pkt.size; + tmp_pkt = av_packet_alloc(); + if (!tmp_pkt) + exit_program(1); + av_packet_move_ref(tmp_pkt, pkt); + ost->muxing_queue_data_size += tmp_pkt->size; av_fifo_generic_write(ost->muxing_queue, &tmp_pkt, sizeof(tmp_pkt), NULL); return; } @@ -999,13 +1005,9 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, AVFrame *frame) { AVCodecContext *enc = ost->enc_ctx; - AVPacket pkt; + AVPacket *pkt = ost->pkt; int ret; - av_init_packet(&pkt); - pkt.data = NULL; - pkt.size = 0; - adjust_frame_pts_to_encoder_tb(of, ost, frame); if (!check_recording_time(ost)) @@ -1017,7 +1019,6 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, ost->samples_encoded += frame->nb_samples; ost->frames_encoded++; - av_assert0(pkt.size || !pkt.data); update_benchmark(NULL); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder <- type:audio " @@ -1031,7 +1032,8 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, goto error; while (1) { - ret = avcodec_receive_packet(enc, &pkt); + av_packet_unref(pkt); + ret = avcodec_receive_packet(enc, pkt); if (ret == AVERROR(EAGAIN)) break; if (ret < 0) @@ -1039,16 +1041,16 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, update_benchmark("encode_audio %d.%d", ost->file_index, ost->index); - av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase); + av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:audio " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", - av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &enc->time_base), - av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &enc->time_base)); + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base)); } - output_packet(of, &pkt, ost, 0); + output_packet(of, pkt, ost, 0); } return; @@ -1064,7 +1066,7 @@ static void do_subtitle_out(OutputFile *of, int subtitle_out_max_size = 1024 * 1024; int subtitle_out_size, nb, i; AVCodecContext *enc; - AVPacket pkt; + AVPacket *pkt = ost->pkt; int64_t pts; if (sub->pts == AV_NOPTS_VALUE) { @@ -1122,21 +1124,21 @@ static void do_subtitle_out(OutputFile *of, exit_program(1); } - av_init_packet(&pkt); - pkt.data = subtitle_out; - pkt.size = subtitle_out_size; - pkt.pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->mux_timebase); - pkt.duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); + av_packet_unref(pkt); + pkt->data = subtitle_out; + pkt->size = subtitle_out_size; + pkt->pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->mux_timebase); + pkt->duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); if (enc->codec_id == AV_CODEC_ID_DVB_SUBTITLE) { /* XXX: the pts correction is handled here. Maybe handling it in the codec would be better */ if (i == 0) - pkt.pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); + pkt->pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); else - pkt.pts += av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); + pkt->pts += av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->mux_timebase); } - pkt.dts = pkt.pts; - output_packet(of, &pkt, ost, 0); + pkt->dts = pkt->pts; + output_packet(of, pkt, ost, 0); } } @@ -1145,7 +1147,7 @@ static void do_video_out(OutputFile *of, AVFrame *next_picture) { int ret, format_video_sync; - AVPacket pkt; + AVPacket *pkt = ost->pkt; AVCodecContext *enc = ost->enc_ctx; AVRational frame_rate; int nb_frames, nb0_frames, i; @@ -1291,9 +1293,6 @@ static void do_video_out(OutputFile *of, AVFrame *in_picture; int forced_keyframe = 0; double pts_time; - av_init_packet(&pkt); - pkt.data = NULL; - pkt.size = 0; if (i < nb0_frames && ost->last_frame) { in_picture = ost->last_frame; @@ -1372,7 +1371,8 @@ static void do_video_out(OutputFile *of, av_frame_remove_side_data(in_picture, AV_FRAME_DATA_A53_CC); while (1) { - ret = avcodec_receive_packet(enc, &pkt); + av_packet_unref(pkt); + ret = avcodec_receive_packet(enc, pkt); update_benchmark("encode_video %d.%d", ost->file_index, ost->index); if (ret == AVERROR(EAGAIN)) break; @@ -1382,24 +1382,24 @@ static void do_video_out(OutputFile *of, if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:video " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", - av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &enc->time_base), - av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &enc->time_base)); + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base)); } - if (pkt.pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & AV_CODEC_CAP_DELAY)) - pkt.pts = ost->sync_opts; + if (pkt->pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & AV_CODEC_CAP_DELAY)) + pkt->pts = ost->sync_opts; - av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase); + av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "encoder -> type:video " "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", - av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ost->mux_timebase), - av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->mux_timebase)); + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->mux_timebase), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->mux_timebase)); } - frame_size = pkt.size; - output_packet(of, &pkt, ost, 0); + frame_size = pkt->size; + output_packet(of, pkt, ost, 0); /* if two pass, output log */ if (ost->logfile && enc->stats_out) { @@ -1528,6 +1528,9 @@ static int reap_filters(int flush) if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_AUDIO) init_output_stream_wrapper(ost, NULL, 1); + if (!ost->pkt && !(ost->pkt = av_packet_alloc())) { + return AVERROR(ENOMEM); + } if (!ost->filtered_frame && !(ost->filtered_frame = av_frame_alloc())) { return AVERROR(ENOMEM); } @@ -1968,7 +1971,7 @@ static void flush_encoders(void) for (;;) { const char *desc = NULL; - AVPacket pkt; + AVPacket *pkt = ost->pkt; int pkt_size; switch (enc->codec_type) { @@ -1982,13 +1985,10 @@ static void flush_encoders(void) av_assert0(0); } - av_init_packet(&pkt); - pkt.data = NULL; - pkt.size = 0; - update_benchmark(NULL); - while ((ret = avcodec_receive_packet(enc, &pkt)) == AVERROR(EAGAIN)) { + av_packet_unref(pkt); + while ((ret = avcodec_receive_packet(enc, pkt)) == AVERROR(EAGAIN)) { ret = avcodec_send_frame(enc, NULL); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "%s encoding failed: %s\n", @@ -2009,16 +2009,16 @@ static void flush_encoders(void) fprintf(ost->logfile, "%s", enc->stats_out); } if (ret == AVERROR_EOF) { - output_packet(of, &pkt, ost, 1); + output_packet(of, pkt, ost, 1); break; } if (ost->finished & MUXER_FINISHED) { - av_packet_unref(&pkt); + av_packet_unref(pkt); continue; } - av_packet_rescale_ts(&pkt, enc->time_base, ost->mux_timebase); - pkt_size = pkt.size; - output_packet(of, &pkt, ost, 0); + av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); + pkt_size = pkt->size; + output_packet(of, pkt, ost, 0); if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) { do_video_stats(ost, pkt_size); } @@ -2052,14 +2052,12 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p InputFile *f = input_files [ist->file_index]; int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->mux_timebase); - AVPacket opkt; + AVPacket *opkt = ost->pkt; + av_packet_unref(opkt); // EOF: flush output bitstream filters. if (!pkt) { - av_init_packet(&opkt); - opkt.data = NULL; - opkt.size = 0; - output_packet(of, &opkt, ost, 1); + output_packet(of, opkt, ost, 1); return; } @@ -2097,30 +2095,30 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) ost->sync_opts++; - if (av_packet_ref(&opkt, pkt) < 0) + if (av_packet_ref(opkt, pkt) < 0) exit_program(1); if (pkt->pts != AV_NOPTS_VALUE) - opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->mux_timebase) - ost_tb_start_time; + opkt->pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->mux_timebase) - ost_tb_start_time; if (pkt->dts == AV_NOPTS_VALUE) { - opkt.dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->mux_timebase); + opkt->dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->mux_timebase); } else if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { int duration = av_get_audio_frame_duration(ist->dec_ctx, pkt->size); if(!duration) duration = ist->dec_ctx->frame_size; - opkt.dts = av_rescale_delta(ist->st->time_base, pkt->dts, + opkt->dts = av_rescale_delta(ist->st->time_base, pkt->dts, (AVRational){1, ist->dec_ctx->sample_rate}, duration, &ist->filter_in_rescale_delta_last, ost->mux_timebase); /* dts will be set immediately afterwards to what pts is now */ - opkt.pts = opkt.dts - ost_tb_start_time; + opkt->pts = opkt->dts - ost_tb_start_time; } else - opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->mux_timebase); - opkt.dts -= ost_tb_start_time; + opkt->dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->mux_timebase); + opkt->dts -= ost_tb_start_time; - opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); + opkt->duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); - output_packet(of, &opkt, ost, 0); + output_packet(of, opkt, ost, 0); } int guess_input_channel_layout(InputStream *ist) @@ -2395,7 +2393,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ int i, ret = 0, err = 0; int64_t best_effort_timestamp; int64_t dts = AV_NOPTS_VALUE; - AVPacket avpkt; // With fate-indeo3-2, we're getting 0-sized packets before EOF for some // reason. This seems like a semi-critical bug. Don't trigger EOF, and @@ -2411,8 +2408,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ if (ist->dts != AV_NOPTS_VALUE) dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base); if (pkt) { - avpkt = *pkt; - avpkt.dts = dts; // ffmpeg.c probably shouldn't do this + pkt->dts = dts; // ffmpeg.c probably shouldn't do this } // The old code used to set dts on the drain packet, which does not work @@ -2426,7 +2422,7 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ } update_benchmark(NULL); - ret = decode(ist->dec_ctx, decoded_frame, got_output, pkt ? &avpkt : NULL); + ret = decode(ist->dec_ctx, decoded_frame, got_output, pkt); update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index); if (ret < 0) *decode_failed = 1; @@ -2585,6 +2581,8 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output, for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; + if (!ost->pkt && !(ost->pkt = av_packet_alloc())) + exit_program(1); if (!check_output_constraints(ist, ost) || !ost->encoding_needed || ost->enc->type != AVMEDIA_TYPE_SUBTITLE) continue; @@ -2620,7 +2618,12 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo int repeating = 0; int eof_reached = 0; - AVPacket avpkt; + AVPacket *avpkt; + + if (!ist->pkt && !(ist->pkt = av_packet_alloc())) + return AVERROR(ENOMEM); + avpkt = ist->pkt; + if (!ist->saw_first_ts) { ist->dts = ist->st->avg_frame_rate.num ? - ist->dec_ctx->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0; ist->pts = 0; @@ -2636,13 +2639,11 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo if (ist->next_pts == AV_NOPTS_VALUE) ist->next_pts = ist->pts; - if (!pkt) { - /* EOF handling */ - av_init_packet(&avpkt); - avpkt.data = NULL; - avpkt.size = 0; - } else { - avpkt = *pkt; + if (pkt) { + av_packet_unref(avpkt); + ret = av_packet_ref(avpkt, pkt); + if (ret < 0) + return ret; } if (pkt && pkt->dts != AV_NOPTS_VALUE) { @@ -2663,11 +2664,12 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo switch (ist->dec_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: - ret = decode_audio (ist, repeating ? NULL : &avpkt, &got_output, + ret = decode_audio (ist, repeating ? NULL : avpkt, &got_output, &decode_failed); + av_packet_unref(avpkt); break; case AVMEDIA_TYPE_VIDEO: - ret = decode_video (ist, repeating ? NULL : &avpkt, &got_output, &duration_pts, !pkt, + ret = decode_video (ist, repeating ? NULL : avpkt, &got_output, &duration_pts, !pkt, &decode_failed); if (!repeating || !pkt || got_output) { if (pkt && pkt->duration) { @@ -2692,13 +2694,15 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo ist->next_pts += duration_dts; } } + av_packet_unref(avpkt); break; case AVMEDIA_TYPE_SUBTITLE: if (repeating) break; - ret = transcode_subtitles(ist, &avpkt, &got_output, &decode_failed); + ret = transcode_subtitles(ist, avpkt, &got_output, &decode_failed); if (!pkt && ret >= 0) ret = AVERROR_EOF; + av_packet_unref(avpkt); break; default: return -1; @@ -2787,6 +2791,8 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; + if (!ost->pkt && !(ost->pkt = av_packet_alloc())) + exit_program(1); if (!check_output_constraints(ist, ost) || ost->encoding_needed) continue; @@ -3054,10 +3060,11 @@ static int check_init_output_file(OutputFile *of, int file_index) ost->mux_timebase = ost->st->time_base; while (av_fifo_size(ost->muxing_queue)) { - AVPacket pkt; + AVPacket *pkt; av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL); - ost->muxing_queue_data_size -= pkt.size; - write_packet(of, &pkt, ost, 1); + ost->muxing_queue_data_size -= pkt->size; + write_packet(of, pkt, ost, 1); + av_packet_free(&pkt); } } @@ -4082,12 +4089,12 @@ static int check_keyboard_interaction(int64_t cur_time) static void *input_thread(void *arg) { InputFile *f = arg; + AVPacket *pkt = f->pkt, *queue_pkt; unsigned flags = f->non_blocking ? AV_THREAD_MESSAGE_NONBLOCK : 0; int ret = 0; while (1) { - AVPacket pkt; - ret = av_read_frame(f->ctx, &pkt); + ret = av_read_frame(f->ctx, pkt); if (ret == AVERROR(EAGAIN)) { av_usleep(10000); @@ -4097,10 +4104,17 @@ static void *input_thread(void *arg) av_thread_message_queue_set_err_recv(f->in_thread_queue, ret); break; } - ret = av_thread_message_queue_send(f->in_thread_queue, &pkt, flags); + queue_pkt = av_packet_alloc(); + if (!queue_pkt) { + av_packet_unref(pkt); + av_thread_message_queue_set_err_recv(f->in_thread_queue, AVERROR(ENOMEM)); + break; + } + av_packet_move_ref(queue_pkt, pkt); + ret = av_thread_message_queue_send(f->in_thread_queue, &queue_pkt, flags); if (flags && ret == AVERROR(EAGAIN)) { flags = 0; - ret = av_thread_message_queue_send(f->in_thread_queue, &pkt, flags); + ret = av_thread_message_queue_send(f->in_thread_queue, &queue_pkt, flags); av_log(f->ctx, AV_LOG_WARNING, "Thread message queue blocking; consider raising the " "thread_queue_size option (current value: %d)\n", @@ -4111,7 +4125,7 @@ static void *input_thread(void *arg) av_log(f->ctx, AV_LOG_ERROR, "Unable to send packet to main thread: %s\n", av_err2str(ret)); - av_packet_unref(&pkt); + av_packet_free(&queue_pkt); av_thread_message_queue_set_err_recv(f->in_thread_queue, ret); break; } @@ -4123,13 +4137,13 @@ static void *input_thread(void *arg) static void free_input_thread(int i) { InputFile *f = input_files[i]; - AVPacket pkt; + AVPacket *pkt; if (!f || !f->in_thread_queue) return; av_thread_message_queue_set_err_send(f->in_thread_queue, AVERROR_EOF); while (av_thread_message_queue_recv(f->in_thread_queue, &pkt, 0) >= 0) - av_packet_unref(&pkt); + av_packet_free(&pkt); pthread_join(f->thread, NULL); f->joined = 1; @@ -4158,7 +4172,7 @@ static int init_input_thread(int i) strcmp(f->ctx->iformat->name, "lavfi")) f->non_blocking = 1; ret = av_thread_message_queue_alloc(&f->in_thread_queue, - f->thread_queue_size, sizeof(AVPacket)); + f->thread_queue_size, sizeof(f->pkt)); if (ret < 0) return ret; @@ -4183,7 +4197,7 @@ static int init_input_threads(void) return 0; } -static int get_input_packet_mt(InputFile *f, AVPacket *pkt) +static int get_input_packet_mt(InputFile *f, AVPacket **pkt) { return av_thread_message_queue_recv(f->in_thread_queue, pkt, f->non_blocking ? @@ -4191,7 +4205,7 @@ static int get_input_packet_mt(InputFile *f, AVPacket *pkt) } #endif -static int get_input_packet(InputFile *f, AVPacket *pkt) +static int get_input_packet(InputFile *f, AVPacket **pkt) { if (f->rate_emu) { int i; @@ -4208,7 +4222,8 @@ static int get_input_packet(InputFile *f, AVPacket *pkt) if (f->thread_queue_size) return get_input_packet_mt(f, pkt); #endif - return av_read_frame(f->ctx, pkt); + *pkt = f->pkt; + return av_read_frame(f->ctx, *pkt); } static int got_eagain(void) @@ -4320,7 +4335,7 @@ static int process_input(int file_index) InputFile *ifile = input_files[file_index]; AVFormatContext *is; InputStream *ist; - AVPacket pkt; + AVPacket *pkt; int ret, thread_ret, i, j; int64_t duration; int64_t pkt_dts; @@ -4395,27 +4410,27 @@ static int process_input(int file_index) reset_eagain(); if (do_pkt_dump) { - av_pkt_dump_log2(NULL, AV_LOG_INFO, &pkt, do_hex_dump, - is->streams[pkt.stream_index]); + av_pkt_dump_log2(NULL, AV_LOG_INFO, pkt, do_hex_dump, + is->streams[pkt->stream_index]); } /* the following test is needed in case new streams appear dynamically in stream : we ignore them */ - if (pkt.stream_index >= ifile->nb_streams) { - report_new_stream(file_index, &pkt); + if (pkt->stream_index >= ifile->nb_streams) { + report_new_stream(file_index, pkt); goto discard_packet; } - ist = input_streams[ifile->ist_index + pkt.stream_index]; + ist = input_streams[ifile->ist_index + pkt->stream_index]; - ist->data_size += pkt.size; + ist->data_size += pkt->size; ist->nb_packets++; if (ist->discard) goto discard_packet; - if (pkt.flags & AV_PKT_FLAG_CORRUPT) { + if (pkt->flags & AV_PKT_FLAG_CORRUPT) { av_log(NULL, exit_on_error ? AV_LOG_FATAL : AV_LOG_WARNING, - "%s: corrupt input packet in stream %d\n", is->url, pkt.stream_index); + "%s: corrupt input packet in stream %d\n", is->url, pkt->stream_index); if (exit_on_error) exit_program(1); } @@ -4423,11 +4438,11 @@ static int process_input(int file_index) if (debug_ts) { av_log(NULL, AV_LOG_INFO, "demuxer -> ist_index:%d type:%s " "next_dts:%s next_dts_time:%s next_pts:%s next_pts_time:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n", - ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), + ifile->ist_index + pkt->stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), av_ts2str(ist->next_dts), av_ts2timestr(ist->next_dts, &AV_TIME_BASE_Q), av_ts2str(ist->next_pts), av_ts2timestr(ist->next_pts, &AV_TIME_BASE_Q), - av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base), - av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base), + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base), av_ts2str(input_files[ist->file_index]->ts_offset), av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q)); } @@ -4457,12 +4472,12 @@ static int process_input(int file_index) stime2= stime + (1ULL<st->pts_wrap_bits); ist->wrap_correction_done = 1; - if(stime2 > stime && pkt.dts != AV_NOPTS_VALUE && pkt.dts > stime + (1LL<<(ist->st->pts_wrap_bits-1))) { - pkt.dts -= 1ULL<st->pts_wrap_bits; + if(stime2 > stime && pkt->dts != AV_NOPTS_VALUE && pkt->dts > stime + (1LL<<(ist->st->pts_wrap_bits-1))) { + pkt->dts -= 1ULL<st->pts_wrap_bits; ist->wrap_correction_done = 0; } - if(stime2 > stime && pkt.pts != AV_NOPTS_VALUE && pkt.pts > stime + (1LL<<(ist->st->pts_wrap_bits-1))) { - pkt.pts -= 1ULL<st->pts_wrap_bits; + if(stime2 > stime && pkt->pts != AV_NOPTS_VALUE && pkt->pts > stime + (1LL<<(ist->st->pts_wrap_bits-1))) { + pkt->pts -= 1ULL<st->pts_wrap_bits; ist->wrap_correction_done = 0; } } @@ -4476,10 +4491,10 @@ static int process_input(int file_index) if (src_sd->type == AV_PKT_DATA_DISPLAYMATRIX) continue; - if (av_packet_get_side_data(&pkt, src_sd->type, NULL)) + if (av_packet_get_side_data(pkt, src_sd->type, NULL)) continue; - dst_data = av_packet_new_side_data(&pkt, src_sd->type, src_sd->size); + dst_data = av_packet_new_side_data(pkt, src_sd->type, src_sd->size); if (!dst_data) exit_program(1); @@ -4487,17 +4502,17 @@ static int process_input(int file_index) } } - if (pkt.dts != AV_NOPTS_VALUE) - pkt.dts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts *= ist->ts_scale; - if (pkt.dts != AV_NOPTS_VALUE) - pkt.dts *= ist->ts_scale; + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts *= ist->ts_scale; + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts *= ist->ts_scale; - pkt_dts = av_rescale_q_rnd(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); + pkt_dts = av_rescale_q_rnd(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); if ((ist->dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO || ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) && pkt_dts != AV_NOPTS_VALUE && ist->next_dts == AV_NOPTS_VALUE && !copy_ts @@ -4509,27 +4524,27 @@ static int process_input(int file_index) av_log(NULL, AV_LOG_DEBUG, "Inter stream timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", delta, ifile->ts_offset); - pkt.dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); } } duration = av_rescale_q(ifile->duration, ifile->time_base, ist->st->time_base); - if (pkt.pts != AV_NOPTS_VALUE) { - pkt.pts += duration; - ist->max_pts = FFMAX(pkt.pts, ist->max_pts); - ist->min_pts = FFMIN(pkt.pts, ist->min_pts); + if (pkt->pts != AV_NOPTS_VALUE) { + pkt->pts += duration; + ist->max_pts = FFMAX(pkt->pts, ist->max_pts); + ist->min_pts = FFMIN(pkt->pts, ist->min_pts); } - if (pkt.dts != AV_NOPTS_VALUE) - pkt.dts += duration; + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts += duration; - pkt_dts = av_rescale_q_rnd(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); + pkt_dts = av_rescale_q_rnd(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); if (copy_ts && pkt_dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && (is->iformat->flags & AVFMT_TS_DISCONT) && ist->st->pts_wrap_bits < 60) { - int64_t wrap_dts = av_rescale_q_rnd(pkt.dts + (1LL<st->pts_wrap_bits), + int64_t wrap_dts = av_rescale_q_rnd(pkt->dts + (1LL<st->pts_wrap_bits), ist->st->time_base, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); if (FFABS(wrap_dts - ist->next_dts) < FFABS(pkt_dts - ist->next_dts)/10) @@ -4552,46 +4567,51 @@ static int process_input(int file_index) ist->file_index, ist->st->index, ist->st->id, av_get_media_type_string(ist->dec_ctx->codec_type), delta, ifile->ts_offset); - pkt.dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); } } else { if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || delta > 1LL*dts_error_threshold*AV_TIME_BASE) { - av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt.dts, ist->next_dts, pkt.stream_index); - pkt.dts = AV_NOPTS_VALUE; + av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt->dts, ist->next_dts, pkt->stream_index); + pkt->dts = AV_NOPTS_VALUE; } - if (pkt.pts != AV_NOPTS_VALUE){ - int64_t pkt_pts = av_rescale_q(pkt.pts, ist->st->time_base, AV_TIME_BASE_Q); + if (pkt->pts != AV_NOPTS_VALUE){ + int64_t pkt_pts = av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q); delta = pkt_pts - ist->next_dts; if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || delta > 1LL*dts_error_threshold*AV_TIME_BASE) { - av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt.pts, ist->next_dts, pkt.stream_index); - pkt.pts = AV_NOPTS_VALUE; + av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt->pts, ist->next_dts, pkt->stream_index); + pkt->pts = AV_NOPTS_VALUE; } } } } - if (pkt.dts != AV_NOPTS_VALUE) - ifile->last_ts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); + if (pkt->dts != AV_NOPTS_VALUE) + ifile->last_ts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); if (debug_ts) { av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n", - ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), - av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base), - av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base), + ifile->ist_index + pkt->stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base), av_ts2str(input_files[ist->file_index]->ts_offset), av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q)); } - sub2video_heartbeat(ist, pkt.pts); + sub2video_heartbeat(ist, pkt->pts); - process_input_packet(ist, &pkt, 0); + process_input_packet(ist, pkt, 0); discard_packet: - av_packet_unref(&pkt); +#if HAVE_THREADS + if (ifile->thread_queue_size) + av_packet_free(&pkt); + else +#endif + av_packet_unref(pkt); return 0; } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 8813eaf2e3..606f2afe0c 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -310,6 +310,7 @@ typedef struct InputStream { const AVCodec *dec; AVFrame *decoded_frame; AVFrame *filter_frame; /* a ref of decoded_frame, to be sent to filters */ + AVPacket *pkt; int64_t start; /* time when read started */ /* predicted dts of the next packet read for this stream or (when there are @@ -418,6 +419,8 @@ typedef struct InputFile { int rate_emu; int accurate_seek; + AVPacket *pkt; + #if HAVE_THREADS AVThreadMessageQueue *in_thread_queue; pthread_t thread; /* thread reading from this file */ @@ -474,6 +477,7 @@ typedef struct OutputStream { int64_t max_frames; AVFrame *filtered_frame; AVFrame *last_frame; + AVPacket *pkt; int last_dropped; int last_nb0_frames[3]; diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 85feeb89f2..807e783422 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1280,6 +1280,9 @@ static int open_input_file(OptionsContext *o, const char *filename) f->loop = o->loop; f->duration = 0; f->time_base = (AVRational){ 1, 1 }; + f->pkt = av_packet_alloc(); + if (!f->pkt) + exit_program(1); #if HAVE_THREADS f->thread_queue_size = o->thread_queue_size; #endif @@ -1571,7 +1574,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->max_muxing_queue_size = 128; MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ost->max_muxing_queue_size, oc, st); - ost->max_muxing_queue_size *= sizeof(AVPacket); + ost->max_muxing_queue_size *= sizeof(ost->pkt); ost->muxing_queue_data_size = 0;