Fix y4m monochrome output; split raw/y4m logic
BUG=aomedia:2091
Change-Id: I2eed6a0b70c57415b323b7e8207592a7fdebba2b
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c99dbed..8f209ae 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -132,6 +132,8 @@
"${AOM_ROOT}/common/tools_common.c"
"${AOM_ROOT}/common/tools_common.h"
"${AOM_ROOT}/common/video_common.h"
+ "${AOM_ROOT}/common/rawenc.c"
+ "${AOM_ROOT}/common/rawenc.h"
"${AOM_ROOT}/common/y4menc.c"
"${AOM_ROOT}/common/y4menc.h")
diff --git a/apps/aomdec.c b/apps/aomdec.c
index 1e34eaa..1bc5029 100644
--- a/apps/aomdec.c
+++ b/apps/aomdec.c
@@ -40,6 +40,7 @@
#include "common/webmdec.h"
#endif
+#include "common/rawenc.h"
#include "common/y4menc.h"
#if CONFIG_LIBYUV
@@ -255,44 +256,6 @@
}
}
-static void update_image_md5(const aom_image_t *img, const int planes[3],
- MD5Context *md5) {
- int i, y;
-
- for (i = 0; i < 3; ++i) {
- const int plane = planes[i];
- const unsigned char *buf = img->planes[plane];
- const int stride = img->stride[plane];
- const int w = aom_img_plane_width(img, plane) *
- ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
- const int h = aom_img_plane_height(img, plane);
-
- for (y = 0; y < h; ++y) {
- MD5Update(md5, buf, w);
- buf += stride;
- }
- }
-}
-
-static void write_image_file(const aom_image_t *img, const int *planes,
- const int num_planes, FILE *file) {
- int i, y;
- const int bytes_per_sample = ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
-
- for (i = 0; i < num_planes; ++i) {
- const int plane = planes[i];
- const unsigned char *buf = img->planes[plane];
- const int stride = img->stride[plane];
- const int w = aom_img_plane_width(img, plane);
- const int h = aom_img_plane_height(img, plane);
-
- for (y = 0; y < h; ++y) {
- fwrite(buf, bytes_per_sample, w, file);
- buf += stride;
- }
- }
-}
-
static int file_is_raw(struct AvxInputContext *input) {
uint8_t buf[32];
int is_raw = 0;
@@ -904,6 +867,7 @@
scaled_img =
aom_img_alloc(NULL, img->fmt, render_width, render_height, 16);
scaled_img->bit_depth = img->bit_depth;
+ scaled_img->monochrome = img->monochrome;
}
if (img->d_w != scaled_img->d_w || img->d_h != scaled_img->d_h) {
@@ -960,8 +924,7 @@
aom_input_ctx.width = img->d_w;
aom_input_ctx.height = img->d_h;
- int num_planes = (!use_y4m && opt_raw && img->monochrome) ? 1 : 3;
-
+ int num_planes = (opt_raw && img->monochrome) ? 1 : 3;
if (single_file) {
if (use_y4m) {
char y4m_buf[Y4M_BUFFER_SIZE] = { 0 };
@@ -970,8 +933,8 @@
// Y4M file header
len = y4m_write_file_header(
y4m_buf, sizeof(y4m_buf), aom_input_ctx.width,
- aom_input_ctx.height, &aom_input_ctx.framerate, img->fmt,
- img->bit_depth);
+ aom_input_ctx.height, &aom_input_ctx.framerate,
+ img->monochrome, img->fmt, img->bit_depth);
if (do_md5) {
MD5Update(&md5_ctx, (md5byte *)y4m_buf, (unsigned int)len);
} else {
@@ -983,8 +946,10 @@
len = y4m_write_frame_header(y4m_buf, sizeof(y4m_buf));
if (do_md5) {
MD5Update(&md5_ctx, (md5byte *)y4m_buf, (unsigned int)len);
+ y4m_update_image_md5(img, planes, &md5_ctx);
} else {
fputs(y4m_buf, outfile);
+ y4m_write_image_file(img, planes, outfile);
}
} else {
if (frame_out == 1) {
@@ -1008,24 +973,31 @@
}
}
}
- }
-
- if (do_md5) {
- update_image_md5(img, planes, &md5_ctx);
- } else {
- write_image_file(img, planes, num_planes, outfile);
+ if (do_md5) {
+ raw_update_image_md5(img, planes, num_planes, &md5_ctx);
+ } else {
+ raw_write_image_file(img, planes, num_planes, outfile);
+ }
}
} else {
generate_filename(outfile_pattern, outfile_name, PATH_MAX, img->d_w,
img->d_h, frame_in);
if (do_md5) {
MD5Init(&md5_ctx);
- update_image_md5(img, planes, &md5_ctx);
+ if (use_y4m) {
+ y4m_update_image_md5(img, planes, &md5_ctx);
+ } else {
+ raw_update_image_md5(img, planes, num_planes, &md5_ctx);
+ }
MD5Final(md5_digest, &md5_ctx);
print_md5(md5_digest, outfile_name);
} else {
outfile = open_outfile(outfile_name);
- write_image_file(img, planes, num_planes, outfile);
+ if (use_y4m) {
+ y4m_write_image_file(img, planes, outfile);
+ } else {
+ raw_write_image_file(img, planes, num_planes, outfile);
+ }
fclose(outfile);
}
}
diff --git a/common/rawenc.c b/common/rawenc.c
new file mode 100644
index 0000000..5a2731d
--- /dev/null
+++ b/common/rawenc.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+
+#include "common/rawenc.h"
+
+void raw_write_image_file(const aom_image_t *img, const int *planes,
+ const int num_planes, FILE *file) {
+ const int bytes_per_sample = ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
+ for (int i = 0; i < num_planes; ++i) {
+ const int plane = planes[i];
+ const unsigned char *buf = img->planes[plane];
+ const int stride = img->stride[plane];
+ const int w = aom_img_plane_width(img, plane);
+ const int h = aom_img_plane_height(img, plane);
+ for (int y = 0; y < h; ++y) {
+ fwrite(buf, bytes_per_sample, w, file);
+ buf += stride;
+ }
+ }
+}
+
+void raw_update_image_md5(const aom_image_t *img, const int *planes,
+ const int num_planes, MD5Context *md5) {
+ for (int i = 0; i < num_planes; ++i) {
+ const int plane = planes[i];
+ const unsigned char *buf = img->planes[plane];
+ const int stride = img->stride[plane];
+ const int w = aom_img_plane_width(img, plane) *
+ ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
+ const int h = aom_img_plane_height(img, plane);
+ for (int y = 0; y < h; ++y) {
+ MD5Update(md5, buf, w);
+ buf += stride;
+ }
+ }
+}
diff --git a/common/rawenc.h b/common/rawenc.h
new file mode 100644
index 0000000..5c4a148
--- /dev/null
+++ b/common/rawenc.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+
+#ifndef RAWENC_H_
+#define RAWENC_H_
+
+#include "aom/aom_decoder.h"
+#include "common/md5_utils.h"
+#include "common/tools_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void raw_write_image_file(const aom_image_t *img, const int *planes,
+ const int num_planes, FILE *file);
+void raw_update_image_md5(const aom_image_t *img, const int *planes,
+ const int num_planes, MD5Context *md5);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // RAWENC_H_
diff --git a/common/y4menc.c b/common/y4menc.c
index d33d031..2daee87 100644
--- a/common/y4menc.c
+++ b/common/y4menc.c
@@ -11,56 +11,80 @@
#include <assert.h>
+#include "common/rawenc.h"
#include "common/y4menc.h"
-int y4m_write_file_header(char *buf, size_t len, int width, int height,
- const struct AvxRational *framerate,
- aom_img_fmt_t fmt, unsigned int bit_depth) {
- const char *color;
+// Returns the Y4M name associated with the monochrome colorspace.
+const char *monochrome_colorspace(unsigned int bit_depth) {
+ switch (bit_depth) {
+ case 8: return "Cmono";
+ case 9: return "Cmono9";
+ case 10: return "Cmono10";
+ case 12: return "Cmono12";
+ case 16: return "Cmono16";
+ default: assert(0); return NULL;
+ }
+}
+
+// Return the Y4M name of the colorspace, given the bit depth and image format.
+const char *colorspace(unsigned int bit_depth, aom_img_fmt_t fmt) {
switch (bit_depth) {
case 8:
- color = fmt == AOM_IMG_FMT_444A
- ? "C444alpha\n"
- : fmt == AOM_IMG_FMT_I444
- ? "C444\n"
- : fmt == AOM_IMG_FMT_I422 ? "C422\n" : "C420jpeg\n";
- break;
+ return fmt == AOM_IMG_FMT_444A
+ ? "C444alpha"
+ : fmt == AOM_IMG_FMT_I444
+ ? "C444"
+ : fmt == AOM_IMG_FMT_I422 ? "C422" : "C420jpeg";
case 9:
- color = fmt == AOM_IMG_FMT_I44416
- ? "C444p9 XYSCSS=444P9\n"
- : fmt == AOM_IMG_FMT_I42216 ? "C422p9 XYSCSS=422P9\n"
- : "C420p9 XYSCSS=420P9\n";
- break;
+ return fmt == AOM_IMG_FMT_I44416
+ ? "C444p9 XYSCSS=444P9"
+ : fmt == AOM_IMG_FMT_I42216 ? "C422p9 XYSCSS=422P9"
+ : "C420p9 XYSCSS=420P9";
case 10:
- color = fmt == AOM_IMG_FMT_I44416
- ? "C444p10 XYSCSS=444P10\n"
- : fmt == AOM_IMG_FMT_I42216 ? "C422p10 XYSCSS=422P10\n"
- : "C420p10 XYSCSS=420P10\n";
- break;
+ return fmt == AOM_IMG_FMT_I44416
+ ? "C444p10 XYSCSS=444P10"
+ : fmt == AOM_IMG_FMT_I42216 ? "C422p10 XYSCSS=422P10"
+ : "C420p10 XYSCSS=420P10";
case 12:
- color = fmt == AOM_IMG_FMT_I44416
- ? "C444p12 XYSCSS=444P12\n"
- : fmt == AOM_IMG_FMT_I42216 ? "C422p12 XYSCSS=422P12\n"
- : "C420p12 XYSCSS=420P12\n";
- break;
+ return fmt == AOM_IMG_FMT_I44416
+ ? "C444p12 XYSCSS=444P12"
+ : fmt == AOM_IMG_FMT_I42216 ? "C422p12 XYSCSS=422P12"
+ : "C420p12 XYSCSS=420P12";
case 14:
- color = fmt == AOM_IMG_FMT_I44416
- ? "C444p14 XYSCSS=444P14\n"
- : fmt == AOM_IMG_FMT_I42216 ? "C422p14 XYSCSS=422P14\n"
- : "C420p14 XYSCSS=420P14\n";
- break;
+ return fmt == AOM_IMG_FMT_I44416
+ ? "C444p14 XYSCSS=444P14"
+ : fmt == AOM_IMG_FMT_I42216 ? "C422p14 XYSCSS=422P14"
+ : "C420p14 XYSCSS=420P14";
case 16:
- color = fmt == AOM_IMG_FMT_I44416
- ? "C444p16 XYSCSS=444P16\n"
- : fmt == AOM_IMG_FMT_I42216 ? "C422p16 XYSCSS=422P16\n"
- : "C420p16 XYSCSS=420P16\n";
- break;
- default: color = NULL; assert(0);
+ return fmt == AOM_IMG_FMT_I44416
+ ? "C444p16 XYSCSS=444P16"
+ : fmt == AOM_IMG_FMT_I42216 ? "C422p16 XYSCSS=422P16"
+ : "C420p16 XYSCSS=420P16";
+ default: assert(0); return NULL;
}
- return snprintf(buf, len, "YUV4MPEG2 W%u H%u F%u:%u I%c %s", width, height,
+}
+
+int y4m_write_file_header(char *buf, size_t len, int width, int height,
+ const struct AvxRational *framerate, int monochrome,
+ aom_img_fmt_t fmt, unsigned int bit_depth) {
+ const char *color = monochrome ? monochrome_colorspace(bit_depth)
+ : colorspace(bit_depth, fmt);
+ return snprintf(buf, len, "YUV4MPEG2 W%u H%u F%u:%u I%c %s\n", width, height,
framerate->numerator, framerate->denominator, 'p', color);
}
int y4m_write_frame_header(char *buf, size_t len) {
return snprintf(buf, len, "FRAME\n");
}
+
+void y4m_write_image_file(const aom_image_t *img, const int *planes,
+ FILE *file) {
+ int num_planes = img->monochrome ? 1 : 3;
+ raw_write_image_file(img, planes, num_planes, file);
+}
+
+void y4m_update_image_md5(const aom_image_t *img, const int *planes,
+ MD5Context *md5) {
+ int num_planes = img->monochrome ? 1 : 3;
+ raw_update_image_md5(img, planes, num_planes, md5);
+}
diff --git a/common/y4menc.h b/common/y4menc.h
index 6344176..a133a3d 100644
--- a/common/y4menc.h
+++ b/common/y4menc.h
@@ -13,6 +13,7 @@
#define Y4MENC_H_
#include "aom/aom_decoder.h"
+#include "common/md5_utils.h"
#include "common/tools_common.h"
#ifdef __cplusplus
@@ -22,9 +23,13 @@
#define Y4M_BUFFER_SIZE 128
int y4m_write_file_header(char *buf, size_t len, int width, int height,
- const struct AvxRational *framerate,
+ const struct AvxRational *framerate, int monochrome,
aom_img_fmt_t fmt, unsigned int bit_depth);
int y4m_write_frame_header(char *buf, size_t len);
+void y4m_write_image_file(const aom_image_t *img, const int *planes,
+ FILE *file);
+void y4m_update_image_md5(const aom_image_t *img, const int *planes,
+ MD5Context *md5);
#ifdef __cplusplus
} // extern "C"
diff --git a/test/y4m_test.cc b/test/y4m_test.cc
index b801193..de241283 100644
--- a/test/y4m_test.cc
+++ b/test/y4m_test.cc
@@ -37,6 +37,8 @@
const Y4mTestParam kY4mTestVectors[] = {
{ "park_joy_90p_8_420.y4m", 8, AOM_IMG_FMT_I420,
"e5406275b9fc6bb3436c31d4a05c1cab" },
+ { "park_joy_90p_8_420_monochrome.y4m", 8, AOM_IMG_FMT_I420,
+ "95ef5bf6218580588be24a5271bb6a7f" },
{ "park_joy_90p_8_422.y4m", 8, AOM_IMG_FMT_I422,
"284a47a47133b12884ec3a14e959a0b6" },
{ "park_joy_90p_8_444.y4m", 8, AOM_IMG_FMT_I444,
@@ -55,24 +57,7 @@
"5a6481a550821dab6d0192f5c63845e9" },
};
-static void write_image_file(const aom_image_t *img, FILE *file) {
- int plane, y;
- for (plane = 0; plane < 3; ++plane) {
- const unsigned char *buf = img->planes[plane];
- const int stride = img->stride[plane];
- const int bytes_per_sample = (img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1;
- const int h =
- (plane ? (img->d_h + img->y_chroma_shift) >> img->y_chroma_shift
- : img->d_h);
- const int w =
- (plane ? (img->d_w + img->x_chroma_shift) >> img->x_chroma_shift
- : img->d_w);
- for (y = 0; y < h; ++y) {
- fwrite(buf, bytes_per_sample, w, file);
- buf += stride;
- }
- }
-}
+static const int PLANES_YUV[] = { AOM_PLANE_Y, AOM_PLANE_U, AOM_PLANE_V };
class Y4mVideoSourceTest : public ::testing::TestWithParam<Y4mTestParam>,
public ::libaom_test::Y4mVideoSource {
@@ -162,12 +147,12 @@
tmpfile_ = new libaom_test::TempOutFile;
ASSERT_TRUE(tmpfile_->file() != NULL);
y4m_write_file_header(buf, sizeof(buf), kWidth, kHeight, &framerate,
- y4m_.aom_fmt, y4m_.bit_depth);
+ img()->monochrome, y4m_.aom_fmt, y4m_.bit_depth);
fputs(buf, tmpfile_->file());
for (unsigned int i = start_; i < limit_; i++) {
y4m_write_frame_header(buf, sizeof(buf));
fputs(buf, tmpfile_->file());
- write_image_file(img(), tmpfile_->file());
+ y4m_write_image_file(img(), PLANES_YUV, tmpfile_->file());
Next();
}
ReplaceInputFile(tmpfile_->file());