From 6118260e017185a2a2b02d1bf43ffa9122cdeb91 Mon Sep 17 00:00:00 2001 From: Mike Solar Date: Mon, 20 Jul 2026 05:51:53 +0800 Subject: [PATCH] engine: expose sequence video dimensions in the timeline facade - oakengine_sequence_get_video_params (width/height/pixel aspect) with assertions for the default 1920x1080 square-pixel sequence and the invalid-handle path - oak-cli now renders at the sequence's real dimensions instead of the hardcoded 1920x1080 --- cli/main.cpp | 20 ++++++++++++-------- engine/include/oakengine/timeline.h | 8 ++++++++ engine/src/capi/timeline.cpp | 24 ++++++++++++++++++++++++ engine/tests/oakengine_init_test.cpp | 10 ++++++++++ 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/cli/main.cpp b/cli/main.cpp index 1d10757f8..ac4c8a6c3 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -61,11 +61,6 @@ constexpr int k_exit_error = 1; constexpr int k_exit_render_unavailable = 2; constexpr int k_exit_usage = 64; -// The facade does not expose sequence dimensions yet, so rendering uses the -// application's default sequence size (also the native size of the demo -// assets). -constexpr int k_render_width = 1920; -constexpr int k_render_height = 1080; constexpr int k_pixel_format_f32 = 4; // olive::core::PixelFormat::f32 void print_usage(FILE *out) @@ -390,9 +385,18 @@ int cmd_render(const char *path, const char *start_str, const char *end_str, break; } - renderer = oakengine_renderer_create(seq, k_render_width, - k_render_height, k_pixel_format_f32, - fr_num, fr_den, nullptr); + int width = 0, height = 0; + if (oakengine_sequence_get_video_params(seq, &width, &height, nullptr, + nullptr) != OAKENGINE_OK || + width <= 0 || height <= 0) { + fprintf(stderr, "error: sequence has no valid video dimensions\n"); + rc = k_exit_error; + break; + } + + renderer = oakengine_renderer_create(seq, width, height, + k_pixel_format_f32, fr_num, fr_den, + nullptr); if (!renderer) { fprintf(stderr, "error: failed to create renderer\n"); rc = k_exit_error; diff --git a/engine/include/oakengine/timeline.h b/engine/include/oakengine/timeline.h index 91284b814..9dfc0b8ae 100644 --- a/engine/include/oakengine/timeline.h +++ b/engine/include/oakengine/timeline.h @@ -109,6 +109,14 @@ OAKENGINE_API int oakengine_sequence_get_frame_rate(const OakEngineSequence *self, int *num, int *den); +/** + * @brief Sequence video dimensions and pixel aspect ratio + * (ViewerOutput::get_video_params()). Any output pointer may be NULL. + */ +OAKENGINE_API int +oakengine_sequence_get_video_params(const OakEngineSequence *self, int *width, + int *height, int *par_num, int *par_den); + /** * @brief Number of tracks per track type (Sequence::track_list(type)-> * get_track_count()). Any of `video`/`audio`/`subtitle` may be NULL. diff --git a/engine/src/capi/timeline.cpp b/engine/src/capi/timeline.cpp index 7717bfd61..c24016293 100644 --- a/engine/src/capi/timeline.cpp +++ b/engine/src/capi/timeline.cpp @@ -191,6 +191,30 @@ int oakengine_sequence_get_frame_rate(const OakEngineSequence *self, int *num, return OAKENGINE_OK; } +int oakengine_sequence_get_video_params(const OakEngineSequence *self, + int *width, int *height, int *par_num, + int *par_den) +{ + if (!self) { + return OAKENGINE_E_INVALID; + } + const olive::VideoParams params = impl(self)->get_video_params(); + if (width) { + *width = params.width(); + } + if (height) { + *height = params.height(); + } + const olive::Rational par = params.pixel_aspect_ratio(); + if (par_num) { + *par_num = par.numerator(); + } + if (par_den) { + *par_den = par.denominator(); + } + return OAKENGINE_OK; +} + int oakengine_sequence_track_count(const OakEngineSequence *self, int *video, int *audio, int *subtitle) { diff --git a/engine/tests/oakengine_init_test.cpp b/engine/tests/oakengine_init_test.cpp index fa705d49a..b35cefae5 100644 --- a/engine/tests/oakengine_init_test.cpp +++ b/engine/tests/oakengine_init_test.cpp @@ -180,6 +180,16 @@ static void test_sequence_and_save_load(void) assert(oakengine_sequence_get_frame_rate(seq, &num, &den) == OAKENGINE_OK); assert(num == 30000 && den == 1001); + // Default video dimensions (Config's DefaultSequenceWidth/Height) and + // square pixels + int width = -1, height = -1, par_num = -1, par_den = -1; + assert(oakengine_sequence_get_video_params(seq, &width, &height, &par_num, + &par_den) == OAKENGINE_OK); + assert(width == 1920 && height == 1080); + assert(par_num == 1 && par_den == 1); + assert(oakengine_sequence_get_video_params(NULL, NULL, NULL, NULL, NULL) == + OAKENGINE_E_INVALID); + // Fresh sequences have no tracks. int video = -1, audio = -1, subtitle = -1; assert(oakengine_sequence_track_count(seq, &video, &audio, &subtitle) ==