summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Cheng <jacheng@mozilla.com>2022-05-02 14:06:50 -0500
committerMatt A. Tobin <email@mattatobin.com>2022-05-02 14:07:05 -0500
commitb405e6878e4e303f7fbe51035e251f51a2eb5887 (patch)
tree2870557f837688b1eb31329e09d3bcaaa294a65d
parentb17c689b521e44fcf6cbc0ffaa5b635466c95671 (diff)
downloadaura-central-b405e6878e4e303f7fbe51035e251f51a2eb5887.tar.gz
Issue #28 - Support new RFC-6381 VPx codec strings
* Add an extraction function to parse the RFC-6381 VP9 codec string. * Add VP9-in-MP4 support to the decoder * Use Codec detail extractor helper to tell if it's a new style VP8/VP9 codec string. * Add a gtest for testing the extraction function. * Add mBitDepth field to VideoInfo. * Extract bit depth information from codec parameter string into VideoInfo::mBitDepth. * Check bit depth in WebMDecoder to determine if we support HDR. * Add an extraction function to parse the RFC-6381 VP9 codec string. Based on Bug 1407919
-rw-r--r--dom/media/MediaInfo.h4
-rw-r--r--dom/media/VideoUtils.cpp189
-rw-r--r--dom/media/VideoUtils.h28
-rw-r--r--dom/media/fmp4/MP4Decoder.cpp13
-rw-r--r--dom/media/mediasource/gtest/TestExtractVPXCodecDetails.cpp111
-rw-r--r--dom/media/mediasource/gtest/moz.build1
-rw-r--r--dom/media/platforms/PlatformDecoderModule.h17
-rw-r--r--dom/media/platforms/ffmpeg/FFmpegDecoderModule.h15
-rw-r--r--dom/media/platforms/wmf/WMFDecoderModule.cpp10
-rw-r--r--dom/media/webm/WebMDecoder.cpp30
-rw-r--r--libs/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp3
-rw-r--r--libs/libstagefright/frameworks/av/media/libstagefright/MediaDefs.cpp2
12 files changed, 410 insertions, 13 deletions
diff --git a/dom/media/MediaInfo.h b/dom/media/MediaInfo.h
index 29dcf2cc9..4d37dd674 100644
--- a/dom/media/MediaInfo.h
+++ b/dom/media/MediaInfo.h
@@ -210,6 +210,7 @@ public:
, mCodecSpecificConfig(aOther.mCodecSpecificConfig)
, mExtraData(aOther.mExtraData)
, mRotation(aOther.mRotation)
+ , mBitDepth(aOther.mBitDepth)
, mImageRect(aOther.mImageRect)
{
}
@@ -300,6 +301,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.
diff --git a/dom/media/VideoUtils.cpp b/dom/media/VideoUtils.cpp
index 56033c2fa..cc8d56146 100644
--- a/dom/media/VideoUtils.cpp
+++ b/dom/media/VideoUtils.cpp
@@ -223,12 +223,185 @@ already_AddRefed<SharedThreadPool> GetMediaThreadPool(MediaThreadType aType)
}
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<nsString> 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<uint8_t>(fieldsArr[fieldsItr].ToInteger(&rv));
+ // We got invalid field value, parsing error.
+ NS_ENSURE_SUCCESS(rv, false);
+ }
+ // Mandatory Fields
+ // <sample entry 4CC>.<profile>.<level>.<bitDepth>.
+ // Optional Fields
+ // <chromaSubsampling>.<colourPrimaries>.<transferCharacteristics>.
+ // <matrixCoefficients>.<videoFullRangeFlag>
+ // 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.
@@ -468,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
diff --git a/dom/media/VideoUtils.h b/dom/media/VideoUtils.h
index eee6561fd..421e6bb51 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
diff --git a/dom/media/fmp4/MP4Decoder.cpp b/dom/media/fmp4/MP4Decoder.cpp
index 8cddfc4f4..9b0886e74 100644
--- a/dom/media/fmp4/MP4Decoder.cpp
+++ b/dom/media/fmp4/MP4Decoder.cpp
@@ -131,6 +131,19 @@ MP4Decoder::CanHandleMediaType(const MediaContentType& aType,
NS_LITERAL_CSTRING("audio/flac"), aType));
continue;
}
+ if (IsVP9CodecString(codec)) {
+ 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
if (IsAV1CodecString(codec)) {
trackInfos.AppendElement(
diff --git a/dom/media/mediasource/gtest/TestExtractVPXCodecDetails.cpp b/dom/media/mediasource/gtest/TestExtractVPXCodecDetails.cpp
new file mode 100644
index 000000000..be8a120f6
--- /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 <gtest/gtest.h>
+#include <stdint.h>
+
+#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 2cccc80a2..2a59a8343 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 += [
diff --git a/dom/media/platforms/PlatformDecoderModule.h b/dom/media/platforms/PlatformDecoderModule.h
index 54feb13c7..1507b4492 100644
--- a/dom/media/platforms/PlatformDecoderModule.h
+++ b/dom/media/platforms/PlatformDecoderModule.h
@@ -125,9 +125,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 {
@@ -149,6 +151,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 969ac7e0b..d220fcf91 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 6268135ec..26c01aba5 100644
--- a/dom/media/platforms/wmf/WMFDecoderModule.cpp
+++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp
@@ -213,6 +213,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()) {
@@ -229,7 +237,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;
}
diff --git a/dom/media/webm/WebMDecoder.cpp b/dom/media/webm/WebMDecoder.cpp
index cbe9ffdb7..b4cc794e7 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,11 +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) &&
- (codec.EqualsLiteral("vp8") || codec.EqualsLiteral("vp8.0") ||
- codec.EqualsLiteral("vp9") || codec.EqualsLiteral("vp9.0"))) {
-
- continue;
+ if (isWebMVideo || isMatroskaVideo) {
+ UniquePtr<TrackInfo> 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<PDMFactory> platform = new PDMFactory();
+ if (!platform->Supports(*trackInfo, nullptr)) {
+ return false;
+ }
+ continue;
+ }
}
#ifdef MOZ_AV1
if (MediaPrefs::AV1Enabled() && IsAV1CodecString(codec)) {
diff --git a/libs/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp b/libs/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
index 786e80487..bbc067ab1 100644
--- a/libs/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp
+++ b/libs/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/libs/libstagefright/frameworks/av/media/libstagefright/MediaDefs.cpp b/libs/libstagefright/frameworks/av/media/libstagefright/MediaDefs.cpp
index a7c6e75fc..bc81dceb3 100644
--- a/libs/libstagefright/frameworks/av/media/libstagefright/MediaDefs.cpp
+++ b/libs/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";