Bug 1657521 - P1. Add method to generate a vpcC box from the VP9 bitstream. r=jolin
☠☠ backed out by 6e2551ab206b ☠ ☠
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 12 Aug 2020 04:08:23 +0000
changeset 544359 132eb437fdda4a5cde692625073778696d67be74
parent 544358 51b465c34f8aca7ed48752788546177ad15da28f
child 544360 5c3c1ec039d2579557cf4f15789c0d7d356a0e78
push id123990
push userjyavenard@mozilla.com
push dateWed, 12 Aug 2020 05:42:22 +0000
treeherderautoland@a0f450666c5b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjolin
bugs1657521
milestone81.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1657521 - P1. Add method to generate a vpcC box from the VP9 bitstream. r=jolin The mac VP9 decoder; like the H264 requires some out of band settings before it can be created. This information is only found in the mp4 container, we can create it from the vp9 bitstream. For now we ignore the colors information as we can't handle it properly yet in our compositor and this is not available in the bytestream. Differential Revision: https://phabricator.services.mozilla.com/D86542
dom/media/platforms/agnostic/VPXDecoder.cpp
dom/media/platforms/agnostic/VPXDecoder.h
--- a/dom/media/platforms/agnostic/VPXDecoder.cpp
+++ b/dom/media/platforms/agnostic/VPXDecoder.cpp
@@ -1,27 +1,29 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "VPXDecoder.h"
+
+#include <algorithm>
+
 #include "BitReader.h"
+#include "ByteWriter.h"
+#include "ImageContainer.h"
 #include "TimeUnits.h"
 #include "gfx2DGlue.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/SyncRunnable.h"
 #include "mozilla/Unused.h"
-#include "ImageContainer.h"
 #include "nsError.h"
 #include "prsystem.h"
 
-#include <algorithm>
-
 #undef LOG
 #define LOG(arg, ...)                                                  \
   DDMOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, "::%s: " arg, __func__, \
             ##__VA_ARGS__)
 
 namespace mozilla {
 
 using namespace gfx;
@@ -477,10 +479,65 @@ bool VPXDecoder::GetStreamInfo(Span<cons
       Unused << br.ReadBits(8);  // refresh_frame_flags
       frame_size();
       render_size();
     }
   }
   return true;
 }
 
+// Ref: "VP Codec ISO Media File Format Binding, v1.0, 2017-03-31"
+// <https://www.webmproject.org/vp9/mp4/>
+//
+// class VPCodecConfigurationBox extends FullBox('vpcC', version = 1, 0)
+// {
+//     VPCodecConfigurationRecord() vpcConfig;
+// }
+//
+// aligned (8) class VPCodecConfigurationRecord {
+//     unsigned int (8)     profile;
+//     unsigned int (8)     level;
+//     unsigned int (4)     bitDepth;
+//     unsigned int (3)     chromaSubsampling;
+//     unsigned int (1)     videoFullRangeFlag;
+//     unsigned int (8)     colourPrimaries;
+//     unsigned int (8)     transferCharacteristics;
+//     unsigned int (8)     matrixCoefficients;
+//     unsigned int (16)    codecIntializationDataSize;
+//     unsigned int (8)[]   codecIntializationData;
+// }
+
+/* static */
+void VPXDecoder::GetVPCCBox(MediaByteBuffer* aDestBox,
+                            const VPXStreamInfo& aInfo) {
+  ByteWriter<BigEndian> writer(*aDestBox);
+
+  int chroma = [&]() {
+    if (aInfo.mSubSampling_x && aInfo.mSubSampling_y) {
+      return 1;  // 420 Colocated;
+    }
+    if (aInfo.mSubSampling_x && !aInfo.mSubSampling_y) {
+      return 2;  // 422
+    }
+    if (!aInfo.mSubSampling_x && !aInfo.mSubSampling_y) {
+      return 3;  // 444
+    }
+    // This indicates 4:4:0 subsampling, which is not expressable in the
+    // 'vpcC' box. Default to 4:2:0.
+    return 1;
+  }();
+
+  MOZ_ALWAYS_TRUE(writer.WriteU32(1 << 24));        // version & flag
+  MOZ_ALWAYS_TRUE(writer.WriteU8(aInfo.mProfile));  // profile
+  MOZ_ALWAYS_TRUE(writer.WriteU8(10));              // level set it to 1.0
+  MOZ_ALWAYS_TRUE(writer.WriteU8(
+      (0xF & aInfo.mBitDepth) << 4 | (0x7 & chroma) << 1 |
+      (0x1 & aInfo.mFullRange)));      // bitdepth (4 bits), chroma (3 bits),
+                                       // video full/restrice range (1 bit)
+  MOZ_ALWAYS_TRUE(writer.WriteU8(2));  // color primaries: unknown
+  MOZ_ALWAYS_TRUE(writer.WriteU8(2));  // transfer characteristics: unknown
+  MOZ_ALWAYS_TRUE(writer.WriteU8(2));  // matrix coefficient: unknown
+  MOZ_ALWAYS_TRUE(
+      writer.WriteU16(0));  // codecIntializationDataSize (must be 0 for VP9)
+}
+
 }  // namespace mozilla
 #undef LOG
