From: Timo Rothenpieler <timo@rothenpieler.org> To: ffmpeg-devel@ffmpeg.org Cc: Timo Rothenpieler <timo@rothenpieler.org> Subject: [FFmpeg-devel] [PATCH v2 6/8] avdevice/lavfi: output wrapped AVFrames Date: Sat, 9 Jul 2022 00:54:02 +0200 Message-ID: <20220708225404.23748-7-timo@rothenpieler.org> (raw) In-Reply-To: <20220708225404.23748-1-timo@rothenpieler.org> This avoids an extra copy of potentially quite big video frames. Instead of copying the entire frames data into a rawvideo packet it packs the frame into a wrapped avframe packet and passes it through as-is. Unfortunately, wrapped avframes are set up to be video frames, so the audio frames continue to be copied. Additionally, this enabled passing through video frames that previously were impossible to process, like hardware frames or other special formats that couldn't be packed into a rawvideo packet. --- libavdevice/lavfi.c | 89 +++++++++-------------- libavdevice/version.h | 2 +- tests/ref/fate/filter-metadata-cropdetect | 3 +- 3 files changed, 38 insertions(+), 56 deletions(-) diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index db5d0b94de..1b282a70cb 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -54,32 +54,10 @@ typedef struct { int *sink_eof; int *stream_sink_map; int *sink_stream_subcc_map; - AVFrame *decoded_frame; int nb_sinks; AVPacket subcc_packet; } LavfiContext; -static int *create_all_formats(int n) -{ - int i, j, *fmts, count = 0; - - for (i = 0; i < n; i++) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i); - if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) - count++; - } - - if (!(fmts = av_malloc_array(count + 1, sizeof(*fmts)))) - return NULL; - for (j = 0, i = 0; i < n; i++) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i); - if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) - fmts[j++] = i; - } - fmts[j] = AV_PIX_FMT_NONE; - return fmts; -} - av_cold static int lavfi_read_close(AVFormatContext *avctx) { LavfiContext *lavfi = avctx->priv_data; @@ -90,7 +68,6 @@ av_cold static int lavfi_read_close(AVFormatContext *avctx) av_freep(&lavfi->sink_stream_subcc_map); av_freep(&lavfi->sinks); avfilter_graph_free(&lavfi->graph); - av_frame_free(&lavfi->decoded_frame); return 0; } @@ -125,15 +102,11 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) LavfiContext *lavfi = avctx->priv_data; AVFilterInOut *input_links = NULL, *output_links = NULL, *inout; const AVFilter *buffersink, *abuffersink; - int *pix_fmts = create_all_formats(AV_PIX_FMT_NB); enum AVMediaType type; int ret = 0, i, n; #define FAIL(ERR) { ret = ERR; goto end; } - if (!pix_fmts) - FAIL(AVERROR(ENOMEM)); - buffersink = avfilter_get_by_name("buffersink"); abuffersink = avfilter_get_by_name("abuffersink"); @@ -264,8 +237,6 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) ret = avfilter_graph_create_filter(&sink, buffersink, inout->name, NULL, NULL, lavfi->graph); - if (ret >= 0) - ret = av_opt_set_int_list(sink, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN); if (ret < 0) goto end; } else if (type == AVMEDIA_TYPE_AUDIO) { @@ -321,15 +292,12 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) avpriv_set_pts_info(st, 64, time_base.num, time_base.den); par->codec_type = av_buffersink_get_type(sink); if (par->codec_type == AVMEDIA_TYPE_VIDEO) { - int64_t probesize; - par->codec_id = AV_CODEC_ID_RAWVIDEO; + par->codec_id = AV_CODEC_ID_WRAPPED_AVFRAME; par->format = av_buffersink_get_format(sink); par->width = av_buffersink_get_w(sink); par->height = av_buffersink_get_h(sink); - probesize = par->width * par->height * 30 * - av_get_padded_bits_per_pixel(av_pix_fmt_desc_get(par->format)); - avctx->probesize = FFMAX(avctx->probesize, probesize); - st ->sample_aspect_ratio = + avctx->probesize = FFMAX(avctx->probesize, sizeof(AVFrame) * 30); + st ->sample_aspect_ratio = par->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(sink); } else if (par->codec_type == AVMEDIA_TYPE_AUDIO) { par->sample_rate = av_buffersink_get_sample_rate(sink); @@ -348,11 +316,7 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) if ((ret = create_subcc_streams(avctx)) < 0) goto end; - if (!(lavfi->decoded_frame = av_frame_alloc())) - FAIL(AVERROR(ENOMEM)); - end: - av_free(pix_fmts); avfilter_inout_free(&input_links); avfilter_inout_free(&output_links); return ret; @@ -378,15 +342,20 @@ static int create_subcc_packet(AVFormatContext *avctx, AVFrame *frame, return 0; } +static void lavfi_free_frame(void *opaque, uint8_t *data) +{ + AVFrame *frame = (AVFrame*)data; + av_frame_free(&frame); +} + static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt) { LavfiContext *lavfi = avctx->priv_data; double min_pts = DBL_MAX; int stream_idx, min_pts_sink_idx = 0; - AVFrame *frame = lavfi->decoded_frame; + AVFrame *frame; AVDictionary *frame_metadata; int ret, i; - int size = 0; AVStream *st; if (lavfi->subcc_packet.size) { @@ -394,12 +363,15 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt) return pkt->size; } + frame = av_frame_alloc(); + if (!frame) + return AVERROR(ENOMEM); + /* iterate through all the graph sinks. Select the sink with the * minimum PTS */ for (i = 0; i < lavfi->nb_sinks; i++) { AVRational tb = av_buffersink_get_time_base(lavfi->sinks[i]); double d; - int ret; if (lavfi->sink_eof[i]) continue; @@ -411,7 +383,7 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt) lavfi->sink_eof[i] = 1; continue; } else if (ret < 0) - return ret; + goto fail; d = av_rescale_q_rnd(frame->pts, tb, AV_TIME_BASE_Q, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); ff_dlog(avctx, "sink_idx:%d time:%f\n", i, d); av_frame_unref(frame); @@ -421,8 +393,10 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt) min_pts_sink_idx = i; } } - if (min_pts == DBL_MAX) - return AVERROR_EOF; + if (min_pts == DBL_MAX) { + ret = AVERROR_EOF; + goto fail; + } ff_dlog(avctx, "min_pts_sink_idx:%i\n", min_pts_sink_idx); @@ -431,15 +405,19 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt) st = avctx->streams[stream_idx]; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - size = av_image_get_buffer_size(frame->format, frame->width, frame->height, 1); - if ((ret = av_new_packet(pkt, size)) < 0) + pkt->buf = av_buffer_create((uint8_t*)frame, sizeof(*frame), + &lavfi_free_frame, NULL, 0); + if (!pkt->buf) { + ret = AVERROR(ENOMEM); goto fail; + } - av_image_copy_to_buffer(pkt->data, size, (const uint8_t **)frame->data, frame->linesize, - frame->format, frame->width, frame->height, 1); + pkt->data = pkt->buf->data; + pkt->size = pkt->buf->size; + pkt->flags |= AV_PKT_FLAG_TRUSTED; } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - size = frame->nb_samples * av_get_bytes_per_sample(frame->format) * - frame->ch_layout.nb_channels; + int size = frame->nb_samples * av_get_bytes_per_sample(frame->format) * + frame->ch_layout.nb_channels; if ((ret = av_new_packet(pkt, size)) < 0) goto fail; memcpy(pkt->data, frame->data[0], size); @@ -468,10 +446,13 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt) pkt->stream_index = stream_idx; pkt->pts = frame->pts; pkt->pos = frame->pkt_pos; - av_frame_unref(frame); - return size; + + if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) + av_frame_free(&frame); + + return pkt->size; fail: - av_frame_unref(frame); + av_frame_free(&frame); return ret; } diff --git a/libavdevice/version.h b/libavdevice/version.h index 09c1d778dc..5462173f17 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -30,7 +30,7 @@ #include "version_major.h" #define LIBAVDEVICE_VERSION_MINOR 6 -#define LIBAVDEVICE_VERSION_MICRO 100 +#define LIBAVDEVICE_VERSION_MICRO 101 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ LIBAVDEVICE_VERSION_MINOR, \ diff --git a/tests/ref/fate/filter-metadata-cropdetect b/tests/ref/fate/filter-metadata-cropdetect index e7c03ead4e..104acdd77f 100644 --- a/tests/ref/fate/filter-metadata-cropdetect +++ b/tests/ref/fate/filter-metadata-cropdetect @@ -1,4 +1,5 @@ -pts=0 +pts=0| + pts=400 pts=800|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68 pts=1200|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68 -- 2.34.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2022-07-08 22:55 UTC|newest] Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-07-08 22:53 [FFmpeg-devel] [PATCH v2 0/8] ddagrab source filter, lavfi.c wrapped_avframe and dependent changes Timo Rothenpieler 2022-07-08 22:53 ` [FFmpeg-devel] [PATCH v2 1/8] fftools/ffmpeg: make debug_ts print raw filter output Timo Rothenpieler 2022-07-08 22:53 ` [FFmpeg-devel] [PATCH v2 2/8] avutil/hwcontext_d3d11va: fix mixed declaration and code Timo Rothenpieler 2022-07-08 22:53 ` [FFmpeg-devel] [PATCH v2 3/8] avutil/hwcontext_d3d11va: fix texture_infos writes on non-fixed-size pools Timo Rothenpieler 2022-07-08 22:54 ` [FFmpeg-devel] [PATCH v2 4/8] avutil/hwcontext_d3d11va: update hwctx flags from input texture Timo Rothenpieler 2022-07-08 22:54 ` [FFmpeg-devel] [PATCH v2 5/8] avutil/hwcontext_d3d11va: add BGRA/RGBA10 formats support Timo Rothenpieler 2022-07-08 22:54 ` Timo Rothenpieler [this message] 2022-07-08 22:54 ` [FFmpeg-devel] [PATCH v2 7/8] avdevice/lavfi: pass forward video framerate Timo Rothenpieler 2022-07-08 22:54 ` [FFmpeg-devel] [PATCH v2 8/8] avfilter: add vsrc_ddagrab Timo Rothenpieler 2022-07-09 5:01 ` Gyan Doshi 2022-07-09 11:21 ` Timo Rothenpieler 2022-07-08 23:46 ` [FFmpeg-devel] [PATCH v2 0/8] ddagrab source filter, lavfi.c wrapped_avframe and dependent changes Soft Works 2022-07-08 23:48 ` Soft Works 2022-07-08 23:49 ` Timo Rothenpieler 2022-07-09 0:01 ` Soft Works 2022-07-09 0:15 ` Timo Rothenpieler 2022-07-09 0:28 ` Soft Works 2022-07-09 0:57 ` Timo Rothenpieler 2022-07-14 13:51 ` Timo Rothenpieler 2022-07-14 13:56 ` Gyan Doshi 2022-07-14 13:59 ` Timo Rothenpieler 2022-07-17 11:37 ` Timo Rothenpieler 2022-07-19 7:25 ` Mark Himsley 2022-07-19 11:34 ` Timo Rothenpieler 2022-07-19 12:20 ` Timo Rothenpieler 2022-07-20 8:21 ` Mark Himsley 2022-07-20 20:24 ` Timo Rothenpieler 2022-07-19 15:21 ` Mark Himsley
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220708225404.23748-7-timo@rothenpieler.org \ --to=timo@rothenpieler.org \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git