Cleanup aom_codec_control function Add documentation, fix inconsistency with the sentinel value BUG=aomedia:2651 Change-Id: I000712b5131658ed23ea64bfad29a47dd4ead412
diff --git a/aom/internal/aom_codec_internal.h b/aom/internal/aom_codec_internal.h index 0096003..efebd17 100644 --- a/aom/internal/aom_codec_internal.h +++ b/aom/internal/aom_codec_internal.h
@@ -157,18 +157,24 @@ * * This structure stores the mapping between control identifiers and * implementing functions. Each algorithm provides a list of these - * mappings. This list is searched by the aom_codec_control() wrapper + * mappings. This list is searched by the aom_codec_control() * function to determine which function to invoke. The special - * value {0, NULL} is used to indicate end-of-list, and must be - * present. The special value {0, <non-null>} can be used as a catch-all - * mapping. This implies that ctrl_id values chosen by the algorithm - * \ref MUST be non-zero. + * value defined by CTRL_MAP_END is used to indicate end-of-list, and must be + * present. It can be tested with the at_ctrl_map_end function. Note that + * ctrl_id values \ref MUST be non-zero. */ typedef const struct aom_codec_ctrl_fn_map { int ctrl_id; aom_codec_control_fn_t fn; } aom_codec_ctrl_fn_map_t; +#define CTRL_MAP_END \ + { 0, NULL } + +static AOM_INLINE int at_ctrl_map_end(aom_codec_ctrl_fn_map_t *e) { + return e->ctrl_id == 0 && e->fn == NULL; +} + /*!\brief decode data function pointer prototype * * Processes a buffer of coded data. This function is called by the generic
diff --git a/aom/src/aom_codec.c b/aom/src/aom_codec.c index 196ab83..d418463 100644 --- a/aom/src/aom_codec.c +++ b/aom/src/aom_codec.c
@@ -22,8 +22,6 @@ #include "aom/aom_integer.h" #include "aom/internal/aom_codec_internal.h" -#define SAVE_STATUS(ctx, var) (ctx ? (ctx->err = var) : var) - int aom_codec_version(void) { return VERSION_PACKED; } const char *aom_codec_version_str(void) { return VERSION_STRING_NOSP; } @@ -67,22 +65,19 @@ } aom_codec_err_t aom_codec_destroy(aom_codec_ctx_t *ctx) { - aom_codec_err_t res; - - if (!ctx) - res = AOM_CODEC_INVALID_PARAM; - else if (!ctx->iface || !ctx->priv) - res = AOM_CODEC_ERROR; - else { - ctx->iface->destroy((aom_codec_alg_priv_t *)ctx->priv); - - ctx->iface = NULL; - ctx->name = NULL; - ctx->priv = NULL; - res = AOM_CODEC_OK; + if (!ctx) { + return AOM_CODEC_INVALID_PARAM; } - - return SAVE_STATUS(ctx, res); + if (!ctx->iface || !ctx->priv) { + ctx->err = AOM_CODEC_ERROR; + return AOM_CODEC_ERROR; + } + ctx->iface->destroy((aom_codec_alg_priv_t *)ctx->priv); + ctx->iface = NULL; + ctx->name = NULL; + ctx->priv = NULL; + ctx->err = AOM_CODEC_OK; + return AOM_CODEC_OK; } aom_codec_caps_t aom_codec_get_caps(aom_codec_iface_t *iface) { @@ -90,30 +85,33 @@ } aom_codec_err_t aom_codec_control(aom_codec_ctx_t *ctx, int ctrl_id, ...) { - aom_codec_err_t res; - - if (!ctx || !ctrl_id) - res = AOM_CODEC_INVALID_PARAM; - else if (!ctx->iface || !ctx->priv || !ctx->iface->ctrl_maps) - res = AOM_CODEC_ERROR; - else { - aom_codec_ctrl_fn_map_t *entry; - - res = AOM_CODEC_ERROR; - - for (entry = ctx->iface->ctrl_maps; entry && entry->fn; entry++) { - if (!entry->ctrl_id || entry->ctrl_id == ctrl_id) { - va_list ap; - - va_start(ap, ctrl_id); - res = entry->fn((aom_codec_alg_priv_t *)ctx->priv, ap); - va_end(ap); - break; - } - } + if (!ctx) { + return AOM_CODEC_INVALID_PARAM; + } + // Control ID must be non-zero. + if (!ctrl_id) { + ctx->err = AOM_CODEC_INVALID_PARAM; + return AOM_CODEC_INVALID_PARAM; + } + if (!ctx->iface || !ctx->priv || !ctx->iface->ctrl_maps) { + ctx->err = AOM_CODEC_ERROR; + return AOM_CODEC_ERROR; } - return SAVE_STATUS(ctx, res); + // "ctrl_maps" is an array of (control ID, function pointer) elements, + // with CTRL_MAP_END as a sentinel. + for (aom_codec_ctrl_fn_map_t *entry = ctx->iface->ctrl_maps; + !at_ctrl_map_end(entry); ++entry) { + if (entry->ctrl_id == ctrl_id) { + va_list ap; + va_start(ap, ctrl_id); + ctx->err = entry->fn((aom_codec_alg_priv_t *)ctx->priv, ap); + va_end(ap); + return ctx->err; + } + } + ctx->err = AOM_CODEC_ERROR; + return AOM_CODEC_ERROR; } void aom_internal_error(struct aom_internal_error_info *info,
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c index ee4ab09..5d9bc1c 100644 --- a/av1/av1_cx_iface.c +++ b/av1/av1_cx_iface.c
@@ -2783,7 +2783,8 @@ { AV1E_SET_CHROMA_SUBSAMPLING_X, ctrl_set_chroma_subsampling_x }, { AV1E_SET_CHROMA_SUBSAMPLING_Y, ctrl_set_chroma_subsampling_y }, { AV1E_GET_SEQ_LEVEL_IDX, ctrl_get_seq_level_idx }, - { -1, NULL }, + + CTRL_MAP_END, }; static const aom_codec_enc_cfg_t encoder_usage_cfg[] = {
diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c index b5d856e..e621cd2 100644 --- a/av1/av1_dx_iface.c +++ b/av1/av1_dx_iface.c
@@ -1362,7 +1362,7 @@ { AV1D_GET_FRAME_HEADER_INFO, ctrl_get_frame_header_info }, { AV1D_GET_TILE_DATA, ctrl_get_tile_data }, - { -1, NULL }, + CTRL_MAP_END, }; // This data structure and function are exported in aom/aomdx.h
diff --git a/test/encode_api_test.cc b/test/encode_api_test.cc index c1f2932..4b79f25 100644 --- a/test/encode_api_test.cc +++ b/test/encode_api_test.cc
@@ -21,11 +21,6 @@ namespace { TEST(EncodeAPI, InvalidParams) { - static aom_codec_iface_t *kCodecs[] = { -#if CONFIG_AV1_ENCODER - aom_codec_av1_cx(), -#endif - }; uint8_t buf[1] = { 0 }; aom_image_t img; aom_codec_ctx_t enc; @@ -44,31 +39,35 @@ aom_codec_enc_config_default(NULL, &cfg, 0)); EXPECT_TRUE(aom_codec_error(NULL) != NULL); - for (aom_codec_iface_t *iface : kCodecs) { - SCOPED_TRACE(aom_codec_iface_name(iface)); - EXPECT_EQ(AOM_CODEC_INVALID_PARAM, - aom_codec_enc_init(NULL, iface, NULL, 0)); - EXPECT_EQ(AOM_CODEC_INVALID_PARAM, - aom_codec_enc_init(&enc, iface, NULL, 0)); - EXPECT_EQ(AOM_CODEC_INVALID_PARAM, - aom_codec_enc_config_default(iface, &cfg, 2)); + aom_codec_iface_t *iface = aom_codec_av1_cx(); + SCOPED_TRACE(aom_codec_iface_name(iface)); + EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_enc_init(NULL, iface, NULL, 0)); + EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_enc_init(&enc, iface, NULL, 0)); + EXPECT_EQ(AOM_CODEC_INVALID_PARAM, + aom_codec_enc_config_default(iface, &cfg, 2)); + EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_default(iface, &cfg, 0)); + EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0)); + EXPECT_EQ(NULL, aom_codec_get_global_headers(NULL)); - EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_default(iface, &cfg, 0)); - EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0)); - - EXPECT_EQ(NULL, aom_codec_get_global_headers(NULL)); - - aom_fixed_buf_t *glob_headers = aom_codec_get_global_headers(&enc); - EXPECT_TRUE(glob_headers->buf != NULL); - if (glob_headers) { - free(glob_headers->buf); - free(glob_headers); - } - - EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, NULL, 0, 0, 0)); - - EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc)); + aom_fixed_buf_t *glob_headers = aom_codec_get_global_headers(&enc); + EXPECT_TRUE(glob_headers->buf != NULL); + if (glob_headers) { + free(glob_headers->buf); + free(glob_headers); } + EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, NULL, 0, 0, 0)); + EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc)); +} + +TEST(EncodeAPI, InvalidControlId) { + aom_codec_iface_t *iface = aom_codec_av1_cx(); + aom_codec_ctx_t enc; + aom_codec_enc_cfg_t cfg; + EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_default(iface, &cfg, 0)); + EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0)); + EXPECT_EQ(AOM_CODEC_ERROR, aom_codec_control(&enc, -1, 0)); + EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_control(&enc, 0, 0)); + EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc)); } } // namespace