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