Adding API to get vpx encoder/decoder interface.
authorDmitry Kovalev <dkovalev@google.com>
Wed, 12 Feb 2014 05:12:23 +0000 (21:12 -0800)
committerDmitry Kovalev <dkovalev@google.com>
Wed, 12 Feb 2014 05:12:23 +0000 (21:12 -0800)
Change-Id: I137e5e6585356792913e1e84da6c0a439c5153a5

12 files changed:
examples/decode_to_md5.c
examples/decode_with_drops.c
examples/postproc.c
examples/simple_decoder.c
examples/simple_encoder.c
examples/twopass_encoder.c
examples/vpx_temporal_scalable_patterns.c
tools_common.c
tools_common.h
vpxdec.c
vpxenc.c
vpxenc.h

index 077513c..aabac60 100644 (file)
@@ -82,9 +82,9 @@ int main(int argc, char **argv) {
   int frame_cnt = 0;
   FILE *outfile = NULL;
   vpx_codec_ctx_t codec;
-  vpx_codec_iface_t *iface = NULL;
   VpxVideoReader *reader = NULL;
   const VpxVideoInfo *info = NULL;
+  const VpxInterface *decoder = NULL;
 
   exec_name = argv[0];
 
@@ -100,13 +100,13 @@ int main(int argc, char **argv) {
 
   info = vpx_video_reader_get_info(reader);
 
-  iface = get_codec_interface(info->codec_fourcc);
-  if (!iface)
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
     die("Unknown input codec.");
 
-  printf("Using %s\n", vpx_codec_iface_name(iface));
+  printf("Using %s\n", vpx_codec_iface_name(decoder->interface()));
 
-  if (vpx_codec_dec_init(&codec, iface, NULL, 0))
+  if (vpx_codec_dec_init(&codec, decoder->interface(), NULL, 0))
     die_codec(&codec, "Failed to initialize decoder");
 
   while (vpx_video_reader_read_frame(reader)) {
index e8fc076..c6f7d43 100644 (file)
@@ -76,7 +76,7 @@ int main(int argc, char **argv) {
   int frame_cnt = 0;
   FILE *outfile = NULL;
   vpx_codec_ctx_t codec;
-  vpx_codec_iface_t *iface = NULL;
+  const VpxInterface *decoder = NULL;
   VpxVideoReader *reader = NULL;
   const VpxVideoInfo *info = NULL;
   int n = 0;
@@ -104,13 +104,13 @@ int main(int argc, char **argv) {
 
   info = vpx_video_reader_get_info(reader);
 
-  iface = get_codec_interface(info->codec_fourcc);
-  if (!iface)
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
     die("Unknown input codec.");
 
-  printf("Using %s\n", vpx_codec_iface_name(iface));
+  printf("Using %s\n", vpx_codec_iface_name(decoder->interface()));
 
-  if (vpx_codec_dec_init(&codec, iface, NULL, 0))
+  if (vpx_codec_dec_init(&codec, decoder->interface(), NULL, 0))
     die_codec(&codec, "Failed to initialize decoder.");
 
   while (vpx_video_reader_read_frame(reader)) {
index 7281f1e..2912fe6 100644 (file)
@@ -64,8 +64,8 @@ int main(int argc, char **argv) {
   FILE *outfile = NULL;
   vpx_codec_ctx_t codec;
   vpx_codec_err_t res;
-  vpx_codec_iface_t *iface = NULL;
   VpxVideoReader *reader = NULL;
+  const VpxInterface *decoder = NULL;
   const VpxVideoInfo *info = NULL;
 
   exec_name = argv[0];
@@ -82,17 +82,16 @@ int main(int argc, char **argv) {
 
   info = vpx_video_reader_get_info(reader);
 
-  iface = get_codec_interface(info->codec_fourcc);
-  if (!iface)
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
     die("Unknown input codec.");
 
-  printf("Using %s\n", vpx_codec_iface_name(iface));
+  printf("Using %s\n", vpx_codec_iface_name(decoder->interface()));
 
-  res = vpx_codec_dec_init(&codec, iface, NULL, VPX_CODEC_USE_POSTPROC);
-  if (res == VPX_CODEC_INCAPABLE) {
-    printf("NOTICE: Postproc not supported.\n");
-    res = vpx_codec_dec_init(&codec, iface, NULL, 0);
-  }
+  res = vpx_codec_dec_init(&codec, decoder->interface(), NULL,
+                           VPX_CODEC_USE_POSTPROC);
+  if (res == VPX_CODEC_INCAPABLE)
+    die_codec(&codec, "Postproc not supported by this decoder.");
 
   if (res)
     die_codec(&codec, "Failed to initialize decoder.");
index 4dc9308..b0ca77d 100644 (file)
@@ -101,8 +101,8 @@ int main(int argc, char **argv) {
   int frame_cnt = 0;
   FILE *outfile = NULL;
   vpx_codec_ctx_t codec;
-  vpx_codec_iface_t *iface = NULL;
   VpxVideoReader *reader = NULL;
+  const VpxInterface *decoder = NULL;
   const VpxVideoInfo *info = NULL;
 
   exec_name = argv[0];
@@ -119,13 +119,13 @@ int main(int argc, char **argv) {
 
   info = vpx_video_reader_get_info(reader);
 
-  iface = get_codec_interface(info->codec_fourcc);
-  if (!iface)
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
     die("Unknown input codec.");
 
-  printf("Using %s\n", vpx_codec_iface_name(iface));
+  printf("Using %s\n", vpx_codec_iface_name(decoder->interface()));
 
-  if (vpx_codec_dec_init(&codec, iface, NULL, 0))
+  if (vpx_codec_dec_init(&codec, decoder->interface(), NULL, 0))
     die_codec(&codec, "Failed to initialize decoder.");
 
   while (vpx_video_reader_read_frame(reader)) {
index 5076054..2e7c7a6 100644 (file)
 #include <string.h>
 
 #define VPX_CODEC_DISABLE_COMPAT 1
-#include "vpx/vp8cx.h"
 #include "vpx/vpx_encoder.h"
 
 #include "./tools_common.h"
 #include "./video_writer.h"
 
-#define interface (vpx_codec_vp8_cx())
-
 static const char *exec_name;
 
 void usage_exit() {
-  fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile>\n", exec_name);
+  fprintf(stderr, "Usage: %s <codec> <width> <height> <infile> <outfile>\n",
+          exec_name);
   exit(EXIT_FAILURE);
 }
 
@@ -110,17 +108,27 @@ int main(int argc, char **argv) {
   vpx_codec_err_t res;
   VpxVideoInfo info = {0};
   VpxVideoWriter *writer = NULL;
+  const VpxInterface *encoder = NULL;
   const int fps = 30;        // TODO(dkovalev) add command line argument
   const int bitrate = 200;   // kbit/s TODO(dkovalev) add command line argument
+  const char *const codec_arg = argv[1];
+  const char *const width_arg = argv[2];
+  const char *const height_arg = argv[3];
+  const char *const infile_arg = argv[4];
+  const char *const outfile_arg = argv[5];
 
   exec_name = argv[0];
 
-  if (argc != 5)
+  if (argc != 6)
     die("Invalid number of arguments");
 
-  info.codec_fourcc = VP8_FOURCC;
-  info.frame_width = strtol(argv[1], NULL, 0);
-  info.frame_height = strtol(argv[2], NULL, 0);
+  encoder = get_vpx_encoder_by_name(codec_arg);
+  if (!encoder)
+     die("Unsupported codec.");
+
+  info.codec_fourcc = encoder->fourcc;
+  info.frame_width = strtol(width_arg, NULL, 0);
+  info.frame_height = strtol(height_arg, NULL, 0);
   info.time_base.numerator = 1;
   info.time_base.denominator = fps;
 
@@ -136,9 +144,9 @@ int main(int argc, char **argv) {
     die("Failed to allocate image.");
   }
 
-  printf("Using %s\n", vpx_codec_iface_name(interface));
+  printf("Using %s\n", vpx_codec_iface_name(encoder->interface()));
 
-  res = vpx_codec_enc_config_default(interface, &cfg, 0);
+  res = vpx_codec_enc_config_default(encoder->interface(), &cfg, 0);
   if (res)
     die_codec(&codec, "Failed to get default codec config.");
 
@@ -148,14 +156,14 @@ int main(int argc, char **argv) {
   cfg.g_timebase.den = info.time_base.denominator;
   cfg.rc_target_bitrate = bitrate;
 
-  writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
+  writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info);
   if (!writer)
-    die("Failed to open %s for writing.", argv[4]);
+    die("Failed to open %s for writing.", outfile_arg);
 
-  if (!(infile = fopen(argv[3], "rb")))
-    die("Failed to open %s for reading.", argv[3]);
+  if (!(infile = fopen(infile_arg, "rb")))
+    die("Failed to open %s for reading.", infile_arg);
 
-  if (vpx_codec_enc_init(&codec, interface, &cfg, 0))
+  if (vpx_codec_enc_init(&codec, encoder->interface(), &cfg, 0))
     die_codec(&codec, "Failed to initialize encoder");
 
   while (vpx_img_read(&raw, infile)) {
index 93b6150..f16db66 100644 (file)
 #include <string.h>
 
 #define VPX_CODEC_DISABLE_COMPAT 1
-#include "vpx/vp8cx.h"
 #include "vpx/vpx_encoder.h"
 
 #include "./tools_common.h"
 #include "./video_writer.h"
 
-#define interface (vpx_codec_vp8_cx())
-
 static const char *exec_name;
 
 void usage_exit() {
-  fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile>\n", exec_name);
+  fprintf(stderr, "Usage: %s <codec> <width> <height> <infile> <outfile>\n",
+          exec_name);
   exit(EXIT_FAILURE);
 }
 
@@ -130,18 +128,29 @@ int main(int argc, char **argv) {
   vpx_codec_err_t res;
   vpx_fixed_buf_t stats = {0};
   VpxVideoInfo info = {0};
+  const VpxInterface *encoder = NULL;
   int pass;
   const int fps = 30;        // TODO(dkovalev) add command line argument
   const int bitrate = 200;   // kbit/s TODO(dkovalev) add command line argument
-
-  if (argc != 5)
+  const char *const codec_arg = argv[1];
+  const char *const width_arg = argv[2];
+  const char *const height_arg = argv[3];
+  const char *const infile_arg = argv[4];
+  const char *const outfile_arg = argv[5];
+  exec_name = argv[0];
+
+  if (argc != 6)
     die("Invalid number of arguments.");
 
-  info.codec_fourcc = VP8_FOURCC;
+  encoder = get_vpx_encoder_by_name(codec_arg);
+  if (!encoder)
+    die("Unsupported codec.");
+
+  info.codec_fourcc = encoder->fourcc;
   info.time_base.numerator = 1;
   info.time_base.denominator = fps;
-  info.frame_width = strtol(argv[1], NULL, 0);
-  info.frame_height = strtol(argv[2], NULL, 0);
+  info.frame_width = strtol(width_arg, NULL, 0);
+  info.frame_height = strtol(height_arg, NULL, 0);
 
   if (info.frame_width <= 0 ||
       info.frame_height <= 0 ||
@@ -155,13 +164,13 @@ int main(int argc, char **argv) {
     die("Failed to allocate image", info.frame_width, info.frame_height);
   }
 
-  writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
+  writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info);
   if (!writer)
-    die("Failed to open %s for writing", argv[4]);
+    die("Failed to open %s for writing", outfile_arg);
 
-  printf("Using %s\n", vpx_codec_iface_name(interface));
+  printf("Using %s\n", vpx_codec_iface_name(encoder->interface()));
 
-  res = vpx_codec_enc_config_default(interface, &cfg, 0);
+  res = vpx_codec_enc_config_default(encoder->interface(), &cfg, 0);
   if (res)
     die_codec(&codec, "Failed to get default codec config.");
 
@@ -181,10 +190,10 @@ int main(int argc, char **argv) {
       cfg.rc_twopass_stats_in = stats;
     }
 
-    if (!(infile = fopen(argv[3], "rb")))
-      die("Failed to open %s for reading", argv[3]);
+    if (!(infile = fopen(infile_arg, "rb")))
+      die("Failed to open %s for reading", infile_arg);
 
-    if (vpx_codec_enc_init(&codec, interface, &cfg, 0))
+    if (vpx_codec_enc_init(&codec, encoder->interface(), &cfg, 0))
       die_codec(&codec, "Failed to initialize encoder");
 
     while (vpx_img_read(&raw, infile)) {
index 11d331b..c40450e 100644 (file)
@@ -360,9 +360,7 @@ int main(int argc, char **argv) {
   int flag_periodicity = 1;
   int max_intra_size_pct;
   vpx_svc_layer_id_t layer_id = {0, 0};
-  char *codec_type;
-  vpx_codec_iface_t *(*interface)(void);
-  unsigned int fourcc;
+  const VpxInterface *encoder = NULL;
   struct VpxInputContext input_ctx = {0};
 
   exec_name = argv[0];
@@ -373,23 +371,11 @@ int main(int argc, char **argv) {
         argv[0]);
   }
 
-  codec_type = argv[3];
-  if (strncmp(codec_type, "vp9", 3) == 0) {
-#if CONFIG_VP9_ENCODER
-    interface = vpx_codec_vp9_cx;
-    fourcc = VP9_FOURCC;
-#else
-    die("Encoder vp9 selected but not configured");
-#endif
-  } else  {
-#if CONFIG_VP8_ENCODER
-    interface = vpx_codec_vp8_cx;
-    fourcc = VP8_FOURCC;
-#else
-    die("Encoder vp8 selected but not configured");
-#endif
-  }
-  printf("Using %s\n", vpx_codec_iface_name(interface()));
+  encoder = get_vpx_encoder_by_name(argv[3]);
+  if (!encoder)
+    die("Unsupported codec.");
+
+  printf("Using %s\n", vpx_codec_iface_name(encoder->interface()));
 
   width = strtol(argv[4], NULL, 0);
   height = strtol(argv[5], NULL, 0);
@@ -411,7 +397,7 @@ int main(int argc, char **argv) {
   }
 
   // Populate encoder configuration.
-  res = vpx_codec_enc_config_default(interface(), &cfg, 0);
+  res = vpx_codec_enc_config_default(encoder->interface(), &cfg, 0);
   if (res) {
     printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
     return EXIT_FAILURE;
@@ -467,7 +453,7 @@ int main(int argc, char **argv) {
   for (i = 0; i < cfg.ts_number_layers; ++i) {
     char file_name[PATH_MAX];
     VpxVideoInfo info;
-    info.codec_fourcc = fourcc;
+    info.codec_fourcc = encoder->fourcc;
     info.frame_width = cfg.g_w;
     info.frame_height = cfg.g_h;
     info.time_base.numerator = cfg.g_timebase.num;
@@ -482,12 +468,12 @@ int main(int argc, char **argv) {
   cfg.ss_number_layers = 1;
 
   // Initialize codec.
-  if (vpx_codec_enc_init(&codec, interface(), &cfg, 0))
+  if (vpx_codec_enc_init(&codec, encoder->interface(), &cfg, 0))
     die_codec(&codec, "Failed to initialize encoder");
 
   vpx_codec_control(&codec, VP8E_SET_CPUUSED, -6);
   vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, 1);
-  if (strncmp(codec_type, "vp9", 3) == 0) {
+  if (strncmp(encoder->name, "vp9", 3) == 0) {
     vpx_codec_control(&codec, VP8E_SET_CPUUSED, 3);
     vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, 0);
     if (vpx_codec_control(&codec, VP9E_SET_SVC, 1)) {
index 5354687..5a1b701 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
+#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
+#include "vpx/vp8cx.h"
+#endif
+
 #if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
 #include "vpx/vp8dx.h"
 #endif
@@ -144,19 +148,75 @@ int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame) {
   return shortread;
 }
 
-vpx_codec_iface_t *get_codec_interface(unsigned int fourcc) {
-  switch (fourcc) {
+static const VpxInterface vpx_encoders[] = {
+#if CONFIG_VP8_ENCODER
+  {"vp8", VP8_FOURCC, &vpx_codec_vp8_cx},
+#endif
+
+#if CONFIG_VP9_ENCODER
+  {"vp9", VP9_FOURCC, &vpx_codec_vp9_cx},
+#endif
+};
+
+int get_vpx_encoder_count() {
+  return sizeof(vpx_encoders) / sizeof(vpx_encoders[0]);
+}
+
+const VpxInterface *get_vpx_encoder_by_index(int i) {
+  return &vpx_encoders[i];
+}
+
+const VpxInterface *get_vpx_encoder_by_name(const char *name) {
+  int i;
+
+  for (i = 0; i < get_vpx_encoder_count(); ++i) {
+    const VpxInterface *encoder = get_vpx_encoder_by_index(i);
+    if (strcmp(encoder->name, name) == 0)
+      return encoder;
+  }
+
+  return NULL;
+}
+
+static const VpxInterface vpx_decoders[] = {
 #if CONFIG_VP8_DECODER
-    case VP8_FOURCC:
-      return vpx_codec_vp8_dx();
+  {"vp8", VP8_FOURCC, &vpx_codec_vp8_dx},
 #endif
+
 #if CONFIG_VP9_DECODER
-    case VP9_FOURCC:
-      return vpx_codec_vp9_dx();
+  {"vp9", VP9_FOURCC, &vpx_codec_vp9_dx},
 #endif
-    default:
-      return NULL;
+};
+
+int get_vpx_decoder_count() {
+  return sizeof(vpx_decoders) / sizeof(vpx_decoders[0]);
+}
+
+const VpxInterface *get_vpx_decoder_by_index(int i) {
+  return &vpx_decoders[i];
+}
+
+const VpxInterface *get_vpx_decoder_by_name(const char *name) {
+  int i;
+
+  for (i = 0; i < get_vpx_decoder_count(); ++i) {
+     const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
+     if (strcmp(decoder->name, name) == 0)
+       return decoder;
   }
+
+  return NULL;
+}
+
+const VpxInterface *get_vpx_decoder_by_fourcc(uint32_t fourcc) {
+  int i;
+
+  for (i = 0; i < get_vpx_decoder_count(); ++i) {
+    const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
+    if (decoder->fourcc == fourcc)
+      return decoder;
+  }
+
   return NULL;
 }
 
index 0f60c4c..da87b6d 100644 (file)
@@ -123,7 +123,20 @@ uint32_t mem_get_le32(const void *data);
 
 int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame);
 
-vpx_codec_iface_t *get_codec_interface(unsigned int fourcc);
+typedef struct VpxInterface {
+  const char *const name;
+  const uint32_t fourcc;
+  vpx_codec_iface_t *(*const interface)();
+} VpxInterface;
+
+int get_vpx_encoder_count();
+const VpxInterface *get_vpx_encoder_by_index(int i);
+const VpxInterface *get_vpx_encoder_by_name(const char *name);
+
+int get_vpx_decoder_count();
+const VpxInterface *get_vpx_decoder_by_index(int i);
+const VpxInterface *get_vpx_decoder_by_name(const char *name);
+const VpxInterface *get_vpx_decoder_by_fourcc(uint32_t fourcc);
 
 // TODO(dkovalev): move this function to vpx_image.{c, h}, so it will be part
 // of vpx_image_t support
index 98d1550..7f85fc9 100644 (file)
--- a/vpxdec.c
+++ b/vpxdec.c
 
 static const char *exec_name;
 
-static const struct {
-  char const *name;
-  vpx_codec_iface_t *(*iface)(void);
-  uint32_t fourcc;
-} ifaces[] = {
-#if CONFIG_VP8_DECODER
-  {"vp8",  vpx_codec_vp8_dx,   VP8_FOURCC},
-#endif
-#if CONFIG_VP9_DECODER
-  {"vp9",  vpx_codec_vp9_dx,   VP9_FOURCC},
-#endif
-};
-
 struct VpxDecInputContext {
   struct VpxInputContext *vpx_input_ctx;
   struct WebmInputContext *webm_ctx;
@@ -170,10 +157,11 @@ void usage_exit() {
          );
   fprintf(stderr, "\nIncluded decoders:\n\n");
 
-  for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
+  for (i = 0; i < get_vpx_decoder_count(); ++i) {
+    const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
     fprintf(stderr, "    %-6s - %s\n",
-            ifaces[i].name,
-            vpx_codec_iface_name(ifaces[i].iface()));
+            decoder->name, vpx_codec_iface_name(decoder->interface()));
+  }
 
   exit(EXIT_FAILURE);
 }
@@ -300,11 +288,12 @@ int file_is_raw(struct VpxInputContext *input) {
     int i;
 
     if (mem_get_le32(buf) < 256 * 1024 * 1024) {
-      for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) {
-        if (!vpx_codec_peek_stream_info(ifaces[i].iface(),
+      for (i = 0; i < get_vpx_decoder_count(); ++i) {
+        const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
+        if (!vpx_codec_peek_stream_info(decoder->interface(),
                                         buf + 4, 32 - 4, &si)) {
           is_raw = 1;
-          input->fourcc = ifaces[i].fourcc;
+          input->fourcc = decoder->fourcc;
           input->width = si.w;
           input->height = si.h;
           input->framerate.numerator = 30;
@@ -441,7 +430,6 @@ static FILE *open_outfile(const char *name) {
 int main_loop(int argc, const char **argv_) {
   vpx_codec_ctx_t       decoder;
   char                  *fn = NULL;
-  int                    i;
   uint8_t               *buf = NULL;
   size_t                 bytes_in_buffer = 0, buffer_size = 0;
   FILE                  *infile;
@@ -450,7 +438,8 @@ int main_loop(int argc, const char **argv_) {
   int                    stop_after = 0, postproc = 0, summary = 0, quiet = 1;
   int                    arg_skip = 0;
   int                    ec_enabled = 0;
-  vpx_codec_iface_t       *iface = NULL;
+  const VpxInterface *interface = NULL;
+  const VpxInterface *fourcc_interface = NULL;
   unsigned long          dx_time = 0;
   struct arg               arg;
   char                   **argv, **argi, **argj;
@@ -493,17 +482,9 @@ int main_loop(int argc, const char **argv_) {
     arg.argv_step = 1;
 
     if (arg_match(&arg, &codecarg, argi)) {
-      int j, k = -1;
-
-      for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
-        if (!strcmp(ifaces[j].name, arg.val))
-          k = j;
-
-      if (k >= 0)
-        iface = ifaces[k].iface();
-      else
-        die("Error: Unrecognized argument (%s) to --codec\n",
-            arg.val);
+      interface = get_vpx_decoder_by_name(arg.val);
+      if (!interface)
+        die("Error: Unrecognized argument (%s) to --codec\n", arg.val);
     } else if (arg_match(&arg, &looparg, argi)) {
       // no-op
     } else if (arg_match(&arg, &outputfile, argi))
@@ -660,24 +641,20 @@ int main_loop(int argc, const char **argv_) {
     }
   }
 
-  /* Try to determine the codec from the fourcc. */
-  for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
-    if (vpx_input_ctx.fourcc == ifaces[i].fourcc) {
-      vpx_codec_iface_t *vpx_iface = ifaces[i].iface();
+  fourcc_interface = get_vpx_decoder_by_fourcc(vpx_input_ctx.fourcc);
+  if (interface && fourcc_interface && interface != fourcc_interface)
+    warn("Header indicates codec: %s\n", fourcc_interface->name);
+  else
+    interface = fourcc_interface;
 
-      if (iface && iface != vpx_iface)
-        warn("Header indicates codec: %s\n", ifaces[i].name);
-      else
-        iface = vpx_iface;
-
-      break;
-    }
+  if (!interface)
+    interface = get_vpx_decoder_by_index(0);
 
   dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) |
               (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0);
-  if (vpx_codec_dec_init(&decoder, iface ? iface :  ifaces[0].iface(), &cfg,
-                         dec_flags)) {
-    fprintf(stderr, "Failed to initialize decoder: %s\n", vpx_codec_error(&decoder));
+  if (vpx_codec_dec_init(&decoder, interface->interface(), &cfg, dec_flags)) {
+    fprintf(stderr, "Failed to initialize decoder: %s\n",
+            vpx_codec_error(&decoder));
     return EXIT_FAILURE;
   }
 
index 5e36fd9..73b3144 100644 (file)
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -61,24 +61,6 @@ static size_t wrap_fwrite(const void *ptr, size_t size, size_t nmemb,
 
 static const char *exec_name;
 
-static const struct codec_item {
-  char const              *name;
-  vpx_codec_iface_t *(*iface)(void);
-  vpx_codec_iface_t *(*dx_iface)(void);
-  unsigned int             fourcc;
-} codecs[] = {
-#if CONFIG_VP8_ENCODER && CONFIG_VP8_DECODER
-  {"vp8", &vpx_codec_vp8_cx, &vpx_codec_vp8_dx, VP8_FOURCC},
-#elif CONFIG_VP8_ENCODER && !CONFIG_VP8_DECODER
-  {"vp8", &vpx_codec_vp8_cx, NULL, VP8_FOURCC},
-#endif
-#if CONFIG_VP9_ENCODER && CONFIG_VP9_DECODER
-  {"vp9", &vpx_codec_vp9_cx, &vpx_codec_vp9_dx, VP9_FOURCC},
-#elif CONFIG_VP9_ENCODER && !CONFIG_VP9_DECODER
-  {"vp9", &vpx_codec_vp9_cx, NULL, VP9_FOURCC},
-#endif
-};
-
 static void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal,
                                    const char *s, va_list ap) {
   if (ctx->err) {
@@ -462,14 +444,13 @@ void usage_exit() {
   fprintf(stderr, "\nStream timebase (--timebase):\n"
           "  The desired precision of timestamps in the output, expressed\n"
           "  in fractional seconds. Default is 1/1000.\n");
-  fprintf(stderr, "\n"
-          "Included encoders:\n"
-          "\n");
+  fprintf(stderr, "\nIncluded encoders:\n\n");
 
-  for (i = 0; i < sizeof(codecs) / sizeof(codecs[0]); i++)
+  for (i = 0; i < get_vpx_encoder_count(); ++i) {
+    const VpxInterface *const encoder = get_vpx_encoder_by_index(i);
     fprintf(stderr, "    %-6s - %s\n",
-            codecs[i].name,
-            vpx_codec_iface_name(codecs[i].iface()));
+            encoder->name, vpx_codec_iface_name(encoder->interface()));
+  }
 
   exit(EXIT_FAILURE);
 }
@@ -666,7 +647,7 @@ static void parse_global_config(struct VpxEncoderConfig *global, char **argv) {
 
   /* Initialize default parameters */
   memset(global, 0, sizeof(*global));
-  global->codec = codecs;
+  global->codec = get_vpx_encoder_by_index(0);
   global->passes = 0;
   global->use_i420 = 1;
   /* Assign default deadline to good quality */
@@ -676,18 +657,9 @@ static void parse_global_config(struct VpxEncoderConfig *global, char **argv) {
     arg.argv_step = 1;
 
     if (arg_match(&arg, &codecarg, argi)) {
-      int j, k = -1;
-
-      for (j = 0; j < sizeof(codecs) / sizeof(codecs[0]); j++)
-        if (!strcmp(codecs[j].name, arg.val))
-          k = j;
-
-      if (k >= 0)
-        global->codec = codecs + k;
-      else
-        die("Error: Unrecognized argument (%s) to --codec\n",
-            arg.val);
-
+      global->codec = get_vpx_encoder_by_name(arg.val);
+      if (!global->codec)
+        die("Error: Unrecognized argument (%s) to --codec\n", arg.val);
     } else if (arg_match(&arg, &passes, argi)) {
       global->passes = arg_parse_uint(&arg);
 
@@ -750,7 +722,7 @@ static void parse_global_config(struct VpxEncoderConfig *global, char **argv) {
 #if CONFIG_VP9_ENCODER
     // Make default VP9 passes = 2 until there is a better quality 1-pass
     // encoder
-    global->passes = (global->codec->iface == vpx_codec_vp9_cx ? 2 : 1);
+    global->passes = strcmp(global->codec->name, "vp9") == 0 ? 2 : 1;
 #else
     global->passes = 1;
 #endif
@@ -830,7 +802,7 @@ static struct stream_state *new_stream(struct VpxEncoderConfig *global,
     vpx_codec_err_t  res;
 
     /* Populate encoder configuration */
-    res = vpx_codec_enc_config_default(global->codec->iface(),
+    res = vpx_codec_enc_config_default(global->codec->interface(),
                                        &stream->config.cfg,
                                        global->usage);
     if (res)
@@ -874,15 +846,15 @@ static int parse_stream_params(struct VpxEncoderConfig *global,
   struct stream_config    *config = &stream->config;
   int                      eos_mark_found = 0;
 
-  /* Handle codec specific options */
+  // Handle codec specific options
   if (0) {
 #if CONFIG_VP8_ENCODER
-  } else if (global->codec->iface == vpx_codec_vp8_cx) {
+  } else if (strcmp(global->codec->name, "vp8") == 0) {
     ctrl_args = vp8_args;
     ctrl_args_map = vp8_arg_ctrl_map;
 #endif
 #if CONFIG_VP9_ENCODER
-  } else if (global->codec->iface == vpx_codec_vp9_cx) {
+  } else if (strcmp(global->codec->name, "vp9") == 0) {
     ctrl_args = vp9_args;
     ctrl_args_map = vp9_arg_ctrl_map;
 #endif
@@ -1090,7 +1062,7 @@ static void show_stream_config(struct stream_state *stream,
 
   if (stream->index == 0) {
     fprintf(stderr, "Codec: %s\n",
-            vpx_codec_iface_name(global->codec->iface()));
+            vpx_codec_iface_name(global->codec->interface()));
     fprintf(stderr, "Source file: %s Format: %s\n", input->filename,
             input->use_i420 ? "I420" : "YV12");
   }
@@ -1214,7 +1186,7 @@ static void initialize_encoder(struct stream_state *stream,
   flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0;
 
   /* Construct Encoder Context */
-  vpx_codec_enc_init(&stream->encoder, global->codec->iface(),
+  vpx_codec_enc_init(&stream->encoder, global->codec->interface(),
                      &stream->config.cfg, flags);
   ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder");
 
@@ -1234,7 +1206,8 @@ static void initialize_encoder(struct stream_state *stream,
 
 #if CONFIG_DECODERS
   if (global->test_decode != TEST_DECODE_OFF) {
-    vpx_codec_dec_init(&stream->decoder, global->codec->dx_iface(), NULL, 0);
+    const VpxInterface *decoder = get_vpx_decoder_by_name(global->codec->name);
+    vpx_codec_dec_init(&stream->decoder, decoder->interface(), NULL, 0);
   }
 #endif
 }
@@ -1420,14 +1393,14 @@ static float usec_to_fps(uint64_t usec, unsigned int frames) {
 
 static void test_decode(struct stream_state  *stream,
                         enum TestDecodeFatality fatal,
-                        const struct codec_item *codec) {
+                        const VpxInterface *codec) {
   vpx_image_t enc_img, dec_img;
 
   if (stream->mismatch_seen)
     return;
 
   /* Get the internal reference frame */
-  if (codec->fourcc == VP8_FOURCC) {
+  if (strcmp(codec->name, "vp8") == 0) {
     struct vpx_ref_frame ref_enc, ref_dec;
     int width, height;
 
index 5103ee6..1e6acaa 100644 (file)
--- a/vpxenc.h
+++ b/vpxenc.h
@@ -22,9 +22,11 @@ enum TestDecodeFatality {
   TEST_DECODE_WARN,
 };
 
+struct VpxInterface;
+
 /* Configuration elements common to all streams. */
 struct VpxEncoderConfig {
-  const struct codec_item *codec;
+  const struct VpxInterface *codec;
   int passes;
   int pass;
   int usage;