Adds support for raw yuv files for 422/444
authorDeb Mukherjee <debargha@google.com>
Wed, 16 Jul 2014 16:37:13 +0000 (09:37 -0700)
committerDeb Mukherjee <debargha@google.com>
Wed, 16 Jul 2014 16:44:30 +0000 (09:44 -0700)
Adds support for raw yuv inputs in 422/444 sampling for use
in profiles 1 and 3.
New options added to vpxenc are:
--i422 and --i444, which are to be used in conjunction with
--width, --height, and --fps for proper raw yuv handling.
A new option is added to vpxdec:
--rawvideo, which enforces raw yuv video output for the
bit-stream decoded irrespective of 420, 422 or 444 sampling.
The existing options --i420 and --yv12
are specialized for use only for 420 content.

Change-Id: I2e3028380709afa673bf2e2c25ad5e271a626055

tools_common.c
vpxdec.c
vpxenc.c
vpxenc.h

index 8825528..b481579 100644 (file)
@@ -83,7 +83,7 @@ int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame) {
   struct FileTypeDetectionBuffer *detect = &input_ctx->detect;
   int plane = 0;
   int shortread = 0;
-  const int bytespp = (input_ctx->fmt & VPX_IMG_FMT_HIGH) ? 2 : 1;
+  const int bytespp = (yuv_frame->fmt & VPX_IMG_FMT_HIGH) ? 2 : 1;
 
   for (plane = 0; plane < 3; ++plane) {
     uint8_t *ptr;
index 1b1cb05..58cd03e 100644 (file)
--- a/vpxdec.c
+++ b/vpxdec.c
@@ -55,6 +55,8 @@ static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
                                           "Output raw I420 frames");
 static const arg_def_t flipuvarg = ARG_DEF(NULL, "flipuv", 0,
                                            "Flip the chroma planes in the output");
+static const arg_def_t rawvideo = ARG_DEF(NULL, "rawvideo", 0,
+                                          "Output raw YUV frames");
 static const arg_def_t noblitarg = ARG_DEF(NULL, "noblit", 0,
                                            "Don't process the decoded frames");
 static const arg_def_t progressarg = ARG_DEF(NULL, "progress", 0,
@@ -87,7 +89,7 @@ static const arg_def_t md5arg = ARG_DEF(NULL, "md5", 0,
                                         "Compute the MD5 sum of the decoded frame");
 
 static const arg_def_t *all_args[] = {
-  &codecarg, &use_yv12, &use_i420, &flipuvarg, &noblitarg,
+  &codecarg, &use_yv12, &use_i420, &flipuvarg, &rawvideo, &noblitarg,
   &progressarg, &limitarg, &skiparg, &postprocarg, &summaryarg, &outputfile,
   &threadsarg, &verbosearg, &scalearg, &fb_arg,
   &md5arg, &error_concealment, &continuearg,
@@ -507,6 +509,8 @@ int main_loop(int argc, const char **argv_) {
 
   int                     single_file;
   int                     use_y4m = 1;
+  int                     opt_yv12 = 0;
+  int                     opt_i420 = 0;
   vpx_codec_dec_cfg_t     cfg = {0};
 #if CONFIG_VP8_DECODER
   vp8_postproc_cfg_t      vp8_pp_cfg = {0};
@@ -557,9 +561,13 @@ int main_loop(int argc, const char **argv_) {
     else if (arg_match(&arg, &use_yv12, argi)) {
       use_y4m = 0;
       flipuv = 1;
+      opt_yv12 = 1;
     } else if (arg_match(&arg, &use_i420, argi)) {
       use_y4m = 0;
       flipuv = 0;
+      opt_i420 = 1;
+    } else if (arg_match(&arg, &rawvideo, argi)) {
+      use_y4m = 0;
     } else if (arg_match(&arg, &flipuvarg, argi))
       flipuv = 1;
     else if (arg_match(&arg, &noblitarg, argi))
@@ -918,6 +926,25 @@ int main_loop(int argc, const char **argv_) {
           } else {
             fputs(buf, outfile);
           }
+        } else {
+          if (frame_out == 1) {
+            // Check if --yv12 or --i420 options are consistent with the
+            // bit-stream decoded
+            if (opt_i420) {
+              if (img->fmt != VPX_IMG_FMT_I420 &&
+                  img->fmt != VPX_IMG_FMT_I42016) {
+                fprintf(stderr, "Cannot produce i420 output for bit-stream.\n");
+                goto fail;
+              }
+            }
+            if (opt_yv12) {
+              if ((img->fmt != VPX_IMG_FMT_I420 &&
+                   img->fmt != VPX_IMG_FMT_YV12) || img->bit_depth != 8) {
+                fprintf(stderr, "Cannot produce yv12 output for bit-stream.\n");
+                goto fail;
+              }
+            }
+          }
         }
 
         if (do_md5) {
index fcb4368..d4bb034 100644 (file)
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -133,6 +133,10 @@ static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
                                           "Input file is YV12 ");
 static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
                                           "Input file is I420 (default)");
+static const arg_def_t use_i422 = ARG_DEF(NULL, "i422", 0,
+                                          "Input file is I422");
+static const arg_def_t use_i444 = ARG_DEF(NULL, "i444", 0,
+                                          "Input file is I444");
 static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
                                           "Codec to use");
 static const arg_def_t passes           = ARG_DEF("p", "passes", 1,
@@ -233,7 +237,8 @@ static const arg_def_t lag_in_frames    = ARG_DEF(NULL, "lag-in-frames", 1,
                                                   "Max number of frames to lag");
 
 static const arg_def_t *global_args[] = {
-  &use_yv12, &use_i420, &usage, &threads, &profile,
+  &use_yv12, &use_i420, &use_i422, &use_i444,
+  &usage, &threads, &profile,
   &width, &height,
 #if CONFIG_WEBM_IO
   &stereo_mode,
@@ -636,7 +641,7 @@ static void parse_global_config(struct VpxEncoderConfig *global, char **argv) {
   memset(global, 0, sizeof(*global));
   global->codec = get_vpx_encoder_by_index(0);
   global->passes = 0;
-  global->use_i420 = 1;
+  global->color_type = I420;
   /* Assign default deadline to good quality */
   global->deadline = VPX_DL_GOOD_QUALITY;
 
@@ -669,9 +674,13 @@ static void parse_global_config(struct VpxEncoderConfig *global, char **argv) {
     else if (arg_match(&arg, &rt_dl, argi))
       global->deadline = VPX_DL_REALTIME;
     else if (arg_match(&arg, &use_yv12, argi))
-      global->use_i420 = 0;
+      global->color_type = YV12;
     else if (arg_match(&arg, &use_i420, argi))
-      global->use_i420 = 1;
+      global->color_type = I420;
+    else if (arg_match(&arg, &use_i422, argi))
+      global->color_type = I422;
+    else if (arg_match(&arg, &use_i444, argi))
+      global->color_type = I444;
     else if (arg_match(&arg, &quietarg, argi))
       global->quiet = 1;
     else if (arg_match(&arg, &verbosearg, argi))
@@ -1593,7 +1602,20 @@ int main(int argc, const char **argv_) {
   argv = argv_dup(argc - 1, argv_ + 1);
   parse_global_config(&global, argv);
 
-  input.fmt = global.use_i420 ? VPX_IMG_FMT_I420 : VPX_IMG_FMT_YV12;
+  switch (global.color_type) {
+    case I420:
+      input.fmt = VPX_IMG_FMT_I420;
+      break;
+    case I422:
+      input.fmt = VPX_IMG_FMT_I422;
+      break;
+    case I444:
+      input.fmt = VPX_IMG_FMT_I444;
+      break;
+    case YV12:
+      input.fmt = VPX_IMG_FMT_YV12;
+      break;
+  }
 
   {
     /* Now parse each stream's parameters. Using a local scope here
index a8c3722..3d6728e 100644 (file)
--- a/vpxenc.h
+++ b/vpxenc.h
@@ -22,6 +22,13 @@ enum TestDecodeFatality {
   TEST_DECODE_WARN,
 };
 
+typedef enum {
+  I420,  // 4:2:0 8+ bit-depth
+  I422,  // 4:2:2 8+ bit-depth
+  I444,  // 4:4:4 8+ bit-depth
+  YV12,  // 4:2:0 with uv flipped, only 8-bit depth
+} ColorInputType;
+
 struct VpxInterface;
 
 /* Configuration elements common to all streams. */
@@ -31,7 +38,7 @@ struct VpxEncoderConfig {
   int pass;
   int usage;
   int deadline;
-  int use_i420;
+  ColorInputType color_type;
   int quiet;
   int verbose;
   int limit;