--- a/dom/media/platforms/agnostic/VPXDecoder.h
+++ b/dom/media/platforms/agnostic/VPXDecoder.h
@@ -1,20 +1,20 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(VPXDecoder_h_)
 #  define VPXDecoder_h_
 
+#  include <stdint.h>
+
 #  include "PlatformDecoderModule.h"
 #  include "mozilla/Span.h"
-
-#  include <stdint.h>
 #  include "mozilla/gfx/Types.h"
 #  include "vpx/vp8dx.h"
 #  include "vpx/vpx_codec.h"
 #  include "vpx/vpx_decoder.h"
 
 namespace mozilla {
 
 DDLoggedTypeDeclNameAndBase(VPXDecoder, MediaDataDecoder);
@@ -89,16 +89,70 @@ class VPXDecoder : public MediaDataDecod
           return gfx::YUVColorSpace::BT709;
         case 5:
           return gfx::YUVColorSpace::BT2020;
         default:
           return gfx::YUVColorSpace::UNKNOWN;
       }
     }
 
+    // Ref: ISO/IEC 23091-2:2019
+    enum class ColorPrimaries {
+      BT_709_6 = 1,
+      Unspecified = 2,
+      BT_470_6_M = 4,
+      BT_470_7_BG = 5,
+      BT_601_7 = 6,
+      SMPTE_ST_240 = 7,
+      Film = 8,
+      BT_2020_Nonconstant_Luminance = 9,
+      SMPTE_ST_428_1 = 10,
+      SMPTE_RP_431_2 = 11,
+      SMPTE_EG_432_1 = 12,
+      EBU_Tech_3213_E = 22,
+    };
+
+    // Ref: ISO/IEC 23091-2:2019
+    enum class TransferCharacteristics {
+      BT_709_6 = 1,
+      Unspecified = 2,
+      BT_470_6_M = 4,
+      BT_470_7_BG = 5,
+      BT_601_7 = 6,
+      SMPTE_ST_240 = 7,
+      Linear = 8,
+      Logrithmic = 9,
+      Logrithmic_Sqrt = 10,
+      IEC_61966_2_4 = 11,
+      BT_1361_0 = 12,
+      IEC_61966_2_1 = 13,
+      BT_2020_10bit = 14,
+      BT_2020_12bit = 15,
+      SMPTE_ST_2084 = 16,
+      SMPTE_ST_428_1 = 17,
+      BT_2100_HLG = 18,
+    };
+
+    enum class MatrixCoefficients {
+      Identity = 0,
+      BT_709_6 = 1,
+      Unspecified = 2,
+      FCC = 4,
+      BT_470_7_BG = 5,
+      BT_601_7 = 6,
+      SMPTE_ST_240 = 7,
+      YCgCo = 8,
+      BT_2020_Nonconstant_Luminance = 9,
+      BT_2020_Constant_Luminance = 10,
+      SMPTE_ST_2085 = 11,
+      Chromacity_Constant_Luminance = 12,
+      Chromacity_Nonconstant_Luminance = 13,
+      BT_2100_ICC = 14,
+    };
+
     /*
     mFullRange == false then:
       For BitDepth equals 8:
         Y is between 16 and 235 inclusive.
         U and V are between 16 and 240 inclusive.
       For BitDepth equals 10:
         Y is between 64 and 940 inclusive.
         U and V are between 64 and 960 inclusive.
@@ -133,16 +187,18 @@ class VPXDecoder : public MediaDataDecod
              mColorSpace == aOther.mColorSpace &&
              mFullRange == aOther.mFullRange;
     }
   };
 
   static bool GetStreamInfo(Span<const uint8_t> aBuffer, VPXStreamInfo& aInfo,
                             Codec aCodec);
 
+  static void GetVPCCBox(MediaByteBuffer* aDestBox, const VPXStreamInfo& aInfo);
+
  private:
   ~VPXDecoder();
   RefPtr<DecodePromise> ProcessDecode(MediaRawData* aSample);
   MediaResult DecodeAlpha(vpx_image_t** aImgAlpha, const MediaRawData* aSample);
 
   const RefPtr<layers::ImageContainer> mImageContainer;
   RefPtr<layers::KnowsCompositor> mImageAllocator;
   const RefPtr<TaskQueue> mTaskQueue;