summaryrefslogtreecommitdiffstats
path: root/dom/media/platforms/agnostic/AOMDecoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/platforms/agnostic/AOMDecoder.cpp')
-rw-r--r--dom/media/platforms/agnostic/AOMDecoder.cpp84
1 files changed, 83 insertions, 1 deletions
diff --git a/dom/media/platforms/agnostic/AOMDecoder.cpp b/dom/media/platforms/agnostic/AOMDecoder.cpp
index 009654a5f..c2b62eaa4 100644
--- a/dom/media/platforms/agnostic/AOMDecoder.cpp
+++ b/dom/media/platforms/agnostic/AOMDecoder.cpp
@@ -8,6 +8,7 @@
#include "MediaResult.h"
#include "TimeUnits.h"
#include "aom/aomdx.h"
+#include "aom/aom_image.h"
#include "gfx2DGlue.h"
#include "mozilla/PodOperations.h"
#include "mozilla/SyncRunnable.h"
@@ -82,6 +83,62 @@ AOMDecoder::Flush()
mIsFlushing = false;
}
+// Ported from third_party/aom/tools_common.c.
+static aom_codec_err_t
+highbd_img_downshift(aom_image_t *dst, aom_image_t *src, int down_shift) {
+ int plane;
+ if (dst->d_w != src->d_w || dst->d_h != src->d_h)
+ return AOM_CODEC_INVALID_PARAM;
+ if (dst->x_chroma_shift != src->x_chroma_shift)
+ return AOM_CODEC_INVALID_PARAM;
+ if (dst->y_chroma_shift != src->y_chroma_shift)
+ return AOM_CODEC_INVALID_PARAM;
+ if (dst->fmt != (src->fmt & ~AOM_IMG_FMT_HIGHBITDEPTH))
+ return AOM_CODEC_INVALID_PARAM;
+ if (down_shift < 0)
+ return AOM_CODEC_INVALID_PARAM;
+ switch (dst->fmt) {
+ case AOM_IMG_FMT_I420:
+ case AOM_IMG_FMT_I422:
+ case AOM_IMG_FMT_I444:
+ case AOM_IMG_FMT_I440:
+ break;
+ default:
+ return AOM_CODEC_INVALID_PARAM;
+ }
+ switch (src->fmt) {
+ case AOM_IMG_FMT_I42016:
+ case AOM_IMG_FMT_I42216:
+ case AOM_IMG_FMT_I44416:
+ case AOM_IMG_FMT_I44016:
+ break;
+ default:
+ return AOM_CODEC_UNSUP_BITSTREAM;
+ }
+ for (plane = 0; plane < 3; plane++) {
+ int w = src->d_w;
+ int h = src->d_h;
+ int x, y;
+ if (plane) {
+ w = (w + src->x_chroma_shift) >> src->x_chroma_shift;
+ h = (h + src->y_chroma_shift) >> src->y_chroma_shift;
+ }
+ for (y = 0; y < h; y++) {
+ uint16_t *p_src =
+ (uint16_t *)(src->planes[plane] + y * src->stride[plane]);
+ uint8_t *p_dst =
+ dst->planes[plane] + y * dst->stride[plane];
+ for (x = 0; x < w; x++) *p_dst++ = (*p_src++ >> down_shift) & 0xFF;
+ }
+ }
+ return AOM_CODEC_OK;
+}
+
+// UniquePtr dtor wrapper for aom_image_t.
+struct AomImageFree {
+ void operator()(aom_image_t* img) { aom_img_free(img); }
+};
+
MediaResult
AOMDecoder::DoDecode(MediaRawData* aSample)
{
@@ -101,11 +158,36 @@ AOMDecoder::DoDecode(MediaRawData* aSample)
aom_codec_iter_t iter = nullptr;
aom_image_t *img;
+ UniquePtr<aom_image_t, AomImageFree> img8;
while ((img = aom_codec_get_frame(&mCodec, &iter))) {
+ if (img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
+ // Downsample images with more than 8 bits per channel.
+ aom_img_fmt_t fmt8 = static_cast<aom_img_fmt_t>(img->fmt ^ AOM_IMG_FMT_HIGHBITDEPTH);
+ img8.reset(aom_img_alloc(NULL, fmt8, img->d_w, img->d_h, 16));
+ if (img8 == nullptr) {
+ LOG("Couldn't allocate bitdepth reduction target!");
+ return MediaResult(
+ NS_ERROR_OUT_OF_MEMORY,
+ RESULT_DETAIL("Couldn't allocate conversion buffer for AV1 frame"));
+ }
+ if (aom_codec_err_t r = highbd_img_downshift(img8.get(), img, img->bit_depth - 8)) {
+ LOG_RESULT(r, "Image downconversion failed");
+ return MediaResult(
+ NS_ERROR_DOM_MEDIA_DECODE_ERR,
+ RESULT_DETAIL("Error converting AV1 frame to 8 bits: %s",
+ aom_codec_err_to_string(r)));
+ }
+ // img normally points to storage owned by mCodec, so it is not freed.
+ // To copy out the contents of img8 we can overwrite img with an alias.
+ // Since img is assigned at the start of the while loop and img8 is held
+ // outside that loop, the alias won't outlive the storage it points to.
+ img = img8.get();
+ }
+
NS_ASSERTION(img->fmt == AOM_IMG_FMT_I420 ||
img->fmt == AOM_IMG_FMT_I444,
- "WebM image format not I420 or I444");
+ "AV1 image format not I420 or I444");
// Chroma shifts are rounded down as per the decoding examples in the SDK
VideoData::YCbCrBuffer b;