avfilter/lavfutils: Avoid copying frame in ff_load_image()

Return the data in an AVFrame instead. This is what several users
({find,cover}_rect*) want anyway. This also avoids accessing
AVFrame.format (an int) via an enum AVPixelFormat*.

*: This commit actually avoids two frame copies For find_rect:
av_frame_clone() contained an implicit alloc+copy.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt
2026-01-30 18:24:05 +01:00
parent 31173f148c
commit 2273902be8
6 changed files with 47 additions and 74 deletions
+13 -15
View File
@@ -404,33 +404,31 @@ static int init_axis_empty(ShowCQTContext *s)
static int init_axis_from_file(ShowCQTContext *s)
{
uint8_t *tmp_data[4] = { NULL };
int tmp_linesize[4];
enum AVPixelFormat tmp_format;
int tmp_w, tmp_h, ret;
if ((ret = ff_load_image(tmp_data, tmp_linesize, &tmp_w, &tmp_h, &tmp_format,
s->axisfile, s->ctx)) < 0)
goto error;
AVFrame *tmp_frame;
int ret = ff_load_image(&tmp_frame, s->axisfile, s->ctx);
if (ret < 0)
return ret;
ret = AVERROR(ENOMEM);
if (!(s->axis_frame = av_frame_alloc()))
goto error;
if ((ret = ff_scale_image(s->axis_frame->data, s->axis_frame->linesize, s->width, s->axis_h,
convert_axis_pixel_format(s->format), tmp_data, tmp_linesize, tmp_w, tmp_h,
tmp_format, s->ctx)) < 0)
ret = ff_scale_image(s->axis_frame->data, s->axis_frame->linesize, s->width, s->axis_h,
convert_axis_pixel_format(s->format),
tmp_frame->data, tmp_frame->linesize, tmp_frame->width, tmp_frame->height,
tmp_frame->format, s->ctx);
if (ret < 0) {
av_frame_free(&s->axis_frame);
goto error;
}
s->axis_frame->width = s->width;
s->axis_frame->height = s->axis_h;
s->axis_frame->format = convert_axis_pixel_format(s->format);
av_freep(tmp_data);
return 0;
ret = 0;
error:
av_frame_free(&s->axis_frame);
av_freep(tmp_data);
av_frame_free(&tmp_frame);
return ret;
}
+13 -23
View File
@@ -21,9 +21,8 @@
#include <stdint.h>
#include "libavutil/dict.h"
#include "libavutil/imgutils.h"
#include "libavutil/frame.h"
#include "libavutil/log.h"
#include "libavutil/pixfmt.h"
#include "libavformat/avformat.h"
@@ -31,8 +30,7 @@
#include "lavfutils.h"
int ff_load_image(uint8_t *data[4], int linesize[4],
int *w, int *h, enum AVPixelFormat *pix_fmt,
int ff_load_image(struct AVFrame **outframe,
const char *filename, void *log_ctx)
{
const AVInputFormat *iformat = NULL;
@@ -45,6 +43,8 @@ int ff_load_image(uint8_t *data[4], int linesize[4],
AVPacket pkt;
AVDictionary *opt=NULL;
*outframe = NULL;
iformat = av_find_input_format("image2pipe");
if ((ret = avformat_open_input(&format_ctx, filename, iformat, NULL)) < 0) {
av_log(log_ctx, AV_LOG_ERROR,
@@ -84,12 +84,6 @@ int ff_load_image(uint8_t *data[4], int linesize[4],
goto end;
}
if (!(frame = av_frame_alloc()) ) {
av_log(log_ctx, AV_LOG_ERROR, "Failed to alloc frame\n");
ret = AVERROR(ENOMEM);
goto end;
}
ret = av_read_frame(format_ctx, &pkt);
if (ret < 0) {
av_log(log_ctx, AV_LOG_ERROR, "Failed to read frame from file\n");
@@ -103,27 +97,23 @@ int ff_load_image(uint8_t *data[4], int linesize[4],
goto end;
}
ret = avcodec_receive_frame(codec_ctx, frame);
if (ret < 0) {
av_log(log_ctx, AV_LOG_ERROR, "Failed to decode image from file\n");
if (!(frame = av_frame_alloc()) ) {
av_log(log_ctx, AV_LOG_ERROR, "Failed to alloc frame\n");
ret = AVERROR(ENOMEM);
goto end;
}
*w = frame->width;
*h = frame->height;
*pix_fmt = frame->format;
if ((ret = av_image_alloc(data, linesize, *w, *h, *pix_fmt, 16)) < 0)
ret = avcodec_receive_frame(codec_ctx, frame);
if (ret < 0) {
av_frame_free(&frame);
av_log(log_ctx, AV_LOG_ERROR, "Failed to decode image from file\n");
goto end;
ret = 0;
av_image_copy2(data, linesize, frame->data, frame->linesize,
*pix_fmt, *w, *h);
}
*outframe = frame;
end:
avcodec_free_context(&codec_ctx);
avformat_close_input(&format_ctx);
av_frame_free(&frame);
av_dict_free(&opt);
if (ret < 0)
+5 -8
View File
@@ -24,21 +24,18 @@
#ifndef AVFILTER_LAVFUTILS_H
#define AVFILTER_LAVFUTILS_H
#include <stdint.h>
#include "libavutil/pixfmt.h"
struct AVFrame;
/**
* Load image from filename and put the resulting image in data.
* Load image from filename and put the resulting image in an AVFrame.
*
* @param w pointer to the width of the loaded image
* @param h pointer to the height of the loaded image
* @param pix_fmt pointer to the pixel format of the loaded image
* @param outframe pointer to a pointer to an AVFrame; *outframe will
* point to a new allocated AVFrame on success
* @param filename the name of the image file to load
* @param log_ctx log context
* @return >= 0 in case of success, a negative error code otherwise.
*/
int ff_load_image(uint8_t *data[4], int linesize[4],
int *w, int *h, enum AVPixelFormat *pix_fmt,
int ff_load_image(struct AVFrame **outframe,
const char *filename, void *log_ctx);
#endif /* AVFILTER_LAVFUTILS_H */
+2 -10
View File
@@ -22,7 +22,6 @@
* @todo switch to dualinput
*/
#include "libavutil/mem.h"
#include "libavutil/opt.h"
#include "filters.h"
#include "video.h"
@@ -189,8 +188,6 @@ static av_cold void uninit(AVFilterContext *ctx)
{
CoverContext *cover = ctx->priv;
if (cover->cover_frame)
av_freep(&cover->cover_frame->data[0]);
av_frame_free(&cover->cover_frame);
}
@@ -205,13 +202,8 @@ static av_cold int init(AVFilterContext *ctx)
return AVERROR(EINVAL);
}
cover->cover_frame = av_frame_alloc();
if (!cover->cover_frame)
return AVERROR(ENOMEM);
if ((ret = ff_load_image(cover->cover_frame->data, cover->cover_frame->linesize,
&cover->cover_frame->width, &cover->cover_frame->height,
&cover->cover_frame->format, cover->cover_filename, ctx)) < 0)
ret = ff_load_image(&cover->cover_frame, cover->cover_filename, ctx);
if (ret < 0)
return ret;
if (cover->cover_frame->format != AV_PIX_FMT_YUV420P && cover->cover_frame->format != AV_PIX_FMT_YUVJ420P) {
+2 -10
View File
@@ -22,7 +22,6 @@
* @todo switch to dualinput
*/
#include "libavutil/mem.h"
#include "libavutil/opt.h"
#include "filters.h"
@@ -250,8 +249,6 @@ static av_cold void uninit(AVFilterContext *ctx)
av_frame_free(&foc->haystack_frame[i]);
}
if (foc->obj_frame)
av_freep(&foc->obj_frame->data[0]);
av_frame_free(&foc->obj_frame);
}
@@ -265,13 +262,8 @@ static av_cold int init(AVFilterContext *ctx)
return AVERROR(EINVAL);
}
foc->obj_frame = av_frame_alloc();
if (!foc->obj_frame)
return AVERROR(ENOMEM);
if ((ret = ff_load_image(foc->obj_frame->data, foc->obj_frame->linesize,
&foc->obj_frame->width, &foc->obj_frame->height,
&foc->obj_frame->format, foc->obj_filename, ctx)) < 0)
ret = ff_load_image(&foc->obj_frame, foc->obj_filename, ctx);
if (ret < 0)
return ret;
if (foc->obj_frame->format != AV_PIX_FMT_GRAY8) {
+12 -8
View File
@@ -207,18 +207,22 @@ static int load_mask(uint8_t **mask, int *w, int *h,
const char *filename, void *log_ctx)
{
int ret;
enum AVPixelFormat pix_fmt;
uint8_t *src_data[4], *gray_data[4];
int src_linesize[4], gray_linesize[4];
uint8_t *gray_data[4];
AVFrame *src_frame;
int gray_linesize[4];
/* load image from file */
if ((ret = ff_load_image(src_data, src_linesize, w, h, &pix_fmt, filename, log_ctx)) < 0)
ret = ff_load_image(&src_frame, filename, log_ctx);
if (ret < 0)
return ret;
*w = src_frame->width;
*h = src_frame->height;
/* convert the image to GRAY8 */
if ((ret = ff_scale_image(gray_data, gray_linesize, *w, *h, AV_PIX_FMT_GRAY8,
src_data, src_linesize, *w, *h, pix_fmt,
log_ctx)) < 0)
ret = ff_scale_image(gray_data, gray_linesize, *w, *h, AV_PIX_FMT_GRAY8,
src_frame->data, src_frame->linesize, *w, *h,
src_frame->format, log_ctx);
if (ret < 0)
goto end;
/* copy mask to a newly allocated array */
@@ -230,8 +234,8 @@ static int load_mask(uint8_t **mask, int *w, int *h,
av_image_copy_plane(*mask, *w, gray_data[0], gray_linesize[0], *w, *h);
end:
av_freep(&src_data[0]);
av_freep(&gray_data[0]);
av_frame_free(&src_frame);
return ret;
}