refactor(codec): de-Qt oakcodec and wrap it in a pure C ABI; switch common handles to refcounted value structs

- oakcodec: de-Qt all 20 sources (QThread decode loop -> std::thread,
  QObject/signals -> callbacks), pure C ABI in include/codec with
  refcounted neutral handles (OakFrame/OakDecoder/OakEncoder),
  framemanager moved in from render, frame_to_buffer/buffer_to_frame
  moved in from oakcommon oiioutils, codec->task via submit callback
  (M8 will register), all cross-module calls go through the other
  side's C API, -fvisibility=hidden + OAKCODEC_API
- oakcommon: handles become refcounted value structs
  {ctx, addref, release, abi_version} (FFmpeg-style), pass-by-value
  signatures, free() as release wrapper; init_from_native/get_native
  for copyable value objects; OakCommonXxx renamed to OakXxx
- oakcommon: add logging (log_debug/info/warning/critical with level
  filtering and sink injection) + printf-style oakcommon_log C wrapper
- oakrender: add CancelAtom C API family; complete
  oakrender_color_processor_convert_frame; fix get_processor() missing
  definition and OCIO env var lookup
- tests: oakcommon 174, oaknode 96, oakrender 42, oakcodec 18, all
  green in their standalone builds
This commit is contained in:
2026-08-06 18:50:07 +08:00
parent edbd3913af
commit 3d004c081b
127 changed files with 13760 additions and 1222 deletions
+62 -30
View File
@@ -23,10 +23,15 @@
#include <cstring>
#include "../src/colortransform.h"
#include "refcounted.h"
struct OakCommonColorTransform {
olive::ColorTransform impl;
};
/**
* @brief Recover the boxed olive::ColorTransform from a handle (NULL-safe).
*/
static olive::ColorTransform *ct(OakColorTransform transform)
{
return oakcommon::handle_impl<olive::ColorTransform>(transform.ctx);
}
static int copy_string(const std::string &value, char *buf, int buf_size)
{
@@ -36,89 +41,116 @@ static int copy_string(const std::string &value, char *buf, int buf_size)
return needed;
}
OakCommonColorTransform *oakcommon_colortransform_init_output(
OakColorTransform oakcommon_colortransform_init_output(
const char *output)
{
OakColorTransform h = {};
if (!output)
return nullptr;
return h;
try {
return new OakCommonColorTransform{
olive::ColorTransform(std::string(output))};
return oakcommon::make_handle<OakColorTransform>(
olive::ColorTransform(std::string(output)));
} catch (...) {
return nullptr;
OakColorTransform empty = {};
return empty;
}
}
OakCommonColorTransform *oakcommon_colortransform_init_display(
OakColorTransform oakcommon_colortransform_init_display(
const char *display, const char *view, const char *look)
{
OakColorTransform h = {};
if (!display || !view || !look)
return nullptr;
return h;
try {
return new OakCommonColorTransform{olive::ColorTransform(
std::string(display), std::string(view), std::string(look))};
return oakcommon::make_handle<OakColorTransform>(
olive::ColorTransform(std::string(display), std::string(view),
std::string(look)));
} catch (...) {
return nullptr;
OakColorTransform empty = {};
return empty;
}
}
void oakcommon_colortransform_free(OakCommonColorTransform *transform)
OakColorTransform oakcommon_colortransform_init_from_native(
const olive::ColorTransform *src)
{
delete transform;
if (!src) {
OakColorTransform h = {};
return h;
}
try {
return oakcommon::make_handle<OakColorTransform>(
olive::ColorTransform(*src));
} catch (...) {
OakColorTransform h = {};
return h;
}
}
int oakcommon_colortransform_is_display(OakCommonColorTransform *transform,
const olive::ColorTransform *oakcommon_colortransform_get_native(
OakColorTransform transform)
{
return ct(transform);
}
void oakcommon_colortransform_free(OakColorTransform *transform)
{
oakcommon::free_handle(transform);
}
int oakcommon_colortransform_is_display(OakColorTransform transform,
int *is_display)
{
if (!transform || !is_display)
if (!ct(transform) || !is_display)
return OAKCOMMON_E_INVALID;
*is_display = transform->impl.is_display() ? 1 : 0;
*is_display = ct(transform)->is_display() ? 1 : 0;
return OAKCOMMON_OK;
}
int oakcommon_colortransform_get_display(OakCommonColorTransform *transform,
int oakcommon_colortransform_get_display(OakColorTransform transform,
char *buf, int buf_size)
{
if (!transform)
if (!ct(transform))
return OAKCOMMON_E_INVALID;
try {
return copy_string(transform->impl.display(), buf, buf_size);
return copy_string(ct(transform)->display(), buf, buf_size);
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_colortransform_get_output(OakCommonColorTransform *transform,
int oakcommon_colortransform_get_output(OakColorTransform transform,
char *buf, int buf_size)
{
if (!transform)
if (!ct(transform))
return OAKCOMMON_E_INVALID;
try {
return copy_string(transform->impl.output(), buf, buf_size);
return copy_string(ct(transform)->output(), buf, buf_size);
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_colortransform_get_view(OakCommonColorTransform *transform,
int oakcommon_colortransform_get_view(OakColorTransform transform,
char *buf, int buf_size)
{
if (!transform)
if (!ct(transform))
return OAKCOMMON_E_INVALID;
try {
return copy_string(transform->impl.view(), buf, buf_size);
return copy_string(ct(transform)->view(), buf, buf_size);
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_colortransform_get_look(OakCommonColorTransform *transform,
int oakcommon_colortransform_get_look(OakColorTransform transform,
char *buf, int buf_size)
{
if (!transform)
if (!ct(transform))
return OAKCOMMON_E_INVALID;
try {
return copy_string(transform->impl.look(), buf, buf_size);
return copy_string(ct(transform)->look(), buf, buf_size);
} catch (...) {
return OAKCOMMON_E_FAILED;
}
+91 -57
View File
@@ -26,43 +26,79 @@
#include <vector>
#include "../src/commandlineparser.h"
#include "refcounted.h"
struct OakCommonCommandLineParser {
CommandLineParser impl;
};
namespace
{
struct OakCommonCommandLineOption {
/**
* @brief State boxed behind an option handle's ctx pointer.
*
* The option pointer is borrowed: the option itself is owned by the
* parser, so releasing the box never destroys it.
*/
struct OptionState {
CommandLineParser::Option *option;
};
struct OakCommonCommandLinePositionalArgument {
/**
* @brief State boxed behind a positional-argument handle's ctx pointer.
*
* The argument pointer is borrowed: the argument itself is owned by the
* parser, so releasing the box never destroys it.
*/
struct PositionalArgumentState {
CommandLineParser::PositionalArgument *argument;
};
OakCommonCommandLineParser *oakcommon_commandlineparser_init(void)
CommandLineParser *clp(OakCommandLineParser parser)
{
return oakcommon::handle_impl<CommandLineParser>(parser.ctx);
}
CommandLineParser::Option *clo(OakCommandLineOption option)
{
OptionState *state =
oakcommon::handle_impl<OptionState>(option.ctx);
return state ? state->option : nullptr;
}
CommandLineParser::PositionalArgument *clpa(
OakCommandLinePositionalArgument argument)
{
PositionalArgumentState *state =
oakcommon::handle_impl<PositionalArgumentState>(argument.ctx);
return state ? state->argument : nullptr;
}
} // namespace
OakCommandLineParser oakcommon_commandlineparser_init(void)
{
try {
return new (std::nothrow) OakCommonCommandLineParser();
return oakcommon::make_handle_in_place<OakCommandLineParser,
CommandLineParser>();
} catch (...) {
return NULL;
OakCommandLineParser h = {};
return h;
}
}
void oakcommon_commandlineparser_free(OakCommonCommandLineParser *parser)
void oakcommon_commandlineparser_free(OakCommandLineParser *parser)
{
delete parser;
oakcommon::free_handle(parser);
}
int oakcommon_commandlineparser_set_app_info(OakCommonCommandLineParser *parser,
int oakcommon_commandlineparser_set_app_info(OakCommandLineParser parser,
const char *name,
const char *version)
{
if (!parser || !name) {
if (!clp(parser) || !name) {
return OAKCOMMON_E_INVALID;
}
try {
parser->impl.set_app_info(name, version ? version : "");
clp(parser)->set_app_info(name, version ? version : "");
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
@@ -70,11 +106,11 @@ int oakcommon_commandlineparser_set_app_info(OakCommonCommandLineParser *parser,
}
int oakcommon_commandlineparser_add_option(
OakCommonCommandLineParser *parser, const char *const *names, int name_count,
OakCommandLineParser parser, const char *const *names, int name_count,
const char *description, int takes_arg, const char *arg_placeholder,
int hidden, OakCommonCommandLineOption **out_option)
int hidden, OakCommandLineOption *out_option)
{
if (!parser || !names || name_count <= 0) {
if (!clp(parser) || !names || name_count <= 0) {
return OAKCOMMON_E_INVALID;
}
@@ -88,18 +124,16 @@ int oakcommon_commandlineparser_add_option(
strings.emplace_back(names[i]);
}
const CommandLineParser::Option *option = parser->impl.add_option(
const CommandLineParser::Option *option = clp(parser)->add_option(
strings, description ? description : "", takes_arg != 0,
arg_placeholder ? arg_placeholder : "", hidden != 0);
if (out_option) {
auto *handle =
new (std::nothrow) OakCommonCommandLineOption();
if (!handle) {
*out_option = oakcommon::make_handle<OakCommandLineOption>(
OptionState{const_cast<CommandLineParser::Option *>(option)});
if (!out_option->ctx) {
return OAKCOMMON_E_NOMEM;
}
handle->option = const_cast<CommandLineParser::Option *>(option);
*out_option = handle;
}
return OAKCOMMON_OK;
@@ -109,28 +143,28 @@ int oakcommon_commandlineparser_add_option(
}
int oakcommon_commandlineparser_add_positional_argument(
OakCommonCommandLineParser *parser, const char *name,
OakCommandLineParser parser, const char *name,
const char *description, int required,
OakCommonCommandLinePositionalArgument **out_argument)
OakCommandLinePositionalArgument *out_argument)
{
if (!parser || !name) {
if (!clp(parser) || !name) {
return OAKCOMMON_E_INVALID;
}
try {
const CommandLineParser::PositionalArgument *argument =
parser->impl.add_positional_argument(
clp(parser)->add_positional_argument(
name, description ? description : "", required != 0);
if (out_argument) {
auto *handle =
new (std::nothrow) OakCommonCommandLinePositionalArgument();
if (!handle) {
*out_argument =
oakcommon::make_handle<OakCommandLinePositionalArgument>(
PositionalArgumentState{
const_cast<CommandLineParser::PositionalArgument *>(
argument)});
if (!out_argument->ctx) {
return OAKCOMMON_E_NOMEM;
}
handle->argument =
const_cast<CommandLineParser::PositionalArgument *>(argument);
*out_argument = handle;
}
return OAKCOMMON_OK;
@@ -139,10 +173,10 @@ int oakcommon_commandlineparser_add_positional_argument(
}
}
int oakcommon_commandlineparser_process(OakCommonCommandLineParser *parser,
int oakcommon_commandlineparser_process(OakCommandLineParser parser,
const char *const *argv, int argc)
{
if (!parser || !argv || argc < 0) {
if (!clp(parser) || !argv || argc < 0) {
return OAKCOMMON_E_INVALID;
}
@@ -153,37 +187,37 @@ int oakcommon_commandlineparser_process(OakCommonCommandLineParser *parser,
args.emplace_back(argv[i] ? argv[i] : "");
}
parser->impl.process(args);
clp(parser)->process(args);
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_commandlineparser_print_help(OakCommonCommandLineParser *parser,
int oakcommon_commandlineparser_print_help(OakCommandLineParser parser,
const char *filename)
{
if (!parser || !filename) {
if (!clp(parser) || !filename) {
return OAKCOMMON_E_INVALID;
}
try {
parser->impl.print_help(filename);
clp(parser)->print_help(filename);
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_commandlineoption_is_set(OakCommonCommandLineOption *option,
int oakcommon_commandlineoption_is_set(OakCommandLineOption option,
bool *is_set)
{
if (!option || !option->option || !is_set) {
if (!clo(option) || !is_set) {
return OAKCOMMON_E_INVALID;
}
try {
*is_set = option->option->is_set();
*is_set = clo(option)->is_set();
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
@@ -212,29 +246,29 @@ static int copy_setting(const std::string &value, char *buf, int buf_size)
return required;
}
int oakcommon_commandlineoption_get_setting(OakCommonCommandLineOption *option,
int oakcommon_commandlineoption_get_setting(OakCommandLineOption option,
char *buf, int buf_size)
{
if (!option || !option->option) {
if (!clo(option)) {
return OAKCOMMON_E_INVALID;
}
try {
return copy_setting(option->option->get_setting(), buf, buf_size);
return copy_setting(clo(option)->get_setting(), buf, buf_size);
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_commandlineoption_set_setting(OakCommonCommandLineOption *option,
int oakcommon_commandlineoption_set_setting(OakCommandLineOption option,
const char *value)
{
if (!option || !option->option || !value) {
if (!clo(option) || !value) {
return OAKCOMMON_E_INVALID;
}
try {
option->option->set_setting(value);
clo(option)->set_setting(value);
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
@@ -242,41 +276,41 @@ int oakcommon_commandlineoption_set_setting(OakCommonCommandLineOption *option,
}
int oakcommon_commandlinepositionalargument_get_setting(
OakCommonCommandLinePositionalArgument *argument, char *buf, int buf_size)
OakCommandLinePositionalArgument argument, char *buf, int buf_size)
{
if (!argument || !argument->argument) {
if (!clpa(argument)) {
return OAKCOMMON_E_INVALID;
}
try {
return copy_setting(argument->argument->get_setting(), buf, buf_size);
return copy_setting(clpa(argument)->get_setting(), buf, buf_size);
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_commandlinepositionalargument_set_setting(
OakCommonCommandLinePositionalArgument *argument, const char *value)
OakCommandLinePositionalArgument argument, const char *value)
{
if (!argument || !argument->argument || !value) {
if (!clpa(argument) || !value) {
return OAKCOMMON_E_INVALID;
}
try {
argument->argument->set_setting(value);
clpa(argument)->set_setting(value);
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
void oakcommon_commandlineoption_free(OakCommonCommandLineOption *option)
void oakcommon_commandlineoption_free(OakCommandLineOption *option)
{
delete option;
oakcommon::free_handle(option);
}
void oakcommon_commandlinepositionalargument_free(
OakCommonCommandLinePositionalArgument *argument)
OakCommandLinePositionalArgument *argument)
{
delete argument;
oakcommon::free_handle(argument);
}
+63 -41
View File
@@ -22,25 +22,47 @@
#include "../src/current.h"
struct OakCommonCurrent {
Current *current;
};
OakCommonCurrent *oakcommon_current_instance(void)
namespace
{
static OakCommonCurrent handle = { &Current::get_instance() };
return &handle;
/**
* @brief No-op addref/release for the singleton: it is never destroyed.
*/
void singleton_noop(void *ctx)
{
(void)ctx;
}
void oakcommon_current_free(OakCommonCurrent *self)
/**
* @brief Recover the Current singleton from a handle (NULL-safe).
*/
Current *current_of(OakCurrent self)
{
// No-op: the handle wraps a process-wide singleton.
return static_cast<Current *>(self.ctx);
}
} // namespace
OakCurrent oakcommon_current_instance(void)
{
OakCurrent h = {};
h.ctx = &Current::get_instance();
h.addref = &singleton_noop;
h.release = &singleton_noop;
h.abi_version = OAKCOMMON_ABI_VERSION;
return h;
}
void oakcommon_current_free(OakCurrent *self)
{
// No-op: the handle wraps a process-wide singleton whose release()
// intentionally never destroys anything.
(void)self;
}
static int current_set(Current *current,
void (Current::*set_fn)(std::shared_ptr<void>),
void *obj, OakCommonDestroyFn destroy)
void *obj, OakDestroyFn destroy)
{
try {
std::shared_ptr<void> value;
@@ -70,78 +92,78 @@ static int current_get(Current *current,
return OAKCOMMON_OK;
}
int oakcommon_current_set_video_params(OakCommonCurrent *self, void *obj,
OakCommonDestroyFn destroy)
int oakcommon_current_set_video_params(OakCurrent self, void *obj,
OakDestroyFn destroy)
{
if (!self)
if (!current_of(self))
return OAKCOMMON_E_INVALID;
return current_set(self->current, &Current::set_current_video_params,
return current_set(current_of(self), &Current::set_current_video_params,
obj, destroy);
}
int oakcommon_current_set_audio_params(OakCommonCurrent *self, void *obj,
OakCommonDestroyFn destroy)
int oakcommon_current_set_audio_params(OakCurrent self, void *obj,
OakDestroyFn destroy)
{
if (!self)
if (!current_of(self))
return OAKCOMMON_E_INVALID;
return current_set(self->current, &Current::set_current_audio_params,
return current_set(current_of(self), &Current::set_current_audio_params,
obj, destroy);
}
int oakcommon_current_set_plugin_host(OakCommonCurrent *self, void *obj,
OakCommonDestroyFn destroy)
int oakcommon_current_set_plugin_host(OakCurrent self, void *obj,
OakDestroyFn destroy)
{
if (!self)
if (!current_of(self))
return OAKCOMMON_E_INVALID;
return current_set(self->current, &Current::set_plugin_host, obj,
return current_set(current_of(self), &Current::set_plugin_host, obj,
destroy);
}
int oakcommon_current_set_plugin_cache(OakCommonCurrent *self, void *obj,
OakCommonDestroyFn destroy)
int oakcommon_current_set_plugin_cache(OakCurrent self, void *obj,
OakDestroyFn destroy)
{
if (!self)
if (!current_of(self))
return OAKCOMMON_E_INVALID;
return current_set(self->current, &Current::set_plugin_cache, obj,
return current_set(current_of(self), &Current::set_plugin_cache, obj,
destroy);
}
int oakcommon_current_get_video_params(OakCommonCurrent *self, void **out)
int oakcommon_current_get_video_params(OakCurrent self, void **out)
{
if (!self || !out)
if (!current_of(self) || !out)
return OAKCOMMON_E_INVALID;
return current_get(self->current, &Current::current_video_params,
return current_get(current_of(self), &Current::current_video_params,
out);
}
int oakcommon_current_get_audio_params(OakCommonCurrent *self, void **out)
int oakcommon_current_get_audio_params(OakCurrent self, void **out)
{
if (!self || !out)
if (!current_of(self) || !out)
return OAKCOMMON_E_INVALID;
return current_get(self->current, &Current::current_audio_params,
return current_get(current_of(self), &Current::current_audio_params,
out);
}
int oakcommon_current_get_plugin_host(OakCommonCurrent *self, void **out)
int oakcommon_current_get_plugin_host(OakCurrent self, void **out)
{
if (!self || !out)
if (!current_of(self) || !out)
return OAKCOMMON_E_INVALID;
return current_get(self->current, &Current::plugin_host, out);
return current_get(current_of(self), &Current::plugin_host, out);
}
int oakcommon_current_get_plugin_cache(OakCommonCurrent *self, void **out)
int oakcommon_current_get_plugin_cache(OakCurrent self, void **out)
{
if (!self || !out)
if (!current_of(self) || !out)
return OAKCOMMON_E_INVALID;
return current_get(self->current, &Current::plugin_cache, out);
return current_get(current_of(self), &Current::plugin_cache, out);
}
int oakcommon_current_is_interactive(OakCommonCurrent *self, int *out)
int oakcommon_current_is_interactive(OakCurrent self, int *out)
{
if (!self || !out)
if (!current_of(self) || !out)
return OAKCOMMON_E_INVALID;
try {
*out = self->current->interactive() ? 1 : 0;
*out = current_of(self)->interactive() ? 1 : 0;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
+68
View File
@@ -20,6 +20,9 @@
#include "common/debug.h"
#include <cstdarg>
#include <vector>
#include "../src/debug.h"
int oakcommon_debug_log(int level, const char *msg)
@@ -43,3 +46,68 @@ int oakcommon_debug_level_name(int level, char *buf, int buf_size)
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_log(int level, const char *fmt, ...)
{
if (!fmt)
return OAKCOMMON_E_INVALID;
va_list args;
va_start(args, fmt);
va_list sizing;
va_copy(sizing, args);
int needed = vsnprintf(nullptr, 0, fmt, sizing);
va_end(sizing);
if (needed < 0) {
va_end(args);
return OAKCOMMON_E_FAILED;
}
std::string msg;
try {
// Dynamically sized: arbitrary message length, no truncation,
// no fixed stack buffer.
std::vector<char> buf(static_cast<size_t>(needed) + 1);
vsnprintf(buf.data(), buf.size(), fmt, args);
msg.assign(buf.data(), static_cast<size_t>(needed));
} catch (...) {
va_end(args);
return OAKCOMMON_E_FAILED;
}
va_end(args);
try {
olive::log_message(level, msg);
} catch (...) {
return OAKCOMMON_E_FAILED;
}
return OAKCOMMON_OK;
}
int oakcommon_log_set_level(int level)
{
if (level < OAKCOMMON_DEBUG_DEBUG || level > OAKCOMMON_DEBUG_FATAL)
return OAKCOMMON_E_INVALID;
try {
olive::set_log_level(static_cast<olive::DebugLevel>(level));
} catch (...) {
return OAKCOMMON_E_FAILED;
}
return OAKCOMMON_OK;
}
int oakcommon_log_get_level(int *out_level)
{
if (!out_level)
return OAKCOMMON_E_INVALID;
try {
*out_level = static_cast<int>(olive::get_log_level());
} catch (...) {
return OAKCOMMON_E_FAILED;
}
return OAKCOMMON_OK;
}
+45 -33
View File
@@ -24,11 +24,21 @@
#include <string>
#include "../src/filefunctions.h"
#include "refcounted.h"
struct OakCommonFileFunctions {
int unused; /**< Stateless family; handle kept for API uniformity. */
namespace
{
/**
* @brief Stateless family; the boxed object is empty and only exists so
* the handle has something to reference-count.
*/
struct FileFunctionsState {
int unused;
};
} // namespace
namespace
{
@@ -54,25 +64,27 @@ bool is_valid_string_out(const char *buf, int buf_size)
} // namespace
OakCommonFileFunctions *oakcommon_filefunctions_init(void)
OakFileFunctions oakcommon_filefunctions_init(void)
{
try {
return new OakCommonFileFunctions{0};
return oakcommon::make_handle<OakFileFunctions>(
FileFunctionsState{0});
} catch (...) {
return nullptr;
OakFileFunctions h = {};
return h;
}
}
void oakcommon_filefunctions_free(OakCommonFileFunctions *self)
void oakcommon_filefunctions_free(OakFileFunctions *self)
{
delete self;
oakcommon::free_handle(self);
}
int oakcommon_filefunctions_get_unique_file_identifier(
OakCommonFileFunctions *self, const char *filename, char *buf,
OakFileFunctions self, const char *filename, char *buf,
int buf_size)
{
if (self == nullptr || filename == nullptr ||
if (self.ctx == nullptr || filename == nullptr ||
!is_valid_string_out(buf, buf_size)) {
return OAKCOMMON_E_INVALID;
}
@@ -87,9 +99,9 @@ int oakcommon_filefunctions_get_unique_file_identifier(
}
int oakcommon_filefunctions_get_configuration_location(
OakCommonFileFunctions *self, char *buf, int buf_size)
OakFileFunctions self, char *buf, int buf_size)
{
if (self == nullptr || !is_valid_string_out(buf, buf_size)) {
if (self.ctx == nullptr || !is_valid_string_out(buf, buf_size)) {
return OAKCOMMON_E_INVALID;
}
@@ -103,9 +115,9 @@ int oakcommon_filefunctions_get_configuration_location(
}
int oakcommon_filefunctions_get_application_path(
OakCommonFileFunctions *self, char *buf, int buf_size)
OakFileFunctions self, char *buf, int buf_size)
{
if (self == nullptr || !is_valid_string_out(buf, buf_size)) {
if (self.ctx == nullptr || !is_valid_string_out(buf, buf_size)) {
return OAKCOMMON_E_INVALID;
}
@@ -118,9 +130,9 @@ int oakcommon_filefunctions_get_application_path(
}
int oakcommon_filefunctions_get_temp_file_path(
OakCommonFileFunctions *self, char *buf, int buf_size)
OakFileFunctions self, char *buf, int buf_size)
{
if (self == nullptr || !is_valid_string_out(buf, buf_size)) {
if (self.ctx == nullptr || !is_valid_string_out(buf, buf_size)) {
return OAKCOMMON_E_INVALID;
}
@@ -133,9 +145,9 @@ int oakcommon_filefunctions_get_temp_file_path(
}
int oakcommon_filefunctions_get_auto_recovery_root(
OakCommonFileFunctions *self, char *buf, int buf_size)
OakFileFunctions self, char *buf, int buf_size)
{
if (self == nullptr || !is_valid_string_out(buf, buf_size)) {
if (self.ctx == nullptr || !is_valid_string_out(buf, buf_size)) {
return OAKCOMMON_E_INVALID;
}
@@ -148,10 +160,10 @@ int oakcommon_filefunctions_get_auto_recovery_root(
}
int oakcommon_filefunctions_can_copy_directory_without_overwriting(
OakCommonFileFunctions *self, const char *source, const char *dest,
OakFileFunctions self, const char *source, const char *dest,
int *out)
{
if (self == nullptr || source == nullptr || dest == nullptr ||
if (self.ctx == nullptr || source == nullptr || dest == nullptr ||
out == nullptr) {
return OAKCOMMON_E_INVALID;
}
@@ -167,11 +179,11 @@ int oakcommon_filefunctions_can_copy_directory_without_overwriting(
}
}
int oakcommon_filefunctions_copy_directory(OakCommonFileFunctions *self,
int oakcommon_filefunctions_copy_directory(OakFileFunctions self,
const char *source,
const char *dest, int overwrite)
{
if (self == nullptr || source == nullptr || dest == nullptr) {
if (self.ctx == nullptr || source == nullptr || dest == nullptr) {
return OAKCOMMON_E_INVALID;
}
@@ -184,10 +196,10 @@ int oakcommon_filefunctions_copy_directory(OakCommonFileFunctions *self,
}
int oakcommon_filefunctions_directory_is_valid(
OakCommonFileFunctions *self, const char *dir,
OakFileFunctions self, const char *dir,
int try_to_create_if_not_exists, int *out)
{
if (self == nullptr || dir == nullptr || out == nullptr) {
if (self.ctx == nullptr || dir == nullptr || out == nullptr) {
return OAKCOMMON_E_INVALID;
}
@@ -203,10 +215,10 @@ int oakcommon_filefunctions_directory_is_valid(
}
int oakcommon_filefunctions_ensure_filename_extension(
OakCommonFileFunctions *self, const char *filename,
OakFileFunctions self, const char *filename,
const char *extension, char *buf, int buf_size)
{
if (self == nullptr || filename == nullptr || extension == nullptr ||
if (self.ctx == nullptr || filename == nullptr || extension == nullptr ||
!is_valid_string_out(buf, buf_size)) {
return OAKCOMMON_E_INVALID;
}
@@ -222,10 +234,10 @@ int oakcommon_filefunctions_ensure_filename_extension(
}
int oakcommon_filefunctions_read_file_as_string(
OakCommonFileFunctions *self, const char *filename, char *buf,
OakFileFunctions self, const char *filename, char *buf,
int buf_size)
{
if (self == nullptr || filename == nullptr ||
if (self.ctx == nullptr || filename == nullptr ||
!is_valid_string_out(buf, buf_size)) {
return OAKCOMMON_E_INVALID;
}
@@ -240,10 +252,10 @@ int oakcommon_filefunctions_read_file_as_string(
}
int oakcommon_filefunctions_get_safe_temporary_filename(
OakCommonFileFunctions *self, const char *original, char *buf,
OakFileFunctions self, const char *original, char *buf,
int buf_size)
{
if (self == nullptr || original == nullptr ||
if (self.ctx == nullptr || original == nullptr ||
!is_valid_string_out(buf, buf_size)) {
return OAKCOMMON_E_INVALID;
}
@@ -258,10 +270,10 @@ int oakcommon_filefunctions_get_safe_temporary_filename(
}
int oakcommon_filefunctions_rename_file_allow_overwrite(
OakCommonFileFunctions *self, const char *from, const char *to,
OakFileFunctions self, const char *from, const char *to,
int *out)
{
if (self == nullptr || from == nullptr || to == nullptr ||
if (self.ctx == nullptr || from == nullptr || to == nullptr ||
out == nullptr) {
return OAKCOMMON_E_INVALID;
}
@@ -276,10 +288,10 @@ int oakcommon_filefunctions_rename_file_allow_overwrite(
}
int oakcommon_filefunctions_get_formatted_executable_for_platform(
OakCommonFileFunctions *self, const char *unformatted, char *buf,
OakFileFunctions self, const char *unformatted, char *buf,
int buf_size)
{
if (self == nullptr || unformatted == nullptr ||
if (self.ctx == nullptr || unformatted == nullptr ||
!is_valid_string_out(buf, buf_size)) {
return OAKCOMMON_E_INVALID;
}
+21 -9
View File
@@ -23,30 +23,42 @@
#include <new>
#include "../src/ocioutils.h"
#include "refcounted.h"
struct OakCommonOCIOUtils {
int unused; /**< Stateless; only the address matters. */
namespace
{
/**
* @brief Stateless family; the boxed object is empty and only exists so
* the handle has something to reference-count.
*/
struct OCIOUtilsState {
int unused;
};
OakCommonOCIOUtils *oakcommon_ocioutils_init(void)
} // namespace
OakOCIOUtils oakcommon_ocioutils_init(void)
{
try {
return new (std::nothrow) OakCommonOCIOUtils{};
return oakcommon::make_handle<OakOCIOUtils>(
OCIOUtilsState{0});
} catch (...) {
return NULL;
OakOCIOUtils h = {};
return h;
}
}
void oakcommon_ocioutils_free(OakCommonOCIOUtils *self)
void oakcommon_ocioutils_free(OakOCIOUtils *self)
{
delete self;
oakcommon::free_handle(self);
}
int oakcommon_ocioutils_get_ocio_bit_depth_from_pixel_format(
OakCommonOCIOUtils *self, int pixel_format, int *out_bit_depth)
OakOCIOUtils self, int pixel_format, int *out_bit_depth)
{
try {
if (self == NULL || out_bit_depth == NULL)
if (self.ctx == NULL || out_bit_depth == NULL)
return OAKCOMMON_E_INVALID;
if (pixel_format < OAKCOMMON_PIXEL_FORMAT_INVALID ||
pixel_format >= OAKCOMMON_PIXEL_FORMAT_COUNT)
+25 -13
View File
@@ -23,30 +23,42 @@
#include <new>
#include "../src/oiioutils.h"
#include "refcounted.h"
struct OakCommonOIIOUtils {
int unused; /**< Stateless; only the address matters. */
namespace
{
/**
* @brief Stateless family; the boxed object is empty and only exists so
* the handle has something to reference-count.
*/
struct OIIOUtilsState {
int unused;
};
OakCommonOIIOUtils *oakcommon_oiioutils_init(void)
} // namespace
OakOIIOUtils oakcommon_oiioutils_init(void)
{
try {
return new (std::nothrow) OakCommonOIIOUtils{};
return oakcommon::make_handle<OakOIIOUtils>(
OIIOUtilsState{0});
} catch (...) {
return NULL;
OakOIIOUtils h = {};
return h;
}
}
void oakcommon_oiioutils_free(OakCommonOIIOUtils *self)
void oakcommon_oiioutils_free(OakOIIOUtils *self)
{
delete self;
oakcommon::free_handle(self);
}
int oakcommon_oiioutils_get_oiio_base_type_from_format(
OakCommonOIIOUtils *self, int pixel_format, int *out_base_type)
OakOIIOUtils self, int pixel_format, int *out_base_type)
{
try {
if (self == NULL || out_base_type == NULL)
if (self.ctx == NULL || out_base_type == NULL)
return OAKCOMMON_E_INVALID;
if (pixel_format < OAKCOMMON_PIXEL_FORMAT_INVALID ||
pixel_format >= OAKCOMMON_PIXEL_FORMAT_COUNT)
@@ -63,10 +75,10 @@ int oakcommon_oiioutils_get_oiio_base_type_from_format(
}
int oakcommon_oiioutils_get_format_from_oiio_basetype(
OakCommonOIIOUtils *self, int base_type, int *out_pixel_format)
OakOIIOUtils self, int base_type, int *out_pixel_format)
{
try {
if (self == NULL || out_pixel_format == NULL)
if (self.ctx == NULL || out_pixel_format == NULL)
return OAKCOMMON_E_INVALID;
if (base_type < 0 || base_type >= OIIO::TypeDesc::LASTBASE)
return OAKCOMMON_E_INVALID;
@@ -82,11 +94,11 @@ int oakcommon_oiioutils_get_format_from_oiio_basetype(
}
int oakcommon_oiioutils_get_pixel_aspect_ratio(
OakCommonOIIOUtils *self, double pixel_aspect_ratio, int *out_numerator,
OakOIIOUtils self, double pixel_aspect_ratio, int *out_numerator,
int *out_denominator)
{
try {
if (self == NULL || out_numerator == NULL || out_denominator == NULL)
if (self.ctx == NULL || out_numerator == NULL || out_denominator == NULL)
return OAKCOMMON_E_INVALID;
olive::core::Rational par =
+132
View File
@@ -0,0 +1,132 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAKCOMMON_C_API_REFCOUNTED_H
#define OAKCOMMON_C_API_REFCOUNTED_H
#include <atomic>
#include <cstdint>
#include <type_traits>
#include <utility>
#include "common/handle.h"
namespace oakcommon
{
/**
* @brief Heap box behind every handle's ctx pointer.
*
* Holds the wrapped object plus its atomic reference count. addref and
* release are emitted per boxed type so that the function pointers stored
* in a handle always run code from the DLL that created the object.
*/
template <typename T> struct RefCounted {
T impl;
std::atomic<uint32_t> refs;
template <typename... Args>
explicit RefCounted(Args &&...args)
: impl(std::forward<Args>(args)...)
, refs(1)
{
}
};
/**
* @brief Handle addref thunk: atomically increments the count.
*/
template <typename T> void ref_counted_addref(void *ctx)
{
auto *box = static_cast<RefCounted<T> *>(ctx);
if (box)
box->refs.fetch_add(1, std::memory_order_relaxed);
}
/**
* @brief Handle release thunk: decrements the count, destroys at zero.
*/
template <typename T> void ref_counted_release(void *ctx)
{
auto *box = static_cast<RefCounted<T> *>(ctx);
if (box && box->refs.fetch_sub(1, std::memory_order_acq_rel) == 1)
delete box;
}
/**
* @brief Build a by-value handle owning a freshly boxed object (count 1).
*
* The object is constructed in place inside the box, so non-movable
* types are supported. On allocation failure the returned handle has
* ctx == NULL (all C API functions treat that as OAKCOMMON_E_INVALID
* and free() as a no-op).
*/
template <typename Handle, typename T, typename... Args>
Handle make_handle_in_place(Args &&...args)
{
Handle h = {};
try {
h.ctx = new RefCounted<T>(std::forward<Args>(args)...);
} catch (...) {
h.ctx = nullptr;
}
h.addref = &ref_counted_addref<T>;
h.release = &ref_counted_release<T>;
h.abi_version = OAKCOMMON_ABI_VERSION;
return h;
}
/**
* @brief Build a by-value handle from an existing object (copied/moved
* into the box, reference count 1).
*/
template <typename Handle, typename T>
Handle make_handle(T &&value)
{
return make_handle_in_place<Handle, typename std::decay<T>::type>(
std::forward<T>(value));
}
/**
* @brief Recover the boxed object from a handle ctx (NULL-safe).
*/
template <typename T> T *handle_impl(void *ctx)
{
auto *box = static_cast<RefCounted<T> *>(ctx);
return box ? &box->impl : nullptr;
}
/**
* @brief Shared free() body: release the ctx, no-op on NULL/empty handle.
*
* Clears ctx afterwards so a double free through the same (copied)
* struct is caught by the caller's own bookkeeping, not by us.
*/
template <typename Handle> void free_handle(Handle *h)
{
if (!h || !h->ctx || !h->release)
return;
h->release(h->ctx);
h->ctx = nullptr;
}
} // namespace oakcommon
#endif // OAKCOMMON_C_API_REFCOUNTED_H
+73 -50
View File
@@ -23,14 +23,19 @@
#include <cstring>
#include "../src/subtitleparams.h"
struct OakCommonSubtitleParams {
olive::SubtitleParams impl;
};
#include "refcounted.h"
namespace
{
/**
* @brief Recover the boxed olive::SubtitleParams from a handle (NULL-safe).
*/
olive::SubtitleParams *sp(OakSubtitleParams params)
{
return oakcommon::handle_impl<olive::SubtitleParams>(params.ctx);
}
int copy_string(const std::string &value, char *buf, int buf_size)
{
int needed = (int)value.size() + 1;
@@ -41,92 +46,110 @@ int copy_string(const std::string &value, char *buf, int buf_size)
} // namespace
OakCommonSubtitleParams *oakcommon_subtitleparams_init(void)
OakSubtitleParams oakcommon_subtitleparams_init(void)
{
try {
return new OakCommonSubtitleParams{olive::SubtitleParams()};
return oakcommon::make_handle<OakSubtitleParams>(
olive::SubtitleParams());
} catch (...) {
return nullptr;
OakSubtitleParams h = {};
return h;
}
}
void oakcommon_subtitleparams_free(OakCommonSubtitleParams *params)
OakSubtitleParams oakcommon_subtitleparams_init_from_native(
const olive::SubtitleParams *src)
{
delete params;
if (!src) {
OakSubtitleParams h = {};
return h;
}
try {
return oakcommon::make_handle<OakSubtitleParams>(
olive::SubtitleParams(*src));
} catch (...) {
OakSubtitleParams h = {};
return h;
}
}
void oakcommon_subtitleparams_free(OakSubtitleParams *params)
{
oakcommon::free_handle(params);
}
int oakcommon_subtitleparams_get_stream_index(
OakCommonSubtitleParams *params, int *index)
OakSubtitleParams params, int *index)
{
if (!params || !index)
if (!sp(params) || !index)
return OAKCOMMON_E_INVALID;
*index = params->impl.stream_index();
*index = sp(params)->stream_index();
return OAKCOMMON_OK;
}
int oakcommon_subtitleparams_set_stream_index(
OakCommonSubtitleParams *params, int index)
OakSubtitleParams params, int index)
{
if (!params)
if (!sp(params))
return OAKCOMMON_E_INVALID;
params->impl.set_stream_index(index);
sp(params)->set_stream_index(index);
return OAKCOMMON_OK;
}
int oakcommon_subtitleparams_get_enabled(OakCommonSubtitleParams *params,
int oakcommon_subtitleparams_get_enabled(OakSubtitleParams params,
int *enabled)
{
if (!params || !enabled)
if (!sp(params) || !enabled)
return OAKCOMMON_E_INVALID;
*enabled = params->impl.enabled() ? 1 : 0;
*enabled = sp(params)->enabled() ? 1 : 0;
return OAKCOMMON_OK;
}
int oakcommon_subtitleparams_set_enabled(OakCommonSubtitleParams *params,
int oakcommon_subtitleparams_set_enabled(OakSubtitleParams params,
int enabled)
{
if (!params)
if (!sp(params))
return OAKCOMMON_E_INVALID;
params->impl.set_enabled(enabled != 0);
sp(params)->set_enabled(enabled != 0);
return OAKCOMMON_OK;
}
int oakcommon_subtitleparams_is_valid(OakCommonSubtitleParams *params,
int oakcommon_subtitleparams_is_valid(OakSubtitleParams params,
int *is_valid)
{
if (!params || !is_valid)
if (!sp(params) || !is_valid)
return OAKCOMMON_E_INVALID;
*is_valid = params->impl.is_valid() ? 1 : 0;
*is_valid = sp(params)->is_valid() ? 1 : 0;
return OAKCOMMON_OK;
}
int oakcommon_subtitleparams_count(OakCommonSubtitleParams *params, int *count)
int oakcommon_subtitleparams_count(OakSubtitleParams params, int *count)
{
if (!params || !count)
if (!sp(params) || !count)
return OAKCOMMON_E_INVALID;
*count = (int)params->impl.size();
*count = (int)sp(params)->size();
return OAKCOMMON_OK;
}
int oakcommon_subtitleparams_duration(OakCommonSubtitleParams *params,
int oakcommon_subtitleparams_duration(OakSubtitleParams params,
int *numerator, int *denominator)
{
if (!params || !numerator || !denominator)
if (!sp(params) || !numerator || !denominator)
return OAKCOMMON_E_INVALID;
olive::core::Rational d = params->impl.duration();
olive::core::Rational d = sp(params)->duration();
*numerator = d.numerator();
*denominator = d.denominator();
return OAKCOMMON_OK;
}
int oakcommon_subtitleparams_add_subtitle(OakCommonSubtitleParams *params,
int oakcommon_subtitleparams_add_subtitle(OakSubtitleParams params,
int in_num, int in_den, int out_num,
int out_den, const char *text)
{
if (!params || !text)
if (!sp(params) || !text)
return OAKCOMMON_E_INVALID;
try {
params->impl.push_back(olive::Subtitle(
sp(params)->push_back(olive::Subtitle(
olive::core::TimeRange(olive::core::Rational(in_num, in_den),
olive::core::Rational(out_num, out_den)),
text));
@@ -136,23 +159,23 @@ int oakcommon_subtitleparams_add_subtitle(OakCommonSubtitleParams *params,
}
}
int oakcommon_subtitleparams_clear(OakCommonSubtitleParams *params)
int oakcommon_subtitleparams_clear(OakSubtitleParams params)
{
if (!params)
if (!sp(params))
return OAKCOMMON_E_INVALID;
params->impl.clear();
sp(params)->clear();
return OAKCOMMON_OK;
}
int oakcommon_subtitleparams_get_subtitle(OakCommonSubtitleParams *params,
int oakcommon_subtitleparams_get_subtitle(OakSubtitleParams params,
int index, int *in_num, int *in_den,
int *out_num, int *out_den)
{
if (!params || !in_num || !in_den || !out_num || !out_den)
if (!sp(params) || !in_num || !in_den || !out_num || !out_den)
return OAKCOMMON_E_INVALID;
if (index < 0 || index >= (int)params->impl.size())
if (index < 0 || index >= (int)sp(params)->size())
return OAKCOMMON_E_NOT_FOUND;
const olive::Subtitle &s = params->impl.at(index);
const olive::Subtitle &s = sp(params)->at(index);
olive::core::Rational in = s.time().in();
olive::core::Rational out = s.time().out();
*in_num = in.numerator();
@@ -162,16 +185,16 @@ int oakcommon_subtitleparams_get_subtitle(OakCommonSubtitleParams *params,
return OAKCOMMON_OK;
}
int oakcommon_subtitleparams_get_subtitle_text(OakCommonSubtitleParams *params,
int oakcommon_subtitleparams_get_subtitle_text(OakSubtitleParams params,
int index, char *buf,
int buf_size)
{
if (!params)
if (!sp(params))
return OAKCOMMON_E_INVALID;
if (index < 0 || index >= (int)params->impl.size())
if (index < 0 || index >= (int)sp(params)->size())
return OAKCOMMON_E_NOT_FOUND;
try {
return copy_string(params->impl.at(index).text(), buf, buf_size);
return copy_string(sp(params)->at(index).text(), buf, buf_size);
} catch (...) {
return OAKCOMMON_E_FAILED;
}
@@ -187,10 +210,10 @@ int oakcommon_subtitleparams_generate_ass_header(char *buf, int buf_size)
}
}
int oakcommon_subtitleparams_load_xml(OakCommonSubtitleParams *params,
int oakcommon_subtitleparams_load_xml(OakSubtitleParams params,
const char *xml)
{
if (!params || !xml)
if (!sp(params) || !xml)
return OAKCOMMON_E_INVALID;
try {
olive::XmlStreamReader reader(xml);
@@ -199,22 +222,22 @@ int oakcommon_subtitleparams_load_xml(OakCommonSubtitleParams *params,
// Position on the root element; load() consumes its children.
if (!olive::xml_read_next_start_element(&reader))
return OAKCOMMON_E_FAILED;
params->impl.load(&reader);
sp(params)->load(&reader);
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_subtitleparams_save_xml(OakCommonSubtitleParams *params,
int oakcommon_subtitleparams_save_xml(OakSubtitleParams params,
char *buf, int buf_size)
{
if (!params)
if (!sp(params))
return OAKCOMMON_E_INVALID;
try {
olive::XmlStreamWriter writer;
writer.write_start_element("subtitleparams");
params->impl.save(&writer);
sp(params)->save(&writer);
writer.write_end_element();
return copy_string(writer.output(), buf, buf_size);
} catch (...) {
+200 -132
View File
@@ -23,10 +23,20 @@
#include <cstring>
#include "../src/videoparams.h"
#include "refcounted.h"
struct OakCommonVideoParams {
olive::VideoParams impl;
};
namespace
{
/**
* @brief Recover the boxed olive::VideoParams from a handle (NULL-safe).
*/
olive::VideoParams *vp(OakVideoParams params)
{
return oakcommon::handle_impl<olive::VideoParams>(params.ctx);
}
} // namespace
namespace
{
@@ -51,317 +61,345 @@ int get_rational(const olive::core::Rational &r, int *numerator,
} // namespace
OakCommonVideoParams *oakcommon_videoparams_init(void)
OakVideoParams oakcommon_videoparams_init(void)
{
try {
return new OakCommonVideoParams{olive::VideoParams()};
return oakcommon::make_handle<OakVideoParams>(
olive::VideoParams());
} catch (...) {
return nullptr;
OakVideoParams h = {};
return h;
}
}
OakCommonVideoParams *oakcommon_videoparams_init_basic(
OakVideoParams oakcommon_videoparams_init_basic(
int width, int height, int pixel_format, int nb_channels,
int pixel_aspect_num, int pixel_aspect_den, int interlacing, int divider)
{
try {
return new OakCommonVideoParams{olive::VideoParams(
width, height,
static_cast<olive::core::PixelFormat::Format>(pixel_format),
nb_channels,
olive::core::Rational(pixel_aspect_num, pixel_aspect_den),
static_cast<olive::VideoParams::Interlacing>(interlacing),
divider)};
return oakcommon::make_handle<OakVideoParams>(
olive::VideoParams(
width, height,
static_cast<olive::core::PixelFormat::Format>(pixel_format),
nb_channels,
olive::core::Rational(pixel_aspect_num, pixel_aspect_den),
static_cast<olive::VideoParams::Interlacing>(interlacing),
divider));
} catch (...) {
return nullptr;
OakVideoParams h = {};
return h;
}
}
OakCommonVideoParams *oakcommon_videoparams_init_with_time_base(
OakVideoParams oakcommon_videoparams_init_with_time_base(
int width, int height, int time_base_num, int time_base_den,
int pixel_format, int nb_channels, int pixel_aspect_num,
int pixel_aspect_den, int interlacing, int divider)
{
try {
return new OakCommonVideoParams{olive::VideoParams(
width, height,
olive::core::Rational(time_base_num, time_base_den),
static_cast<olive::core::PixelFormat::Format>(pixel_format),
nb_channels,
olive::core::Rational(pixel_aspect_num, pixel_aspect_den),
static_cast<olive::VideoParams::Interlacing>(interlacing),
divider)};
return oakcommon::make_handle<OakVideoParams>(
olive::VideoParams(
width, height,
olive::core::Rational(time_base_num, time_base_den),
static_cast<olive::core::PixelFormat::Format>(pixel_format),
nb_channels,
olive::core::Rational(pixel_aspect_num, pixel_aspect_den),
static_cast<olive::VideoParams::Interlacing>(interlacing),
divider));
} catch (...) {
return nullptr;
OakVideoParams h = {};
return h;
}
}
void oakcommon_videoparams_free(OakCommonVideoParams *params)
OakVideoParams oakcommon_videoparams_init_from_native(
const olive::VideoParams *src)
{
delete params;
if (!src) {
OakVideoParams h = {};
return h;
}
try {
return oakcommon::make_handle<OakVideoParams>(
olive::VideoParams(*src));
} catch (...) {
OakVideoParams h = {};
return h;
}
}
const olive::VideoParams *oakcommon_videoparams_get_native(
OakVideoParams params)
{
return vp(params);
}
void oakcommon_videoparams_free(OakVideoParams *params)
{
oakcommon::free_handle(params);
}
#define OAKCOMMON_VIDEOPARAMS_INT_GETTER(name, expr) \
int oakcommon_videoparams_get_##name(OakCommonVideoParams *params, \
int oakcommon_videoparams_get_##name(OakVideoParams params, \
int *out) \
{ \
if (!params || !out) \
if (!vp(params) || !out) \
return OAKCOMMON_E_INVALID; \
*out = (expr); \
return OAKCOMMON_OK; \
}
#define OAKCOMMON_VIDEOPARAMS_INT_SETTER(name, stmt) \
int oakcommon_videoparams_set_##name(OakCommonVideoParams *params, \
int oakcommon_videoparams_set_##name(OakVideoParams params, \
int value) \
{ \
if (!params) \
if (!vp(params)) \
return OAKCOMMON_E_INVALID; \
stmt; \
return OAKCOMMON_OK; \
}
OAKCOMMON_VIDEOPARAMS_INT_GETTER(width, params->impl.width())
OAKCOMMON_VIDEOPARAMS_INT_SETTER(width, params->impl.set_width(value))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(height, params->impl.height())
OAKCOMMON_VIDEOPARAMS_INT_SETTER(height, params->impl.set_height(value))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(depth, params->impl.depth())
OAKCOMMON_VIDEOPARAMS_INT_SETTER(depth, params->impl.set_depth(value))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(is_3d, params->impl.is_3d() ? 1 : 0)
OAKCOMMON_VIDEOPARAMS_INT_GETTER(format, static_cast<int>(params->impl.format()))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(width, vp(params)->width())
OAKCOMMON_VIDEOPARAMS_INT_SETTER(width, vp(params)->set_width(value))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(height, vp(params)->height())
OAKCOMMON_VIDEOPARAMS_INT_SETTER(height, vp(params)->set_height(value))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(depth, vp(params)->depth())
OAKCOMMON_VIDEOPARAMS_INT_SETTER(depth, vp(params)->set_depth(value))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(is_3d, vp(params)->is_3d() ? 1 : 0)
OAKCOMMON_VIDEOPARAMS_INT_GETTER(format, static_cast<int>(vp(params)->format()))
OAKCOMMON_VIDEOPARAMS_INT_SETTER(
format, params->impl.set_format(
format, vp(params)->set_format(
static_cast<olive::core::PixelFormat::Format>(value)))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(channel_count, params->impl.channel_count())
OAKCOMMON_VIDEOPARAMS_INT_GETTER(channel_count, vp(params)->channel_count())
OAKCOMMON_VIDEOPARAMS_INT_SETTER(channel_count,
params->impl.set_channel_count(value))
vp(params)->set_channel_count(value))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(interlacing,
static_cast<int>(params->impl.interlacing()))
static_cast<int>(vp(params)->interlacing()))
OAKCOMMON_VIDEOPARAMS_INT_SETTER(
interlacing,
params->impl.set_interlacing(
vp(params)->set_interlacing(
static_cast<olive::VideoParams::Interlacing>(value)))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(divider, params->impl.divider())
OAKCOMMON_VIDEOPARAMS_INT_SETTER(divider, params->impl.set_divider(value))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(enabled, params->impl.enabled() ? 1 : 0)
OAKCOMMON_VIDEOPARAMS_INT_SETTER(enabled, params->impl.set_enabled(value != 0))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(stream_index, params->impl.stream_index())
OAKCOMMON_VIDEOPARAMS_INT_GETTER(divider, vp(params)->divider())
OAKCOMMON_VIDEOPARAMS_INT_SETTER(divider, vp(params)->set_divider(value))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(enabled, vp(params)->enabled() ? 1 : 0)
OAKCOMMON_VIDEOPARAMS_INT_SETTER(enabled, vp(params)->set_enabled(value != 0))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(stream_index, vp(params)->stream_index())
OAKCOMMON_VIDEOPARAMS_INT_SETTER(stream_index,
params->impl.set_stream_index(value))
vp(params)->set_stream_index(value))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(video_type,
static_cast<int>(params->impl.video_type()))
static_cast<int>(vp(params)->video_type()))
OAKCOMMON_VIDEOPARAMS_INT_SETTER(
video_type,
params->impl.set_video_type(static_cast<olive::VideoParams::Type>(value)))
vp(params)->set_video_type(static_cast<olive::VideoParams::Type>(value)))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(premultiplied_alpha,
params->impl.premultiplied_alpha() ? 1 : 0)
vp(params)->premultiplied_alpha() ? 1 : 0)
OAKCOMMON_VIDEOPARAMS_INT_SETTER(premultiplied_alpha,
params->impl.set_premultiplied_alpha(
vp(params)->set_premultiplied_alpha(
value != 0))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(color_range,
static_cast<int>(params->impl.color_range()))
static_cast<int>(vp(params)->color_range()))
OAKCOMMON_VIDEOPARAMS_INT_SETTER(
color_range, params->impl.set_color_range(
color_range, vp(params)->set_color_range(
static_cast<olive::VideoParams::ColorRange>(value)))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(color_primaries,
params->impl.color_primaries())
vp(params)->color_primaries())
OAKCOMMON_VIDEOPARAMS_INT_SETTER(color_primaries,
params->impl.set_color_primaries(value))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(color_transfer, params->impl.color_transfer())
vp(params)->set_color_primaries(value))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(color_transfer, vp(params)->color_transfer())
OAKCOMMON_VIDEOPARAMS_INT_SETTER(color_transfer,
params->impl.set_color_transfer(value))
vp(params)->set_color_transfer(value))
OAKCOMMON_VIDEOPARAMS_INT_GETTER(square_pixel_width,
params->impl.square_pixel_width())
vp(params)->square_pixel_width())
OAKCOMMON_VIDEOPARAMS_INT_GETTER(effective_width,
params->impl.effective_width())
vp(params)->effective_width())
OAKCOMMON_VIDEOPARAMS_INT_GETTER(effective_height,
params->impl.effective_height())
vp(params)->effective_height())
OAKCOMMON_VIDEOPARAMS_INT_GETTER(effective_depth,
params->impl.effective_depth())
OAKCOMMON_VIDEOPARAMS_INT_GETTER(is_valid, params->impl.is_valid() ? 1 : 0)
vp(params)->effective_depth())
OAKCOMMON_VIDEOPARAMS_INT_GETTER(is_valid, vp(params)->is_valid() ? 1 : 0)
OAKCOMMON_VIDEOPARAMS_INT_GETTER(bytes_per_channel,
params->impl.get_bytes_per_channel())
vp(params)->get_bytes_per_channel())
OAKCOMMON_VIDEOPARAMS_INT_GETTER(bytes_per_pixel,
params->impl.get_bytes_per_pixel())
OAKCOMMON_VIDEOPARAMS_INT_GETTER(buffer_size, params->impl.get_buffer_size())
vp(params)->get_bytes_per_pixel())
OAKCOMMON_VIDEOPARAMS_INT_GETTER(buffer_size, vp(params)->get_buffer_size())
int oakcommon_videoparams_get_x(OakCommonVideoParams *params, float *x)
int oakcommon_videoparams_get_x(OakVideoParams params, float *x)
{
if (!params || !x)
if (!vp(params) || !x)
return OAKCOMMON_E_INVALID;
*x = params->impl.x();
*x = vp(params)->x();
return OAKCOMMON_OK;
}
int oakcommon_videoparams_set_x(OakCommonVideoParams *params, float x)
int oakcommon_videoparams_set_x(OakVideoParams params, float x)
{
if (!params)
if (!vp(params))
return OAKCOMMON_E_INVALID;
params->impl.set_x(x);
vp(params)->set_x(x);
return OAKCOMMON_OK;
}
int oakcommon_videoparams_get_y(OakCommonVideoParams *params, float *y)
int oakcommon_videoparams_get_y(OakVideoParams params, float *y)
{
if (!params || !y)
if (!vp(params) || !y)
return OAKCOMMON_E_INVALID;
*y = params->impl.y();
*y = vp(params)->y();
return OAKCOMMON_OK;
}
int oakcommon_videoparams_set_y(OakCommonVideoParams *params, float y)
int oakcommon_videoparams_set_y(OakVideoParams params, float y)
{
if (!params)
if (!vp(params))
return OAKCOMMON_E_INVALID;
params->impl.set_y(y);
vp(params)->set_y(y);
return OAKCOMMON_OK;
}
int oakcommon_videoparams_get_start_time(OakCommonVideoParams *params,
int oakcommon_videoparams_get_start_time(OakVideoParams params,
int64_t *start_time)
{
if (!params || !start_time)
if (!vp(params) || !start_time)
return OAKCOMMON_E_INVALID;
*start_time = params->impl.start_time();
*start_time = vp(params)->start_time();
return OAKCOMMON_OK;
}
int oakcommon_videoparams_set_start_time(OakCommonVideoParams *params,
int oakcommon_videoparams_set_start_time(OakVideoParams params,
int64_t start_time)
{
if (!params)
if (!vp(params))
return OAKCOMMON_E_INVALID;
params->impl.set_start_time(start_time);
vp(params)->set_start_time(start_time);
return OAKCOMMON_OK;
}
int oakcommon_videoparams_get_duration(OakCommonVideoParams *params,
int oakcommon_videoparams_get_duration(OakVideoParams params,
int64_t *duration)
{
if (!params || !duration)
if (!vp(params) || !duration)
return OAKCOMMON_E_INVALID;
*duration = params->impl.duration();
*duration = vp(params)->duration();
return OAKCOMMON_OK;
}
int oakcommon_videoparams_set_duration(OakCommonVideoParams *params,
int oakcommon_videoparams_set_duration(OakVideoParams params,
int64_t duration)
{
if (!params)
if (!vp(params))
return OAKCOMMON_E_INVALID;
params->impl.set_duration(duration);
vp(params)->set_duration(duration);
return OAKCOMMON_OK;
}
int oakcommon_videoparams_get_time_base(OakCommonVideoParams *params,
int oakcommon_videoparams_get_time_base(OakVideoParams params,
int *numerator, int *denominator)
{
if (!params)
if (!vp(params))
return OAKCOMMON_E_INVALID;
return get_rational(params->impl.time_base(), numerator, denominator);
return get_rational(vp(params)->time_base(), numerator, denominator);
}
int oakcommon_videoparams_set_time_base(OakCommonVideoParams *params,
int oakcommon_videoparams_set_time_base(OakVideoParams params,
int numerator, int denominator)
{
if (!params)
if (!vp(params))
return OAKCOMMON_E_INVALID;
params->impl.set_time_base(olive::core::Rational(numerator, denominator));
vp(params)->set_time_base(olive::core::Rational(numerator, denominator));
return OAKCOMMON_OK;
}
int oakcommon_videoparams_get_frame_rate(OakCommonVideoParams *params,
int oakcommon_videoparams_get_frame_rate(OakVideoParams params,
int *numerator, int *denominator)
{
if (!params)
if (!vp(params))
return OAKCOMMON_E_INVALID;
return get_rational(params->impl.frame_rate(), numerator, denominator);
return get_rational(vp(params)->frame_rate(), numerator, denominator);
}
int oakcommon_videoparams_set_frame_rate(OakCommonVideoParams *params,
int oakcommon_videoparams_set_frame_rate(OakVideoParams params,
int numerator, int denominator)
{
if (!params)
if (!vp(params))
return OAKCOMMON_E_INVALID;
params->impl.set_frame_rate(olive::core::Rational(numerator, denominator));
vp(params)->set_frame_rate(olive::core::Rational(numerator, denominator));
return OAKCOMMON_OK;
}
int oakcommon_videoparams_frame_rate_as_time_base(OakCommonVideoParams *params,
int oakcommon_videoparams_frame_rate_as_time_base(OakVideoParams params,
int *numerator,
int *denominator)
{
if (!params)
if (!vp(params))
return OAKCOMMON_E_INVALID;
return get_rational(params->impl.frame_rate_as_time_base(), numerator,
return get_rational(vp(params)->frame_rate_as_time_base(), numerator,
denominator);
}
int oakcommon_videoparams_get_pixel_aspect_ratio(OakCommonVideoParams *params,
int oakcommon_videoparams_get_pixel_aspect_ratio(OakVideoParams params,
int *numerator,
int *denominator)
{
if (!params)
if (!vp(params))
return OAKCOMMON_E_INVALID;
return get_rational(params->impl.pixel_aspect_ratio(), numerator,
return get_rational(vp(params)->pixel_aspect_ratio(), numerator,
denominator);
}
int oakcommon_videoparams_set_pixel_aspect_ratio(OakCommonVideoParams *params,
int oakcommon_videoparams_set_pixel_aspect_ratio(OakVideoParams params,
int numerator, int denominator)
{
if (!params)
if (!vp(params))
return OAKCOMMON_E_INVALID;
params->impl.set_pixel_aspect_ratio(
vp(params)->set_pixel_aspect_ratio(
olive::core::Rational(numerator, denominator));
return OAKCOMMON_OK;
}
int oakcommon_videoparams_get_colorspace(OakCommonVideoParams *params,
int oakcommon_videoparams_get_colorspace(OakVideoParams params,
char *buf, int buf_size)
{
if (!params)
if (!vp(params))
return OAKCOMMON_E_INVALID;
try {
return copy_string(params->impl.colorspace(), buf, buf_size);
return copy_string(vp(params)->colorspace(), buf, buf_size);
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_videoparams_set_colorspace(OakCommonVideoParams *params,
int oakcommon_videoparams_set_colorspace(OakVideoParams params,
const char *colorspace)
{
if (!params || !colorspace)
if (!vp(params) || !colorspace)
return OAKCOMMON_E_INVALID;
params->impl.set_colorspace(colorspace);
vp(params)->set_colorspace(colorspace);
return OAKCOMMON_OK;
}
int oakcommon_videoparams_get_time_in_timebase_units(
OakCommonVideoParams *params, int time_num, int time_den,
OakVideoParams params, int time_num, int time_den,
int64_t *timestamp)
{
if (!params || !timestamp)
if (!vp(params) || !timestamp)
return OAKCOMMON_E_INVALID;
*timestamp = params->impl.get_time_in_timebase_units(
*timestamp = vp(params)->get_time_in_timebase_units(
olive::core::Rational(time_num, time_den));
return OAKCOMMON_OK;
}
int oakcommon_videoparams_equals(OakCommonVideoParams *params,
OakCommonVideoParams *other, int *equal)
int oakcommon_videoparams_equals(OakVideoParams params,
OakVideoParams other, int *equal)
{
if (!params || !other || !equal)
if (!vp(params) || !vp(other) || !equal)
return OAKCOMMON_E_INVALID;
*equal = (params->impl == other->impl) ? 1 : 0;
*equal = (*vp(params) == *vp(other)) ? 1 : 0;
return OAKCOMMON_OK;
}
int oakcommon_videoparams_load_xml(OakCommonVideoParams *params,
int oakcommon_videoparams_load_xml(OakVideoParams params,
const char *xml)
{
if (!params || !xml)
if (!vp(params) || !xml)
return OAKCOMMON_E_INVALID;
try {
olive::XmlStreamReader reader(xml);
@@ -370,22 +408,22 @@ int oakcommon_videoparams_load_xml(OakCommonVideoParams *params,
// Position on the root element; load() consumes its children.
if (!olive::xml_read_next_start_element(&reader))
return OAKCOMMON_E_FAILED;
params->impl.load(&reader);
vp(params)->load(&reader);
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_videoparams_save_xml(OakCommonVideoParams *params, char *buf,
int oakcommon_videoparams_save_xml(OakVideoParams params, char *buf,
int buf_size)
{
if (!params)
if (!vp(params))
return OAKCOMMON_E_INVALID;
try {
olive::XmlStreamWriter writer;
writer.write_start_element("videoparams");
params->impl.save(&writer);
vp(params)->save(&writer);
writer.write_end_element();
return copy_string(writer.output(), buf, buf_size);
} catch (...) {
@@ -476,3 +514,33 @@ int oakcommon_videoparams_frame_rate_to_string(int numerator, int denominator,
return OAKCOMMON_E_FAILED;
}
}
static olive::PixelFormat convert_to_olive_format(OakPixelFormat format)
{
switch (format) {
case OAKCOMMON_PIXEL_FORMAT_INVALID:
return olive::PixelFormat::invalid;
case OAKCOMMON_PIXEL_FORMAT_COUNT:
return olive::PixelFormat::count;
case OAKCOMMON_PIXEL_FORMAT_U8:
return olive::PixelFormat::u8;
case OAKCOMMON_PIXEL_FORMAT_U10:
return olive::PixelFormat::u10;
case OAKCOMMON_PIXEL_FORMAT_U16:
return olive::PixelFormat::u16;
case OAKCOMMON_PIXEL_FORMAT_F16:
return olive::PixelFormat::f16;
case OAKCOMMON_PIXEL_FORMAT_F32:
return olive::PixelFormat::f32;
}
return olive::PixelFormat::invalid;
}
int oakcommon_videoparams_static_get_bytes_per_channel(OakPixelFormat format)
{
return olive::VideoParams::get_bytes_per_channel(convert_to_olive_format(format));
}
int oakcommon_videoparams_static_get_bytes_per_pixel(OakPixelFormat format, int channels)
{
return olive::VideoParams::get_bytes_per_pixel(convert_to_olive_format(format), channels);
}
+89 -68
View File
@@ -24,24 +24,40 @@
#include <new>
#include "../src/xmlutils.h"
#include "refcounted.h"
struct OakCommonXmlReader {
namespace
{
/**
* @brief Reader state boxed behind the handle's ctx pointer.
*/
struct XmlReaderState {
olive::XmlStreamReader reader;
std::string cached_text;
bool has_cached_text = false;
explicit OakCommonXmlReader(const char *data)
explicit XmlReaderState(const char *data)
: reader(data)
{
}
};
struct OakCommonXmlWriter {
olive::XmlStreamWriter writer;
};
namespace
/**
* @brief Recover the boxed reader state from a handle (NULL-safe).
*/
XmlReaderState *xr(OakXmlReader reader)
{
return oakcommon::handle_impl<XmlReaderState>(reader.ctx);
}
/**
* @brief Recover the boxed writer from a handle (NULL-safe).
*/
olive::XmlStreamWriter *xw(OakXmlWriter writer)
{
return oakcommon::handle_impl<olive::XmlStreamWriter>(writer.ctx);
}
/**
* @brief Copy @p value into the two-stage string buffer.
@@ -62,99 +78,102 @@ int copy_string(const std::string &value, char *buf, int buf_size)
extern "C" {
OakCommonXmlReader *oakcommon_xml_reader_init(const char *data)
OakXmlReader oakcommon_xml_reader_init(const char *data)
{
OakXmlReader h = {};
if (!data)
return nullptr;
return h;
try {
return new (std::nothrow) OakCommonXmlReader(data);
return oakcommon::make_handle<OakXmlReader>(
XmlReaderState(data));
} catch (...) {
return nullptr;
OakXmlReader empty = {};
return empty;
}
}
void oakcommon_xml_reader_free(OakCommonXmlReader *reader)
void oakcommon_xml_reader_free(OakXmlReader *reader)
{
delete reader;
oakcommon::free_handle(reader);
}
int oakcommon_xml_reader_read_next_start_element(OakCommonXmlReader *reader,
int oakcommon_xml_reader_read_next_start_element(OakXmlReader reader,
int *found)
{
if (!reader || !found)
if (!xr(reader) || !found)
return OAKCOMMON_E_INVALID;
try {
reader->has_cached_text = false;
*found = olive::xml_read_next_start_element(&reader->reader) ? 1 : 0;
xr(reader)->has_cached_text = false;
*found = olive::xml_read_next_start_element(&xr(reader)->reader) ? 1 : 0;
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_xml_reader_name(OakCommonXmlReader *reader, char *buf,
int oakcommon_xml_reader_name(OakXmlReader reader, char *buf,
int buf_size)
{
if (!reader)
if (!xr(reader))
return OAKCOMMON_E_INVALID;
try {
return copy_string(reader->reader.name(), buf, buf_size);
return copy_string(xr(reader)->reader.name(), buf, buf_size);
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_xml_reader_read_element_text(OakCommonXmlReader *reader,
int oakcommon_xml_reader_read_element_text(OakXmlReader reader,
char *buf, int buf_size)
{
if (!reader)
if (!xr(reader))
return OAKCOMMON_E_INVALID;
try {
// read_element_text() consumes the stream, so cache the result to
// keep the two-stage (size query then copy) buffer convention working.
if (!reader->has_cached_text) {
reader->cached_text = reader->reader.read_element_text();
reader->has_cached_text = true;
if (!xr(reader)->has_cached_text) {
xr(reader)->cached_text = xr(reader)->reader.read_element_text();
xr(reader)->has_cached_text = true;
}
return copy_string(reader->cached_text, buf, buf_size);
return copy_string(xr(reader)->cached_text, buf, buf_size);
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_xml_reader_skip_current_element(OakCommonXmlReader *reader)
int oakcommon_xml_reader_skip_current_element(OakXmlReader reader)
{
if (!reader)
if (!xr(reader))
return OAKCOMMON_E_INVALID;
try {
reader->has_cached_text = false;
reader->reader.skip_current_element();
xr(reader)->has_cached_text = false;
xr(reader)->reader.skip_current_element();
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_xml_reader_attribute_count(OakCommonXmlReader *reader,
int oakcommon_xml_reader_attribute_count(OakXmlReader reader,
int *count)
{
if (!reader || !count)
if (!xr(reader) || !count)
return OAKCOMMON_E_INVALID;
try {
*count = static_cast<int>(reader->reader.attributes().size());
*count = static_cast<int>(xr(reader)->reader.attributes().size());
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_xml_reader_attribute_name(OakCommonXmlReader *reader, int index,
int oakcommon_xml_reader_attribute_name(OakXmlReader reader, int index,
char *buf, int buf_size)
{
if (!reader)
if (!xr(reader))
return OAKCOMMON_E_INVALID;
try {
const auto &attrs = reader->reader.attributes();
const auto &attrs = xr(reader)->reader.attributes();
if (index < 0 || index >= static_cast<int>(attrs.size()))
return OAKCOMMON_E_NOT_FOUND;
return copy_string(attrs[index].name, buf, buf_size);
@@ -163,13 +182,13 @@ int oakcommon_xml_reader_attribute_name(OakCommonXmlReader *reader, int index,
}
}
int oakcommon_xml_reader_attribute_value(OakCommonXmlReader *reader,
int oakcommon_xml_reader_attribute_value(OakXmlReader reader,
int index, char *buf, int buf_size)
{
if (!reader)
if (!xr(reader))
return OAKCOMMON_E_INVALID;
try {
const auto &attrs = reader->reader.attributes();
const auto &attrs = xr(reader)->reader.attributes();
if (index < 0 || index >= static_cast<int>(attrs.size()))
return OAKCOMMON_E_NOT_FOUND;
return copy_string(attrs[index].value, buf, buf_size);
@@ -178,117 +197,119 @@ int oakcommon_xml_reader_attribute_value(OakCommonXmlReader *reader,
}
}
int oakcommon_xml_reader_has_error(OakCommonXmlReader *reader,
int oakcommon_xml_reader_has_error(OakXmlReader reader,
int *has_error)
{
if (!reader || !has_error)
if (!xr(reader) || !has_error)
return OAKCOMMON_E_INVALID;
try {
*has_error = reader->reader.has_error() ? 1 : 0;
*has_error = xr(reader)->reader.has_error() ? 1 : 0;
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
OakCommonXmlWriter *oakcommon_xml_writer_init(void)
OakXmlWriter oakcommon_xml_writer_init(void)
{
try {
return new (std::nothrow) OakCommonXmlWriter();
return oakcommon::make_handle<OakXmlWriter>(
olive::XmlStreamWriter());
} catch (...) {
return nullptr;
OakXmlWriter h = {};
return h;
}
}
void oakcommon_xml_writer_free(OakCommonXmlWriter *writer)
void oakcommon_xml_writer_free(OakXmlWriter *writer)
{
delete writer;
oakcommon::free_handle(writer);
}
int oakcommon_xml_writer_write_start_element(OakCommonXmlWriter *writer,
int oakcommon_xml_writer_write_start_element(OakXmlWriter writer,
const char *name)
{
if (!writer || !name)
if (!xw(writer) || !name)
return OAKCOMMON_E_INVALID;
try {
writer->writer.write_start_element(name);
xw(writer)->write_start_element(name);
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_xml_writer_write_attribute(OakCommonXmlWriter *writer,
int oakcommon_xml_writer_write_attribute(OakXmlWriter writer,
const char *name, const char *value)
{
if (!writer || !name || !value)
if (!xw(writer) || !name || !value)
return OAKCOMMON_E_INVALID;
try {
writer->writer.write_attribute(name, value);
xw(writer)->write_attribute(name, value);
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_xml_writer_write_characters(OakCommonXmlWriter *writer,
int oakcommon_xml_writer_write_characters(OakXmlWriter writer,
const char *text)
{
if (!writer || !text)
if (!xw(writer) || !text)
return OAKCOMMON_E_INVALID;
try {
writer->writer.write_characters(text);
xw(writer)->write_characters(text);
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_xml_writer_write_text_element(OakCommonXmlWriter *writer,
int oakcommon_xml_writer_write_text_element(OakXmlWriter writer,
const char *name,
const char *text)
{
if (!writer || !name || !text)
if (!xw(writer) || !name || !text)
return OAKCOMMON_E_INVALID;
try {
writer->writer.write_text_element(name, text);
xw(writer)->write_text_element(name, text);
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_xml_writer_write_end_element(OakCommonXmlWriter *writer)
int oakcommon_xml_writer_write_end_element(OakXmlWriter writer)
{
if (!writer)
if (!xw(writer))
return OAKCOMMON_E_INVALID;
try {
writer->writer.write_end_element();
xw(writer)->write_end_element();
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_xml_writer_write_end_document(OakCommonXmlWriter *writer)
int oakcommon_xml_writer_write_end_document(OakXmlWriter writer)
{
if (!writer)
if (!xw(writer))
return OAKCOMMON_E_INVALID;
try {
writer->writer.write_end_document();
xw(writer)->write_end_document();
return OAKCOMMON_OK;
} catch (...) {
return OAKCOMMON_E_FAILED;
}
}
int oakcommon_xml_writer_output(OakCommonXmlWriter *writer, char *buf,
int oakcommon_xml_writer_output(OakXmlWriter writer, char *buf,
int buf_size)
{
if (!writer)
if (!xw(writer))
return OAKCOMMON_E_INVALID;
try {
return copy_string(writer->writer.output(), buf, buf_size);
return copy_string(xw(writer)->output(), buf, buf_size);
} catch (...) {
return OAKCOMMON_E_FAILED;
}
+98 -5
View File
@@ -20,12 +20,39 @@
#include "debug.h"
#include <atomic>
#include <cstdio>
#include <cstring>
#include <mutex>
namespace olive
{
namespace
{
/**
* @brief Minimum level emitted by log_message(); default k_debug_info.
*/
std::atomic<int> g_log_level{ k_debug_info };
/**
* @brief Guards g_log_sink (std::function is not atomic).
*/
std::mutex g_sink_mutex;
LogSink g_log_sink;
/**
* @brief Default sink: stderr + flush, same as debug_handler().
*/
void stderr_sink(const std::string &line)
{
fputs(line.c_str(), stderr);
fflush(stderr);
}
} // namespace
int debug_level_name(int level, char *buf, int buf_size)
{
const char *name;
@@ -58,16 +85,82 @@ int debug_level_name(int level, char *buf, int buf_size)
return needed;
}
void debug_handler(int level, const char *msg)
std::string format_log_line(int level, const std::string &msg)
{
char level_name[16];
debug_level_name(level, level_name, sizeof(level_name));
fprintf(stderr, "[%s] %s\n", level_name, msg ? msg : "");
// Always flush so debug messages appear immediately, even on
// platforms that buffer stderr.
fflush(stderr);
std::string line;
line.reserve(strlen(level_name) + msg.size() + 4);
line += '[';
line += level_name;
line += "] ";
line += msg;
line += '\n';
return line;
}
void debug_handler(int level, const char *msg)
{
stderr_sink(format_log_line(level, msg ? msg : ""));
}
void set_log_sink(LogSink sink)
{
std::lock_guard<std::mutex> lock(g_sink_mutex);
g_log_sink = std::move(sink);
}
void set_log_level(DebugLevel level)
{
if (level < k_debug_debug || level > k_debug_fatal)
return;
g_log_level.store(static_cast<int>(level), std::memory_order_relaxed);
}
DebugLevel get_log_level()
{
return static_cast<DebugLevel>(g_log_level.load(std::memory_order_relaxed));
}
void log_message(int level, const std::string &msg)
{
if (level < g_log_level.load(std::memory_order_relaxed))
return;
std::string line = format_log_line(level, msg);
LogSink sink;
{
std::lock_guard<std::mutex> lock(g_sink_mutex);
sink = g_log_sink;
}
// Invoke outside the lock so a sink may log re-entrantly.
if (sink)
sink(line);
else
stderr_sink(line);
}
void log_debug(const std::string &msg)
{
log_message(k_debug_debug, msg);
}
void log_info(const std::string &msg)
{
log_message(k_debug_info, msg);
}
void log_warning(const std::string &msg)
{
log_message(k_debug_warning, msg);
}
void log_critical(const std::string &msg)
{
log_message(k_debug_error, msg);
}
}
+61 -1
View File
@@ -21,6 +21,9 @@
#ifndef OAK_DEBUG_H
#define OAK_DEBUG_H
#include <functional>
#include <string>
namespace olive
{
@@ -28,7 +31,8 @@ namespace olive
* @brief Severity levels for debug output.
*
* Replaces Qt's QtMsgType now that the debug handler no longer depends
* on QDebug.
* on QDebug. Values are ordered by ascending severity so that a simple
* `level < threshold` comparison implements level filtering.
*/
enum DebugLevel {
k_debug_debug,
@@ -56,9 +60,65 @@ int debug_level_name(int level, char *buf, int buf_size);
* De-Qt replacement for the old Qt message handler: qDebug() output is
* replaced by fprintf(stderr). A NULL message is treated as an empty
* string. Lines are always flushed so messages appear immediately.
*
* This is the unfiltered low-level writer; use log_message() (or the
* log_debug()/log_info()/... helpers) for level-filtered logging.
*/
void debug_handler(int level, const char *msg);
/**
* @brief Format a log line as "[LEVEL] message\n".
*/
std::string format_log_line(int level, const std::string &msg);
/**
* @brief Destination for filtered log lines.
*
* Receives the fully formatted line ("[LEVEL] message\n"). The default
* sink writes to stderr and flushes, matching debug_handler().
*/
using LogSink = std::function<void(const std::string &line)>;
/**
* @brief Install a custom log sink (e.g. for tests or log files).
*
* Passing an empty LogSink restores the default stderr sink.
* Thread-safe; the sink is invoked without the internal lock held.
*/
void set_log_sink(LogSink sink);
/**
* @brief Set the minimum level emitted by log_message().
*
* Messages with a lower level are dropped. The default is
* k_debug_info. Values outside the DebugLevel range are ignored.
* Thread-safe (atomic store).
*/
void set_log_level(DebugLevel level);
/**
* @brief The current minimum level emitted by log_message().
*/
DebugLevel get_log_level();
/**
* @brief Emit a message if `level` passes the current level filter.
*
* The formatted line ("[LEVEL] message\n") is handed to the installed
* sink. Messages below the level set with set_log_level() are dropped.
*/
void log_message(int level, const std::string &msg);
/**
* @brief Level-filtered convenience wrappers, replacing qDebug(),
* qInfo(), qWarning() and qCritical(). Callers compose the message
* themselves (plain std::string concatenation).
*/
void log_debug(const std::string &msg);
void log_info(const std::string &msg);
void log_warning(const std::string &msg);
void log_critical(const std::string &msg);
}
#endif // OAK_DEBUG_H
-14
View File
@@ -88,17 +88,3 @@ OIIOUtils::get_pixel_aspect_ratio_from_oiio(const OIIO::ImageSpec &spec)
return olive::core::Rational::from_double(
spec.get_float_attribute("PixelAspectRatio", 1));
}
void OIIOUtils::frame_to_buffer(const void *data, int64_t linesize_bytes,
OIIO::ImageBuf *buf)
{
buf->set_pixels(OIIO::ROI(), buf->spec().format, data, OIIO::AutoStride,
static_cast<OIIO::stride_t>(linesize_bytes));
}
void OIIOUtils::buffer_to_frame(OIIO::ImageBuf *buf, void *data,
int64_t linesize_bytes)
{
buf->get_pixels(OIIO::ROI(), buf->spec().format, data, OIIO::AutoStride,
static_cast<OIIO::stride_t>(linesize_bytes));
}
+3 -20
View File
@@ -35,8 +35,9 @@
* Qt-free reimplementation of the former olive::OIIOUtils. The reverse
* dependencies on codec/frame.h and render/videoparams.h (which pull in
* Qt) were replaced with the Qt-free olive/core/render/pixelformat.h and
* olive/core/util/rational.h. The Frame-based helpers were flattened to
* raw data pointer + linesize, which is all they ever used from Frame.
* olive/core/util/rational.h. The Frame-based helpers (frame_to_buffer /
* buffer_to_frame) moved to oakcodec in M5
* (src/codec/src/oiioframebridge.h) — they are only used by codec.
*/
class OIIOUtils {
public:
@@ -65,24 +66,6 @@ public:
*/
static olive::core::Rational
get_pixel_aspect_ratio_from_oiio(const OIIO::ImageSpec &spec);
/**
* @brief Copies raw pixel data into an OIIO image buffer
*
* Flattened form of the former Frame-based frame_to_buffer(); pass
* Frame::const_data() and Frame::linesize_bytes() at the call site.
*/
static void frame_to_buffer(const void *data, int64_t linesize_bytes,
OIIO::ImageBuf *buf);
/**
* @brief Copies an OIIO image buffer's pixels into raw memory
*
* Flattened form of the former Frame-based buffer_to_frame(); pass
* Frame::data() and Frame::linesize_bytes() at the call site.
*/
static void buffer_to_frame(OIIO::ImageBuf *buf, void *data,
int64_t linesize_bytes);
};
#endif // OAK_OIIOUTILS_H
+2
View File
@@ -26,6 +26,8 @@ add_executable(oakcommon-gtest
dropworkflowbehavior_test.cpp
ffmpegutils_test.cpp
filefunctions_test.cpp
handle_test.cpp
log_test.cpp
memorypool_test.cpp
miscutils_test.cpp
ocioutils_test.cpp
+21 -23
View File
@@ -29,8 +29,8 @@
namespace
{
std::string read_string(int (*fn)(OakCommonColorTransform *, char *, int),
OakCommonColorTransform *t)
std::string read_string(int (*fn)(OakColorTransform, char *, int),
OakColorTransform t)
{
int needed = fn(t, nullptr, 0);
EXPECT_GT(needed, 0);
@@ -43,9 +43,8 @@ std::string read_string(int (*fn)(OakCommonColorTransform *, char *, int),
TEST(CommonColorTransformCApi, InitOutput)
{
OakCommonColorTransform *t =
oakcommon_colortransform_init_output("sRGB");
ASSERT_NE(t, nullptr);
OakColorTransform t = oakcommon_colortransform_init_output("sRGB");
ASSERT_NE(t.ctx, nullptr);
int is_display = -1;
EXPECT_EQ(oakcommon_colortransform_is_display(t, &is_display),
@@ -54,19 +53,19 @@ TEST(CommonColorTransformCApi, InitOutput)
EXPECT_EQ(read_string(oakcommon_colortransform_get_output, t), "sRGB");
EXPECT_EQ(read_string(oakcommon_colortransform_get_display, t), "sRGB");
oakcommon_colortransform_free(t);
oakcommon_colortransform_free(&t);
}
TEST(CommonColorTransformCApi, InitOutputNullString)
{
EXPECT_EQ(oakcommon_colortransform_init_output(nullptr), nullptr);
EXPECT_EQ(oakcommon_colortransform_init_output(nullptr).ctx,
nullptr);
}
TEST(CommonColorTransformCApi, InitDisplay)
{
OakCommonColorTransform *t =
oakcommon_colortransform_init_display("sRGB", "Studio", "None");
ASSERT_NE(t, nullptr);
OakColorTransform t = oakcommon_colortransform_init_display("sRGB", "Studio", "None");
ASSERT_NE(t.ctx, nullptr);
int is_display = 0;
EXPECT_EQ(oakcommon_colortransform_is_display(t, &is_display),
@@ -76,16 +75,16 @@ TEST(CommonColorTransformCApi, InitDisplay)
EXPECT_EQ(read_string(oakcommon_colortransform_get_view, t), "Studio");
EXPECT_EQ(read_string(oakcommon_colortransform_get_look, t), "None");
oakcommon_colortransform_free(t);
oakcommon_colortransform_free(&t);
}
TEST(CommonColorTransformCApi, InitDisplayNullString)
{
EXPECT_EQ(oakcommon_colortransform_init_display(nullptr, "v", "l"),
EXPECT_EQ(oakcommon_colortransform_init_display(nullptr, "v", "l").ctx,
nullptr);
EXPECT_EQ(oakcommon_colortransform_init_display("d", nullptr, "l"),
EXPECT_EQ(oakcommon_colortransform_init_display("d", nullptr, "l").ctx,
nullptr);
EXPECT_EQ(oakcommon_colortransform_init_display("d", "v", nullptr),
EXPECT_EQ(oakcommon_colortransform_init_display("d", "v", nullptr).ctx,
nullptr);
}
@@ -98,24 +97,23 @@ TEST(CommonColorTransformCApi, NullHandleErrors)
{
int i = 0;
char buf[16];
EXPECT_EQ(oakcommon_colortransform_is_display(nullptr, &i),
EXPECT_EQ(oakcommon_colortransform_is_display(OakColorTransform{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_colortransform_get_display(nullptr, buf, sizeof(buf)),
EXPECT_EQ(oakcommon_colortransform_get_display(OakColorTransform{}, buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_colortransform_get_output(nullptr, buf, sizeof(buf)),
EXPECT_EQ(oakcommon_colortransform_get_output(OakColorTransform{}, buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_colortransform_get_view(nullptr, buf, sizeof(buf)),
EXPECT_EQ(oakcommon_colortransform_get_view(OakColorTransform{}, buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_colortransform_get_look(nullptr, buf, sizeof(buf)),
EXPECT_EQ(oakcommon_colortransform_get_look(OakColorTransform{}, buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
}
TEST(CommonColorTransformCApi, NullOutParam)
{
OakCommonColorTransform *t =
oakcommon_colortransform_init_output("sRGB");
ASSERT_NE(t, nullptr);
OakColorTransform t = oakcommon_colortransform_init_output("sRGB");
ASSERT_NE(t.ctx, nullptr);
EXPECT_EQ(oakcommon_colortransform_is_display(t, nullptr),
OAKCOMMON_E_INVALID);
oakcommon_colortransform_free(t);
oakcommon_colortransform_free(&t);
}
+52 -53
View File
@@ -27,9 +27,9 @@
TEST(CommandLineParser, InitFree)
{
OakCommonCommandLineParser *parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser, nullptr);
oakcommon_commandlineparser_free(parser);
OakCommandLineParser parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser.ctx, nullptr);
oakcommon_commandlineparser_free(&parser);
}
TEST(CommandLineParser, FreeNull)
@@ -41,14 +41,13 @@ TEST(CommandLineParser, FreeNull)
TEST(CommandLineParser, AddOptionInvalidArgs)
{
OakCommonCommandLineParser *parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser, nullptr);
OakCommandLineParser parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser.ctx, nullptr);
const char *names[] = { "h", "-help" };
OakCommonCommandLineOption *option = nullptr;
OakCommandLineOption option = {};
EXPECT_EQ(oakcommon_commandlineparser_add_option(
nullptr, names, 2, "desc", 0, nullptr, 0, &option),
EXPECT_EQ(oakcommon_commandlineparser_add_option(OakCommandLineParser{}, names, 2, "desc", 0, nullptr, 0, &option),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_commandlineparser_add_option(
parser, nullptr, 2, "desc", 0, nullptr, 0, &option),
@@ -57,28 +56,28 @@ TEST(CommandLineParser, AddOptionInvalidArgs)
parser, names, 0, "desc", 0, nullptr, 0, &option),
OAKCOMMON_E_INVALID);
oakcommon_commandlineparser_free(parser);
oakcommon_commandlineparser_free(&parser);
}
TEST(CommandLineParser, ProcessOptionHitAndMiss)
{
OakCommonCommandLineParser *parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser, nullptr);
OakCommandLineParser parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser.ctx, nullptr);
const char *names[] = { "h", "-help" };
OakCommonCommandLineOption *hit = nullptr;
OakCommonCommandLineOption *miss = nullptr;
OakCommandLineOption hit = {};
OakCommandLineOption miss = {};
ASSERT_EQ(oakcommon_commandlineparser_add_option(
parser, names, 2, "Show help", 0, nullptr, 0, &hit),
OAKCOMMON_OK);
ASSERT_NE(hit, nullptr);
ASSERT_NE(hit.ctx, nullptr);
const char *other_names[] = { "v", "-version" };
ASSERT_EQ(oakcommon_commandlineparser_add_option(
parser, other_names, 2, "Show version", 0, nullptr, 0, &miss),
OAKCOMMON_OK);
ASSERT_NE(miss, nullptr);
ASSERT_NE(miss.ctx, nullptr);
const char *argv[] = { "oak", "-h" };
ASSERT_EQ(oakcommon_commandlineparser_process(parser, argv, 2),
@@ -92,18 +91,18 @@ TEST(CommandLineParser, ProcessOptionHitAndMiss)
ASSERT_EQ(oakcommon_commandlineoption_is_set(miss, &is_set), OAKCOMMON_OK);
EXPECT_FALSE(is_set);
oakcommon_commandlineoption_free(hit);
oakcommon_commandlineoption_free(miss);
oakcommon_commandlineparser_free(parser);
oakcommon_commandlineoption_free(&hit);
oakcommon_commandlineoption_free(&miss);
oakcommon_commandlineparser_free(&parser);
}
TEST(CommandLineParser, ProcessMatchesSecondAliasCaseInsensitive)
{
OakCommonCommandLineParser *parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser, nullptr);
OakCommandLineParser parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser.ctx, nullptr);
const char *names[] = { "h", "-help" };
OakCommonCommandLineOption *option = nullptr;
OakCommandLineOption option = {};
ASSERT_EQ(oakcommon_commandlineparser_add_option(
parser, names, 2, "Show help", 0, nullptr, 0, &option),
OAKCOMMON_OK);
@@ -118,17 +117,17 @@ TEST(CommandLineParser, ProcessMatchesSecondAliasCaseInsensitive)
OAKCOMMON_OK);
EXPECT_TRUE(is_set);
oakcommon_commandlineoption_free(option);
oakcommon_commandlineparser_free(parser);
oakcommon_commandlineoption_free(&option);
oakcommon_commandlineparser_free(&parser);
}
TEST(CommandLineParser, OptionTakesArg)
{
OakCommonCommandLineParser *parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser, nullptr);
OakCommandLineParser parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser.ctx, nullptr);
const char *names[] = { "e", "-export" };
OakCommonCommandLineOption *option = nullptr;
OakCommandLineOption option = {};
ASSERT_EQ(oakcommon_commandlineparser_add_option(
parser, names, 2, "Export", 1, "filename", 0, &option),
OAKCOMMON_OK);
@@ -153,20 +152,20 @@ TEST(CommandLineParser, OptionTakesArg)
required);
EXPECT_STREQ(buf.data(), "/tmp/out.mp4");
oakcommon_commandlineoption_free(option);
oakcommon_commandlineparser_free(parser);
oakcommon_commandlineoption_free(&option);
oakcommon_commandlineparser_free(&parser);
}
TEST(CommandLineParser, PositionalArgument)
{
OakCommonCommandLineParser *parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser, nullptr);
OakCommandLineParser parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser.ctx, nullptr);
OakCommonCommandLinePositionalArgument *arg = nullptr;
OakCommandLinePositionalArgument arg = {};
ASSERT_EQ(oakcommon_commandlineparser_add_positional_argument(
parser, "project", "Project file", 0, &arg),
OAKCOMMON_OK);
ASSERT_NE(arg, nullptr);
ASSERT_NE(arg.ctx, nullptr);
const char *argv[] = { "oak", "/tmp/project.ove" };
ASSERT_EQ(oakcommon_commandlineparser_process(parser, argv, 2),
@@ -182,20 +181,20 @@ TEST(CommandLineParser, PositionalArgument)
required);
EXPECT_STREQ(buf.data(), "/tmp/project.ove");
oakcommon_commandlinepositionalargument_free(arg);
oakcommon_commandlineparser_free(parser);
oakcommon_commandlinepositionalargument_free(&arg);
oakcommon_commandlineparser_free(&parser);
}
TEST(CommandLineParser, PositionalArgumentSetGetSetting)
{
OakCommonCommandLineParser *parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser, nullptr);
OakCommandLineParser parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser.ctx, nullptr);
OakCommonCommandLinePositionalArgument *arg = nullptr;
OakCommandLinePositionalArgument arg = {};
ASSERT_EQ(oakcommon_commandlineparser_add_positional_argument(
parser, "project", "Project file", 0, &arg),
OAKCOMMON_OK);
ASSERT_NE(arg, nullptr);
ASSERT_NE(arg.ctx, nullptr);
ASSERT_EQ(oakcommon_commandlinepositionalargument_set_setting(arg,
"hello.ove"),
@@ -209,28 +208,28 @@ TEST(CommandLineParser, PositionalArgumentSetGetSetting)
EXPECT_STREQ(buf, "hello.ove");
// Error paths
EXPECT_EQ(oakcommon_commandlinepositionalargument_set_setting(nullptr,
EXPECT_EQ(oakcommon_commandlinepositionalargument_set_setting(OakCommandLinePositionalArgument{},
"x"),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_commandlinepositionalargument_set_setting(arg,
nullptr),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_commandlinepositionalargument_get_setting(nullptr,
EXPECT_EQ(oakcommon_commandlinepositionalargument_get_setting(OakCommandLinePositionalArgument{},
buf,
sizeof(buf)),
OAKCOMMON_E_INVALID);
oakcommon_commandlinepositionalargument_free(arg);
oakcommon_commandlineparser_free(parser);
oakcommon_commandlinepositionalargument_free(&arg);
oakcommon_commandlineparser_free(&parser);
}
TEST(CommandLineParser, TwoStageStringGetterSmallBuffer)
{
OakCommonCommandLineParser *parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser, nullptr);
OakCommandLineParser parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser.ctx, nullptr);
const char *names[] = { "e" };
OakCommonCommandLineOption *option = nullptr;
OakCommandLineOption option = {};
ASSERT_EQ(oakcommon_commandlineparser_add_option(
parser, names, 1, "Export", 1, "filename", 0, &option),
OAKCOMMON_OK);
@@ -249,27 +248,27 @@ TEST(CommandLineParser, TwoStageStringGetterSmallBuffer)
EXPECT_EQ(oakcommon_commandlineoption_get_setting(option, nullptr, 0), 7);
// Error paths
EXPECT_EQ(oakcommon_commandlineoption_get_setting(nullptr, buf,
EXPECT_EQ(oakcommon_commandlineoption_get_setting(OakCommandLineOption{}, buf,
sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_commandlineoption_is_set(option, nullptr),
OAKCOMMON_E_INVALID);
bool dummy = false;
EXPECT_EQ(oakcommon_commandlineoption_is_set(nullptr, &dummy),
EXPECT_EQ(oakcommon_commandlineoption_is_set(OakCommandLineOption{}, &dummy),
OAKCOMMON_E_INVALID);
oakcommon_commandlineoption_free(option);
oakcommon_commandlineparser_free(parser);
oakcommon_commandlineoption_free(&option);
oakcommon_commandlineparser_free(&parser);
}
TEST(CommandLineParser, ProcessInvalidArgs)
{
EXPECT_EQ(oakcommon_commandlineparser_process(nullptr, nullptr, 0),
EXPECT_EQ(oakcommon_commandlineparser_process(OakCommandLineParser{}, nullptr, 0),
OAKCOMMON_E_INVALID);
OakCommonCommandLineParser *parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser, nullptr);
OakCommandLineParser parser = oakcommon_commandlineparser_init();
ASSERT_NE(parser.ctx, nullptr);
EXPECT_EQ(oakcommon_commandlineparser_process(parser, nullptr, 1),
OAKCOMMON_E_INVALID);
oakcommon_commandlineparser_free(parser);
oakcommon_commandlineparser_free(&parser);
}
+27 -25
View File
@@ -24,25 +24,29 @@
#include "common/current.h"
TEST(OakCommonCurrent, InstanceIsSingleton)
TEST(OakCurrent, InstanceIsSingleton)
{
OakCommonCurrent *a = oakcommon_current_instance();
OakCommonCurrent *b = oakcommon_current_instance();
OakCurrent a = oakcommon_current_instance();
OakCurrent b = oakcommon_current_instance();
ASSERT_NE(a, nullptr);
EXPECT_EQ(a, b);
ASSERT_NE(a.ctx, nullptr);
EXPECT_EQ(a.ctx, b.ctx);
EXPECT_EQ(a.abi_version, OAKCOMMON_ABI_VERSION);
}
TEST(OakCommonCurrent, FreeNullIsNoOp)
TEST(OakCurrent, FreeNullIsNoOp)
{
oakcommon_current_free(nullptr);
oakcommon_current_free(oakcommon_current_instance());
OakCurrent c = oakcommon_current_instance();
oakcommon_current_free(&c);
// Releasing the singleton handle never destroys the object.
EXPECT_NE(c.ctx, nullptr);
SUCCEED();
}
TEST(OakCommonCurrent, VideoParamsSetGetRoundTrip)
TEST(OakCurrent, VideoParamsSetGetRoundTrip)
{
OakCommonCurrent *c = oakcommon_current_instance();
OakCurrent c = oakcommon_current_instance();
int *params = static_cast<int *>(malloc(sizeof(int)));
ASSERT_NE(params, nullptr);
*params = 42;
@@ -62,9 +66,9 @@ TEST(OakCommonCurrent, VideoParamsSetGetRoundTrip)
EXPECT_EQ(out, nullptr);
}
TEST(OakCommonCurrent, AudioParamsSetGetRoundTrip)
TEST(OakCurrent, AudioParamsSetGetRoundTrip)
{
OakCommonCurrent *c = oakcommon_current_instance();
OakCurrent c = oakcommon_current_instance();
int value = 7; // non-owning storage, no destroy callback
ASSERT_EQ(oakcommon_current_set_audio_params(c, &value, nullptr),
@@ -78,9 +82,9 @@ TEST(OakCommonCurrent, AudioParamsSetGetRoundTrip)
OAKCOMMON_OK);
}
TEST(OakCommonCurrent, PluginHostAndCacheRoundTrip)
TEST(OakCurrent, PluginHostAndCacheRoundTrip)
{
OakCommonCurrent *c = oakcommon_current_instance();
OakCurrent c = oakcommon_current_instance();
int host = 1, cache = 2;
ASSERT_EQ(oakcommon_current_set_plugin_host(c, &host, nullptr),
@@ -100,31 +104,29 @@ TEST(OakCommonCurrent, PluginHostAndCacheRoundTrip)
OAKCOMMON_OK);
}
TEST(OakCommonCurrent, NullHandleAndOutArgs)
TEST(OakCurrent, NullHandleAndOutArgs)
{
void *out = nullptr;
int flag = 0;
EXPECT_EQ(oakcommon_current_set_video_params(nullptr, &flag, nullptr),
EXPECT_EQ(oakcommon_current_set_video_params(OakCurrent{}, &flag, nullptr),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_current_get_video_params(nullptr, &out),
EXPECT_EQ(oakcommon_current_get_video_params(OakCurrent{}, &out),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_current_get_video_params(
oakcommon_current_instance(), nullptr),
OakCurrent c = oakcommon_current_instance();
EXPECT_EQ(oakcommon_current_get_video_params(c, nullptr),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_current_is_interactive(nullptr, &flag),
EXPECT_EQ(oakcommon_current_is_interactive(OakCurrent{}, &flag),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_current_is_interactive(
oakcommon_current_instance(), nullptr),
EXPECT_EQ(oakcommon_current_is_interactive(c, nullptr),
OAKCOMMON_E_INVALID);
}
TEST(OakCommonCurrent, IsInteractive)
TEST(OakCurrent, IsInteractive)
{
int flag = 0;
ASSERT_EQ(oakcommon_current_is_interactive(
oakcommon_current_instance(), &flag),
OAKCOMMON_OK);
OakCurrent c = oakcommon_current_instance();
ASSERT_EQ(oakcommon_current_is_interactive(c, &flag), OAKCOMMON_OK);
EXPECT_EQ(flag, 1);
}
+6 -6
View File
@@ -22,25 +22,25 @@
#include "common/debug.h"
TEST(OakCommonDebug, LogValidMessage)
TEST(OakDebug, LogValidMessage)
{
EXPECT_EQ(oakcommon_debug_log(OAKCOMMON_DEBUG_WARNING, "hello"),
OAKCOMMON_OK);
}
TEST(OakCommonDebug, LogNullMessage)
TEST(OakDebug, LogNullMessage)
{
EXPECT_EQ(oakcommon_debug_log(OAKCOMMON_DEBUG_WARNING, nullptr),
OAKCOMMON_E_INVALID);
}
TEST(OakCommonDebug, LogOutOfRangeLevel)
TEST(OakDebug, LogOutOfRangeLevel)
{
// Out-of-range levels are tolerated and print as UNKNOWN.
EXPECT_EQ(oakcommon_debug_log(999, "odd level"), OAKCOMMON_OK);
}
TEST(OakCommonDebug, LevelNameRoundTrip)
TEST(OakDebug, LevelNameRoundTrip)
{
char buf[16];
@@ -51,14 +51,14 @@ TEST(OakCommonDebug, LevelNameRoundTrip)
EXPECT_STREQ(buf, "WARNING");
}
TEST(OakCommonDebug, LevelNameQuerySize)
TEST(OakDebug, LevelNameQuerySize)
{
int needed = oakcommon_debug_level_name(OAKCOMMON_DEBUG_DEBUG,
nullptr, 0);
EXPECT_EQ(needed, 6); // "DEBUG" + NUL
}
TEST(OakCommonDebug, LevelNameUnknownLevel)
TEST(OakDebug, LevelNameUnknownLevel)
{
char buf[16];
@@ -22,7 +22,7 @@
#include "common/dropworkflowbehavior.h"
TEST(OakCommonDropWorkflowBehavior, IsValidAcceptsAllEnumerators)
TEST(OakDropWorkflowBehavior, IsValidAcceptsAllEnumerators)
{
EXPECT_EQ(oakcommon_drop_workflow_behavior_is_valid(OAKCOMMON_DWS_ASK),
1);
@@ -36,13 +36,13 @@ TEST(OakCommonDropWorkflowBehavior, IsValidAcceptsAllEnumerators)
1);
}
TEST(OakCommonDropWorkflowBehavior, IsValidRejectsOutOfRange)
TEST(OakDropWorkflowBehavior, IsValidRejectsOutOfRange)
{
EXPECT_EQ(oakcommon_drop_workflow_behavior_is_valid(-1), 0);
EXPECT_EQ(oakcommon_drop_workflow_behavior_is_valid(4), 0);
}
TEST(OakCommonDropWorkflowBehavior, NameRoundTrip)
TEST(OakDropWorkflowBehavior, NameRoundTrip)
{
char buf[16];
@@ -53,7 +53,7 @@ TEST(OakCommonDropWorkflowBehavior, NameRoundTrip)
EXPECT_STREQ(buf, "AUTO");
}
TEST(OakCommonDropWorkflowBehavior, NameQuerySizeAndTooSmallBuffer)
TEST(OakDropWorkflowBehavior, NameQuerySizeAndTooSmallBuffer)
{
int needed = oakcommon_drop_workflow_behavior_name(OAKCOMMON_DWS_DISABLE,
nullptr, 0);
@@ -65,7 +65,7 @@ TEST(OakCommonDropWorkflowBehavior, NameQuerySizeAndTooSmallBuffer)
needed);
}
TEST(OakCommonDropWorkflowBehavior, NameInvalidValue)
TEST(OakDropWorkflowBehavior, NameInvalidValue)
{
char buf[16];
+12 -12
View File
@@ -26,7 +26,7 @@
#include "../src/ffmpegutils.h"
TEST(OakCommonFFmpegUtils, GetCompatiblePixelFormatMapsCorrectly)
TEST(OakFFmpegUtils, GetCompatiblePixelFormatMapsCorrectly)
{
int out = -2;
@@ -51,14 +51,14 @@ TEST(OakCommonFFmpegUtils, GetCompatiblePixelFormatMapsCorrectly)
EXPECT_EQ(out, olive::core::PixelFormat::invalid);
}
TEST(OakCommonFFmpegUtils, GetCompatiblePixelFormatNullOut)
TEST(OakFFmpegUtils, GetCompatiblePixelFormatNullOut)
{
EXPECT_EQ(oakcommon_ffmpegutils_get_compatible_pixel_format(
olive::core::PixelFormat::u8, nullptr),
OAKCOMMON_E_INVALID);
}
TEST(OakCommonFFmpegUtils, GetFFmpegPixelFormatMapsCorrectly)
TEST(OakFFmpegUtils, GetFFmpegPixelFormatMapsCorrectly)
{
int out = -2;
@@ -92,7 +92,7 @@ TEST(OakCommonFFmpegUtils, GetFFmpegPixelFormatMapsCorrectly)
EXPECT_EQ(out, fb_pix_fmt_none);
}
TEST(OakCommonFFmpegUtils, GetFFmpegPixelFormatNullOut)
TEST(OakFFmpegUtils, GetFFmpegPixelFormatNullOut)
{
EXPECT_EQ(oakcommon_ffmpegutils_get_ffmpeg_pixel_format(
olive::core::PixelFormat::u8,
@@ -100,7 +100,7 @@ TEST(OakCommonFFmpegUtils, GetFFmpegPixelFormatNullOut)
OAKCOMMON_E_INVALID);
}
TEST(OakCommonFFmpegUtils, GetNativeSampleFormatMapsCorrectly)
TEST(OakFFmpegUtils, GetNativeSampleFormatMapsCorrectly)
{
int out = -2;
@@ -125,14 +125,14 @@ TEST(OakCommonFFmpegUtils, GetNativeSampleFormatMapsCorrectly)
EXPECT_EQ(out, olive::core::SampleFormat::invalid);
}
TEST(OakCommonFFmpegUtils, GetNativeSampleFormatNullOut)
TEST(OakFFmpegUtils, GetNativeSampleFormatNullOut)
{
EXPECT_EQ(oakcommon_ffmpegutils_get_native_sample_format(
fb_sample_fmt_u8, nullptr),
OAKCOMMON_E_INVALID);
}
TEST(OakCommonFFmpegUtils, GetFFmpegSampleFormatMapsCorrectly)
TEST(OakFFmpegUtils, GetFFmpegSampleFormatMapsCorrectly)
{
int out = -2;
@@ -157,14 +157,14 @@ TEST(OakCommonFFmpegUtils, GetFFmpegSampleFormatMapsCorrectly)
EXPECT_EQ(out, fb_sample_fmt_none);
}
TEST(OakCommonFFmpegUtils, GetFFmpegSampleFormatNullOut)
TEST(OakFFmpegUtils, GetFFmpegSampleFormatNullOut)
{
EXPECT_EQ(oakcommon_ffmpegutils_get_ffmpeg_sample_format(
olive::core::SampleFormat::u8, nullptr),
OAKCOMMON_E_INVALID);
}
TEST(OakCommonFFmpegUtils, ConvertJpegSpaceToRegularSpaceMapsCorrectly)
TEST(OakFFmpegUtils, ConvertJpegSpaceToRegularSpaceMapsCorrectly)
{
int out = -2;
@@ -184,21 +184,21 @@ TEST(OakCommonFFmpegUtils, ConvertJpegSpaceToRegularSpaceMapsCorrectly)
EXPECT_EQ(out, fb_pix_fmt_rgba);
}
TEST(OakCommonFFmpegUtils, ConvertJpegSpaceToRegularSpaceNullOut)
TEST(OakFFmpegUtils, ConvertJpegSpaceToRegularSpaceNullOut)
{
EXPECT_EQ(oakcommon_ffmpegutils_convert_jpeg_space_to_regular_space(
fb_pix_fmt_rgba, nullptr),
OAKCOMMON_E_INVALID);
}
TEST(OakCommonFFmpegUtils, GetCompatibleBridgePixelFormatNullOut)
TEST(OakFFmpegUtils, GetCompatibleBridgePixelFormatNullOut)
{
EXPECT_EQ(oakcommon_ffmpegutils_get_compatible_bridge_pixel_format(
fb_pix_fmt_rgba, -1, nullptr),
OAKCOMMON_E_INVALID);
}
TEST(OakCommonFFmpegUtils, GetCompatibleBridgePixelFormatMapsCorrectly)
TEST(OakFFmpegUtils, GetCompatibleBridgePixelFormatMapsCorrectly)
{
/* Calls fb_find_best_pix_fmt_of_list() in ffmpeg_bridge, which
* requires a working FFmpeg runtime environment. */
+17 -24
View File
@@ -35,7 +35,7 @@ protected:
void SetUp() override
{
handle_ = oakcommon_filefunctions_init();
ASSERT_NE(handle_, nullptr);
ASSERT_NE(handle_.ctx, nullptr);
temp_dir_ = fs::temp_directory_path() /
fs::path("oakcommon_filefunctions_test_" +
@@ -46,8 +46,8 @@ protected:
void TearDown() override
{
oakcommon_filefunctions_free(handle_);
handle_ = nullptr;
oakcommon_filefunctions_free(&handle_);
handle_.ctx = nullptr;
std::error_code ec;
fs::remove_all(temp_dir_, ec);
@@ -84,7 +84,7 @@ protected:
return std::string(buf.data());
}
OakCommonFileFunctions *handle_ = nullptr;
OakFileFunctions handle_ = {};
fs::path temp_dir_;
};
@@ -98,43 +98,36 @@ TEST_F(FileFunctionsTest, NullHandleReturnsInvalid)
{
char buf[16];
int out = 0;
EXPECT_EQ(oakcommon_filefunctions_get_configuration_location(
nullptr, buf, sizeof(buf)),
EXPECT_EQ(oakcommon_filefunctions_get_configuration_location(OakFileFunctions{}, buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_filefunctions_get_application_path(nullptr, buf,
EXPECT_EQ(oakcommon_filefunctions_get_application_path(OakFileFunctions{}, buf,
sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_filefunctions_get_temp_file_path(nullptr, buf,
EXPECT_EQ(oakcommon_filefunctions_get_temp_file_path(OakFileFunctions{}, buf,
sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_filefunctions_get_auto_recovery_root(nullptr, buf,
EXPECT_EQ(oakcommon_filefunctions_get_auto_recovery_root(OakFileFunctions{}, buf,
sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_filefunctions_get_unique_file_identifier(
nullptr, "x", buf, sizeof(buf)),
EXPECT_EQ(oakcommon_filefunctions_get_unique_file_identifier(OakFileFunctions{}, "x", buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_filefunctions_ensure_filename_extension(
nullptr, "x", "y", buf, sizeof(buf)),
EXPECT_EQ(oakcommon_filefunctions_ensure_filename_extension(OakFileFunctions{}, "x", "y", buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_filefunctions_read_file_as_string(nullptr, "x",
EXPECT_EQ(oakcommon_filefunctions_read_file_as_string(OakFileFunctions{}, "x",
buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_filefunctions_get_safe_temporary_filename(
nullptr, "x", buf, sizeof(buf)),
EXPECT_EQ(oakcommon_filefunctions_get_safe_temporary_filename(OakFileFunctions{}, "x", buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_filefunctions_get_formatted_executable_for_platform(
nullptr, "x", buf, sizeof(buf)),
EXPECT_EQ(oakcommon_filefunctions_get_formatted_executable_for_platform(OakFileFunctions{}, "x", buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_filefunctions_directory_is_valid(nullptr, "x", 1,
EXPECT_EQ(oakcommon_filefunctions_directory_is_valid(OakFileFunctions{}, "x", 1,
&out),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_filefunctions_can_copy_directory_without_overwriting(
nullptr, "a", "b", &out),
EXPECT_EQ(oakcommon_filefunctions_can_copy_directory_without_overwriting(OakFileFunctions{}, "a", "b", &out),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_filefunctions_copy_directory(nullptr, "a", "b", 0),
EXPECT_EQ(oakcommon_filefunctions_copy_directory(OakFileFunctions{}, "a", "b", 0),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_filefunctions_rename_file_allow_overwrite(
nullptr, "a", "b", &out),
EXPECT_EQ(oakcommon_filefunctions_rename_file_allow_overwrite(OakFileFunctions{}, "a", "b", &out),
OAKCOMMON_E_INVALID);
}
+259
View File
@@ -0,0 +1,259 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <gtest/gtest.h>
#include "common/colortransform.h"
#include "common/commandlineparser.h"
#include "common/current.h"
#include "common/filefunctions.h"
#include "common/ocioutils.h"
#include "common/oiioutils.h"
#include "common/subtitleparams.h"
#include "common/videoparams.h"
#include "common/xmlutils.h"
// Native C++ headers (exported through the oakcommon target's public
// include dirs) for the init_from_native tests.
#include "colortransform.h"
#include "subtitleparams.h"
#include "videoparams.h"
namespace
{
/**
* @brief Every init-produced handle must carry the current ABI version
* and non-NULL addref/release thunks.
*/
template <typename Handle> void expect_valid_handle(const Handle &h)
{
EXPECT_NE(h.ctx, nullptr);
EXPECT_NE(h.addref, nullptr);
EXPECT_NE(h.release, nullptr);
EXPECT_EQ(h.abi_version, OAKCOMMON_ABI_VERSION);
}
} // namespace
TEST(OakHandle, AbiVersionStampedEverywhere)
{
OakVideoParams vp = oakcommon_videoparams_init();
expect_valid_handle(vp);
oakcommon_videoparams_free(&vp);
OakSubtitleParams sp = oakcommon_subtitleparams_init();
expect_valid_handle(sp);
oakcommon_subtitleparams_free(&sp);
OakColorTransform ct = oakcommon_colortransform_init_output("sRGB");
expect_valid_handle(ct);
oakcommon_colortransform_free(&ct);
OakCommandLineParser parser = oakcommon_commandlineparser_init();
expect_valid_handle(parser);
const char *names[] = { "h" };
OakCommandLineOption option = {};
ASSERT_EQ(oakcommon_commandlineparser_add_option(
parser, names, 1, "help", 0, nullptr, 0, &option),
OAKCOMMON_OK);
expect_valid_handle(option);
oakcommon_commandlineoption_free(&option);
OakCommandLinePositionalArgument arg = {};
ASSERT_EQ(oakcommon_commandlineparser_add_positional_argument(
parser, "file", "desc", 0, &arg),
OAKCOMMON_OK);
expect_valid_handle(arg);
oakcommon_commandlinepositionalargument_free(&arg);
oakcommon_commandlineparser_free(&parser);
OakXmlReader reader =
oakcommon_xml_reader_init("<root/>");
expect_valid_handle(reader);
oakcommon_xml_reader_free(&reader);
OakXmlWriter writer = oakcommon_xml_writer_init();
expect_valid_handle(writer);
oakcommon_xml_writer_free(&writer);
OakFileFunctions ff = oakcommon_filefunctions_init();
expect_valid_handle(ff);
oakcommon_filefunctions_free(&ff);
OakOCIOUtils ocio = oakcommon_ocioutils_init();
expect_valid_handle(ocio);
oakcommon_ocioutils_free(&ocio);
OakOIIOUtils oiio = oakcommon_oiioutils_init();
expect_valid_handle(oiio);
oakcommon_oiioutils_free(&oiio);
OakCurrent current = oakcommon_current_instance();
expect_valid_handle(current);
}
TEST(OakHandle, AddrefReleaseCountSemantics)
{
OakVideoParams h = oakcommon_videoparams_init();
ASSERT_NE(h.ctx, nullptr);
ASSERT_EQ(oakcommon_videoparams_set_width(h, 1920), OAKCOMMON_OK);
// Copy the handle struct and take a second reference through the
// function pointer, like a foreign (Rust/DLL) consumer would.
OakVideoParams copy = h;
h.addref(h.ctx);
// Dropping the first reference must not destroy the object: the copy
// is still fully usable.
h.release(h.ctx);
int width = 0;
ASSERT_EQ(oakcommon_videoparams_get_width(copy, &width), OAKCOMMON_OK);
EXPECT_EQ(width, 1920);
// Dropping the last reference destroys the object; free() clears ctx.
oakcommon_videoparams_free(&copy);
EXPECT_EQ(copy.ctx, nullptr);
}
TEST(OakHandle, FreeNullAndEmptyCtxAreNoOp)
{
// NULL handle pointer.
oakcommon_videoparams_free(nullptr);
oakcommon_subtitleparams_free(nullptr);
oakcommon_colortransform_free(nullptr);
oakcommon_commandlineparser_free(nullptr);
oakcommon_commandlineoption_free(nullptr);
oakcommon_commandlinepositionalargument_free(nullptr);
oakcommon_xml_reader_free(nullptr);
oakcommon_xml_writer_free(nullptr);
oakcommon_filefunctions_free(nullptr);
oakcommon_ocioutils_free(nullptr);
oakcommon_oiioutils_free(nullptr);
oakcommon_current_free(nullptr);
// Handle whose ctx is NULL (e.g. after a failed init or a free).
OakVideoParams h = {};
oakcommon_videoparams_free(&h);
int width = 0;
EXPECT_EQ(oakcommon_videoparams_get_width(h, &width),
OAKCOMMON_E_INVALID);
// release() itself must tolerate a NULL ctx (foreign consumers may
// call it directly).
h.release = nullptr; // no thunk available on a zero-initialized handle
oakcommon_videoparams_free(&h);
SUCCEED();
}
TEST(OakHandle, VideoParamsFromNativeSurvivesSource)
{
OakVideoParams h = {};
{
olive::VideoParams native(
1920, 1080, olive::core::Rational(1, 25),
olive::core::PixelFormat::u8, 4, olive::core::Rational(1, 1),
olive::VideoParams::k_interlace_none, 1);
h = oakcommon_videoparams_init_from_native(&native);
ASSERT_NE(h.ctx, nullptr);
EXPECT_EQ(h.abi_version, OAKCOMMON_ABI_VERSION);
} // native stack object destroyed here
int width = 0, height = 0, num = 0, den = 0;
ASSERT_EQ(oakcommon_videoparams_get_width(h, &width), OAKCOMMON_OK);
ASSERT_EQ(oakcommon_videoparams_get_height(h, &height), OAKCOMMON_OK);
ASSERT_EQ(oakcommon_videoparams_get_time_base(h, &num, &den),
OAKCOMMON_OK);
EXPECT_EQ(width, 1920);
EXPECT_EQ(height, 1080);
EXPECT_EQ(num, 1);
EXPECT_EQ(den, 25);
oakcommon_videoparams_free(&h);
// NULL source yields an empty handle, not a crash.
OakVideoParams empty =
oakcommon_videoparams_init_from_native(nullptr);
EXPECT_EQ(empty.ctx, nullptr);
}
TEST(OakHandle, SubtitleParamsFromNativeSurvivesSource)
{
OakSubtitleParams h = {};
{
olive::SubtitleParams native;
native.push_back(olive::Subtitle(
olive::core::TimeRange(olive::core::Rational(0, 1),
olive::core::Rational(2, 1)),
"hello"));
h = oakcommon_subtitleparams_init_from_native(&native);
ASSERT_NE(h.ctx, nullptr);
} // native stack object destroyed here
int count = 0;
ASSERT_EQ(oakcommon_subtitleparams_count(h, &count), OAKCOMMON_OK);
EXPECT_EQ(count, 1);
char buf[16];
int needed = oakcommon_subtitleparams_get_subtitle_text(h, 0, buf,
sizeof(buf));
ASSERT_EQ(needed, 6);
EXPECT_STREQ(buf, "hello");
oakcommon_subtitleparams_free(&h);
}
TEST(OakHandle, ColorTransformFromNativeSurvivesSource)
{
OakColorTransform h = {};
{
olive::ColorTransform native(std::string("Display"),
std::string("Standard"),
std::string("None"));
h = oakcommon_colortransform_init_from_native(&native);
ASSERT_NE(h.ctx, nullptr);
} // native stack object destroyed here
int is_display = 0;
ASSERT_EQ(oakcommon_colortransform_is_display(h, &is_display),
OAKCOMMON_OK);
EXPECT_EQ(is_display, 1);
char buf[16];
int needed = oakcommon_colortransform_get_view(h, buf, sizeof(buf));
ASSERT_EQ(needed, 9);
EXPECT_STREQ(buf, "Standard");
oakcommon_colortransform_free(&h);
}
TEST(OakHandle, CurrentSingletonReleaseNeverDestroys)
{
OakCurrent h = oakcommon_current_instance();
ASSERT_NE(h.ctx, nullptr);
void *ctx = h.ctx;
// The singleton's addref/release are deliberate no-ops.
h.addref(h.ctx);
h.release(h.ctx);
oakcommon_current_free(&h);
OakCurrent again = oakcommon_current_instance();
EXPECT_EQ(again.ctx, ctx);
}
+174
View File
@@ -0,0 +1,174 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <string>
#include <vector>
#include <gtest/gtest.h>
#include "common/debug.h"
// Native C++ header (exported through the oakcommon target's public
// include dirs) for sink injection.
#include "debug.h"
namespace
{
/**
* @brief RAII helper: captures all filtered log lines into a vector and
* restores the default stderr sink and level on destruction.
*/
class LogCapture {
public:
LogCapture()
{
olive::set_log_sink([this](const std::string &line) {
lines.push_back(line);
});
}
~LogCapture()
{
olive::set_log_sink(nullptr);
olive::set_log_level(olive::k_debug_info);
}
std::vector<std::string> lines;
};
} // namespace
TEST(OakLog, LevelSetGetRoundTrip)
{
ASSERT_EQ(oakcommon_log_set_level(OAKCOMMON_DEBUG_WARNING),
OAKCOMMON_OK);
int level = -1;
ASSERT_EQ(oakcommon_log_get_level(&level), OAKCOMMON_OK);
EXPECT_EQ(level, OAKCOMMON_DEBUG_WARNING);
ASSERT_EQ(oakcommon_log_set_level(OAKCOMMON_DEBUG_DEBUG),
OAKCOMMON_OK);
ASSERT_EQ(oakcommon_log_get_level(&level), OAKCOMMON_OK);
EXPECT_EQ(level, OAKCOMMON_DEBUG_DEBUG);
// Restore default for other tests.
ASSERT_EQ(oakcommon_log_set_level(OAKCOMMON_DEBUG_INFO), OAKCOMMON_OK);
}
TEST(OakLog, LevelSetGetInvalidArgs)
{
EXPECT_EQ(oakcommon_log_set_level(-1), OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_log_set_level(999), OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_log_get_level(nullptr), OAKCOMMON_E_INVALID);
// The failed sets above must not have changed the level.
int level = -1;
ASSERT_EQ(oakcommon_log_get_level(&level), OAKCOMMON_OK);
EXPECT_EQ(level, OAKCOMMON_DEBUG_INFO);
}
TEST(OakLog, LevelFilterDropsLowerLevels)
{
LogCapture capture;
ASSERT_EQ(oakcommon_log_set_level(OAKCOMMON_DEBUG_WARNING),
OAKCOMMON_OK);
EXPECT_EQ(oakcommon_log(OAKCOMMON_DEBUG_DEBUG, "dbg"), OAKCOMMON_OK);
EXPECT_EQ(oakcommon_log(OAKCOMMON_DEBUG_INFO, "inf"), OAKCOMMON_OK);
EXPECT_TRUE(capture.lines.empty());
EXPECT_EQ(oakcommon_log(OAKCOMMON_DEBUG_WARNING, "wrn"), OAKCOMMON_OK);
EXPECT_EQ(oakcommon_log(OAKCOMMON_DEBUG_ERROR, "err"), OAKCOMMON_OK);
ASSERT_EQ(capture.lines.size(), 2u);
EXPECT_EQ(capture.lines[0], "[WARNING] wrn\n");
EXPECT_EQ(capture.lines[1], "[ERROR] err\n");
}
TEST(OakLog, DefaultLevelIsInfo)
{
// The default filter is INFO: DEBUG is dropped, INFO passes.
LogCapture capture;
olive::log_debug("invisible");
olive::log_info("visible");
ASSERT_EQ(capture.lines.size(), 1u);
EXPECT_EQ(capture.lines[0], "[INFO] visible\n");
}
TEST(OakLog, ConvenienceWrappersUseTheirLevels)
{
LogCapture capture;
olive::set_log_level(olive::k_debug_debug);
olive::log_debug("d");
olive::log_info("i");
olive::log_warning("w");
olive::log_critical("c");
ASSERT_EQ(capture.lines.size(), 4u);
EXPECT_EQ(capture.lines[0], "[DEBUG] d\n");
EXPECT_EQ(capture.lines[1], "[INFO] i\n");
EXPECT_EQ(capture.lines[2], "[WARNING] w\n");
EXPECT_EQ(capture.lines[3], "[ERROR] c\n");
}
TEST(OakLog, PrintfFormatting)
{
LogCapture capture;
olive::set_log_level(olive::k_debug_debug);
EXPECT_EQ(oakcommon_log(OAKCOMMON_DEBUG_INFO, "w=%d h=%d name=%s",
1920, 1080, "clip"),
OAKCOMMON_OK);
ASSERT_EQ(capture.lines.size(), 1u);
EXPECT_EQ(capture.lines[0], "[INFO] w=1920 h=1080 name=clip\n");
}
TEST(OakLog, PrintfLongMessageNotTruncated)
{
LogCapture capture;
std::string long_msg(100 * 1024, 'x');
EXPECT_EQ(oakcommon_log(OAKCOMMON_DEBUG_WARNING, "%s",
long_msg.c_str()),
OAKCOMMON_OK);
ASSERT_EQ(capture.lines.size(), 1u);
EXPECT_EQ(capture.lines[0],
"[WARNING] " + long_msg + "\n");
}
TEST(OakLog, PrintfNullFormat)
{
EXPECT_EQ(oakcommon_log(OAKCOMMON_DEBUG_WARNING, nullptr),
OAKCOMMON_E_INVALID);
}
TEST(OakLog, OutOfRangeLevelPrintsUnknown)
{
LogCapture capture;
olive::set_log_level(olive::k_debug_debug);
// Out-of-range levels are tolerated and print as UNKNOWN (same as
// oakcommon_debug_log).
EXPECT_EQ(oakcommon_log(999, "odd"), OAKCOMMON_OK);
ASSERT_EQ(capture.lines.size(), 1u);
EXPECT_EQ(capture.lines[0], "[UNKNOWN] odd\n");
}
+16 -17
View File
@@ -34,9 +34,9 @@ namespace ocio = OCIO_NAMESPACE;
TEST(OCIOUtilsCApi, InitReturnsHandle)
{
OakCommonOCIOUtils *utils = oakcommon_ocioutils_init();
ASSERT_NE(utils, nullptr);
oakcommon_ocioutils_free(utils);
OakOCIOUtils utils = oakcommon_ocioutils_init();
ASSERT_NE(utils.ctx, nullptr);
oakcommon_ocioutils_free(&utils);
}
TEST(OCIOUtilsCApi, FreeNullIsNoOp)
@@ -46,8 +46,8 @@ TEST(OCIOUtilsCApi, FreeNullIsNoOp)
TEST(OCIOUtilsCApi, BitDepthMappingMatchesOCIO)
{
OakCommonOCIOUtils *utils = oakcommon_ocioutils_init();
ASSERT_NE(utils, nullptr);
OakOCIOUtils utils = oakcommon_ocioutils_init();
ASSERT_NE(utils.ctx, nullptr);
const struct {
int pixel_format;
@@ -68,13 +68,13 @@ TEST(OCIOUtilsCApi, BitDepthMappingMatchesOCIO)
EXPECT_EQ(depth, static_cast<int>(c.expected));
}
oakcommon_ocioutils_free(utils);
oakcommon_ocioutils_free(&utils);
}
TEST(OCIOUtilsCApi, InvalidFormatYieldsUnknownDepth)
{
OakCommonOCIOUtils *utils = oakcommon_ocioutils_init();
ASSERT_NE(utils, nullptr);
OakOCIOUtils utils = oakcommon_ocioutils_init();
ASSERT_NE(utils.ctx, nullptr);
int depth = -1;
EXPECT_EQ(oakcommon_ocioutils_get_ocio_bit_depth_from_pixel_format(
@@ -82,33 +82,32 @@ TEST(OCIOUtilsCApi, InvalidFormatYieldsUnknownDepth)
OAKCOMMON_OK);
EXPECT_EQ(depth, static_cast<int>(ocio::BIT_DEPTH_UNKNOWN));
oakcommon_ocioutils_free(utils);
oakcommon_ocioutils_free(&utils);
}
TEST(OCIOUtilsCApi, NullHandleReturnsInvalid)
{
int depth = 0;
EXPECT_EQ(oakcommon_ocioutils_get_ocio_bit_depth_from_pixel_format(
NULL, OAKCOMMON_PIXEL_FORMAT_U8, &depth),
EXPECT_EQ(oakcommon_ocioutils_get_ocio_bit_depth_from_pixel_format(OakOCIOUtils{}, OAKCOMMON_PIXEL_FORMAT_U8, &depth),
OAKCOMMON_E_INVALID);
}
TEST(OCIOUtilsCApi, NullOutParamReturnsInvalid)
{
OakCommonOCIOUtils *utils = oakcommon_ocioutils_init();
ASSERT_NE(utils, nullptr);
OakOCIOUtils utils = oakcommon_ocioutils_init();
ASSERT_NE(utils.ctx, nullptr);
EXPECT_EQ(oakcommon_ocioutils_get_ocio_bit_depth_from_pixel_format(
utils, OAKCOMMON_PIXEL_FORMAT_U8, NULL),
OAKCOMMON_E_INVALID);
oakcommon_ocioutils_free(utils);
oakcommon_ocioutils_free(&utils);
}
TEST(OCIOUtilsCApi, OutOfRangeFormatReturnsInvalid)
{
OakCommonOCIOUtils *utils = oakcommon_ocioutils_init();
ASSERT_NE(utils, nullptr);
OakOCIOUtils utils = oakcommon_ocioutils_init();
ASSERT_NE(utils.ctx, nullptr);
int depth = 0;
EXPECT_EQ(oakcommon_ocioutils_get_ocio_bit_depth_from_pixel_format(
@@ -118,5 +117,5 @@ TEST(OCIOUtilsCApi, OutOfRangeFormatReturnsInvalid)
utils, -2, &depth),
OAKCOMMON_E_INVALID);
oakcommon_ocioutils_free(utils);
oakcommon_ocioutils_free(&utils);
}
+24 -26
View File
@@ -37,9 +37,9 @@
TEST(OIIOUtilsCApi, InitReturnsHandle)
{
OakCommonOIIOUtils *utils = oakcommon_oiioutils_init();
ASSERT_NE(utils, nullptr);
oakcommon_oiioutils_free(utils);
OakOIIOUtils utils = oakcommon_oiioutils_init();
ASSERT_NE(utils.ctx, nullptr);
oakcommon_oiioutils_free(&utils);
}
TEST(OIIOUtilsCApi, FreeNullIsNoOp)
@@ -49,8 +49,8 @@ TEST(OIIOUtilsCApi, FreeNullIsNoOp)
TEST(OIIOUtilsCApi, BaseTypeFromPixelFormat)
{
OakCommonOIIOUtils *utils = oakcommon_oiioutils_init();
ASSERT_NE(utils, nullptr);
OakOIIOUtils utils = oakcommon_oiioutils_init();
ASSERT_NE(utils.ctx, nullptr);
const struct {
int pixel_format;
@@ -72,17 +72,16 @@ TEST(OIIOUtilsCApi, BaseTypeFromPixelFormat)
EXPECT_EQ(base_type, c.expected_base_type);
}
oakcommon_oiioutils_free(utils);
oakcommon_oiioutils_free(&utils);
}
TEST(OIIOUtilsCApi, BaseTypeFromPixelFormatRejectsBadArgs)
{
OakCommonOIIOUtils *utils = oakcommon_oiioutils_init();
ASSERT_NE(utils, nullptr);
OakOIIOUtils utils = oakcommon_oiioutils_init();
ASSERT_NE(utils.ctx, nullptr);
int base_type = 0;
EXPECT_EQ(oakcommon_oiioutils_get_oiio_base_type_from_format(
NULL, OAKCOMMON_PIXEL_FORMAT_U8, &base_type),
EXPECT_EQ(oakcommon_oiioutils_get_oiio_base_type_from_format(OakOIIOUtils{}, OAKCOMMON_PIXEL_FORMAT_U8, &base_type),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_oiioutils_get_oiio_base_type_from_format(
utils, OAKCOMMON_PIXEL_FORMAT_U8, NULL),
@@ -94,13 +93,13 @@ TEST(OIIOUtilsCApi, BaseTypeFromPixelFormatRejectsBadArgs)
utils, -2, &base_type),
OAKCOMMON_E_INVALID);
oakcommon_oiioutils_free(utils);
oakcommon_oiioutils_free(&utils);
}
TEST(OIIOUtilsCApi, PixelFormatFromBaseType)
{
OakCommonOIIOUtils *utils = oakcommon_oiioutils_init();
ASSERT_NE(utils, nullptr);
OakOIIOUtils utils = oakcommon_oiioutils_init();
ASSERT_NE(utils.ctx, nullptr);
const struct {
int base_type;
@@ -123,17 +122,16 @@ TEST(OIIOUtilsCApi, PixelFormatFromBaseType)
EXPECT_EQ(pixel_format, c.expected_pixel_format);
}
oakcommon_oiioutils_free(utils);
oakcommon_oiioutils_free(&utils);
}
TEST(OIIOUtilsCApi, PixelFormatFromBaseTypeRejectsBadArgs)
{
OakCommonOIIOUtils *utils = oakcommon_oiioutils_init();
ASSERT_NE(utils, nullptr);
OakOIIOUtils utils = oakcommon_oiioutils_init();
ASSERT_NE(utils.ctx, nullptr);
int pixel_format = 0;
EXPECT_EQ(oakcommon_oiioutils_get_format_from_oiio_basetype(
NULL, 2, &pixel_format),
EXPECT_EQ(oakcommon_oiioutils_get_format_from_oiio_basetype(OakOIIOUtils{}, 2, &pixel_format),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_oiioutils_get_format_from_oiio_basetype(
utils, 2, NULL),
@@ -145,13 +143,13 @@ TEST(OIIOUtilsCApi, PixelFormatFromBaseTypeRejectsBadArgs)
utils, 100, &pixel_format),
OAKCOMMON_E_INVALID); /* >= LASTBASE */
oakcommon_oiioutils_free(utils);
oakcommon_oiioutils_free(&utils);
}
TEST(OIIOUtilsCApi, PixelAspectRatioConvertsToRational)
{
OakCommonOIIOUtils *utils = oakcommon_oiioutils_init();
ASSERT_NE(utils, nullptr);
OakOIIOUtils utils = oakcommon_oiioutils_init();
ASSERT_NE(utils.ctx, nullptr);
int num = 0;
int den = 0;
@@ -167,17 +165,17 @@ TEST(OIIOUtilsCApi, PixelAspectRatioConvertsToRational)
ASSERT_NE(den, 0);
EXPECT_NEAR(static_cast<double>(num) / den, 1.5, 1e-9);
oakcommon_oiioutils_free(utils);
oakcommon_oiioutils_free(&utils);
}
TEST(OIIOUtilsCApi, PixelAspectRatioRejectsBadArgs)
{
OakCommonOIIOUtils *utils = oakcommon_oiioutils_init();
ASSERT_NE(utils, nullptr);
OakOIIOUtils utils = oakcommon_oiioutils_init();
ASSERT_NE(utils.ctx, nullptr);
int num = 0;
int den = 0;
EXPECT_EQ(oakcommon_oiioutils_get_pixel_aspect_ratio(NULL, 1.0, &num,
EXPECT_EQ(oakcommon_oiioutils_get_pixel_aspect_ratio(OakOIIOUtils{}, 1.0, &num,
&den),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_oiioutils_get_pixel_aspect_ratio(utils, 1.0, NULL,
@@ -187,5 +185,5 @@ TEST(OIIOUtilsCApi, PixelAspectRatioRejectsBadArgs)
NULL),
OAKCOMMON_E_INVALID);
oakcommon_oiioutils_free(utils);
oakcommon_oiioutils_free(&utils);
}
+39 -39
View File
@@ -30,8 +30,8 @@ namespace
{
std::string read_indexed_string(
int (*fn)(OakCommonSubtitleParams *, int, char *, int),
OakCommonSubtitleParams *p, int index)
int (*fn)(OakSubtitleParams, int, char *, int),
OakSubtitleParams p, int index)
{
int needed = fn(p, index, nullptr, 0);
EXPECT_GT(needed, 0);
@@ -53,8 +53,8 @@ std::string read_static_string(int (*fn)(char *, int))
TEST(CommonSubtitleParamsCApi, InitFree)
{
OakCommonSubtitleParams *p = oakcommon_subtitleparams_init();
ASSERT_NE(p, nullptr);
OakSubtitleParams p = oakcommon_subtitleparams_init();
ASSERT_NE(p.ctx, nullptr);
int index = -1;
EXPECT_EQ(oakcommon_subtitleparams_get_stream_index(p, &index),
@@ -66,7 +66,7 @@ TEST(CommonSubtitleParamsCApi, InitFree)
OAKCOMMON_OK);
EXPECT_EQ(enabled, 1);
oakcommon_subtitleparams_free(p);
oakcommon_subtitleparams_free(&p);
}
TEST(CommonSubtitleParamsCApi, FreeNull)
@@ -76,48 +76,48 @@ TEST(CommonSubtitleParamsCApi, FreeNull)
TEST(CommonSubtitleParamsCApi, SetStreamIndex)
{
OakCommonSubtitleParams *p = oakcommon_subtitleparams_init();
ASSERT_NE(p, nullptr);
OakSubtitleParams p = oakcommon_subtitleparams_init();
ASSERT_NE(p.ctx, nullptr);
EXPECT_EQ(oakcommon_subtitleparams_set_stream_index(p, 3), OAKCOMMON_OK);
int index = 0;
EXPECT_EQ(oakcommon_subtitleparams_get_stream_index(p, &index),
OAKCOMMON_OK);
EXPECT_EQ(index, 3);
oakcommon_subtitleparams_free(p);
oakcommon_subtitleparams_free(&p);
}
TEST(CommonSubtitleParamsCApi, SetStreamIndexNullHandle)
{
EXPECT_EQ(oakcommon_subtitleparams_set_stream_index(nullptr, 3),
EXPECT_EQ(oakcommon_subtitleparams_set_stream_index(OakSubtitleParams{}, 3),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_subtitleparams_get_stream_index(nullptr, nullptr),
EXPECT_EQ(oakcommon_subtitleparams_get_stream_index(OakSubtitleParams{}, nullptr),
OAKCOMMON_E_INVALID);
}
TEST(CommonSubtitleParamsCApi, SetEnabled)
{
OakCommonSubtitleParams *p = oakcommon_subtitleparams_init();
ASSERT_NE(p, nullptr);
OakSubtitleParams p = oakcommon_subtitleparams_init();
ASSERT_NE(p.ctx, nullptr);
EXPECT_EQ(oakcommon_subtitleparams_set_enabled(p, 0), OAKCOMMON_OK);
int enabled = 1;
EXPECT_EQ(oakcommon_subtitleparams_get_enabled(p, &enabled),
OAKCOMMON_OK);
EXPECT_EQ(enabled, 0);
oakcommon_subtitleparams_free(p);
oakcommon_subtitleparams_free(&p);
}
TEST(CommonSubtitleParamsCApi, SetEnabledNullHandle)
{
EXPECT_EQ(oakcommon_subtitleparams_set_enabled(nullptr, 0),
EXPECT_EQ(oakcommon_subtitleparams_set_enabled(OakSubtitleParams{}, 0),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_subtitleparams_get_enabled(nullptr, nullptr),
EXPECT_EQ(oakcommon_subtitleparams_get_enabled(OakSubtitleParams{}, nullptr),
OAKCOMMON_E_INVALID);
}
TEST(CommonSubtitleParamsCApi, AddAndReadSubtitles)
{
OakCommonSubtitleParams *p = oakcommon_subtitleparams_init();
ASSERT_NE(p, nullptr);
OakSubtitleParams p = oakcommon_subtitleparams_init();
ASSERT_NE(p.ctx, nullptr);
int is_valid = 1;
EXPECT_EQ(oakcommon_subtitleparams_is_valid(p, &is_valid), OAKCOMMON_OK);
@@ -156,40 +156,40 @@ TEST(CommonSubtitleParamsCApi, AddAndReadSubtitles)
EXPECT_EQ(oakcommon_subtitleparams_count(p, &count), OAKCOMMON_OK);
EXPECT_EQ(count, 0);
oakcommon_subtitleparams_free(p);
oakcommon_subtitleparams_free(&p);
}
TEST(CommonSubtitleParamsCApi, SubtitleErrorPaths)
{
OakCommonSubtitleParams *p = oakcommon_subtitleparams_init();
ASSERT_NE(p, nullptr);
OakSubtitleParams p = oakcommon_subtitleparams_init();
ASSERT_NE(p.ctx, nullptr);
int i = 0;
char buf[16];
EXPECT_EQ(oakcommon_subtitleparams_add_subtitle(nullptr, 0, 1, 1, 1, "x"),
EXPECT_EQ(oakcommon_subtitleparams_add_subtitle(OakSubtitleParams{}, 0, 1, 1, 1, "x"),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_subtitleparams_add_subtitle(p, 0, 1, 1, 1, nullptr),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_subtitleparams_get_subtitle(p, 0, &i, &i, &i, &i),
OAKCOMMON_E_NOT_FOUND);
EXPECT_EQ(oakcommon_subtitleparams_get_subtitle(nullptr, 0, &i, &i, &i,
EXPECT_EQ(oakcommon_subtitleparams_get_subtitle(OakSubtitleParams{}, 0, &i, &i, &i,
&i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_subtitleparams_get_subtitle_text(p, 5, buf,
sizeof(buf)),
OAKCOMMON_E_NOT_FOUND);
EXPECT_EQ(oakcommon_subtitleparams_get_subtitle_text(nullptr, 0, buf,
EXPECT_EQ(oakcommon_subtitleparams_get_subtitle_text(OakSubtitleParams{}, 0, buf,
sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_subtitleparams_is_valid(nullptr, &i),
EXPECT_EQ(oakcommon_subtitleparams_is_valid(OakSubtitleParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_subtitleparams_count(nullptr, &i),
EXPECT_EQ(oakcommon_subtitleparams_count(OakSubtitleParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_subtitleparams_duration(nullptr, &i, &i),
EXPECT_EQ(oakcommon_subtitleparams_duration(OakSubtitleParams{}, &i, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_subtitleparams_clear(nullptr), OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_subtitleparams_clear(OakSubtitleParams{}), OAKCOMMON_E_INVALID);
oakcommon_subtitleparams_free(p);
oakcommon_subtitleparams_free(&p);
}
TEST(CommonSubtitleParamsCApi, GenerateAssHeader)
@@ -203,8 +203,8 @@ TEST(CommonSubtitleParamsCApi, GenerateAssHeader)
TEST(CommonSubtitleParamsCApi, XmlRoundTrip)
{
OakCommonSubtitleParams *p = oakcommon_subtitleparams_init();
ASSERT_NE(p, nullptr);
OakSubtitleParams p = oakcommon_subtitleparams_init();
ASSERT_NE(p.ctx, nullptr);
EXPECT_EQ(oakcommon_subtitleparams_set_stream_index(p, 2), OAKCOMMON_OK);
EXPECT_EQ(oakcommon_subtitleparams_add_subtitle(p, 1, 25, 2, 25,
"First <line>"),
@@ -215,8 +215,8 @@ TEST(CommonSubtitleParamsCApi, XmlRoundTrip)
std::vector<char> buf(needed);
ASSERT_EQ(oakcommon_subtitleparams_save_xml(p, buf.data(), needed), needed);
OakCommonSubtitleParams *q = oakcommon_subtitleparams_init();
ASSERT_NE(q, nullptr);
OakSubtitleParams q = oakcommon_subtitleparams_init();
ASSERT_NE(q.ctx, nullptr);
ASSERT_EQ(oakcommon_subtitleparams_load_xml(q, buf.data()), OAKCOMMON_OK);
int index = 0;
@@ -230,22 +230,22 @@ TEST(CommonSubtitleParamsCApi, XmlRoundTrip)
oakcommon_subtitleparams_get_subtitle_text, q, 0),
"First <line>");
oakcommon_subtitleparams_free(p);
oakcommon_subtitleparams_free(q);
oakcommon_subtitleparams_free(&p);
oakcommon_subtitleparams_free(&q);
}
TEST(CommonSubtitleParamsCApi, XmlErrorPaths)
{
OakCommonSubtitleParams *p = oakcommon_subtitleparams_init();
ASSERT_NE(p, nullptr);
OakSubtitleParams p = oakcommon_subtitleparams_init();
ASSERT_NE(p.ctx, nullptr);
char buf[16];
EXPECT_EQ(oakcommon_subtitleparams_load_xml(nullptr, "<a/>"),
EXPECT_EQ(oakcommon_subtitleparams_load_xml(OakSubtitleParams{}, "<a/>"),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_subtitleparams_load_xml(p, nullptr),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_subtitleparams_load_xml(p, "not xml"),
OAKCOMMON_E_FAILED);
EXPECT_EQ(oakcommon_subtitleparams_save_xml(nullptr, buf, sizeof(buf)),
EXPECT_EQ(oakcommon_subtitleparams_save_xml(OakSubtitleParams{}, buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
oakcommon_subtitleparams_free(p);
oakcommon_subtitleparams_free(&p);
}
+95 -95
View File
@@ -29,8 +29,8 @@
TEST(CommonVideoParamsCApi, InitDefaults)
{
OakCommonVideoParams *p = oakcommon_videoparams_init();
ASSERT_NE(p, nullptr);
OakVideoParams p = oakcommon_videoparams_init();
ASSERT_NE(p.ctx, nullptr);
int v = -1;
EXPECT_EQ(oakcommon_videoparams_get_width(p, &v), OAKCOMMON_OK);
@@ -38,7 +38,7 @@ TEST(CommonVideoParamsCApi, InitDefaults)
EXPECT_EQ(oakcommon_videoparams_get_is_valid(p, &v), OAKCOMMON_OK);
EXPECT_EQ(v, 0);
oakcommon_videoparams_free(p);
oakcommon_videoparams_free(&p);
}
TEST(CommonVideoParamsCApi, FreeNull)
@@ -48,10 +48,10 @@ TEST(CommonVideoParamsCApi, FreeNull)
TEST(CommonVideoParamsCApi, InitBasic)
{
OakCommonVideoParams *p = oakcommon_videoparams_init_basic(
OakVideoParams p = oakcommon_videoparams_init_basic(
1920, 1080, OAKCOMMON_PIXEL_FORMAT_U8,
4, 1, 1, OAKCOMMON_VIDEO_INTERLACE_NONE, 2);
ASSERT_NE(p, nullptr);
ASSERT_NE(p.ctx, nullptr);
int v;
EXPECT_EQ(oakcommon_videoparams_get_width(p, &v), OAKCOMMON_OK);
@@ -91,15 +91,15 @@ TEST(CommonVideoParamsCApi, InitBasic)
EXPECT_EQ(oakcommon_videoparams_get_buffer_size(p, &v), OAKCOMMON_OK);
EXPECT_EQ(v, 1920 * 1080 * 4);
oakcommon_videoparams_free(p);
oakcommon_videoparams_free(&p);
}
TEST(CommonVideoParamsCApi, InitWithTimeBase)
{
OakCommonVideoParams *p = oakcommon_videoparams_init_with_time_base(
OakVideoParams p = oakcommon_videoparams_init_with_time_base(
1280, 720, 1001, 30000, OAKCOMMON_PIXEL_FORMAT_F32, 4, 1, 1,
OAKCOMMON_VIDEO_INTERLACE_NONE, 1);
ASSERT_NE(p, nullptr);
ASSERT_NE(p.ctx, nullptr);
int num, den;
EXPECT_EQ(oakcommon_videoparams_get_time_base(p, &num, &den),
@@ -117,13 +117,13 @@ TEST(CommonVideoParamsCApi, InitWithTimeBase)
EXPECT_EQ(num, 1001);
EXPECT_EQ(den, 30000);
oakcommon_videoparams_free(p);
oakcommon_videoparams_free(&p);
}
TEST(CommonVideoParamsCApi, ScalarSetters)
{
OakCommonVideoParams *p = oakcommon_videoparams_init();
ASSERT_NE(p, nullptr);
OakVideoParams p = oakcommon_videoparams_init();
ASSERT_NE(p.ctx, nullptr);
int v;
EXPECT_EQ(oakcommon_videoparams_set_width(p, 640), OAKCOMMON_OK);
@@ -205,7 +205,7 @@ TEST(CommonVideoParamsCApi, ScalarSetters)
EXPECT_EQ(oakcommon_videoparams_get_effective_depth(p, &v), OAKCOMMON_OK);
EXPECT_EQ(v, 1);
oakcommon_videoparams_free(p);
oakcommon_videoparams_free(&p);
}
TEST(CommonVideoParamsCApi, NullHandleErrors)
@@ -214,123 +214,123 @@ TEST(CommonVideoParamsCApi, NullHandleErrors)
float f;
int64_t i64;
char buf[16];
EXPECT_EQ(oakcommon_videoparams_get_width(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_width(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_width(nullptr, 1),
EXPECT_EQ(oakcommon_videoparams_set_width(OakVideoParams{}, 1),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_height(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_height(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_height(nullptr, 1),
EXPECT_EQ(oakcommon_videoparams_set_height(OakVideoParams{}, 1),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_depth(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_depth(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_depth(nullptr, 1),
EXPECT_EQ(oakcommon_videoparams_set_depth(OakVideoParams{}, 1),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_is_3d(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_is_3d(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_time_base(nullptr, &i, &i),
EXPECT_EQ(oakcommon_videoparams_get_time_base(OakVideoParams{}, &i, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_time_base(nullptr, 1, 1),
EXPECT_EQ(oakcommon_videoparams_set_time_base(OakVideoParams{}, 1, 1),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_frame_rate(nullptr, &i, &i),
EXPECT_EQ(oakcommon_videoparams_get_frame_rate(OakVideoParams{}, &i, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_frame_rate(nullptr, 1, 1),
EXPECT_EQ(oakcommon_videoparams_set_frame_rate(OakVideoParams{}, 1, 1),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_frame_rate_as_time_base(nullptr, &i, &i),
EXPECT_EQ(oakcommon_videoparams_frame_rate_as_time_base(OakVideoParams{}, &i, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_pixel_aspect_ratio(nullptr, &i, &i),
EXPECT_EQ(oakcommon_videoparams_get_pixel_aspect_ratio(OakVideoParams{}, &i, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_pixel_aspect_ratio(nullptr, 1, 1),
EXPECT_EQ(oakcommon_videoparams_set_pixel_aspect_ratio(OakVideoParams{}, 1, 1),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_format(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_format(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_format(nullptr, 0),
EXPECT_EQ(oakcommon_videoparams_set_format(OakVideoParams{}, 0),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_channel_count(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_channel_count(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_channel_count(nullptr, 1),
EXPECT_EQ(oakcommon_videoparams_set_channel_count(OakVideoParams{}, 1),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_interlacing(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_interlacing(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_interlacing(nullptr, 0),
EXPECT_EQ(oakcommon_videoparams_set_interlacing(OakVideoParams{}, 0),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_divider(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_divider(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_divider(nullptr, 1),
EXPECT_EQ(oakcommon_videoparams_set_divider(OakVideoParams{}, 1),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_enabled(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_enabled(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_enabled(nullptr, 1),
EXPECT_EQ(oakcommon_videoparams_set_enabled(OakVideoParams{}, 1),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_x(nullptr, &f), OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_x(nullptr, 0.0f), OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_y(nullptr, &f), OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_y(nullptr, 0.0f), OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_stream_index(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_x(OakVideoParams{}, &f), OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_x(OakVideoParams{}, 0.0f), OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_y(OakVideoParams{}, &f), OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_y(OakVideoParams{}, 0.0f), OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_stream_index(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_stream_index(nullptr, 0),
EXPECT_EQ(oakcommon_videoparams_set_stream_index(OakVideoParams{}, 0),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_video_type(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_video_type(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_video_type(nullptr, 0),
EXPECT_EQ(oakcommon_videoparams_set_video_type(OakVideoParams{}, 0),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_start_time(nullptr, &i64),
EXPECT_EQ(oakcommon_videoparams_get_start_time(OakVideoParams{}, &i64),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_start_time(nullptr, 0),
EXPECT_EQ(oakcommon_videoparams_set_start_time(OakVideoParams{}, 0),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_duration(nullptr, &i64),
EXPECT_EQ(oakcommon_videoparams_get_duration(OakVideoParams{}, &i64),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_duration(nullptr, 0),
EXPECT_EQ(oakcommon_videoparams_set_duration(OakVideoParams{}, 0),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_premultiplied_alpha(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_premultiplied_alpha(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_premultiplied_alpha(nullptr, 0),
EXPECT_EQ(oakcommon_videoparams_set_premultiplied_alpha(OakVideoParams{}, 0),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_color_range(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_color_range(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_color_range(nullptr, 0),
EXPECT_EQ(oakcommon_videoparams_set_color_range(OakVideoParams{}, 0),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_color_primaries(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_color_primaries(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_color_primaries(nullptr, 0),
EXPECT_EQ(oakcommon_videoparams_set_color_primaries(OakVideoParams{}, 0),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_color_transfer(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_color_transfer(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_color_transfer(nullptr, 0),
EXPECT_EQ(oakcommon_videoparams_set_color_transfer(OakVideoParams{}, 0),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_colorspace(nullptr, buf, sizeof(buf)),
EXPECT_EQ(oakcommon_videoparams_get_colorspace(OakVideoParams{}, buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_set_colorspace(nullptr, "x"),
EXPECT_EQ(oakcommon_videoparams_set_colorspace(OakVideoParams{}, "x"),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_square_pixel_width(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_square_pixel_width(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_effective_width(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_effective_width(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_effective_height(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_effective_height(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_effective_depth(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_effective_depth(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_is_valid(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_is_valid(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_bytes_per_channel(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_bytes_per_channel(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_bytes_per_pixel(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_bytes_per_pixel(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_buffer_size(nullptr, &i),
EXPECT_EQ(oakcommon_videoparams_get_buffer_size(OakVideoParams{}, &i),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_time_in_timebase_units(nullptr, 0, 1,
EXPECT_EQ(oakcommon_videoparams_get_time_in_timebase_units(OakVideoParams{}, 0, 1,
&i64),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_load_xml(nullptr, "<a/>"),
EXPECT_EQ(oakcommon_videoparams_load_xml(OakVideoParams{}, "<a/>"),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_save_xml(nullptr, buf, sizeof(buf)),
EXPECT_EQ(oakcommon_videoparams_save_xml(OakVideoParams{}, buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
}
TEST(CommonVideoParamsCApi, NullOutParamErrors)
{
OakCommonVideoParams *p = oakcommon_videoparams_init();
ASSERT_NE(p, nullptr);
OakVideoParams p = oakcommon_videoparams_init();
ASSERT_NE(p.ctx, nullptr);
EXPECT_EQ(oakcommon_videoparams_get_width(p, nullptr),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_get_time_base(p, nullptr, nullptr),
@@ -340,13 +340,13 @@ TEST(CommonVideoParamsCApi, NullOutParamErrors)
EXPECT_EQ(oakcommon_videoparams_load_xml(p, nullptr), OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_load_xml(p, "not xml"),
OAKCOMMON_E_FAILED);
oakcommon_videoparams_free(p);
oakcommon_videoparams_free(&p);
}
TEST(CommonVideoParamsCApi, Colorspace)
{
OakCommonVideoParams *p = oakcommon_videoparams_init();
ASSERT_NE(p, nullptr);
OakVideoParams p = oakcommon_videoparams_init();
ASSERT_NE(p.ctx, nullptr);
EXPECT_EQ(oakcommon_videoparams_set_colorspace(p, "rec709"),
OAKCOMMON_OK);
int needed = oakcommon_videoparams_get_colorspace(p, nullptr, 0);
@@ -355,15 +355,15 @@ TEST(CommonVideoParamsCApi, Colorspace)
EXPECT_EQ(oakcommon_videoparams_get_colorspace(p, buf.data(), needed),
needed);
EXPECT_STREQ(buf.data(), "rec709");
oakcommon_videoparams_free(p);
oakcommon_videoparams_free(&p);
}
TEST(CommonVideoParamsCApi, TimeInTimebaseUnits)
{
OakCommonVideoParams *p = oakcommon_videoparams_init_with_time_base(
OakVideoParams p = oakcommon_videoparams_init_with_time_base(
1920, 1080, 1, 25, OAKCOMMON_PIXEL_FORMAT_U8, 4, 1, 1,
OAKCOMMON_VIDEO_INTERLACE_NONE, 1);
ASSERT_NE(p, nullptr);
ASSERT_NE(p.ctx, nullptr);
int64_t ts = -1;
EXPECT_EQ(oakcommon_videoparams_get_time_in_timebase_units(p, 2, 1, &ts),
@@ -371,26 +371,26 @@ TEST(CommonVideoParamsCApi, TimeInTimebaseUnits)
EXPECT_EQ(ts, 50); // 2 seconds at 25 fps
// Without a time base the result is AV_NOPTS_VALUE
OakCommonVideoParams *q = oakcommon_videoparams_init();
ASSERT_NE(q, nullptr);
OakVideoParams q = oakcommon_videoparams_init();
ASSERT_NE(q.ctx, nullptr);
EXPECT_EQ(oakcommon_videoparams_get_time_in_timebase_units(q, 2, 1, &ts),
OAKCOMMON_OK);
EXPECT_EQ(ts, INT64_MIN);
oakcommon_videoparams_free(p);
oakcommon_videoparams_free(q);
oakcommon_videoparams_free(&p);
oakcommon_videoparams_free(&q);
}
TEST(CommonVideoParamsCApi, Equals)
{
OakCommonVideoParams *a = oakcommon_videoparams_init_basic(
OakVideoParams a = oakcommon_videoparams_init_basic(
1920, 1080, OAKCOMMON_PIXEL_FORMAT_U8, 4, 1, 1,
OAKCOMMON_VIDEO_INTERLACE_NONE, 1);
OakCommonVideoParams *b = oakcommon_videoparams_init_basic(
OakVideoParams b = oakcommon_videoparams_init_basic(
1920, 1080, OAKCOMMON_PIXEL_FORMAT_U8, 4, 1, 1,
OAKCOMMON_VIDEO_INTERLACE_NONE, 1);
ASSERT_NE(a, nullptr);
ASSERT_NE(b, nullptr);
ASSERT_NE(a.ctx, nullptr);
ASSERT_NE(b.ctx, nullptr);
int equal = 0;
EXPECT_EQ(oakcommon_videoparams_equals(a, b, &equal), OAKCOMMON_OK);
@@ -400,23 +400,23 @@ TEST(CommonVideoParamsCApi, Equals)
EXPECT_EQ(oakcommon_videoparams_equals(a, b, &equal), OAKCOMMON_OK);
EXPECT_EQ(equal, 0);
EXPECT_EQ(oakcommon_videoparams_equals(nullptr, b, &equal),
EXPECT_EQ(oakcommon_videoparams_equals(OakVideoParams{}, b, &equal),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_equals(a, nullptr, &equal),
EXPECT_EQ(oakcommon_videoparams_equals(a, OakVideoParams{}, &equal),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_videoparams_equals(a, b, nullptr),
OAKCOMMON_E_INVALID);
oakcommon_videoparams_free(a);
oakcommon_videoparams_free(b);
oakcommon_videoparams_free(&a);
oakcommon_videoparams_free(&b);
}
TEST(CommonVideoParamsCApi, XmlRoundTrip)
{
OakCommonVideoParams *p = oakcommon_videoparams_init_with_time_base(
OakVideoParams p = oakcommon_videoparams_init_with_time_base(
1920, 1080, 1, 25, OAKCOMMON_PIXEL_FORMAT_F16, 4, 4, 3,
OAKCOMMON_VIDEO_INTERLACED_BOTTOM_FIRST, 2);
ASSERT_NE(p, nullptr);
ASSERT_NE(p.ctx, nullptr);
EXPECT_EQ(oakcommon_videoparams_set_colorspace(p, "rec709"),
OAKCOMMON_OK);
EXPECT_EQ(oakcommon_videoparams_set_color_primaries(p, 9), OAKCOMMON_OK);
@@ -426,8 +426,8 @@ TEST(CommonVideoParamsCApi, XmlRoundTrip)
std::vector<char> buf(needed);
ASSERT_EQ(oakcommon_videoparams_save_xml(p, buf.data(), needed), needed);
OakCommonVideoParams *q = oakcommon_videoparams_init();
ASSERT_NE(q, nullptr);
OakVideoParams q = oakcommon_videoparams_init();
ASSERT_NE(q.ctx, nullptr);
ASSERT_EQ(oakcommon_videoparams_load_xml(q, buf.data()), OAKCOMMON_OK);
int equal = 0;
@@ -450,8 +450,8 @@ TEST(CommonVideoParamsCApi, XmlRoundTrip)
EXPECT_EQ(oakcommon_videoparams_get_color_primaries(q, &v), OAKCOMMON_OK);
EXPECT_EQ(v, 9);
oakcommon_videoparams_free(p);
oakcommon_videoparams_free(q);
oakcommon_videoparams_free(&p);
oakcommon_videoparams_free(&q);
}
TEST(CommonVideoParamsCApi, StaticHelpers)
+50 -52
View File
@@ -29,8 +29,8 @@
namespace
{
std::string read_string(int (*fn)(OakCommonXmlReader *, char *, int),
OakCommonXmlReader *reader)
std::string read_string(int (*fn)(OakXmlReader, char *, int),
OakXmlReader reader)
{
int needed = fn(reader, nullptr, 0);
EXPECT_GT(needed, 0);
@@ -43,7 +43,7 @@ std::string read_string(int (*fn)(OakCommonXmlReader *, char *, int),
TEST(CommonXmlUtilsCApi, ReaderInitNullData)
{
EXPECT_EQ(oakcommon_xml_reader_init(nullptr), nullptr);
EXPECT_EQ(oakcommon_xml_reader_init(nullptr).ctx, nullptr);
}
TEST(CommonXmlUtilsCApi, ReaderFreeNull)
@@ -53,9 +53,8 @@ TEST(CommonXmlUtilsCApi, ReaderFreeNull)
TEST(CommonXmlUtilsCApi, ReadNextStartElement)
{
OakCommonXmlReader *r =
oakcommon_xml_reader_init("<root><child>value</child></root>");
ASSERT_NE(r, nullptr);
OakXmlReader r = oakcommon_xml_reader_init("<root><child>value</child></root>");
ASSERT_NE(r.ctx, nullptr);
int found = 0;
EXPECT_EQ(oakcommon_xml_reader_read_next_start_element(r, &found),
@@ -68,26 +67,26 @@ TEST(CommonXmlUtilsCApi, ReadNextStartElement)
EXPECT_EQ(found, 1);
EXPECT_EQ(read_string(oakcommon_xml_reader_name, r), "child");
oakcommon_xml_reader_free(r);
oakcommon_xml_reader_free(&r);
}
TEST(CommonXmlUtilsCApi, ReadNextStartElementNullHandle)
{
int found = 0;
EXPECT_EQ(oakcommon_xml_reader_read_next_start_element(nullptr, &found),
EXPECT_EQ(oakcommon_xml_reader_read_next_start_element(OakXmlReader{}, &found),
OAKCOMMON_E_INVALID);
OakCommonXmlReader *r = oakcommon_xml_reader_init("<root/>");
ASSERT_NE(r, nullptr);
OakXmlReader r = oakcommon_xml_reader_init("<root/>");
ASSERT_NE(r.ctx, nullptr);
EXPECT_EQ(oakcommon_xml_reader_read_next_start_element(r, nullptr),
OAKCOMMON_E_INVALID);
oakcommon_xml_reader_free(r);
oakcommon_xml_reader_free(&r);
}
TEST(CommonXmlUtilsCApi, ReadNextStartElementReturnsFalseAtEnd)
{
OakCommonXmlReader *r = oakcommon_xml_reader_init("<root/>");
ASSERT_NE(r, nullptr);
OakXmlReader r = oakcommon_xml_reader_init("<root/>");
ASSERT_NE(r.ctx, nullptr);
int found = -1;
EXPECT_EQ(oakcommon_xml_reader_read_next_start_element(r, &found),
@@ -97,21 +96,21 @@ TEST(CommonXmlUtilsCApi, ReadNextStartElementReturnsFalseAtEnd)
OAKCOMMON_OK);
EXPECT_EQ(found, 0);
oakcommon_xml_reader_free(r);
oakcommon_xml_reader_free(&r);
}
TEST(CommonXmlUtilsCApi, NameNullHandle)
{
char buf[16];
EXPECT_EQ(oakcommon_xml_reader_name(nullptr, buf, sizeof(buf)),
EXPECT_EQ(oakcommon_xml_reader_name(OakXmlReader{}, buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
}
TEST(CommonXmlUtilsCApi, ReadElementText)
{
OakCommonXmlReader *r =
OakXmlReader r =
oakcommon_xml_reader_init("<root><child>a &amp; b</child></root>");
ASSERT_NE(r, nullptr);
ASSERT_NE(r.ctx, nullptr);
int found = 0;
EXPECT_EQ(oakcommon_xml_reader_read_next_start_element(r, &found),
@@ -122,22 +121,22 @@ TEST(CommonXmlUtilsCApi, ReadElementText)
EXPECT_EQ(read_string(oakcommon_xml_reader_read_element_text, r),
"a & b");
oakcommon_xml_reader_free(r);
oakcommon_xml_reader_free(&r);
}
TEST(CommonXmlUtilsCApi, ReadElementTextNullHandle)
{
char buf[16];
EXPECT_EQ(oakcommon_xml_reader_read_element_text(nullptr, buf,
EXPECT_EQ(oakcommon_xml_reader_read_element_text(OakXmlReader{}, buf,
sizeof(buf)),
OAKCOMMON_E_INVALID);
}
TEST(CommonXmlUtilsCApi, SkipCurrentElement)
{
OakCommonXmlReader *r = oakcommon_xml_reader_init(
OakXmlReader r = oakcommon_xml_reader_init(
"<root><unknown><nested/></unknown><known/></root>");
ASSERT_NE(r, nullptr);
ASSERT_NE(r.ctx, nullptr);
int found = 0;
EXPECT_EQ(oakcommon_xml_reader_read_next_start_element(r, &found),
@@ -153,20 +152,20 @@ TEST(CommonXmlUtilsCApi, SkipCurrentElement)
EXPECT_EQ(found, 1);
EXPECT_EQ(read_string(oakcommon_xml_reader_name, r), "known");
oakcommon_xml_reader_free(r);
oakcommon_xml_reader_free(&r);
}
TEST(CommonXmlUtilsCApi, SkipCurrentElementNullHandle)
{
EXPECT_EQ(oakcommon_xml_reader_skip_current_element(nullptr),
EXPECT_EQ(oakcommon_xml_reader_skip_current_element(OakXmlReader{}),
OAKCOMMON_E_INVALID);
}
TEST(CommonXmlUtilsCApi, Attributes)
{
OakCommonXmlReader *r = oakcommon_xml_reader_init(
OakXmlReader r = oakcommon_xml_reader_init(
"<root><item id=\"7\" name=\"a&quot;b\"/></root>");
ASSERT_NE(r, nullptr);
ASSERT_NE(r.ctx, nullptr);
int found = 0;
EXPECT_EQ(oakcommon_xml_reader_read_next_start_element(r, &found),
@@ -191,16 +190,16 @@ TEST(CommonXmlUtilsCApi, Attributes)
0);
EXPECT_STREQ(buf, "a\"b");
oakcommon_xml_reader_free(r);
oakcommon_xml_reader_free(&r);
}
TEST(CommonXmlUtilsCApi, AttributeErrorPaths)
{
EXPECT_EQ(oakcommon_xml_reader_attribute_count(nullptr, nullptr),
EXPECT_EQ(oakcommon_xml_reader_attribute_count(OakXmlReader{}, nullptr),
OAKCOMMON_E_INVALID);
OakCommonXmlReader *r = oakcommon_xml_reader_init("<root a=\"1\"/>");
ASSERT_NE(r, nullptr);
OakXmlReader r = oakcommon_xml_reader_init("<root a=\"1\"/>");
ASSERT_NE(r.ctx, nullptr);
int found = 0;
EXPECT_EQ(oakcommon_xml_reader_read_next_start_element(r, &found),
OAKCOMMON_OK);
@@ -210,30 +209,29 @@ TEST(CommonXmlUtilsCApi, AttributeErrorPaths)
OAKCOMMON_E_NOT_FOUND);
EXPECT_EQ(oakcommon_xml_reader_attribute_value(r, -1, buf, sizeof(buf)),
OAKCOMMON_E_NOT_FOUND);
EXPECT_EQ(oakcommon_xml_reader_attribute_name(nullptr, 0, buf,
EXPECT_EQ(oakcommon_xml_reader_attribute_name(OakXmlReader{}, 0, buf,
sizeof(buf)),
OAKCOMMON_E_INVALID);
oakcommon_xml_reader_free(r);
oakcommon_xml_reader_free(&r);
}
TEST(CommonXmlUtilsCApi, HasError)
{
OakCommonXmlReader *bad =
oakcommon_xml_reader_init("<root><unclosed></root>");
ASSERT_NE(bad, nullptr);
OakXmlReader bad = oakcommon_xml_reader_init("<root><unclosed></root>");
ASSERT_NE(bad.ctx, nullptr);
int has_error = 0;
EXPECT_EQ(oakcommon_xml_reader_has_error(bad, &has_error), OAKCOMMON_OK);
EXPECT_EQ(has_error, 1);
oakcommon_xml_reader_free(bad);
oakcommon_xml_reader_free(&bad);
OakCommonXmlReader *good = oakcommon_xml_reader_init("<root/>");
ASSERT_NE(good, nullptr);
OakXmlReader good = oakcommon_xml_reader_init("<root/>");
ASSERT_NE(good.ctx, nullptr);
EXPECT_EQ(oakcommon_xml_reader_has_error(good, &has_error), OAKCOMMON_OK);
EXPECT_EQ(has_error, 0);
EXPECT_EQ(oakcommon_xml_reader_has_error(nullptr, &has_error),
EXPECT_EQ(oakcommon_xml_reader_has_error(OakXmlReader{}, &has_error),
OAKCOMMON_E_INVALID);
oakcommon_xml_reader_free(good);
oakcommon_xml_reader_free(&good);
}
TEST(CommonXmlUtilsCApi, WriterFreeNull)
@@ -244,17 +242,17 @@ TEST(CommonXmlUtilsCApi, WriterFreeNull)
TEST(CommonXmlUtilsCApi, WriterNullHandleAndArgs)
{
char buf[16];
EXPECT_EQ(oakcommon_xml_writer_write_start_element(nullptr, "a"),
EXPECT_EQ(oakcommon_xml_writer_write_start_element(OakXmlWriter{}, "a"),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_xml_writer_write_end_element(nullptr),
EXPECT_EQ(oakcommon_xml_writer_write_end_element(OakXmlWriter{}),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_xml_writer_write_end_document(nullptr),
EXPECT_EQ(oakcommon_xml_writer_write_end_document(OakXmlWriter{}),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_xml_writer_output(nullptr, buf, sizeof(buf)),
EXPECT_EQ(oakcommon_xml_writer_output(OakXmlWriter{}, buf, sizeof(buf)),
OAKCOMMON_E_INVALID);
OakCommonXmlWriter *w = oakcommon_xml_writer_init();
ASSERT_NE(w, nullptr);
OakXmlWriter w = oakcommon_xml_writer_init();
ASSERT_NE(w.ctx, nullptr);
EXPECT_EQ(oakcommon_xml_writer_write_start_element(w, nullptr),
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_xml_writer_write_attribute(w, "a", nullptr),
@@ -263,13 +261,13 @@ TEST(CommonXmlUtilsCApi, WriterNullHandleAndArgs)
OAKCOMMON_E_INVALID);
EXPECT_EQ(oakcommon_xml_writer_write_text_element(w, nullptr, "x"),
OAKCOMMON_E_INVALID);
oakcommon_xml_writer_free(w);
oakcommon_xml_writer_free(&w);
}
TEST(CommonXmlUtilsCApi, WriterRoundTrip)
{
OakCommonXmlWriter *w = oakcommon_xml_writer_init();
ASSERT_NE(w, nullptr);
OakXmlWriter w = oakcommon_xml_writer_init();
ASSERT_NE(w.ctx, nullptr);
EXPECT_EQ(oakcommon_xml_writer_write_start_element(w, "root"),
OAKCOMMON_OK);
@@ -287,11 +285,11 @@ TEST(CommonXmlUtilsCApi, WriterRoundTrip)
ASSERT_GT(needed, 0);
std::vector<char> buf(needed);
EXPECT_EQ(oakcommon_xml_writer_output(w, buf.data(), needed), needed);
oakcommon_xml_writer_free(w);
oakcommon_xml_writer_free(&w);
// Read the produced document back.
OakCommonXmlReader *r = oakcommon_xml_reader_init(buf.data());
ASSERT_NE(r, nullptr);
OakXmlReader r = oakcommon_xml_reader_init(buf.data());
ASSERT_NE(r.ctx, nullptr);
int has_error = 1;
EXPECT_EQ(oakcommon_xml_reader_has_error(r, &has_error), OAKCOMMON_OK);
EXPECT_EQ(has_error, 0);
@@ -326,5 +324,5 @@ TEST(CommonXmlUtilsCApi, WriterRoundTrip)
OAKCOMMON_OK);
EXPECT_EQ(found, 0);
oakcommon_xml_reader_free(r);
oakcommon_xml_reader_free(&r);
}