Convert input frames to monochrome before encoding
When encoding a color input to a monochrome output, convert input frames
to monochrome frames in the AOM_IMG_FMT_I420 format before passing them
to aom_codec_encode(). The libaom encoder apparently has some problems
with encoding input frames in the AOM_IMG_FMT_I422 format to a
monochrome output. Although I could not get to the bottom of those
problems, this change allows us to bypass those problems.
Do not upgrade profile 0 to profile 2 when encoding to a monochrome
output, even if the input is YUV 4:2:2.
BUG=aomedia:2913
Change-Id: I86cc6a5a533092e241ba26b95d65a9cbe5fdd67f
diff --git a/apps/aomenc.c b/apps/aomenc.c
index f6969d2..d56594a 100644
--- a/apps/aomenc.c
+++ b/apps/aomenc.c
@@ -1475,6 +1475,33 @@
#endif
}
+// Convert the input image 'img' to a monochrome image. The Y plane of the
+// output image is a shallow copy of the Y plane of the input image, therefore
+// the input image must remain valid for the lifetime of the output image. The U
+// and V planes of the output image are set to null pointers. The output image
+// format is AOM_IMG_FMT_I420 because libaom does not have AOM_IMG_FMT_I400.
+static void convert_image_to_monochrome(const struct aom_image *img,
+ struct aom_image *monochrome_img) {
+ *monochrome_img = *img;
+ monochrome_img->fmt = AOM_IMG_FMT_I420;
+ if (img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
+ monochrome_img->fmt |= AOM_IMG_FMT_HIGHBITDEPTH;
+ }
+ monochrome_img->monochrome = 1;
+ monochrome_img->csp = AOM_CSP_UNKNOWN;
+ monochrome_img->x_chroma_shift = 1;
+ monochrome_img->y_chroma_shift = 1;
+ monochrome_img->planes[AOM_PLANE_U] = NULL;
+ monochrome_img->planes[AOM_PLANE_V] = NULL;
+ monochrome_img->stride[AOM_PLANE_U] = 0;
+ monochrome_img->stride[AOM_PLANE_V] = 0;
+ monochrome_img->sz = 0;
+ monochrome_img->bps = (img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 16 : 8;
+ monochrome_img->img_data = NULL;
+ monochrome_img->img_data_owner = 0;
+ monochrome_img->self_allocd = 0;
+}
+
static void encode_frame(struct stream_state *stream,
struct AvxEncoderConfig *global, struct aom_image *img,
unsigned int frames_in) {
@@ -1554,6 +1581,12 @@
#endif
}
+ struct aom_image monochrome_img;
+ if (img && cfg->monochrome) {
+ convert_image_to_monochrome(img, &monochrome_img);
+ img = &monochrome_img;
+ }
+
aom_usec_timer_start(&timer);
aom_codec_encode(&stream->encoder, img, frame_start,
(uint32_t)(next_frame_start - frame_start), 0);
@@ -1943,8 +1976,10 @@
stream->config.cfg.g_profile = 1;
profile_updated = 1;
}
- } else if (input.bit_depth == 12 || input.fmt == AOM_IMG_FMT_I422 ||
- input.fmt == AOM_IMG_FMT_I42216) {
+ } else if (input.bit_depth == 12 ||
+ ((input.fmt == AOM_IMG_FMT_I422 ||
+ input.fmt == AOM_IMG_FMT_I42216) &&
+ !stream->config.cfg.monochrome)) {
stream->config.cfg.g_profile = 2;
profile_updated = 1;
}