Bug 1657521 - P1. Add method to generate a vpcC box from the VP9 bitstream. r=jolin
authorJean-Yves Avenard <jyavenard@mozilla.com>
Thu, 13 Aug 2020 02:14:11 +0000
changeset 544478 99693abc449917ff26e9c76eedc100c0ee94793c
parent 544477 7aa58ee0e4925b192a96e7e83fc59458b358bb3d
child 544479 233bb07b9bb931d853a956abf8a4cc8b0e73e919
push id37695
push usermalexandru@mozilla.com
push dateThu, 13 Aug 2020 09:29:15 +0000
treeherdermozilla-central@32ec11f12a62 [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;