record: the output and framebuffer sizes are words

struct record_params carries out_dims and fb_dims as VIDEO_SCALE_PACK
words; ffmpeg scales and evens the output size in locals and stores
the result as a word, and sizes its buffers with VIDEO_SCALE_AREA.
This commit is contained in:
LibretroAdmin authored and libretroadmin committed 2026-09-23 22:46:04 +02:00
1 parent 824a200baf
commit 8105343981
5 files changed
+49 -50

No files matched your search

+2 -2
View File
@@ -193,8 +193,8 @@ static void *avfoundation_record_init(const struct record_params *params)
{
unsigned scale = params->video_record_scale_factor > 0
? params->video_record_scale_factor : 1;
handle->width = params->out_width * scale;
handle->height = params->out_height * scale;
handle->width = VIDEO_SCALE_W(params->out_dims) * scale;
handle->height = VIDEO_SCALE_H(params->out_dims) * scale;
/* H.264 requires even dimensions */
handle->width = (handle->width + 1) & ~1;
handle->height = (handle->height + 1) & ~1;
+25 -23
View File
@@ -224,8 +224,8 @@ typedef struct ffmpeg
/* The three queues to the encoder thread. Single producer (the
* main thread in ffmpeg_push_video / ffmpeg_push_audio), single
* consumer (ffmpeg_thread), so lock-free retro_spsc rings: the
* push of a frame - up to MAX_FRAMES frames of fb_width x
* fb_height in video_fifo - and the encoder's read of one no
* push of a frame - up to MAX_FRAMES frames of fb_dims in
* video_fifo - and the encoder's read of one no
* longer exclude each other, where before both copied the whole
* frame under one lock. cond/cond_lock stay for the sleeps.
* After deinit_thread() has joined the encoder, the main thread
@@ -518,6 +518,7 @@ static bool ffmpeg_init_video(ffmpeg_t *handle)
struct ff_video_info *video = &handle->video;
struct record_params *param = &handle->params;
const AVCodec *codec = NULL;
unsigned out_w, out_h;
if (*params->vcodec)
codec = avcodec_find_encoder_by_name(params->vcodec);
@@ -599,8 +600,8 @@ static bool ffmpeg_init_video(ffmpeg_t *handle)
/* Useful to set scale_factor to 2 for chroma subsampled formats to
* maintain full chroma resolution. (Or just use 4:4:4 or RGB ...)
*/
param->out_width = (float)param->out_width * params->scale_factor;
param->out_height = (float)param->out_height * params->scale_factor;
out_w = (float)VIDEO_SCALE_W(param->out_dims) * params->scale_factor;
out_h = (float)VIDEO_SCALE_H(param->out_dims) * params->scale_factor;
/* Ensure even dimensions for chroma-subsampled pixel formats.
* Odd dimensions cause encoder init failure with e.g. libx264.
@@ -608,17 +609,18 @@ static bool ffmpeg_init_video(ffmpeg_t *handle)
if ( video->pix_fmt == AV_PIX_FMT_YUV420P
|| video->pix_fmt == AV_PIX_FMT_YUV422P)
{
param->out_width = (param->out_width + 1) & ~1;
param->out_height = (param->out_height + 1) & ~1;
out_w = (out_w + 1) & ~1;
out_h = (out_h + 1) & ~1;
}
param->out_dims = VIDEO_SCALE_PACK(out_w, out_h);
video->codec->codec_type = AVMEDIA_TYPE_VIDEO;
video->codec->width = param->out_width;
video->codec->height = param->out_height;
video->codec->width = out_w;
video->codec->height = out_h;
video->codec->time_base = av_d2q((double)
params->frame_drop_ratio /param->fps, 1000000); /* Arbitrary big number. */
video->codec->sample_aspect_ratio = av_d2q(
param->aspect_ratio * param->out_height / param->out_width, 255);
param->aspect_ratio * out_h / out_w, 255);
video->codec->pix_fmt = video->pix_fmt;
video->codec->thread_count = params->threads;
@@ -640,8 +642,7 @@ static bool ffmpeg_init_video(ffmpeg_t *handle)
video->frame_drop_ratio = params->frame_drop_ratio;
size = av_image_get_buffer_size(video->pix_fmt, param->out_width,
param->out_height, 1);
size = av_image_get_buffer_size(video->pix_fmt, out_w, out_h, 1);
video->conv_frame_buf = (uint8_t*)av_malloc(size);
/* NULL-check conv_frame_buf: the memset on the next line
* NULL-derefs on OOM, as does av_image_fill_arrays below
@@ -656,10 +657,10 @@ static bool ffmpeg_init_video(ffmpeg_t *handle)
frame = video->conv_frame;
av_image_fill_arrays(frame->data, frame->linesize, video->conv_frame_buf,
video->pix_fmt, param->out_width, param->out_height, 1);
video->pix_fmt, out_w, out_h, 1);
video->conv_frame->width = param->out_width;
video->conv_frame->height = param->out_height;
video->conv_frame->width = out_w;
video->conv_frame->height = out_h;
video->conv_frame->format = video->pix_fmt;
return true;
@@ -1048,7 +1049,8 @@ static bool init_thread(ffmpeg_t *handle)
retro_spsc_init(&handle->audio_fifo, 32000 * sizeof(int16_t) *
handle->params.channels * MAX_FRAMES / 60) /* Some arbitrary max size. */
&& retro_spsc_init(&handle->attr_fifo, sizeof(struct record_video_data) * MAX_FRAMES)
&& retro_spsc_init(&handle->video_fifo, handle->params.fb_width * handle->params.fb_height *
&& retro_spsc_init(&handle->video_fifo,
VIDEO_SCALE_AREA(handle->params.fb_dims) *
handle->video.pix_size * MAX_FRAMES);
if (!handle->fifos_init)
{
@@ -1415,10 +1417,10 @@ static void ffmpeg_scale_input(ffmpeg_t *handle,
unsigned src_h = VIDEO_SCALE_H(vid->dims);
/* When output was padded to even dimensions, clamp the scaling
* destination to the source size. */
unsigned dst_w = (src_w < handle->params.out_width)
? src_w : handle->params.out_width;
unsigned dst_h = (src_h < handle->params.out_height)
? src_h : handle->params.out_height;
unsigned out_w = VIDEO_SCALE_W(handle->params.out_dims);
unsigned out_h = VIDEO_SCALE_H(handle->params.out_dims);
unsigned dst_w = (src_w < out_w) ? src_w : out_w;
unsigned dst_h = (src_h < out_h) ? src_h : out_h;
/* Attempt to preserve more information if we scale down. */
bool shrunk = dst_w < src_w || dst_h < src_h;
@@ -1848,8 +1850,8 @@ static void ffmpeg_flush_buffers(ffmpeg_t *handle)
{
void *audio_buf = NULL;
bool did_work = false;
void *video_buf = av_malloc(2 * handle->params.fb_width *
handle->params.fb_height * handle->video.pix_size);
void *video_buf = av_malloc(2 *
VIDEO_SCALE_AREA(handle->params.fb_dims) * handle->video.pix_size);
size_t audio_buf_size = handle->config.audio_enable ?
(handle->audio.codec->frame_size *
handle->params.channels * sizeof(int16_t)) : 0;
@@ -1939,8 +1941,8 @@ static void ffmpeg_thread(void *data)
ffmpeg_t *ff = (ffmpeg_t*)data;
/* For some reason, FFmpeg has a tendency to crash
* if we don't overallocate a bit. */
void *video_buf = av_malloc(2 * ff->params.fb_width *
ff->params.fb_height * ff->video.pix_size);
void *video_buf = av_malloc(2 *
VIDEO_SCALE_AREA(ff->params.fb_dims) * ff->video.pix_size);
size_t audio_buf_size = ff->config.audio_enable ?
(ff->audio.codec->frame_size * ff->params.channels * sizeof(int16_t)) : 0;
void *audio_buf = audio_buf_size ? av_malloc(audio_buf_size) : NULL;
+16 -17
View File
@@ -301,10 +301,10 @@ bool recording_init(void)
params.video_record_threads = settings->uints.video_record_threads;
params.streaming_mode = settings->uints.streaming_mode;
params.out_width = av_info->geometry.base_width;
params.out_height = av_info->geometry.base_height;
params.fb_width = av_info->geometry.max_width;
params.fb_height = av_info->geometry.max_height;
params.out_dims = VIDEO_SCALE_PACK(
av_info->geometry.base_width, av_info->geometry.base_height);
params.fb_dims = VIDEO_SCALE_PACK(
av_info->geometry.max_width, av_info->geometry.max_height);
/* A core delivering a wider layout than stereo through the
* multi-channel batch entry is recorded in it, where the container
* has a default layout for the count - quad, 5.1 with the pair at
@@ -373,10 +373,10 @@ bool recording_init(void)
return false;
}
params.out_width = VIDEO_SCALE_W(vp.dims);
params.out_height = VIDEO_SCALE_H(vp.dims);
params.fb_width = next_pow2(VIDEO_SCALE_W(vp.dims));
params.fb_height = next_pow2(VIDEO_SCALE_H(vp.dims));
params.out_dims = vp.dims;
params.fb_dims = VIDEO_SCALE_PACK(
next_pow2(VIDEO_SCALE_W(vp.dims)),
next_pow2(VIDEO_SCALE_H(vp.dims)));
if (video_force_aspect &&
(VIDEO_DRIVER_ASPECT_RATIO(video_st) > 0.0f))
@@ -397,16 +397,14 @@ bool recording_init(void)
else
{
if (recording_state.out_dims)
{
params.out_width = VIDEO_SCALE_W(recording_state.out_dims);
params.out_height = VIDEO_SCALE_H(recording_state.out_dims);
}
params.out_dims = recording_state.out_dims;
if (video_force_aspect &&
(VIDEO_DRIVER_ASPECT_RATIO(video_st) > 0.0f))
params.aspect_ratio = VIDEO_DRIVER_ASPECT_RATIO(video_st);
else
params.aspect_ratio = (float)params.out_width / params.out_height;
params.aspect_ratio = (float)VIDEO_SCALE_W(params.out_dims)
/ VIDEO_SCALE_H(params.out_dims);
#ifdef HAVE_VIDEO_FILTER
if (settings->bools.video_post_filter_record
@@ -421,8 +419,9 @@ bool recording_init(void)
rarch_softfilter_get_max_output_size(
video_st->state_filter, &max_dims);
params.fb_width = next_pow2(VIDEO_SCALE_W(max_dims));
params.fb_height = next_pow2(VIDEO_SCALE_H(max_dims));
params.fb_dims = VIDEO_SCALE_PACK(
next_pow2(VIDEO_SCALE_W(max_dims)),
next_pow2(VIDEO_SCALE_H(max_dims)));
}
#endif
}
@@ -430,8 +429,8 @@ bool recording_init(void)
RARCH_LOG("[Recording] %s %s @ %ux%u (FB size: %ux%u pix_fmt: %u).\n",
msg_hash_to_str(MSG_RECORDING_TO),
output,
params.out_width, params.out_height,
params.fb_width, params.fb_height,
VIDEO_SCALE_W(params.out_dims), VIDEO_SCALE_H(params.out_dims),
VIDEO_SCALE_W(params.fb_dims), VIDEO_SCALE_H(params.fb_dims),
(unsigned)params.pix_fmt);
if (!record_driver_init(&params))
+4 -6
View File
@@ -57,13 +57,11 @@ struct record_params
const char *audio_resampler;
/* Desired output resolution. */
unsigned out_width;
unsigned out_height;
/* Desired output resolution, VIDEO_SCALE_PACK'd. */
unsigned out_dims;
/* Total size of framebuffer used in input. */
unsigned fb_width;
unsigned fb_height;
/* Total size of framebuffer used in input, VIDEO_SCALE_PACK'd. */
unsigned fb_dims;
/* Audio channels. */
unsigned channels;
@@ -98,8 +98,8 @@ int main(void)
params.samplerate = RATE;
params.filename = OUT;
params.audio_resampler = "sinc";
params.out_width = params.fb_width = W;
params.out_height = params.fb_height = H;
params.out_dims = VIDEO_SCALE_PACK(W, H);
params.fb_dims = VIDEO_SCALE_PACK(W, H);
params.channels = 2;
params.video_record_scale_factor = 1;
params.video_stream_scale_factor = 1;