Migrate read-only IsTypeSupported / IsSupported call sites to the new process-wide singleton: - container/codec predicates: ADTSDecoder, MP3Decoder, MP4Decoder, WebMDecoder, MatroskaDecoder. - MediaCapabilities audio precheck and WebRTC MediaDataCodec capability check. - MediaFormatReader::OnDemuxerInitDone and MediaBufferDecoder mime-type precheck. Differential Revision: https://phabricator.services.mozilla.com/D299303
190 lines
6.4 KiB
C++
190 lines
6.4 KiB
C++
/* 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 "MatroskaDecoder.h"
|
|
|
|
#include "AOMDecoder.h"
|
|
#include "MediaContainerType.h"
|
|
#include "PDMFactorySupport.h"
|
|
#include "PlatformDecoderModule.h"
|
|
#include "VideoUtils.h"
|
|
#include "mozilla/StaticPrefs_media.h"
|
|
#include "nsMimeTypes.h"
|
|
|
|
namespace mozilla {
|
|
|
|
/* static */
|
|
bool MatroskaDecoder::IsMatroskaType(const MediaContainerType& aType) {
|
|
const auto& mimeType = aType.Type();
|
|
return mimeType == MEDIAMIMETYPE(VIDEO_MATROSKA) ||
|
|
mimeType == MEDIAMIMETYPE(VIDEO_MATROSKA_LEGACY) ||
|
|
mimeType == MEDIAMIMETYPE(AUDIO_MATROSKA) ||
|
|
mimeType == MEDIAMIMETYPE(AUDIO_MATROSKA_LEGACY);
|
|
}
|
|
|
|
/* static */
|
|
nsTArray<UniquePtr<TrackInfo>> MatroskaDecoder::GetTracksInfo(
|
|
const MediaContainerType& aType, MediaResult& aError) {
|
|
nsTArray<UniquePtr<TrackInfo>> tracks;
|
|
|
|
aError = NS_OK;
|
|
|
|
const MediaCodecs& codecs = aType.ExtendedType().Codecs();
|
|
if (codecs.IsEmpty()) {
|
|
return tracks;
|
|
}
|
|
|
|
// TODO : add more codec support.
|
|
for (const auto& codec : codecs.Range()) {
|
|
// Audio codecs
|
|
if (IsAACCodecString(codec)) {
|
|
tracks.AppendElement(
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"audio/mp4a-latm"_ns, aType));
|
|
continue;
|
|
}
|
|
if (codec.EqualsLiteral("opus")) {
|
|
tracks.AppendElement(
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"audio/opus"_ns, aType));
|
|
continue;
|
|
}
|
|
if (codec.EqualsLiteral("vorbis")) {
|
|
tracks.AppendElement(
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"audio/vorbis"_ns, aType));
|
|
continue;
|
|
}
|
|
// Video codecs
|
|
if (IsAllowedH264Codec(codec)) {
|
|
auto trackInfo =
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"video/avc"_ns, aType);
|
|
uint8_t profile = 0, constraint = 0;
|
|
H264_LEVEL level;
|
|
MOZ_ALWAYS_TRUE(
|
|
ExtractH264CodecDetails(codec, profile, constraint, level,
|
|
H264CodecStringStrictness::Lenient));
|
|
uint32_t width = aType.ExtendedType().GetWidth().refOr(1280);
|
|
uint32_t height = aType.ExtendedType().GetHeight().refOr(720);
|
|
trackInfo->GetAsVideoInfo()->mExtraData =
|
|
H264::CreateExtraData(profile, constraint, level, {width, height});
|
|
tracks.AppendElement(std::move(trackInfo));
|
|
continue;
|
|
}
|
|
if (StaticPrefs::media_hevc_enabled() && IsH265CodecString(codec)) {
|
|
auto trackInfo =
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"video/hevc"_ns, aType);
|
|
tracks.AppendElement(std::move(trackInfo));
|
|
continue;
|
|
}
|
|
if (IsVP9CodecString(codec)) {
|
|
auto trackInfo =
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"video/vp9"_ns, aType);
|
|
tracks.AppendElement(std::move(trackInfo));
|
|
continue;
|
|
}
|
|
if (IsVP8CodecString(codec)) {
|
|
auto trackInfo =
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"video/vp8"_ns, aType);
|
|
tracks.AppendElement(std::move(trackInfo));
|
|
continue;
|
|
}
|
|
if (StaticPrefs::media_av1_enabled() && IsAV1CodecString(codec)) {
|
|
auto trackInfo =
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"video/av1"_ns, aType);
|
|
AOMDecoder::SetVideoInfo(trackInfo->GetAsVideoInfo(), codec);
|
|
tracks.AppendElement(std::move(trackInfo));
|
|
continue;
|
|
}
|
|
aError = MediaResult(
|
|
NS_ERROR_DOM_MEDIA_FATAL_ERR,
|
|
RESULT_DETAIL("Unknown codec:%s", NS_ConvertUTF16toUTF8(codec).get()));
|
|
}
|
|
return tracks;
|
|
}
|
|
|
|
/* static */
|
|
bool MatroskaDecoder::IsSupportedType(const MediaContainerType& aContainerType,
|
|
DecoderDoctorDiagnostics* aDiagnostics) {
|
|
if (!StaticPrefs::media_mkv_enabled() || !IsMatroskaType(aContainerType)) {
|
|
return false;
|
|
}
|
|
|
|
MediaResult rv = NS_OK;
|
|
auto tracks = GetTracksInfo(aContainerType, rv);
|
|
if (NS_FAILED(rv)) {
|
|
return false;
|
|
}
|
|
|
|
if (!tracks.IsEmpty()) {
|
|
// Look for exact match as we know the codecs used.
|
|
for (const auto& track : tracks) {
|
|
if (!track || PDMFactorySupport::IsSupported(SupportDecoderParams(*track),
|
|
aDiagnostics)
|
|
.isEmpty()) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// The container doesn't specify codecs, so we guess the content type.
|
|
// TODO : add more codec support.
|
|
if (aContainerType.Type() == MEDIAMIMETYPE(AUDIO_MATROSKA)) {
|
|
tracks.AppendElement(
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"audio/mp4a-latm"_ns, aContainerType));
|
|
tracks.AppendElement(
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"audio/opus"_ns, aContainerType));
|
|
tracks.AppendElement(
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"audio/vorbis"_ns, aContainerType));
|
|
} else {
|
|
tracks.AppendElement(
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"video/avc"_ns, aContainerType));
|
|
if (StaticPrefs::media_hevc_enabled()) {
|
|
tracks.AppendElement(
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"video/hevc"_ns, aContainerType));
|
|
}
|
|
tracks.AppendElement(
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"video/vp8"_ns, aContainerType));
|
|
tracks.AppendElement(
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"video/vp9"_ns, aContainerType));
|
|
if (StaticPrefs::media_av1_enabled()) {
|
|
tracks.AppendElement(
|
|
CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
|
|
"video/av1"_ns, aContainerType));
|
|
}
|
|
}
|
|
|
|
// Check that something is supported at least.
|
|
for (const auto& track : tracks) {
|
|
if (track && !PDMFactorySupport::IsSupported(SupportDecoderParams(*track),
|
|
aDiagnostics)
|
|
.isEmpty()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* static */
|
|
nsTArray<UniquePtr<TrackInfo>> MatroskaDecoder::GetTracksInfo(
|
|
const MediaContainerType& aType) {
|
|
MediaResult rv = NS_OK;
|
|
return GetTracksInfo(aType, rv);
|
|
}
|
|
|
|
} // namespace mozilla
|