tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MatroskaDecoder.cpp (6721B)


      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 "MatroskaDecoder.h"
      8 
      9 #ifdef MOZ_AV1
     10 #  include "AOMDecoder.h"
     11 #endif
     12 #include "MediaContainerType.h"
     13 #include "PDMFactory.h"
     14 #include "PlatformDecoderModule.h"
     15 #include "VideoUtils.h"
     16 #include "mozilla/StaticPrefs_media.h"
     17 #include "nsMimeTypes.h"
     18 
     19 namespace mozilla {
     20 
     21 /* static */
     22 bool MatroskaDecoder::IsMatroskaType(const MediaContainerType& aType) {
     23  const auto& mimeType = aType.Type();
     24  return mimeType == MEDIAMIMETYPE(VIDEO_MATROSKA) ||
     25         mimeType == MEDIAMIMETYPE(VIDEO_MATROSKA_LEGACY) ||
     26         mimeType == MEDIAMIMETYPE(AUDIO_MATROSKA) ||
     27         mimeType == MEDIAMIMETYPE(AUDIO_MATROSKA_LEGACY);
     28 }
     29 
     30 /* static */
     31 nsTArray<UniquePtr<TrackInfo>> MatroskaDecoder::GetTracksInfo(
     32    const MediaContainerType& aType, MediaResult& aError) {
     33  nsTArray<UniquePtr<TrackInfo>> tracks;
     34 
     35  aError = NS_OK;
     36 
     37  const MediaCodecs& codecs = aType.ExtendedType().Codecs();
     38  if (codecs.IsEmpty()) {
     39    return tracks;
     40  }
     41 
     42  // TODO : add more codec support.
     43  for (const auto& codec : codecs.Range()) {
     44    // Audio codecs
     45    if (IsAACCodecString(codec)) {
     46      tracks.AppendElement(
     47          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
     48              "audio/mp4a-latm"_ns, aType));
     49      continue;
     50    }
     51    if (codec.EqualsLiteral("opus")) {
     52      tracks.AppendElement(
     53          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
     54              "audio/opus"_ns, aType));
     55      continue;
     56    }
     57    if (codec.EqualsLiteral("vorbis")) {
     58      tracks.AppendElement(
     59          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
     60              "audio/vorbis"_ns, aType));
     61      continue;
     62    }
     63    // Video codecs
     64    if (IsAllowedH264Codec(codec)) {
     65      auto trackInfo =
     66          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
     67              "video/avc"_ns, aType);
     68      uint8_t profile = 0, constraint = 0;
     69      H264_LEVEL level;
     70      MOZ_ALWAYS_TRUE(
     71          ExtractH264CodecDetails(codec, profile, constraint, level,
     72                                  H264CodecStringStrictness::Lenient));
     73      uint32_t width = aType.ExtendedType().GetWidth().refOr(1280);
     74      uint32_t height = aType.ExtendedType().GetHeight().refOr(720);
     75      trackInfo->GetAsVideoInfo()->mExtraData =
     76          H264::CreateExtraData(profile, constraint, level, {width, height});
     77      tracks.AppendElement(std::move(trackInfo));
     78      continue;
     79    }
     80    if (StaticPrefs::media_hevc_enabled() && IsH265CodecString(codec)) {
     81      auto trackInfo =
     82          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
     83              "video/hevc"_ns, aType);
     84      tracks.AppendElement(std::move(trackInfo));
     85      continue;
     86    }
     87    if (IsVP9CodecString(codec)) {
     88      auto trackInfo =
     89          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
     90              "video/vp9"_ns, aType);
     91      tracks.AppendElement(std::move(trackInfo));
     92      continue;
     93    }
     94    if (IsVP8CodecString(codec)) {
     95      auto trackInfo =
     96          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
     97              "video/vp8"_ns, aType);
     98      tracks.AppendElement(std::move(trackInfo));
     99      continue;
    100    }
    101 #ifdef MOZ_AV1
    102    if (StaticPrefs::media_av1_enabled() && IsAV1CodecString(codec)) {
    103      auto trackInfo =
    104          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
    105              "video/av1"_ns, aType);
    106      AOMDecoder::SetVideoInfo(trackInfo->GetAsVideoInfo(), codec);
    107      tracks.AppendElement(std::move(trackInfo));
    108      continue;
    109    }
    110 #endif
    111    aError = MediaResult(
    112        NS_ERROR_DOM_MEDIA_FATAL_ERR,
    113        RESULT_DETAIL("Unknown codec:%s", NS_ConvertUTF16toUTF8(codec).get()));
    114  }
    115  return tracks;
    116 }
    117 
    118 /* static */
    119 bool MatroskaDecoder::IsSupportedType(const MediaContainerType& aContainerType,
    120                                      DecoderDoctorDiagnostics* aDiagnostics) {
    121  if (!StaticPrefs::media_mkv_enabled() || !IsMatroskaType(aContainerType)) {
    122    return false;
    123  }
    124 
    125  MediaResult rv = NS_OK;
    126  auto tracks = GetTracksInfo(aContainerType, rv);
    127  if (NS_FAILED(rv)) {
    128    return false;
    129  }
    130 
    131  if (!tracks.IsEmpty()) {
    132    // Look for exact match as we know the codecs used.
    133    RefPtr<PDMFactory> platform = new PDMFactory();
    134    for (const auto& track : tracks) {
    135      if (!track ||
    136          platform->Supports(SupportDecoderParams(*track), aDiagnostics)
    137              .isEmpty()) {
    138        return false;
    139      }
    140    }
    141    return true;
    142  }
    143 
    144  // The container doesn't specify codecs, so we guess the content type.
    145  // TODO : add more codec support.
    146  if (aContainerType.Type() == MEDIAMIMETYPE(AUDIO_MATROSKA)) {
    147    tracks.AppendElement(
    148        CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
    149            "audio/mp4a-latm"_ns, aContainerType));
    150    tracks.AppendElement(
    151        CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
    152            "audio/opus"_ns, aContainerType));
    153    tracks.AppendElement(
    154        CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
    155            "audio/vorbis"_ns, aContainerType));
    156  } else {
    157    tracks.AppendElement(
    158        CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
    159            "video/avc"_ns, aContainerType));
    160    if (StaticPrefs::media_hevc_enabled()) {
    161      tracks.AppendElement(
    162          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
    163              "video/hevc"_ns, aContainerType));
    164    }
    165    tracks.AppendElement(
    166        CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
    167            "video/vp8"_ns, aContainerType));
    168    tracks.AppendElement(
    169        CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
    170            "video/vp9"_ns, aContainerType));
    171 #ifdef MOZ_AV1
    172    if (StaticPrefs::media_av1_enabled()) {
    173      tracks.AppendElement(
    174          CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
    175              "video/av1"_ns, aContainerType));
    176    }
    177 #endif
    178  }
    179 
    180  // Check that something is supported at least.
    181  RefPtr<PDMFactory> platform = new PDMFactory();
    182  for (const auto& track : tracks) {
    183    if (track && !platform->Supports(SupportDecoderParams(*track), aDiagnostics)
    184                      .isEmpty()) {
    185      return true;
    186    }
    187  }
    188  return false;
    189 }
    190 
    191 /* static */
    192 nsTArray<UniquePtr<TrackInfo>> MatroskaDecoder::GetTracksInfo(
    193    const MediaContainerType& aType) {
    194  MediaResult rv = NS_OK;
    195  return GetTracksInfo(aType, rv);
    196 }
    197 
    198 }  // namespace mozilla