Bug 1380118 - aom: Don't resample 8-bit images. r?kinetik draft
authorRalph Giles <giles@mozilla.com>
Mon, 14 Aug 2017 14:21:03 -0700
changeset 651859 fa7f4faef4ad04988f1a20934657293fcdf63fd9
parent 651858 9ad34e98705b163593ecb5d41d4a5d9004d680ac
child 651860 6cc5c87677603f8e1f3116b04d5bdb5edfed7e5a
push id75832
push userbmo:giles@thaumas.net
push dateThu, 24 Aug 2017 03:49:46 +0000
reviewerskinetik
bugs1380118
milestone57.0a1
Bug 1380118 - aom: Don't resample 8-bit images. r?kinetik The libaom av1 decoder will return 16 bit per channel aom_image_t structures with only 8 significant bits. Detect this case and use the mSkip fields of PlanarYCbCrImage to handle the extra data instead of allocating and performing an extra copy to obtain the necessary 8 bit representation. MozReview-Commit-ID: 8H9YZe86Qzu
dom/media/platforms/agnostic/AOMDecoder.cpp
--- a/dom/media/platforms/agnostic/AOMDecoder.cpp
+++ b/dom/media/platforms/agnostic/AOMDecoder.cpp
@@ -184,18 +184,20 @@ AOMDecoder::ProcessDecode(MediaRawData* 
   }
 
   aom_codec_iter_t iter = nullptr;
   aom_image_t *img;
   UniquePtr<aom_image_t, AomImageFree> img8;
   DecodedData results;
 
   while ((img = aom_codec_get_frame(&mCodec, &iter))) {
-    if (img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
-      // Downsample images with more than 8 bits per channel.
+    // Track whether the underlying buffer is 8 or 16 bits per channel.
+    bool highbd = bool(img->fmt & AOM_IMG_FMT_HIGHBITDEPTH);
+    if (img->bit_depth > 8) {
+      // Downsample images with more than 8 significant 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 DecodePromise::CreateAndReject(
           MediaResult(NS_ERROR_OUT_OF_MEMORY,
                       RESULT_DETAIL("Couldn't allocate conversion buffer for AV1 frame")),
                       __func__);
@@ -208,39 +210,46 @@ AOMDecoder::ProcessDecode(MediaRawData* 
                                     aom_codec_err_to_string(r))),
           __func__);
       }
       // 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();
+      highbd = false;
     }
 
     NS_ASSERTION(img->fmt == AOM_IMG_FMT_I420 ||
-                 img->fmt == AOM_IMG_FMT_I444,
+                 img->fmt == AOM_IMG_FMT_I42016 ||
+                 img->fmt == AOM_IMG_FMT_I444 ||
+                 img->fmt == AOM_IMG_FMT_I44416,
                  "AV1 image format not I420 or I444");
 
     // Chroma shifts are rounded down as per the decoding examples in the SDK
     VideoData::YCbCrBuffer b;
     b.mPlanes[0].mData = img->planes[0];
     b.mPlanes[0].mStride = img->stride[0];
     b.mPlanes[0].mHeight = img->d_h;
     b.mPlanes[0].mWidth = img->d_w;
-    b.mPlanes[0].mOffset = b.mPlanes[0].mSkip = 0;
+    b.mPlanes[0].mOffset = 0;
+    b.mPlanes[0].mSkip = highbd ? 1 : 0;
 
     b.mPlanes[1].mData = img->planes[1];
     b.mPlanes[1].mStride = img->stride[1];
-    b.mPlanes[1].mOffset = b.mPlanes[1].mSkip = 0;
+    b.mPlanes[1].mOffset = 0;
+    b.mPlanes[1].mSkip = highbd ? 1 : 0;
 
     b.mPlanes[2].mData = img->planes[2];
     b.mPlanes[2].mStride = img->stride[2];
-    b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0;
+    b.mPlanes[2].mOffset = 0;
+    b.mPlanes[2].mSkip = highbd ? 1 : 0;
 
-    if (img->fmt == AOM_IMG_FMT_I420) {
+    if (img->fmt == AOM_IMG_FMT_I420 ||
+        img->fmt == AOM_IMG_FMT_I42016) {
       b.mPlanes[1].mHeight = (img->d_h + 1) >> img->y_chroma_shift;
       b.mPlanes[1].mWidth = (img->d_w + 1) >> img->x_chroma_shift;
 
       b.mPlanes[2].mHeight = (img->d_h + 1) >> img->y_chroma_shift;
       b.mPlanes[2].mWidth = (img->d_w + 1) >> img->x_chroma_shift;
     } else if (img->fmt == AOM_IMG_FMT_I444) {
       b.mPlanes[1].mHeight = img->d_h;
       b.mPlanes[1].mWidth = img->d_w;