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 "PlatformDecoderModule.h"
10 #  include "mozilla/Span.h"
11 
12 #  include <stdint.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 NS_LITERAL_CSTRING("libvpx video decoder");
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::UNKNOWN;
94       }
95     }
96 
97     /*
98     mFullRange == false then:
99       For BitDepth equals 8:
100         Y is between 16 and 235 inclusive.
101         U and V are between 16 and 240 inclusive.
102       For BitDepth equals 10:
103         Y is between 64 and 940 inclusive.
104         U and V are between 64 and 960 inclusive.
105       For BitDepth equals 12:
106         Y is between 256 and 3760.
107         U and V are between 256 and 3840 inclusive.
108     mFullRange == true then:
109       No restriction on Y, U, V values.
110     */
111     bool mFullRange = false;
112 
ColorRangeVPXStreamInfo113     gfx::ColorRange ColorRange() const {
114       return mFullRange ? gfx::ColorRange::FULL : gfx::ColorRange::LIMITED;
115     }
116 
117     /*
118       Sub-sampling, used only for non sRGB colorspace.
119       subsampling_x subsampling_y Description
120           0             0         YUV 4:4:4
121           0             1         YUV 4:4:0
122           1             0         YUV 4:2:2
123           1             1         YUV 4:2:0
124     */
125     bool mSubSampling_x = true;
126     bool mSubSampling_y = true;
127 
IsCompatibleVPXStreamInfo128     bool IsCompatible(const VPXStreamInfo& aOther) const {
129       return mImage == aOther.mImage && mProfile == aOther.mProfile &&
130              mBitDepth == aOther.mBitDepth &&
131              mSubSampling_x == aOther.mSubSampling_x &&
132              mSubSampling_y == aOther.mSubSampling_y &&
133              mColorSpace == aOther.mColorSpace &&
134              mFullRange == aOther.mFullRange;
135     }
136   };
137 
138   static bool GetStreamInfo(Span<const uint8_t> aBuffer, VPXStreamInfo& aInfo,
139                             Codec aCodec);
140 
141  private:
142   ~VPXDecoder();
143   RefPtr<DecodePromise> ProcessDecode(MediaRawData* aSample);
144   MediaResult DecodeAlpha(vpx_image_t** aImgAlpha, const MediaRawData* aSample);
145 
146   const RefPtr<layers::ImageContainer> mImageContainer;
147   RefPtr<layers::KnowsCompositor> mImageAllocator;
148   const RefPtr<TaskQueue> mTaskQueue;
149 
150   // VPx decoder state
151   vpx_codec_ctx_t mVPX;
152 
153   // VPx alpha decoder state
154   vpx_codec_ctx_t mVPXAlpha;
155 
156   const VideoInfo& mInfo;
157 
158   const Codec mCodec;
159   const bool mLowLatency;
160 };
161 
162 }  // namespace mozilla
163 
164 #endif
165