ffmpeg: optimize ffmpeg_postprocess #116309
|
@ -16,8 +16,11 @@
|
|||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
#include "BLI_threads.h"
|
||||
|
||||
/* Check if our ffmpeg is new enough, avoids user complaints.
|
||||
* Minimum supported version is currently 3.2.0 which mean the following library versions:
|
||||
* libavutil > 55.30
|
||||
|
@ -47,11 +50,6 @@
|
|||
# define FFMPEG_USE_OLD_CHANNEL_VARS
|
||||
#endif
|
||||
|
||||
/* Threaded sws_scale_frame was added in ffmpeg 5.0 (swscale version 6.1). */
|
||||
#if (LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(6, 1, 100))
|
||||
# define FFMPEG_SWSCALE_THREADING
|
||||
#endif
|
||||
|
||||
/* AV_CODEC_CAP_AUTO_THREADS was renamed to AV_CODEC_CAP_OTHER_THREADS with
|
||||
* upstream commit
|
||||
* github.com/FFmpeg/FFmpeg/commit/7d09579190def3ef7562399489e628f3b65714ce
|
||||
|
@ -141,6 +139,51 @@ int64_t av_get_frame_duration_in_pts_units(const AVFrame *picture)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Threaded sws_scale_frame was added in ffmpeg 5.0 (swscale version 6.1). */
|
||||
#if (LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(6, 1, 100))
|
||||
# define FFMPEG_SWSCALE_THREADING
|
||||
#endif
|
||||
|
||||
FFMPEG_INLINE SwsContext *sws_getContext_threaded(
|
||||
int width, int height, AVPixelFormat src_format, AVPixelFormat dst_format, int sws_flags)
|
||||
{
|
||||
#if defined(FFMPEG_SWSCALE_THREADING)
|
||||
/* sws_getContext does not allow passing flags that ask for multi-threaded
|
||||
* scaling context, so do it the hard way. */
|
||||
SwsContext *c = sws_alloc_context();
|
||||
if (c == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
av_opt_set_int(c, "srcw", width, 0);
|
||||
av_opt_set_int(c, "srch", height, 0);
|
||||
av_opt_set_int(c, "src_format", src_format, 0);
|
||||
av_opt_set_int(c, "dstw", width, 0);
|
||||
av_opt_set_int(c, "dsth", height, 0);
|
||||
av_opt_set_int(c, "dst_format", dst_format, 0);
|
||||
av_opt_set_int(c, "sws_flags", sws_flags, 0);
|
||||
av_opt_set_int(c, "threads", BLI_system_thread_count(), 0);
|
||||
|
||||
if (sws_init_context(c, nullptr, nullptr) < 0) {
|
||||
sws_freeContext(c);
|
||||
return nullptr;
|
||||
}
|
||||
#else
|
||||
SwsContext *c = sws_getContext(
|
||||
width, height, src_format, width, height, dst_format, sws_flags, nullptr, nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
FFMPEG_INLINE void sws_scale_frame_threaded(SwsContext *ctx, AVFrame *dst, const AVFrame *src)
|
||||
{
|
||||
#if defined(FFMPEG_SWSCALE_THREADING)
|
||||
sws_scale_frame(ctx, dst, src);
|
||||
#else
|
||||
sws_scale(ctx, src->data, src->linesize, 0, src->height, dst->data, dst->linesize);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Deinterlace code block
|
||||
*
|
||||
|
|
|
@ -420,17 +420,7 @@ static AVFrame *generate_video_frame(FFMpegContext *context, const uint8_t *pixe
|
|||
/* Convert to the output pixel format, if it's different that Blender's internal one. */
|
||||
if (context->img_convert_frame != nullptr) {
|
||||
BLI_assert(context->img_convert_ctx != NULL);
|
||||
# if defined(FFMPEG_SWSCALE_THREADING)
|
||||
sws_scale_frame(context->img_convert_ctx, context->current_frame, rgb_frame);
|
||||
# else
|
||||
sws_scale(context->img_convert_ctx,
|
||||
(const uint8_t *const *)rgb_frame->data,
|
||||
rgb_frame->linesize,
|
||||
0,
|
||||
codec->height,
|
||||
context->current_frame->data,
|
||||
context->current_frame->linesize);
|
||||
# endif
|
||||
sws_scale_frame_threaded(context->img_convert_ctx, context->current_frame, rgb_frame);
|
||||
}
|
||||
|
||||
return context->current_frame;
|
||||
|
@ -677,47 +667,6 @@ static const AVCodec *get_av1_encoder(
|
|||
return codec;
|
||||
}
|
||||
|
||||
static SwsContext *get_threaded_sws_context(int width,
|
||||
int height,
|
||||
AVPixelFormat src_format,
|
||||
AVPixelFormat dst_format)
|
||||
{
|
||||
# if defined(FFMPEG_SWSCALE_THREADING)
|
||||
/* sws_getContext does not allow passing flags that ask for multi-threaded
|
||||
* scaling context, so do it the hard way. */
|
||||
SwsContext *c = sws_alloc_context();
|
||||
if (c == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
av_opt_set_int(c, "srcw", width, 0);
|
||||
av_opt_set_int(c, "srch", height, 0);
|
||||
av_opt_set_int(c, "src_format", src_format, 0);
|
||||
av_opt_set_int(c, "dstw", width, 0);
|
||||
av_opt_set_int(c, "dsth", height, 0);
|
||||
av_opt_set_int(c, "dst_format", dst_format, 0);
|
||||
av_opt_set_int(c, "sws_flags", SWS_BICUBIC, 0);
|
||||
av_opt_set_int(c, "threads", BLI_system_thread_count(), 0);
|
||||
|
||||
if (sws_init_context(c, nullptr, nullptr) < 0) {
|
||||
sws_freeContext(c);
|
||||
return nullptr;
|
||||
}
|
||||
# else
|
||||
SwsContext *c = sws_getContext(width,
|
||||
height,
|
||||
src_format,
|
||||
width,
|
||||
height,
|
||||
dst_format,
|
||||
SWS_BICUBIC,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
# endif
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* prepare a video stream for the output file */
|
||||
|
||||
static AVStream *alloc_video_stream(FFMpegContext *context,
|
||||
|
@ -955,8 +904,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
|
|||
else {
|
||||
/* Output pixel format is different, allocate frame for conversion. */
|
||||
context->img_convert_frame = alloc_picture(AV_PIX_FMT_RGBA, c->width, c->height);
|
||||
context->img_convert_ctx = get_threaded_sws_context(
|
||||
c->width, c->height, AV_PIX_FMT_RGBA, c->pix_fmt);
|
||||
context->img_convert_ctx = sws_getContext_threaded(
|
||||
c->width, c->height, AV_PIX_FMT_RGBA, c->pix_fmt, SWS_BICUBIC);
|
||||
}
|
||||
|
||||
avcodec_parameters_from_context(st->codecpar, c);
|
||||
|
|
|
@ -694,16 +694,12 @@ static int startffmpeg(anim *anim)
|
|||
1);
|
||||
}
|
||||
|
||||
anim->img_convert_ctx = sws_getContext(anim->x,
|
||||
anim->y,
|
||||
anim->pCodecCtx->pix_fmt,
|
||||
anim->x,
|
||||
anim->y,
|
||||
AV_PIX_FMT_RGBA,
|
||||
SWS_BILINEAR | SWS_PRINT_INFO | SWS_FULL_CHR_H_INT,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
anim->img_convert_ctx = sws_getContext_threaded(anim->x,
|
||||
anim->y,
|
||||
anim->pCodecCtx->pix_fmt,
|
||||
AV_PIX_FMT_RGBA,
|
||||
SWS_BILINEAR | SWS_PRINT_INFO |
|
||||
SWS_FULL_CHR_H_INT);
|
||||
|
||||
if (!anim->img_convert_ctx) {
|
||||
fprintf(stderr, "Can't transform color space??? Bailing out...\n");
|
||||
|
@ -846,13 +842,7 @@ static void ffmpeg_postprocess(anim *anim, AVFrame *input, ImBuf *ibuf)
|
|||
}
|
||||
}
|
||||
|
||||
sws_scale(anim->img_convert_ctx,
|
||||
(const uint8_t *const *)input->data,
|
||||
input->linesize,
|
||||
0,
|
||||
anim->y,
|
||||
anim->pFrameRGB->data,
|
||||
anim->pFrameRGB->linesize);
|
||||
sws_scale_frame_threaded(anim->img_convert_ctx, anim->pFrameRGB, input);
|
||||
|
||||
/* Copy the valid bytes from the aligned buffer vertically flipped into ImBuf */
|
||||
int aligned_stride = anim->pFrameRGB->linesize[0];
|
||||
|
|
Loading…
Reference in New Issue