1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #if !defined(VPXDecoder_h_)
7 #  define VPXDecoder_h_
8 
9 #  include <stdint.h>
10 
11 #  include "PlatformDecoderModule.h"
12 #  include "mozilla/Span.h"
13 #  include "mozilla/gfx/Types.h"
14 #  include "vpx/vp8dx.h"
15 #  include "vpx/vpx_codec.h"
16 #  include "vpx/vpx_decoder.h"
17 
18 namespace mozilla {
19 
20 DDLoggedTypeDeclNameAndBase(VPXDecoder, MediaDataDecoder);
21 
22 class VPXDecoder : public MediaDataDecoder,
23                    public DecoderDoctorLifeLogger<VPXDecoder> {
24  public:
25   explicit VPXDecoder(const CreateDecoderParams& aParams);
26 
27   RefPtr<InitPromise> Init() override;
28   RefPtr<DecodePromise> Decode(MediaRawData* aSample) override;
29   RefPtr<DecodePromise> Drain() override;
30   RefPtr<FlushPromise> Flush() override;
31   RefPtr<ShutdownPromise> Shutdown() override;
GetDescriptionName()32   nsCString GetDescriptionName() const override {
33     return "libvpx video decoder"_ns;
34   }
35 
36   enum Codec : uint8_t {
37     VP8 = 1 << 0,
38     VP9 = 1 << 1,
39     Unknown = 1 << 7,
40   };
41 
42   // Return true if aMimeType is a one of the strings used by our demuxers to
43   // identify VPX of the specified type. Does not parse general content type
44   // strings, i.e. white space matters.
45   static bool IsVPX(const nsACString& aMimeType,
46                     uint8_t aCodecMask = VP8 | VP9);
47   static bool IsVP8(const nsACString& aMimeType);
48   static bool IsVP9(const nsACString& aMimeType);
49 
50   // Return true if a sample is a keyframe for the specified codec.
51   static bool IsKeyframe(Span<const uint8_t> aBuffer, Codec aCodec);
52 
53   // Return the frame dimensions for a sample for the specified codec.
54   static gfx::IntSize GetFrameSize(Span<const uint8_t> aBuffer, Codec aCodec);
55   // Return the display dimensions for a sample for the specified codec.
56   static gfx::IntSize GetDisplaySize(Span<const uint8_t> aBuffer, Codec aCodec);
57 
58   // Return the VP9 profile as per https://www.webmproject.org/vp9/profiles/
59   // Return negative value if error.
60   static int GetVP9Profile(Span<const uint8_t> aBuffer);
61 
62   struct VPXStreamInfo {
63     gfx::IntSize mImage;
64     gfx::IntSize mDisplay;
65     bool mKeyFrame = false;
66 
67     uint8_t mProfile = 0;
68     uint8_t mBitDepth = 8;
69     /*
70     0 CS_UNKNOWN Unknown (in this case the color space must be signaled outside
71       the VP9 bitstream).
72     1 CS_BT_601 Rec. ITU-R BT.601-7
73     2 CS_BT_709 Rec. ITU-R BT.709-6
74     3 CS_SMPTE_170 SMPTE-170
75     4 CS_SMPTE_240 SMPTE-240
76     5 CS_BT_2020 Rec. ITU-R BT.2020-2
77     6 CS_RESERVED Reserved
78     7 CS_RGB sRGB (IEC 61966-2-1)
79     */
80     int mColorSpace = 1;  // CS_BT_601
81 
ColorSpaceVPXStreamInfo82     gfx::YUVColorSpace ColorSpace() const {
83       switch (mColorSpace) {
84         case 1:
85         case 3:
86         case 4:
87           return gfx::YUVColorSpace::BT601;
88         case 2:
89           return gfx::YUVColorSpace::BT709;
90         case 5:
91           return gfx::YUVColorSpace::BT2020;
92         default:
93           return gfx::YUVColorSpace::Default;
94       }
95     }
96 
97     // Ref: ISO/IEC 23091-2:2019
98     enum class ColorPrimaries {
99       BT_709_6 = 1,
100       Unspecified = 2,
101       BT_470_6_M = 4,
102       BT_470_7_BG = 5,
103       BT_601_7 = 6,
104       SMPTE_ST_240 = 7,
105       Film = 8,
106       BT_2020_Nonconstant_Luminance = 9,
107       SMPTE_ST_428_1 = 10,
108       SMPTE_RP_431_2 = 11,
109       SMPTE_EG_432_1 = 12,
110       EBU_Tech_3213_E = 22,
111     };
112 
113     // Ref: ISO/IEC 23091-2:2019
114     enum class TransferCharacteristics {
115       BT_709_6 = 1,
116       Unspecified = 2,
117       BT_470_6_M = 4,
118       BT_470_7_BG = 5,
119       BT_601_7 = 6,
120       SMPTE_ST_240 = 7,
121       Linear = 8,
122       Logrithmic = 9,
123       Logrithmic_Sqrt = 10,
124       IEC_61966_2_4 = 11,
125       BT_1361_0 = 12,
126       IEC_61966_2_1 = 13,
127       BT_2020_10bit = 14,
128       BT_2020_12bit = 15,
129       SMPTE_ST_2084 = 16,
130       SMPTE_ST_428_1 = 17,
131       BT_2100_HLG = 18,
132     };
133 
134     enum class MatrixCoefficients {
135       Identity = 0,
136       BT_709_6 = 1,
137       Unspecified = 2,
138       FCC = 4,
139       BT_470_7_BG = 5,
140       BT_601_7 = 6,
141       SMPTE_ST_240 = 7,
142       YCgCo = 8,
143       BT_2020_Nonconstant_Luminance = 9,
144       BT_2020_Constant_Luminance = 10,
145       SMPTE_ST_2085 = 11,
146       Chromacity_Constant_Luminance = 12,
147       Chromacity_Nonconstant_Luminance = 13,
148       BT_2100_ICC = 14,
149     };
150 
151     /*
152     mFullRange == false then:
153       For BitDepth equals 8:
154         Y is between 16 and 235 inclusive.
155         U and V are between 16 and 240 inclusive.
156       For BitDepth equals 10:
157         Y is between 64 and 940 inclusive.
158         U and V are between 64 and 960 inclusive.
159       For BitDepth equals 12:
160         Y is between 256 and 3760.
161         U and V are between 256 and 3840 inclusive.
162     mFullRange == true then:
163       No restriction on Y, U, V values.
164     */
165     bool mFullRange = false;
166 
ColorRangeVPXStreamInfo167     gfx::ColorRange ColorRange() const {
168       return mFullRange ? gfx::ColorRange::FULL : gfx::ColorRange::LIMITED;
169     }
170 
171     /*
172       Sub-sampling, used only for non sRGB colorspace.
173       subsampling_x subsampling_y Description
174           0             0         YUV 4:4:4
175           0             1         YUV 4:4:0
176           1             0         YUV 4:2:2
177           1             1         YUV 4:2:0
178     */
179     bool mSubSampling_x = true;
180     bool mSubSampling_y = true;
181 
IsCompatibleVPXStreamInfo182     bool IsCompatible(const VPXStreamInfo& aOther) const {
183       return mImage == aOther.mImage && mProfile == aOther.mProfile &&
184              mBitDepth == aOther.mBitDepth &&
185              mSubSampling_x == aOther.mSubSampling_x &&
186              mSubSampling_y == aOther.mSubSampling_y &&
187              mColorSpace == aOther.mColorSpace &&
188              mFullRange == aOther.mFullRange;
189     }
190   };
191 
192   static bool GetStreamInfo(Span<const uint8_t> aBuffer, VPXStreamInfo& aInfo,
193                             Codec aCodec);
194 
195   static void GetVPCCBox(MediaByteBuffer* aDestBox, const VPXStreamInfo& aInfo);
196 
197  private:
198   ~VPXDecoder();
199   RefPtr<DecodePromise> ProcessDecode(MediaRawData* aSample);
200   MediaResult DecodeAlpha(vpx_image_t** aImgAlpha, const MediaRawData* aSample);
201 
202   const RefPtr<layers::ImageContainer> mImageContainer;
203   RefPtr<layers::KnowsCompositor> mImageAllocator;
204   const RefPtr<TaskQueue> mTaskQueue;
205 
206   // VPx decoder state
207   vpx_codec_ctx_t mVPX;
208 
209   // VPx alpha decoder state
210   vpx_codec_ctx_t mVPXAlpha;
211 
212   const VideoInfo mInfo;
213 
214   const Codec mCodec;
215   const bool mLowLatency;
216 };
217 
218 }  // namespace mozilla
219 
220 #endif
221