Cleanup: Video: change bMovieHandle function to take ImBuf as input

Towards #118493: make movie writing functionality take ImBuf instead
of int* to pixel data.

While at it, make other bMovieHandle functions use "bool" return type
when it is strictly a success/failure result.

Pull Request: https://projects.blender.org/blender/blender/pulls/118559
This commit is contained in:
Aras Pranckevicius 2024-02-21 12:57:36 +01:00 committed by Aras Pranckevicius
parent eac8c381a0
commit e76b848697
5 changed files with 86 additions and 90 deletions

View File

@ -41,24 +41,24 @@ struct ReportList;
struct Scene; struct Scene;
struct SwsContext; struct SwsContext;
int BKE_ffmpeg_start(void *context_v, struct ImBuf;
const Scene *scene,
RenderData *rd, bool BKE_ffmpeg_start(void *context_v,
int rectx, const Scene *scene,
int recty,
ReportList *reports,
bool preview,
const char *suffix);
void BKE_ffmpeg_end(void *context_v);
int BKE_ffmpeg_append(void *context_v,
RenderData *rd, RenderData *rd,
int start_frame,
int frame,
int *pixels,
int rectx, int rectx,
int recty, int recty,
const char *suffix, ReportList *reports,
ReportList *reports); bool preview,
const char *suffix);
void BKE_ffmpeg_end(void *context_v);
bool BKE_ffmpeg_append(void *context_v,
RenderData *rd,
int start_frame,
int frame,
const ImBuf *image,
const char *suffix,
ReportList *reports);
void BKE_ffmpeg_filepath_get(char filepath[/*FILE_MAX*/ 1024], void BKE_ffmpeg_filepath_get(char filepath[/*FILE_MAX*/ 1024],
const RenderData *rd, const RenderData *rd,
bool preview, bool preview,

View File

@ -10,28 +10,27 @@
/* generic blender movie support, could move to own module */ /* generic blender movie support, could move to own module */
struct ImBuf;
struct RenderData; struct RenderData;
struct ReportList; struct ReportList;
struct Scene; struct Scene;
struct bMovieHandle { struct bMovieHandle {
int (*start_movie)(void *context_v, bool (*start_movie)(void *context_v,
const Scene *scene, const Scene *scene,
RenderData *rd,
int rectx,
int recty,
ReportList *reports,
bool preview,
const char *suffix);
int (*append_movie)(void *context_v,
RenderData *rd, RenderData *rd,
int start_frame,
int frame,
int *pixels,
int rectx, int rectx,
int recty, int recty,
const char *suffix, ReportList *reports,
ReportList *reports); bool preview,
const char *suffix);
bool (*append_movie)(void *context_v,
RenderData *rd,
int start_frame,
int frame,
const ImBuf *image,
const char *suffix,
ReportList *reports);
void (*end_movie)(void *context_v); void (*end_movie)(void *context_v);
/* Optional function. */ /* Optional function. */

View File

@ -338,7 +338,7 @@ static const char **get_file_extensions(int format)
} }
/* Write a frame to the output file */ /* Write a frame to the output file */
static int write_video_frame(FFMpegContext *context, AVFrame *frame, ReportList *reports) static bool write_video_frame(FFMpegContext *context, AVFrame *frame, ReportList *reports)
{ {
int ret, success = 1; int ret, success = 1;
AVPacket *packet = av_packet_alloc(); AVPacket *packet = av_packet_alloc();
@ -394,8 +394,14 @@ static int write_video_frame(FFMpegContext *context, AVFrame *frame, ReportList
} }
/* read and encode a frame of video from the buffer */ /* read and encode a frame of video from the buffer */
static AVFrame *generate_video_frame(FFMpegContext *context, const uint8_t *pixels) static AVFrame *generate_video_frame(FFMpegContext *context, const ImBuf *image)
{ {
/* For now only 8-bit/channel images are supported. */
const uint8_t *pixels = image->byte_buffer.data;
if (pixels == nullptr) {
return nullptr;
}
AVCodecParameters *codec = context->video_stream->codecpar; AVCodecParameters *codec = context->video_stream->codecpar;
int height = codec->height; int height = codec->height;
AVFrame *rgb_frame; AVFrame *rgb_frame;
@ -1273,12 +1279,12 @@ static void ffmpeg_add_metadata_callback(void *data,
av_dict_set(metadata, propname, propvalue, 0); av_dict_set(metadata, propname, propvalue, 0);
} }
static int start_ffmpeg_impl(FFMpegContext *context, static bool start_ffmpeg_impl(FFMpegContext *context,
RenderData *rd, RenderData *rd,
int rectx, int rectx,
int recty, int recty,
const char *suffix, const char *suffix,
ReportList *reports) ReportList *reports)
{ {
/* Handle to the output file */ /* Handle to the output file */
AVFormatContext *of; AVFormatContext *of;
@ -1324,19 +1330,19 @@ static int start_ffmpeg_impl(FFMpegContext *context,
exts = get_file_extensions(context->ffmpeg_type); exts = get_file_extensions(context->ffmpeg_type);
if (!exts) { if (!exts) {
BKE_report(reports, RPT_ERROR, "No valid formats found"); BKE_report(reports, RPT_ERROR, "No valid formats found");
return 0; return false;
} }
fmt = av_guess_format(nullptr, exts[0], nullptr); fmt = av_guess_format(nullptr, exts[0], nullptr);
if (!fmt) { if (!fmt) {
BKE_report(reports, RPT_ERROR, "No valid formats found"); BKE_report(reports, RPT_ERROR, "No valid formats found");
return 0; return false;
} }
of = avformat_alloc_context(); of = avformat_alloc_context();
if (!of) { if (!of) {
BKE_report(reports, RPT_ERROR, "Can't allocate FFmpeg format context"); BKE_report(reports, RPT_ERROR, "Can't allocate FFmpeg format context");
return 0; return false;
} }
enum AVCodecID audio_codec = context->ffmpeg_audio_codec; enum AVCodecID audio_codec = context->ffmpeg_audio_codec;
@ -1469,7 +1475,7 @@ static int start_ffmpeg_impl(FFMpegContext *context,
context->outfile = of; context->outfile = of;
av_dump_format(of, 0, filepath, 1); av_dump_format(of, 0, filepath, 1);
return 1; return true;
fail: fail:
if (of->pb) { if (of->pb) {
@ -1485,7 +1491,7 @@ fail:
} }
avformat_free_context(of); avformat_free_context(of);
return 0; return false;
} }
/** /**
@ -1626,23 +1632,22 @@ void BKE_ffmpeg_filepath_get(char filepath[/*FILE_MAX*/ 1024],
ffmpeg_filepath_get(nullptr, filepath, rd, preview, suffix); ffmpeg_filepath_get(nullptr, filepath, rd, preview, suffix);
} }
int BKE_ffmpeg_start(void *context_v, bool BKE_ffmpeg_start(void *context_v,
const Scene *scene, const Scene *scene,
RenderData *rd, RenderData *rd,
int rectx, int rectx,
int recty, int recty,
ReportList *reports, ReportList *reports,
bool preview, bool preview,
const char *suffix) const char *suffix)
{ {
int success;
FFMpegContext *context = static_cast<FFMpegContext *>(context_v); FFMpegContext *context = static_cast<FFMpegContext *>(context_v);
context->ffmpeg_autosplit_count = 0; context->ffmpeg_autosplit_count = 0;
context->ffmpeg_preview = preview; context->ffmpeg_preview = preview;
context->stamp_data = BKE_stamp_info_from_scene_static(scene); context->stamp_data = BKE_stamp_info_from_scene_static(scene);
success = start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports); bool success = start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports);
# ifdef WITH_AUDASPACE # ifdef WITH_AUDASPACE
if (context->audio_stream) { if (context->audio_stream) {
AVCodecContext *c = context->audio_codec; AVCodecContext *c = context->audio_codec;
@ -1699,24 +1704,22 @@ static void write_audio_frames(FFMpegContext *context, double to_pts)
} }
# endif # endif
int BKE_ffmpeg_append(void *context_v, bool BKE_ffmpeg_append(void *context_v,
RenderData *rd, RenderData *rd,
int start_frame, int start_frame,
int frame, int frame,
int *pixels, const ImBuf *image,
int rectx, const char *suffix,
int recty, ReportList *reports)
const char *suffix,
ReportList *reports)
{ {
FFMpegContext *context = static_cast<FFMpegContext *>(context_v); FFMpegContext *context = static_cast<FFMpegContext *>(context_v);
AVFrame *avframe; AVFrame *avframe;
int success = 1; bool success = true;
PRINT("Writing frame %i, render width=%d, render height=%d\n", frame, rectx, recty); PRINT("Writing frame %i, render width=%d, render height=%d\n", frame, image->x, image->y);
if (context->video_stream) { if (context->video_stream) {
avframe = generate_video_frame(context, (uchar *)pixels); avframe = generate_video_frame(context, image);
success = (avframe && write_video_frame(context, avframe, reports)); success = (avframe && write_video_frame(context, avframe, reports));
# ifdef WITH_AUDASPACE # ifdef WITH_AUDASPACE
/* Add +1 frame because we want to encode audio up until the next video frame. */ /* Add +1 frame because we want to encode audio up until the next video frame. */
@ -1731,7 +1734,7 @@ int BKE_ffmpeg_append(void *context_v,
end_ffmpeg_impl(context, true); end_ffmpeg_impl(context, true);
context->ffmpeg_autosplit_count++; context->ffmpeg_autosplit_count++;
success &= start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports); success &= start_ffmpeg_impl(context, rd, image->x, image->y, suffix, reports);
} }
} }
} }

View File

@ -23,31 +23,29 @@
#include "BKE_writemovie.hh" #include "BKE_writemovie.hh"
static int start_stub(void * /*context_v*/, static bool start_stub(void * /*context_v*/,
const Scene * /*scene*/, const Scene * /*scene*/,
RenderData * /*rd*/, RenderData * /*rd*/,
int /*rectx*/, int /*rectx*/,
int /*recty*/, int /*recty*/,
ReportList * /*reports*/, ReportList * /*reports*/,
bool /*preview*/, bool /*preview*/,
const char * /*suffix*/) const char * /*suffix*/)
{ {
return 0; return false;
} }
static void end_stub(void * /*context_v*/) {} static void end_stub(void * /*context_v*/) {}
static int append_stub(void * /*context_v*/, static bool append_stub(void * /*context_v*/,
RenderData * /*rd*/, RenderData * /*rd*/,
int /*start_frame*/, int /*start_frame*/,
int /*frame*/, int /*frame*/,
int * /*pixels*/, const ImBuf * /*image*/,
int /*rectx*/, const char * /*suffix*/,
int /*recty*/, ReportList * /*reports*/)
const char * /*suffix*/,
ReportList * /*reports*/)
{ {
return 0; return false;
} }
static void *context_create_stub() static void *context_create_stub()

View File

@ -2092,9 +2092,7 @@ bool RE_WriteRenderViewsMovie(ReportList *reports,
rd, rd,
preview ? scene->r.psfra : scene->r.sfra, preview ? scene->r.psfra : scene->r.sfra,
scene->r.cfra, scene->r.cfra,
(int *)ibuf->byte_buffer.data, ibuf,
ibuf->x,
ibuf->y,
suffix, suffix,
reports)) reports))
{ {
@ -2126,9 +2124,7 @@ bool RE_WriteRenderViewsMovie(ReportList *reports,
rd, rd,
preview ? scene->r.psfra : scene->r.sfra, preview ? scene->r.psfra : scene->r.sfra,
scene->r.cfra, scene->r.cfra,
(int *)ibuf_arr[2]->byte_buffer.data, ibuf_arr[2],
ibuf_arr[2]->x,
ibuf_arr[2]->y,
"", "",
reports)) reports))
{ {