From b9b1abc871367f2b3456c4b5d39933015d08a689 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 26 Apr 2022 14:49:54 +0000 Subject: Issue #1820 - Part 1 : Add an extraction function to parse the RFC-6381 VP9 codec string. --- dom/media/VideoUtils.cpp | 175 ++++++++++++++++++++++++++++++++++++++++++++++- dom/media/VideoUtils.h | 28 ++++++++ 2 files changed, 202 insertions(+), 1 deletion(-) diff --git a/dom/media/VideoUtils.cpp b/dom/media/VideoUtils.cpp index 56033c2fae..66a6d6f9b7 100644 --- a/dom/media/VideoUtils.cpp +++ b/dom/media/VideoUtils.cpp @@ -222,13 +222,186 @@ already_AddRefed GetMediaThreadPool(MediaThreadType aType) return pool.forget(); } +bool +ExtractVPXCodecDetails(const nsAString& aCodec, + uint8_t& aProfile, + uint8_t& aLevel, + uint8_t& aBitDepth) +{ + uint8_t dummyChromaSubsampling = 1; + VideoColorSpace dummyColorspace; + return ExtractVPXCodecDetails(aCodec, + aProfile, + aLevel, + aBitDepth, + dummyChromaSubsampling, + dummyColorspace); +} + +bool ExtractVPXCodecDetails(const nsAString& aCodec, + uint8_t& aProfile, + uint8_t& aLevel, + uint8_t& aBitDepth, + uint8_t& aChromaSubsampling, + VideoColorSpace& aColorSpace) +{ + nsTArray fieldsArr; + + // Assign default value. + aChromaSubsampling = 1; + + nsCharSeparatedTokenizer tokenizer(aCodec, '.'); + while (tokenizer.hasMoreTokens()) { + const nsSubstring& token = tokenizer.nextToken(); + fieldsArr.AppendElement(token); + } + auto fourCC = fieldsArr[0]; + + if (!fourCC.EqualsLiteral("vp09") && !fourCC.EqualsLiteral("vp08")) { + // Invalid 4CC + return false; + } + uint8_t *fields[] = { &aProfile, &aLevel, &aBitDepth, &aChromaSubsampling, + &aColorSpace.mPrimaryId, &aColorSpace.mTransferId, + &aColorSpace.mMatrixId, &aColorSpace.mRangeId }; + int fieldsCount = 0; + nsresult rv; + for (int fieldsItr = 1; fieldsItr < fieldsArr.Length(); ++fieldsItr, ++fieldsCount) { + if (fieldsCount > 7) { + // No more than 8 fields are expected. + return false; + } + *(fields[fieldsCount]) = + static_cast(fieldsArr[fieldsItr].ToInteger(&rv)); + // We got invalid field value, parsing error. + NS_ENSURE_SUCCESS(rv, false); + } + // Mandatory Fields + // .... + // Optional Fields + // ... + // . + // First three fields are mandatory(we have parsed 4CC). + if (fieldsCount < 3) { + // Invalid number of fields. + return false; + } + // Start to validate the parsing value. + + // profile should be 0,1,2 or 3. + // See https://www.webmproject.org/vp9/profiles/ + // We don't support more than profile 2 + if (aProfile > 2) { + // Invalid profile. + return false; + } + + // level, See https://www.webmproject.org/vp9/mp4/#semantics_1 + switch (aLevel) { + case 10: + case 11: + case 20: + case 21: + case 30: + case 31: + case 40: + case 41: + case 50: + case 51: + case 52: + case 60: + case 61: + case 62: + break; + default: + // Invalid level. + return false; + } + + if (aBitDepth != 8 && aBitDepth != 10 && aBitDepth != 12) { + // Invalid bitDepth: + return false; + } + + if (fieldsCount == 3) { + // No more options. + return true; + } + + // chromaSubsampling should be 0,1,2,3...4~7 are reserved. + if (aChromaSubsampling > 3) { + return false; + } + + if (fieldsCount == 4) { + // No more options. + return true; + } + + // It is an integer that is defined by the "Colour primaries" + // section of ISO/IEC 23001-8:2016 Table 2. + // We treat reserved value as false case. + const auto& primaryId = aColorSpace.mPrimaryId; + if (primaryId == 0 || primaryId == 3 || primaryId > 22) { + // reserved value. + return false; + } + if (primaryId > 12 && primaryId < 22) { + // 13~21 are reserved values. + return false; + } + + if (fieldsCount == 5) { + // No more options. + return true; + } + + // It is an integer that is defined by the + // "Transfer characteristics" section of ISO/IEC 23001-8:2016 Table 3. + // We treat reserved value as false case. + const auto& transferId = aColorSpace.mTransferId; + if (transferId == 0 || transferId == 3 || transferId > 18) { + // reserved value. + return false; + } + + if (fieldsCount == 6) { + // No more options. + return true; + } + + // It is an integer that is defined by the + // "Matrix coefficients" section of ISO/IEC 23001-8:2016 Table 4. + // We treat reserved value as false case. + const auto& matrixId = aColorSpace.mMatrixId; + if (matrixId == 3 || matrixId > 11) { + return false; + } + + // If matrixCoefficients is 0 (RGB), then chroma subsampling MUST be 3 (4:4:4). + if (matrixId == 0 && aChromaSubsampling != 3) { + return false; + } + + if (fieldsCount == 7) { + // No more options. + return true; + } + + // videoFullRangeFlag indicates the black level and range of the luma and + // chroma signals. 0 = legal range (e.g. 16-235 for 8 bit sample depth); + // 1 = full range (e.g. 0-255 for 8-bit sample depth). + const auto& rangeId = aColorSpace.mRangeId; + return rangeId <= 1; +} + bool ExtractH264CodecDetails(const nsAString& aCodec, int16_t& aProfile, int16_t& aLevel) { // H.264 codecs parameters have a type defined as avcN.PPCCLL, where - // N = avc type. avc3 is avcc with SPS & PPS implicit (within stream) + // N = avc type. avc3 is avcc with SPS & PPS implicit (within stream) // PP = profile_idc, CC = constraint_set flags, LL = level_idc. // We ignore the constraint_set flags, as it's not clear from any // documentation what constraints the platform decoders support. diff --git a/dom/media/VideoUtils.h b/dom/media/VideoUtils.h index eee6561fde..421e6bb51d 100644 --- a/dom/media/VideoUtils.h +++ b/dom/media/VideoUtils.h @@ -257,6 +257,34 @@ ExtractH264CodecDetails(const nsAString& aCodecs, int16_t& aProfile, int16_t& aLevel); +struct VideoColorSpace +{ + // TODO: Define the value type as strong type enum + // to better know the exact meaning corresponding to ISO/IEC 23001-8:2016. + // Default value is listed https://www.webmproject.org/vp9/mp4/#optional-fields + uint8_t mPrimaryId = 1; // Table 2 + uint8_t mTransferId = 1; // Table 3 + uint8_t mMatrixId = 1; // Table 4 + uint8_t mRangeId = 0; +}; + +// Extracts the VPX codecs parameter string. +// See https://www.webmproject.org/vp9/mp4/#codecs-parameter-string +// for more details. +// Returns false on failure. +bool +ExtractVPXCodecDetails(const nsAString& aCodec, + uint8_t& aProfile, + uint8_t& aLevel, + uint8_t& aBitDepth); +bool +ExtractVPXCodecDetails(const nsAString& aCodec, + uint8_t& aProfile, + uint8_t& aLevel, + uint8_t& aBitDepth, + uint8_t& aChromaSubsampling, + VideoColorSpace& aColorSpace); + // Use a cryptographic quality PRNG to generate raw random bytes // and convert that to a base64 string. nsresult -- cgit v1.2.3 From 93b170e6292d58d251299b5d3d7c51c5c0afd65b Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 27 Apr 2022 10:18:49 +0000 Subject: Issue #1820 - Part 2: Add VP9-in-MP4 support to the decoder This also adds support in StageFright for VP9.0 FourCCs and consolidates individual string checks to helpers for WebM --- dom/media/fmp4/MP4Decoder.cpp | 6 ++++++ dom/media/webm/WebMDecoder.cpp | 3 +-- .../frameworks/av/media/libstagefright/MPEG4Extractor.cpp | 3 +++ .../libstagefright/frameworks/av/media/libstagefright/MediaDefs.cpp | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/dom/media/fmp4/MP4Decoder.cpp b/dom/media/fmp4/MP4Decoder.cpp index 7a340d8297..b57cd9b528 100644 --- a/dom/media/fmp4/MP4Decoder.cpp +++ b/dom/media/fmp4/MP4Decoder.cpp @@ -134,6 +134,12 @@ MP4Decoder::CanHandleMediaType(const MediaContentType& aType, NS_LITERAL_CSTRING("audio/flac"), aType)); continue; } + if (IsVP9CodecString(codec)) { + trackInfos.AppendElement( + CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters( + NS_LITERAL_CSTRING("video/vp9"), aType)); + continue; + } #ifdef MOZ_AV1 if (IsAV1CodecString(codec)) { trackInfos.AppendElement( diff --git a/dom/media/webm/WebMDecoder.cpp b/dom/media/webm/WebMDecoder.cpp index cbe9ffdb78..f0686577d6 100644 --- a/dom/media/webm/WebMDecoder.cpp +++ b/dom/media/webm/WebMDecoder.cpp @@ -67,8 +67,7 @@ WebMDecoder::CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs, // Note: Only accept VP8/VP9 in a video content type, not in an audio // content type. if ((isWebMVideo || isMatroskaVideo) && - (codec.EqualsLiteral("vp8") || codec.EqualsLiteral("vp8.0") || - codec.EqualsLiteral("vp9") || codec.EqualsLiteral("vp9.0"))) { + (IsVP8CodecString(codec) || IsVP9CodecString(codec))) { continue; } diff --git a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp index 786e804878..bbc067ab19 100644 --- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp @@ -269,6 +269,9 @@ static const char *FourCC2MIME(uint32_t fourcc) { case FOURCC('V', 'P', '6', 'F'): return MEDIA_MIMETYPE_VIDEO_VP6; + case FOURCC('v', 'p', '0', '9'): + return MEDIA_MIMETYPE_VIDEO_VP9; + case FOURCC('a', 'v', '0', '1'): case FOURCC('.', 'a', 'v', '1'): return MEDIA_MIMETYPE_VIDEO_AV1; diff --git a/media/libstagefright/frameworks/av/media/libstagefright/MediaDefs.cpp b/media/libstagefright/frameworks/av/media/libstagefright/MediaDefs.cpp index a7c6e75fcc..bc81dceb38 100644 --- a/media/libstagefright/frameworks/av/media/libstagefright/MediaDefs.cpp +++ b/media/libstagefright/frameworks/av/media/libstagefright/MediaDefs.cpp @@ -22,7 +22,7 @@ const char *MEDIA_MIMETYPE_IMAGE_JPEG = "image/jpeg"; const char *MEDIA_MIMETYPE_VIDEO_VP6 = "video/x-vnd.on2.vp6"; const char *MEDIA_MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8"; -const char *MEDIA_MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9"; +const char *MEDIA_MIMETYPE_VIDEO_VP9 = "video/vp9"; const char *MEDIA_MIMETYPE_VIDEO_AV1 = "video/av1"; const char *MEDIA_MIMETYPE_VIDEO_AVC = "video/avc"; const char *MEDIA_MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es"; -- cgit v1.2.3 From 6b2f1524f88466f9f20e8226abf25274d94947d4 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 27 Apr 2022 10:28:18 +0000 Subject: Issue #1820 - Part 3: Use Codec detail extractor helper to tell if it's a new style VP8/VP9 codec string. --- dom/media/VideoUtils.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/dom/media/VideoUtils.cpp b/dom/media/VideoUtils.cpp index 66a6d6f9b7..cc8d561460 100644 --- a/dom/media/VideoUtils.cpp +++ b/dom/media/VideoUtils.cpp @@ -641,15 +641,25 @@ IsAACCodecString(const nsAString& aCodec) bool IsVP8CodecString(const nsAString& aCodec) { + uint8_t profile = 0; + uint8_t level = 0; + uint8_t bitDepth = 0; return aCodec.EqualsLiteral("vp8") || - aCodec.EqualsLiteral("vp8.0"); + aCodec.EqualsLiteral("vp8.0") || + (StartsWith(NS_ConvertUTF16toUTF8(aCodec), "vp08") && + ExtractVPXCodecDetails(aCodec, profile, level, bitDepth)); } bool IsVP9CodecString(const nsAString& aCodec) { + uint8_t profile = 0; + uint8_t level = 0; + uint8_t bitDepth = 0; return aCodec.EqualsLiteral("vp9") || - aCodec.EqualsLiteral("vp9.0"); + aCodec.EqualsLiteral("vp9.0") || + (StartsWith(NS_ConvertUTF16toUTF8(aCodec), "vp09") && + ExtractVPXCodecDetails(aCodec, profile, level, bitDepth)); } #ifdef MOZ_AV1 -- cgit v1.2.3 From a874f27b5a1ac314b9d560ba1acc3af817e604f6 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 27 Apr 2022 11:03:38 +0000 Subject: Issue #1820 - Part 4: Add a gtest for testing the extraction function. --- .../gtest/TestExtractVPXCodecDetails.cpp | 111 +++++++++++++++++++++ dom/media/mediasource/gtest/moz.build | 1 + 2 files changed, 112 insertions(+) create mode 100644 dom/media/mediasource/gtest/TestExtractVPXCodecDetails.cpp diff --git a/dom/media/mediasource/gtest/TestExtractVPXCodecDetails.cpp b/dom/media/mediasource/gtest/TestExtractVPXCodecDetails.cpp new file mode 100644 index 0000000000..be8a120f61 --- /dev/null +++ b/dom/media/mediasource/gtest/TestExtractVPXCodecDetails.cpp @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 +#include + +#include "VideoUtils.h" + +using namespace mozilla; + +struct TestData +{ + const char16_t* const mCodecParameterString; + const bool mExpectedValue; +}; + +TEST(ExtractVPXCodecDetails, TestDataLength) { + TestData tests[] = + { + {u"vp09.00.11.08", true }, // valid case + {u"vp09.00.11.08.00", true }, // valid case, have extra optional field + {u"vp09.02.10.10.01.09.16.09.01", true}, // maximum length valid case + {u"vp09", false }, // lack of mandatory fields + {u"vp09.00", false }, // lack of mandatory fields + {u"vp09.00.11", false }, // lack of mandatory fields + {u"vp09.02.10.10.01.09.16.09.01.00", false} // more than 9 fields, invalid case. + }; + + for (const auto& data : tests) { + uint8_t profile = 0; + uint8_t level = 0; + uint8_t bitDepth = 0; + bool result = ExtractVPXCodecDetails(nsString(data.mCodecParameterString), profile, level, bitDepth); + EXPECT_EQ(result, data.mExpectedValue) << NS_ConvertUTF16toUTF8(data.mCodecParameterString).get(); + } +} + +TEST(ExtractVPXCodecDetails, TestInputData) { + TestData tests[] = + { + {u"vp09.02..08", false}, // malformed + {u"vp9.02.10.08", false}, // invalid 4CC + {u"vp09.03.11.08", false }, // profile should < 3 + {u"vp09.00.63.08.00", false }, // invalid level + {u"vp09.02.10.13", false}, // invalid bitDepth + {u"vp09.02.10.10.04", false}, // invalid chromasubsampling, should < 4 + {u"vp09.02.10.10.01.00", false}, // invalid Colour primaries, should not be 0,3 or < 23. + {u"vp09.02.10.10.01.03", false}, // invalid Colour primaries. + {u"vp09.02.10.10.01.23", false}, // invalid Colour primaries. + {u"vp09.02.10.10.01.09.00", false}, // invalid Transfer characteristics, should not be 0,3 or < 19. + {u"vp09.02.10.10.01.09.03", false}, // invalid Transfer characteristics. + {u"vp09.02.10.10.01.09.19", false}, // invalid Transfer characteristics. + {u"vp09.02.10.10.01.09.16.12", false}, // invalid Matrix coefficients, should not be 3 or < 12. + {u"vp09.02.10.10.01.09.16.03", false}, // invalid matrix. + {u"vp09.02.10.10.01.09.16.09.02", false}, // invalid range, should < 2. + // Test if matrixCoefficients is 0 (RGB), then chroma subsampling MUST be 3 (4:4:4). + {u"vp09.02.10.08.03.09.16.00.00", true} // invalid combination. + }; + + for (const auto& data : tests) { + uint8_t profile = 0; + uint8_t level = 0; + uint8_t bitDepth = 0; + bool result = ExtractVPXCodecDetails(nsString(data.mCodecParameterString), profile, level, bitDepth); + EXPECT_EQ(result, data.mExpectedValue) << NS_ConvertUTF16toUTF8(data.mCodecParameterString).get(); + } +} + +TEST(ExtractVPXCodecDetails, TestParsingOutput) { + uint8_t profile = 0; + uint8_t level = 0; + uint8_t bitDepth = 0; + uint8_t chromaSubsampling = 0; + VideoColorSpace colorSpace; + auto data = u"vp09.01.11.08"; + bool result = ExtractVPXCodecDetails(nsString(data), + profile, + level, + bitDepth, + chromaSubsampling, + colorSpace); + EXPECT_EQ(result, true); + EXPECT_EQ(profile, 1); + EXPECT_EQ(level, 11); + EXPECT_EQ(bitDepth, 8); + // Should keep spec defined default value. + EXPECT_EQ(chromaSubsampling, 1); + EXPECT_EQ(colorSpace.mPrimaryId, 1); + EXPECT_EQ(colorSpace.mTransferId, 1); + EXPECT_EQ(colorSpace.mMatrixId, 1); + EXPECT_EQ(colorSpace.mRangeId, 0); + + data = u"vp09.02.10.10.01.09.16.09.01"; + result = ExtractVPXCodecDetails(nsString(data), + profile, + level, + bitDepth, + chromaSubsampling, + colorSpace); + EXPECT_EQ(result, true); + EXPECT_EQ(profile, 2); + EXPECT_EQ(level, 10); + EXPECT_EQ(bitDepth, 10); + EXPECT_EQ(chromaSubsampling, 1); + EXPECT_EQ(colorSpace.mPrimaryId, 9); + EXPECT_EQ(colorSpace.mTransferId, 16); + EXPECT_EQ(colorSpace.mMatrixId, 9); + EXPECT_EQ(colorSpace.mRangeId, 1); +} diff --git a/dom/media/mediasource/gtest/moz.build b/dom/media/mediasource/gtest/moz.build index 2cccc80a21..2a59a8343a 100644 --- a/dom/media/mediasource/gtest/moz.build +++ b/dom/media/mediasource/gtest/moz.build @@ -5,6 +5,7 @@ UNIFIED_SOURCES += [ 'TestContainerParser.cpp', + 'TestExtractVPXCodecDetails.cpp', ] LOCAL_INCLUDES += [ -- cgit v1.2.3 From 4e5b100cca8e1b181f4ab8fb66b340ae2a95bd74 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 27 Apr 2022 11:08:27 +0000 Subject: Issue #1820 - Part 5: Add mBitDepth field to VideoInfo. --- dom/media/MediaInfo.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dom/media/MediaInfo.h b/dom/media/MediaInfo.h index d54cf99b2d..2ddaf5a43f 100644 --- a/dom/media/MediaInfo.h +++ b/dom/media/MediaInfo.h @@ -213,6 +213,7 @@ public: , mCodecSpecificConfig(aOther.mCodecSpecificConfig) , mExtraData(aOther.mExtraData) , mRotation(aOther.mRotation) + , mBitDepth(aOther.mBitDepth) , mImageRect(aOther.mImageRect) { } @@ -303,6 +304,9 @@ public: // Describing how many degrees video frames should be rotated in clock-wise to // get correct view. Rotation mRotation; + + // Bits per channel -- Should be 8, 10 or 12. Default value is 8. + uint8_t mBitDepth = 8; private: // mImage may be cropped; currently only used with the WebM container. -- cgit v1.2.3 From bf8359c70453d9f68a6e14cf04fd6ad132329129 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 27 Apr 2022 11:13:34 +0000 Subject: Issue #1820 - Part 6: Extract bit depth information from codec parameter string into VideoInfo::mBitDepth. --- dom/media/fmp4/MP4Decoder.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/dom/media/fmp4/MP4Decoder.cpp b/dom/media/fmp4/MP4Decoder.cpp index b57cd9b528..23f09324b4 100644 --- a/dom/media/fmp4/MP4Decoder.cpp +++ b/dom/media/fmp4/MP4Decoder.cpp @@ -135,9 +135,16 @@ MP4Decoder::CanHandleMediaType(const MediaContentType& aType, continue; } if (IsVP9CodecString(codec)) { - trackInfos.AppendElement( - CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters( - NS_LITERAL_CSTRING("video/vp9"), aType)); + auto trackInfo = + CreateTrackInfoWithMIMETypeAndContentTypeExtraParameters( + NS_LITERAL_CSTRING("video/vp9"), aType); + uint8_t profile = 0; + uint8_t level = 0; + uint8_t bitDepth = 0; + if (ExtractVPXCodecDetails(codec, profile, level, bitDepth)) { + trackInfo->GetAsVideoInfo()->mBitDepth = bitDepth; + } + trackInfos.AppendElement(Move(trackInfo)); continue; } #ifdef MOZ_AV1 -- cgit v1.2.3 From 983a87a9d7d01c8a8750fe070ebc790f12614a63 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 27 Apr 2022 12:34:59 +0000 Subject: Issue #1820 - Part 7: Check bit depth in WebMDecoder to determine if we support HDR. --- dom/media/webm/WebMDecoder.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/dom/media/webm/WebMDecoder.cpp b/dom/media/webm/WebMDecoder.cpp index f0686577d6..b4cc794e76 100644 --- a/dom/media/webm/WebMDecoder.cpp +++ b/dom/media/webm/WebMDecoder.cpp @@ -12,6 +12,7 @@ #include "MediaDecoderStateMachine.h" #include "WebMDemuxer.h" #include "WebMDecoder.h" +#include "PDMFactory.h" #include "VideoUtils.h" #include "nsContentTypeParser.h" @@ -66,10 +67,30 @@ WebMDecoder::CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs, } // Note: Only accept VP8/VP9 in a video content type, not in an audio // content type. - if ((isWebMVideo || isMatroskaVideo) && - (IsVP8CodecString(codec) || IsVP9CodecString(codec))) { - - continue; + if (isWebMVideo || isMatroskaVideo) { + UniquePtr trackInfo; + if (IsVP9CodecString(codec)) { + trackInfo = CreateTrackInfoWithMIMEType( + NS_LITERAL_CSTRING("video/vp9")); + } else if (IsVP8CodecString(codec)) { + trackInfo = CreateTrackInfoWithMIMEType( + NS_LITERAL_CSTRING("video/vp8")); + } + // If it is vp8 or vp9, check the bit depth. + if (trackInfo) { + uint8_t profile = 0; + uint8_t level = 0; + uint8_t bitDepth = 0; + if (ExtractVPXCodecDetails(codec, profile, level, bitDepth)) { + trackInfo->GetAsVideoInfo()->mBitDepth = bitDepth; + } + // Verify that we have a PDM that supports this bit depth. + RefPtr platform = new PDMFactory(); + if (!platform->Supports(*trackInfo, nullptr)) { + return false; + } + continue; + } } #ifdef MOZ_AV1 if (MediaPrefs::AV1Enabled() && IsAV1CodecString(codec)) { -- cgit v1.2.3 From bf110158b926f99fa36c180150d242453c8b0f95 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 27 Apr 2022 16:08:36 +0000 Subject: Issue #1820 - Part 8: Check bit depth in PDM::Supports. --- dom/media/platforms/PlatformDecoderModule.h | 17 ++++++++++++++--- dom/media/platforms/ffmpeg/FFmpegDecoderModule.h | 15 +++++++++++++++ dom/media/platforms/wmf/WMFDecoderModule.cpp | 10 +++++++++- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/dom/media/platforms/PlatformDecoderModule.h b/dom/media/platforms/PlatformDecoderModule.h index 62855335f3..1584706b22 100644 --- a/dom/media/platforms/PlatformDecoderModule.h +++ b/dom/media/platforms/PlatformDecoderModule.h @@ -129,9 +129,11 @@ public: virtual bool Supports(const TrackInfo& aTrackInfo, DecoderDoctorDiagnostics* aDiagnostics) const { - // By default, fall back to SupportsMimeType with just the MIME string. - // (So PDMs do not need to override this method -- yet.) - return SupportsMimeType(aTrackInfo.mMimeType, aDiagnostics); + if (!SupportsMimeType(aTrackInfo.mMimeType, aDiagnostics)) { + return false; + } + const auto videoInfo = aTrackInfo.GetAsVideoInfo(); + return !videoInfo || SupportsBitDepth(videoInfo->mBitDepth, aDiagnostics); } enum class ConversionRequired : uint8_t { @@ -153,6 +155,15 @@ protected: friend class PDMFactory; friend class dom::RemoteDecoderModule; + // Indicates if the PlatformDecoderModule supports decoding of aBitDepth. + // Should override this method when the platform can support bitDepth != 8. + virtual bool SupportsBitDepth(const uint8_t aBitDepth, + DecoderDoctorDiagnostics* aDiagnostics) const + { + return aBitDepth == 8; + } + + // Creates a Video decoder. The layers backend is passed in so that // decoders can determine whether hardware accelerated decoding can be used. // Asynchronous decoding of video should be done in runnables dispatched diff --git a/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h b/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h index 969ac7e0be..d220fcf91c 100644 --- a/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h +++ b/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h @@ -77,6 +77,21 @@ public: } } +protected: + bool SupportsBitDepth(const uint8_t aBitDepth, + DecoderDoctorDiagnostics* aDiagnostics) const override + { + // We don't support bitDepth > 8 when compositor backend is D3D11. + // But we don't have KnowsCompositor or any object + // that we can ask for the layersbackend type. + // We should remove this restriction until + // we solve the D3D11 compositor backend issue. +#if defined(XP_LINUX) || defined(XP_MACOSX) + return true; +#endif + return aBitDepth == 8; + } + private: FFmpegLibWrapper* mLib; }; diff --git a/dom/media/platforms/wmf/WMFDecoderModule.cpp b/dom/media/platforms/wmf/WMFDecoderModule.cpp index 06bf49fa6a..423d58c967 100644 --- a/dom/media/platforms/wmf/WMFDecoderModule.cpp +++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp @@ -205,6 +205,14 @@ bool WMFDecoderModule::Supports(const TrackInfo& aTrackInfo, DecoderDoctorDiagnostics* aDiagnostics) const { + // Check bit depth of video. + // XXXMC: This is here in case we want to start accepting HDR video. Do we? + // This currently defaults to a fail if video bitdepth != 8 + const auto videoInfo = aTrackInfo.GetAsVideoInfo(); + if (videoInfo && !SupportsBitDepth(videoInfo->mBitDepth, aDiagnostics)) { + return false; + } + if ((aTrackInfo.mMimeType.EqualsLiteral("audio/mp4a-latm") || aTrackInfo.mMimeType.EqualsLiteral("audio/mp4")) && WMFDecoderModule::HasAAC()) { @@ -221,7 +229,7 @@ WMFDecoderModule::Supports(const TrackInfo& aTrackInfo, return false; } } else { - // Windows <=7 supports at most 1920x1088. + // Windows 7 supports at most 1920x1088. if (videoInfo->mImage.width > 1920 || videoInfo->mImage.height > 1088) { return false; } -- cgit v1.2.3