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
7 #include "WebMDecoder.h"
8
9 #include <utility>
10
11 #include "mozilla/Preferences.h"
12 #include "mozilla/StaticPrefs_media.h"
13 #ifdef MOZ_AV1
14 # include "AOMDecoder.h"
15 #endif
16 #include "MediaContainerType.h"
17 #include "PDMFactory.h"
18 #include "PlatformDecoderModule.h"
19 #include "VideoUtils.h"
20
21 namespace mozilla {
22
23 /* static */
GetTracksInfo(const MediaContainerType & aType,MediaResult & aError)24 nsTArray<UniquePtr<TrackInfo>> WebMDecoder::GetTracksInfo(
25 const MediaContainerType& aType, MediaResult& aError) {
26 nsTArray<UniquePtr<TrackInfo>> tracks;
27 const bool isVideo = aType.Type() == MEDIAMIMETYPE("video/webm");
28
29 if (aType.Type() != MEDIAMIMETYPE("audio/webm") && !isVideo) {
30 aError = MediaResult(
31 NS_ERROR_DOM_MEDIA_FATAL_ERR,
32 RESULT_DETAIL("Invalid type:%s", aType.Type().AsString().get()));
33 return tracks;
34 }
35
36 aError = NS_OK;
37
38 const MediaCodecs& codecs = aType.ExtendedType().Codecs();
39 if (codecs.IsEmpty()) {
40 return tracks;
41 }
42
43 for (const auto& codec : codecs.Range()) {
44 if (codec.EqualsLiteral("opus") || codec.EqualsLiteral("vorbis")) {
45 tracks.AppendElement(
46 CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
47 "audio/"_ns + NS_ConvertUTF16toUTF8(codec), aType));
48 continue;
49 }
50 if (isVideo) {
51 UniquePtr<TrackInfo> trackInfo;
52 if (IsVP9CodecString(codec)) {
53 trackInfo = CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
54 "video/vp9"_ns, aType);
55 } else if (IsVP8CodecString(codec)) {
56 trackInfo = CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
57 "video/vp8"_ns, aType);
58 }
59 if (trackInfo) {
60 uint8_t profile = 0;
61 uint8_t level = 0;
62 uint8_t bitDepth = 0;
63 if (ExtractVPXCodecDetails(codec, profile, level, bitDepth)) {
64 trackInfo->GetAsVideoInfo()->mColorDepth =
65 gfx::ColorDepthForBitDepth(bitDepth);
66 }
67 tracks.AppendElement(std::move(trackInfo));
68 continue;
69 }
70 }
71 #ifdef MOZ_AV1
72 if (StaticPrefs::media_av1_enabled() && IsAV1CodecString(codec)) {
73 tracks.AppendElement(
74 CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
75 "video/av1"_ns, aType));
76 continue;
77 }
78 #endif
79 // Unknown codec
80 aError = MediaResult(
81 NS_ERROR_DOM_MEDIA_FATAL_ERR,
82 RESULT_DETAIL("Unknown codec:%s", NS_ConvertUTF16toUTF8(codec).get()));
83 }
84 return tracks;
85 }
86
87 /* static */
IsSupportedType(const MediaContainerType & aContainerType)88 bool WebMDecoder::IsSupportedType(const MediaContainerType& aContainerType) {
89 if (!StaticPrefs::media_webm_enabled()) {
90 return false;
91 }
92
93 MediaResult rv = NS_OK;
94 auto tracks = GetTracksInfo(aContainerType, rv);
95
96 if (NS_FAILED(rv)) {
97 return false;
98 }
99
100 if (tracks.IsEmpty()) {
101 // WebM guarantees that the only codecs it contained are vp8, vp9, opus or
102 // vorbis.
103 return true;
104 }
105
106 // Verify that we have a PDM that supports the whitelisted types, include
107 // color depth
108 RefPtr<PDMFactory> platform = new PDMFactory();
109 for (const auto& track : tracks) {
110 if (!track || !platform->Supports(SupportDecoderParams(*track),
111 nullptr /* diagnostic */)) {
112 return false;
113 }
114 }
115
116 return true;
117 }
118
119 /* static */
GetTracksInfo(const MediaContainerType & aType)120 nsTArray<UniquePtr<TrackInfo>> WebMDecoder::GetTracksInfo(
121 const MediaContainerType& aType) {
122 MediaResult rv = NS_OK;
123 return GetTracksInfo(aType, rv);
124 }
125
126 } // namespace mozilla
127