Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/media/platforms/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 12 kB image not shown  

Quelle  MediaCodecsSupport.cpp

  Sprache: 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 "MediaCodecsSupport.h"

#include <array>

#include "AOMDecoder.h"
#include "MP4Decoder.h"
#include "PDMFactory.h"
#include "PEMFactory.h"
#include "PlatformDecoderModule.h"
#include "VPXDecoder.h"
#include "VideoUtils.h"
#include "mozilla/AppShutdown.h"
#include "mozilla/gfx/gfxVars.h"
#include "nsTHashMap.h"

using MediaCodecsSupport = mozilla::media::MediaCodecsSupport;

namespace mozilla::media {

static StaticAutoPtr<MCSInfo> sInstance;
static StaticMutex sMutex;

#define CODEC_SUPPORT_LOG(msg, ...)                                 \
  MOZ_LOG_FMT(sPDMLog, LogLevel::Debug, "MediaCodecsSupport, " msg, \
              ##__VA_ARGS__)

/* static */
MediaCodecsSupported MCSInfo::GetSupportFromFactory(
    bool aForceRefresh /* = false */) {
  return PDMFactory::Supported(aForceRefresh) +
         PEMFactory::Supported(aForceRefresh);
}

void MCSInfo::AddSupport(const MediaCodecsSupported& aSupport) {
  StaticMutexAutoLock lock(sMutex);
  MCSInfo* instance = GetInstance(lock);
  if (!instance) {
    CODEC_SUPPORT_LOG("Can't add codec support without a MCSInfo instance!");
    return;
  }
  instance->mSupport += aSupport;
}

MediaCodecsSupported MCSInfo::GetSupport() {
  StaticMutexAutoLock lock(sMutex);
  MCSInfo* instance = GetInstance(lock);
  if (!instance) {
    CODEC_SUPPORT_LOG("Can't get codec support without a MCSInfo instance!");
    return MediaCodecsSupported{};
  }
  return instance->mSupport;
}

void MCSInfo::ResetSupport() {
  StaticMutexAutoLock lock(sMutex);
  MCSInfo* instance = GetInstance(lock);
  if (!instance) {
    CODEC_SUPPORT_LOG("Can't reset codec support without a MCSInfo instance!");
    return;
  }
  instance->mSupport.clear();
}

DecodeSupportSet MCSInfo::GetDecodeSupportSet(
    const MediaCodec& aCodec, const MediaCodecsSupported& aSupported) {
  DecodeSupportSet support;
  const auto supportInfo = GetCodecDefinition(aCodec);
  if (aSupported.contains(supportInfo.swDecodeSupport)) {
    support += DecodeSupport::SoftwareDecode;
  }
  if (aSupported.contains(supportInfo.hwDecodeSupport)) {
    support += DecodeSupport::HardwareDecode;
  }
  return support;
}

EncodeSupportSet MCSInfo::GetEncodeSupportSet(
    const MediaCodec& aCodec, const MediaCodecsSupported& aSupported) {
  EncodeSupportSet support;
  const auto supportInfo = GetCodecDefinition(aCodec);
  if (aSupported.contains(supportInfo.swEncodeSupport)) {
    support += EncodeSupport::SoftwareEncode;
  }
  if (aSupported.contains(supportInfo.hwEncodeSupport)) {
    support += EncodeSupport::HardwareEncode;
  }
  return support;
}

MediaCodecsSupported MCSInfo::GetDecodeMediaCodecsSupported(
    const MediaCodec& aCodec, const DecodeSupportSet& aSupportSet) {
  MediaCodecsSupported support;
  const auto supportInfo = GetCodecDefinition(aCodec);
  if (aSupportSet.contains(DecodeSupport::SoftwareDecode)) {
    support += supportInfo.swDecodeSupport;
  }
  if (aSupportSet.contains(DecodeSupport::HardwareDecode)) {
    support += supportInfo.hwDecodeSupport;
  }
  if (aSupportSet.contains(DecodeSupport::UnsureDueToLackOfExtension)) {
    // Every codec reaching this arm must declare a real lack-of-extension
    // entry in GetAllCodecDefinitions.
    MOZ_ASSERT(supportInfo.lackOfHWExtenstion != MediaCodecsSupport::SENTINEL);
    support += supportInfo.lackOfHWExtenstion;
  }
  return support;
}

MediaCodecsSupported MCSInfo::GetEncodeMediaCodecsSupported(
    const MediaCodec& aCodec, const EncodeSupportSet& aSupportSet) {
  MediaCodecsSupported support;
  const auto supportInfo = GetCodecDefinition(aCodec);
  if (aSupportSet.contains(EncodeSupport::SoftwareEncode)) {
    support += supportInfo.swEncodeSupport;
  }
  if (aSupportSet.contains(EncodeSupport::HardwareEncode)) {
    support += supportInfo.hwEncodeSupport;
  }
  if (aSupportSet.contains(EncodeSupport::UnsureDueToLackOfExtension)) {
    // Every codec reaching this arm must declare a real lack-of-extension
    // entry in GetAllCodecDefinitions.
    MOZ_ASSERT(supportInfo.lackOfHWExtenstion != MediaCodecsSupport::SENTINEL);
    support += supportInfo.lackOfHWExtenstion;
  }
  return support;
}

bool MCSInfo::SupportsSoftwareDecode(
    const MediaCodecsSupported& aSupportedCodecs, const MediaCodec& aCodec) {
  return (
      aSupportedCodecs.contains(GetCodecDefinition(aCodec).swDecodeSupport));
}

bool MCSInfo::SupportsHardwareDecode(
    const MediaCodecsSupported& aSupportedCodecs, const MediaCodec& aCodec) {
  return (
      aSupportedCodecs.contains(GetCodecDefinition(aCodec).hwDecodeSupport));
}

bool MCSInfo::SupportsSoftwareEncode(
    const MediaCodecsSupported& aSupportedCodecs, const MediaCodec& aCodec) {
  return (
      aSupportedCodecs.contains(GetCodecDefinition(aCodec).swEncodeSupport));
}

bool MCSInfo::SupportsHardwareEncode(
    const MediaCodecsSupported& aSupportedCodecs, const MediaCodec& aCodec) {
  return (
      aSupportedCodecs.contains(GetCodecDefinition(aCodec).hwEncodeSupport));
}

void MCSInfo::GetMediaCodecsSupportedString(
    nsCString& aSupportString, const MediaCodecsSupported& aSupportedCodecs) {
  CodecDefinition supportInfo;
  aSupportString = ""_ns;
  StaticMutexAutoLock lock(sMutex);
  MCSInfo* instance = GetInstance(lock);
  if (!instance) {
    CODEC_SUPPORT_LOG("Can't get codec support string w/o a MCSInfo instance!");
    return;
  }
  for (const auto& it : GetAllCodecDefinitions()) {
    if (it.codec == MediaCodec::SENTINEL) {
      break;
    }
    if (!instance->mHashTableCodec->Get(it.codec, &supportInfo)) {
      CODEC_SUPPORT_LOG("Can't find codec for MediaCodecsSupported enum: {}",
                        static_cast<int>(it.codec));
      continue;
    }
    aSupportString.Append(supportInfo.commonName);
    bool foundSupport = false;
    if (aSupportedCodecs.contains(it.swDecodeSupport)) {
      aSupportString.Append(" SWDEC"_ns);
      foundSupport = true;
    }
    if (aSupportedCodecs.contains(it.hwDecodeSupport)) {
      aSupportString.Append(" HWDEC"_ns);
      foundSupport = true;
    }
    if (aSupportedCodecs.contains(it.swEncodeSupport)) {
      aSupportString.Append(" SWENC"_ns);
      foundSupport = true;
    }
    if (aSupportedCodecs.contains(it.hwEncodeSupport)) {
      aSupportString.Append(" HWENC"_ns);
      foundSupport = true;
    }
    if (aSupportedCodecs.contains(it.lackOfHWExtenstion)) {
      aSupportString.Append(" LACK_OF_EXTENSION"_ns);
      foundSupport = true;
    }
    if (!foundSupport) {
      aSupportString.Append(" NONE"_ns);
    }
    aSupportString.Append("\n"_ns);
  }
  // Remove any trailing newline characters
  if (!aSupportString.IsEmpty()) {
    aSupportString.Truncate(aSupportString.Length() - 1);
  }
}

MCSInfo* MCSInfo::GetInstance(const StaticMutexAutoLock& /* unused */) {
  if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
    CODEC_SUPPORT_LOG("In XPCOM shutdown - not returning MCSInfo instance!");
    return nullptr;
  }
  if (!sInstance) {
    sInstance = new MCSInfo();
  }
  return sInstance.get();
}

MCSInfo::MCSInfo() {
  // Initialize hash tables
  mHashTableMCS.reset(new nsTHashMap<MediaCodecsSupport, CodecDefinition>());
  mHashTableCodec.reset(new nsTHashMap<MediaCodec, CodecDefinition>());

  for (const auto& it : GetAllCodecDefinitions()) {
    // Insert MediaCodecsSupport values as keys
    mHashTableMCS->InsertOrUpdate(it.swDecodeSupport, it);
    mHashTableMCS->InsertOrUpdate(it.hwDecodeSupport, it);
    // Insert codec enum values as keys
    mHashTableCodec->InsertOrUpdate(it.codec, it);
  }

  GetMainThreadSerialEventTarget()->Dispatch(
      NS_NewRunnableFunction("MCSInfo::MCSInfo", [] {
        RunOnShutdown(
            [] {
              StaticMutexAutoLock lock(sMutex);
              sInstance = nullptr;
            },
            ShutdownPhase::XPCOMShutdown);
      }));
}

CodecDefinition MCSInfo::GetCodecDefinition(const MediaCodec& aCodec) {
  CodecDefinition info;
  StaticMutexAutoLock lock(sMutex);
  MCSInfo* instance = GetInstance(lock);
  if (!instance) {
    CODEC_SUPPORT_LOG("Can't get codec definition without a MCSInfo instance!");
  } else if (!instance->mHashTableCodec->Get(aCodec, &info)) {
    CODEC_SUPPORT_LOG("Could not find codec definition for codec enum: {}!",
                      static_cast<int>(aCodec));
  }
  return info;
}

MediaCodecsSupport MCSInfo::GetMediaCodecsSupportEnum(
    const MediaCodec& aCodec, const DecodeSupport& aSupport) {
  const CodecDefinition cd = GetCodecDefinition(aCodec);
  if (aSupport == DecodeSupport::SoftwareDecode) {
    return cd.swDecodeSupport;
  }
  if (aSupport == DecodeSupport::HardwareDecode) {
    return cd.hwDecodeSupport;
  }
  return MediaCodecsSupport::SENTINEL;
}

MediaCodecsSupport MCSInfo::GetMediaCodecsSupportEnum(
    const MediaCodec& aCodec, const EncodeSupport& aSupport) {
  const CodecDefinition cd = GetCodecDefinition(aCodec);
  if (aSupport == EncodeSupport::SoftwareEncode) {
    return cd.swEncodeSupport;
  }
  if (aSupport == EncodeSupport::HardwareEncode) {
    return cd.hwEncodeSupport;
  }
  return MediaCodecsSupport::SENTINEL;
}

MediaCodecSet MCSInfo::GetMediaCodecSetFromMimeTypes(
    const nsTArray<nsCString>& aCodecStrings) {
  MediaCodecSet support;
  for (const auto& ms : aCodecStrings) {
    const MediaCodec codec = MCSInfo::GetMediaCodecFromMimeType(ms);
    if (codec == MediaCodec::SENTINEL) {
      continue;
    }
    MOZ_ASSERT(codec < MediaCodec::SENTINEL);
    support += codec;
  }
  return support;
}

MediaCodec MCSInfo::GetMediaCodecFromMimeType(const nsACString& aMimeType) {
  // Video codecs
  if (MP4Decoder::IsH264(aMimeType)) {
    return MediaCodec::H264;
  }
  if (VPXDecoder::IsVP8(aMimeType)) {
    return MediaCodec::VP8;
  }
  if (VPXDecoder::IsVP9(aMimeType)) {
    return MediaCodec::VP9;
  }
  if (MP4Decoder::IsHEVC(aMimeType)) {
    return MediaCodec::HEVC;
  }
  if (AOMDecoder::IsAV1(aMimeType)) {
    return MediaCodec::AV1;
  }
  if (aMimeType.EqualsLiteral("video/av01")) {
    return MediaCodec::AV1;
  }
  // TODO: Should this be Android only?
#ifdef ANDROID
  if (aMimeType.EqualsLiteral("video/x-vnd.on2.vp8")) {
    return MediaCodec::VP8;
  }
  if (aMimeType.EqualsLiteral("video/x-vnd.on2.vp9")) {
    return MediaCodec::VP9;
  }
#endif
  // Audio codecs
  if (MP4Decoder::IsAAC(aMimeType)) {
    return MediaCodec::AAC;
  }
  if (aMimeType.EqualsLiteral("audio/vorbis")) {
    return MediaCodec::Vorbis;
  }
  if (aMimeType.EqualsLiteral("audio/flac")) {
    return MediaCodec::FLAC;
  }
  if (IsWaveMimetype(aMimeType)) {
    return MediaCodec::Wave;
  }
  if (aMimeType.EqualsLiteral("audio/opus")) {
    return MediaCodec::Opus;
  }
  if (aMimeType.EqualsLiteral("audio/mpeg")) {
    return MediaCodec::MP3;
  }

  CODEC_SUPPORT_LOG("No specific codec enum for MIME type string: {}",
                    nsCString(aMimeType).get());
  return MediaCodec::SENTINEL;
}

#define MEDIA_CODEC_DEF_ENTRY_META(name, mimeType, lackOfExt) \
  {MediaCodec::name,                                          \
   #name,                                                     \
   mimeType,                                                  \
   MediaCodecsSupport::name##SoftwareDecode,                  \
   MediaCodecsSupport::name##HardwareDecode,                  \
   MediaCodecsSupport::name##SoftwareEncode,                  \
   MediaCodecsSupport::name##HardwareEncode,                  \
   MediaCodecsSupport::lackOfExt}

#define MEDIA_CODEC_DEF_ENTRY(name, mimeType) \
  MEDIA_CODEC_DEF_ENTRY_META(name, mimeType, SENTINEL)

#define MEDIA_CODEC_DEF_ENTRY_LACKOFEXT(name, mimeType) \
  MEDIA_CODEC_DEF_ENTRY_META(name, mimeType, name##LackOfExtension)

std::array<CodecDefinition, 13> MCSInfo::GetAllCodecDefinitions() {
  static constexpr std::array<CodecDefinition, 13> codecDefinitions = {
      {MEDIA_CODEC_DEF_ENTRY(H264, "video/avc"),
       MEDIA_CODEC_DEF_ENTRY(VP9, "video/vp9"),
       MEDIA_CODEC_DEF_ENTRY(VP8, "video/vp8"),
       MEDIA_CODEC_DEF_ENTRY_LACKOFEXT(AV1, "video/av1"),
       MEDIA_CODEC_DEF_ENTRY_LACKOFEXT(HEVC, "video/hevc"),
       MEDIA_CODEC_DEF_ENTRY(AAC, "audio/mp4a-latm"),
       MEDIA_CODEC_DEF_ENTRY(MP3, "audio/mpeg"),
       MEDIA_CODEC_DEF_ENTRY(Opus, "audio/opus"),
       MEDIA_CODEC_DEF_ENTRY(Vorbis, "audio/vorbis"),
       MEDIA_CODEC_DEF_ENTRY(FLAC, "audio/flac"),
       MEDIA_CODEC_DEF_ENTRY(Wave, "audio/x-wav")}};
  return codecDefinitions;
}

#undef MEDIA_CODEC_DEF_ENTRY_LACKOFEXT
#undef MEDIA_CODEC_DEF_ENTRY
#undef MEDIA_CODEC_DEF_ENTRY_META

}  // namespace mozilla::media

#undef CODEC_SUPPORT_LOG

Messung V0.5 in Prozent
C=90 H=97 G=93

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.