LCOV - code coverage report
Current view: top level - dom/media - DecoderTraits.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 143 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "ChannelMediaDecoder.h"
       8             : #include "DecoderTraits.h"
       9             : #include "MediaContainerType.h"
      10             : #include "nsMimeTypes.h"
      11             : #include "mozilla/Preferences.h"
      12             : #include "mozilla/Telemetry.h"
      13             : 
      14             : #include "OggDecoder.h"
      15             : #include "OggDemuxer.h"
      16             : 
      17             : #include "WebMDecoder.h"
      18             : #include "WebMDemuxer.h"
      19             : 
      20             : #ifdef MOZ_ANDROID_OMX
      21             : #include "AndroidMediaDecoder.h"
      22             : #include "AndroidMediaReader.h"
      23             : #include "AndroidMediaPluginHost.h"
      24             : #endif
      25             : #ifdef MOZ_ANDROID_HLS_SUPPORT
      26             : #include "HLSDecoder.h"
      27             : #endif
      28             : #ifdef MOZ_FMP4
      29             : #include "MP4Decoder.h"
      30             : #include "MP4Demuxer.h"
      31             : #endif
      32             : #include "MediaFormatReader.h"
      33             : 
      34             : #include "MP3Decoder.h"
      35             : #include "MP3Demuxer.h"
      36             : 
      37             : #include "WaveDecoder.h"
      38             : #include "WaveDemuxer.h"
      39             : 
      40             : #include "ADTSDecoder.h"
      41             : #include "ADTSDemuxer.h"
      42             : 
      43             : #include "FlacDecoder.h"
      44             : #include "FlacDemuxer.h"
      45             : 
      46             : #include "nsPluginHost.h"
      47             : #include "MediaPrefs.h"
      48             : 
      49             : namespace mozilla
      50             : {
      51             : #ifdef MOZ_ANDROID_OMX
      52             : static bool
      53             : IsAndroidMediaType(const MediaContainerType& aType)
      54             : {
      55             :   if (!MediaDecoder::IsAndroidMediaPluginEnabled()) {
      56             :     return false;
      57             :   }
      58             : 
      59             :   return aType.Type() == MEDIAMIMETYPE("audio/mpeg")
      60             :          || aType.Type() == MEDIAMIMETYPE("audio/mp4")
      61             :          || aType.Type() == MEDIAMIMETYPE("video/mp4")
      62             :          || aType.Type() == MEDIAMIMETYPE("video/x-m4v");
      63             : }
      64             : #endif
      65             : 
      66             : 
      67             : /* static */ bool
      68           0 : DecoderTraits::IsHttpLiveStreamingType(const MediaContainerType& aType)
      69             : {
      70           0 :   const auto& mimeType = aType.Type();
      71             :   return // For m3u8.
      72             :          // https://tools.ietf.org/html/draft-pantos-http-live-streaming-19#section-10
      73           0 :          mimeType == MEDIAMIMETYPE("application/vnd.apple.mpegurl")
      74             :          // Some sites serve these as the informal m3u type.
      75           0 :          || mimeType == MEDIAMIMETYPE("application/x-mpegurl")
      76           0 :          || mimeType == MEDIAMIMETYPE("audio/mpegurl")
      77           0 :          || mimeType == MEDIAMIMETYPE("audio/x-mpegurl");
      78             : }
      79             : 
      80             : /* static */ bool
      81           0 : DecoderTraits::IsMP4SupportedType(const MediaContainerType& aType,
      82             :                                   DecoderDoctorDiagnostics* aDiagnostics)
      83             : {
      84             : #ifdef MOZ_FMP4
      85           0 :   return MP4Decoder::IsSupportedType(aType, aDiagnostics);
      86             : #else
      87             :   return false;
      88             : #endif
      89             : }
      90             : 
      91             : static
      92             : CanPlayStatus
      93           0 : CanHandleCodecsType(const MediaContainerType& aType,
      94             :                     DecoderDoctorDiagnostics* aDiagnostics)
      95             : {
      96             :   // We should have been given a codecs string, though it may be empty.
      97           0 :   MOZ_ASSERT(aType.ExtendedType().HaveCodecs());
      98             : 
      99             :   // Container type with the MIME type, no codecs.
     100           0 :   const MediaContainerType mimeType(aType.Type());
     101             : 
     102           0 :   if (OggDecoder::IsSupportedType(mimeType)) {
     103           0 :     if (OggDecoder::IsSupportedType(aType)) {
     104           0 :       return CANPLAY_YES;
     105             :     }
     106             :     // We can only reach this position if a particular codec was requested,
     107             :     // ogg is supported and working: the codec must be invalid.
     108           0 :     return CANPLAY_NO;
     109             :   }
     110           0 :   if (WaveDecoder::IsSupportedType(MediaContainerType(mimeType))) {
     111           0 :     if (WaveDecoder::IsSupportedType(aType)) {
     112           0 :       return CANPLAY_YES;
     113             :     }
     114             :     // We can only reach this position if a particular codec was requested,
     115             :     // ogg is supported and working: the codec must be invalid.
     116           0 :     return CANPLAY_NO;
     117             :   }
     118             : #if !defined(MOZ_OMX_WEBM_DECODER)
     119           0 :   if (WebMDecoder::IsSupportedType(mimeType)) {
     120           0 :     if (WebMDecoder::IsSupportedType(aType)) {
     121           0 :       return CANPLAY_YES;
     122             :     }
     123             :     // We can only reach this position if a particular codec was requested,
     124             :     // webm is supported and working: the codec must be invalid.
     125           0 :     return CANPLAY_NO;
     126             :   }
     127             : #endif
     128             : #ifdef MOZ_FMP4
     129           0 :   if (MP4Decoder::IsSupportedType(mimeType,
     130             :                                   /* DecoderDoctorDiagnostics* */ nullptr)) {
     131           0 :     if (MP4Decoder::IsSupportedType(aType, aDiagnostics)) {
     132           0 :       return CANPLAY_YES;
     133             :     }
     134             :     // We can only reach this position if a particular codec was requested,
     135             :     // fmp4 is supported and working: the codec must be invalid.
     136           0 :     return CANPLAY_NO;
     137             :   }
     138             : #endif
     139           0 :   if (MP3Decoder::IsSupportedType(aType)) {
     140           0 :     return CANPLAY_YES;
     141             :   }
     142           0 :   if (ADTSDecoder::IsSupportedType(aType)) {
     143           0 :     return CANPLAY_YES;
     144             :   }
     145           0 :   if (FlacDecoder::IsSupportedType(aType)) {
     146           0 :     return CANPLAY_YES;
     147             :   }
     148             : 
     149           0 :   MediaCodecs supportedCodecs;
     150             : #ifdef MOZ_ANDROID_OMX
     151             :   if (MediaDecoder::IsAndroidMediaPluginEnabled()) {
     152             :     EnsureAndroidMediaPluginHost()->FindDecoder(aType, &supportedCodecs);
     153             :   }
     154             : #endif
     155           0 :   if (supportedCodecs.IsEmpty()) {
     156           0 :     return CANPLAY_MAYBE;
     157             :   }
     158             : 
     159           0 :   if (!supportedCodecs.ContainsAll(aType.ExtendedType().Codecs())) {
     160             :     // At least one requested codec is not supported.
     161           0 :     return CANPLAY_NO;
     162             :   }
     163           0 :   return CANPLAY_YES;
     164             : }
     165             : 
     166             : static
     167             : CanPlayStatus
     168           0 : CanHandleMediaType(const MediaContainerType& aType,
     169             :                    DecoderDoctorDiagnostics* aDiagnostics)
     170             : {
     171           0 :   MOZ_ASSERT(NS_IsMainThread());
     172             : 
     173             : #ifdef MOZ_ANDROID_HLS_SUPPORT
     174             :   if (HLSDecoder::IsSupportedType(aType)) {
     175             :     return CANPLAY_MAYBE;
     176             :   }
     177             : #endif
     178             : 
     179           0 :   if (DecoderTraits::IsHttpLiveStreamingType(aType)) {
     180           0 :     Telemetry::Accumulate(Telemetry::MEDIA_HLS_CANPLAY_REQUESTED, true);
     181             :   }
     182             : 
     183           0 :   if (aType.ExtendedType().HaveCodecs()) {
     184           0 :     CanPlayStatus result = CanHandleCodecsType(aType, aDiagnostics);
     185           0 :     if (result == CANPLAY_NO || result == CANPLAY_YES) {
     186           0 :       return result;
     187             :     }
     188             :   }
     189             : 
     190             :   // Container type with just the MIME type/subtype, no codecs.
     191           0 :   const MediaContainerType mimeType(aType.Type());
     192             : 
     193           0 :   if (OggDecoder::IsSupportedType(mimeType)) {
     194           0 :     return CANPLAY_MAYBE;
     195             :   }
     196           0 :   if (WaveDecoder::IsSupportedType(mimeType)) {
     197           0 :     return CANPLAY_MAYBE;
     198             :   }
     199             : #ifdef MOZ_FMP4
     200           0 :   if (MP4Decoder::IsSupportedType(mimeType, aDiagnostics)) {
     201           0 :     return CANPLAY_MAYBE;
     202             :   }
     203             : #endif
     204             : #if !defined(MOZ_OMX_WEBM_DECODER)
     205           0 :   if (WebMDecoder::IsSupportedType(mimeType)) {
     206           0 :     return CANPLAY_MAYBE;
     207             :   }
     208             : #endif
     209           0 :   if (MP3Decoder::IsSupportedType(mimeType)) {
     210           0 :     return CANPLAY_MAYBE;
     211             :   }
     212           0 :   if (ADTSDecoder::IsSupportedType(mimeType)) {
     213           0 :     return CANPLAY_MAYBE;
     214             :   }
     215           0 :   if (FlacDecoder::IsSupportedType(mimeType)) {
     216           0 :     return CANPLAY_MAYBE;
     217             :   }
     218             : #ifdef MOZ_ANDROID_OMX
     219             :   if (MediaDecoder::IsAndroidMediaPluginEnabled() &&
     220             :       EnsureAndroidMediaPluginHost()->FindDecoder(mimeType, nullptr)) {
     221             :     return CANPLAY_MAYBE;
     222             :   }
     223             : #endif
     224           0 :   return CANPLAY_NO;
     225             : }
     226             : 
     227             : /* static */
     228             : CanPlayStatus
     229           0 : DecoderTraits::CanHandleContainerType(const MediaContainerType& aContainerType,
     230             :                                       DecoderDoctorDiagnostics* aDiagnostics)
     231             : {
     232           0 :   return CanHandleMediaType(aContainerType, aDiagnostics);
     233             : }
     234             : 
     235             : /* static */
     236           0 : bool DecoderTraits::ShouldHandleMediaType(const char* aMIMEType,
     237             :                                           DecoderDoctorDiagnostics* aDiagnostics)
     238             : {
     239           0 :   Maybe<MediaContainerType> containerType = MakeMediaContainerType(aMIMEType);
     240           0 :   if (!containerType) {
     241           0 :     return false;
     242             :   }
     243             : 
     244           0 :   if (WaveDecoder::IsSupportedType(*containerType)) {
     245             :     // We should not return true for Wave types, since there are some
     246             :     // Wave codecs actually in use in the wild that we don't support, and
     247             :     // we should allow those to be handled by plugins or helper apps.
     248             :     // Furthermore people can play Wave files on most platforms by other
     249             :     // means.
     250           0 :     return false;
     251             :   }
     252             : 
     253             :   // If an external plugin which can handle quicktime video is available
     254             :   // (and not disabled), prefer it over native playback as there several
     255             :   // codecs found in the wild that we do not handle.
     256           0 :   if (containerType->Type() == MEDIAMIMETYPE("video/quicktime")) {
     257           0 :     RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
     258           0 :     if (pluginHost &&
     259           0 :         pluginHost->HavePluginForType(containerType->Type().AsString())) {
     260           0 :       return false;
     261             :     }
     262             :   }
     263             : 
     264           0 :   return CanHandleMediaType(*containerType, aDiagnostics) != CANPLAY_NO;
     265             : }
     266             : 
     267             : // Instantiates but does not initialize decoder.
     268             : static already_AddRefed<ChannelMediaDecoder>
     269           0 : InstantiateDecoder(MediaDecoderInit& aInit,
     270             :                    DecoderDoctorDiagnostics* aDiagnostics)
     271             : {
     272           0 :   MOZ_ASSERT(NS_IsMainThread());
     273           0 :   RefPtr<ChannelMediaDecoder> decoder;
     274             : 
     275           0 :   const MediaContainerType& type = aInit.mContainerType;
     276             : 
     277             : #ifdef MOZ_ANDROID_HLS_SUPPORT
     278             :   if (HLSDecoder::IsSupportedType(type)) {
     279             :     decoder = new HLSDecoder(aInit);
     280             :     return decoder.forget();
     281             :   }
     282             : #endif
     283             : #ifdef MOZ_FMP4
     284           0 :   if (MP4Decoder::IsSupportedType(type, aDiagnostics)) {
     285           0 :     decoder = new MP4Decoder(aInit);
     286           0 :     return decoder.forget();
     287             :   }
     288             : #endif
     289           0 :   if (MP3Decoder::IsSupportedType(type)) {
     290           0 :     decoder = new MP3Decoder(aInit);
     291           0 :     return decoder.forget();
     292             :   }
     293           0 :   if (ADTSDecoder::IsSupportedType(type)) {
     294           0 :     decoder = new ADTSDecoder(aInit);
     295           0 :     return decoder.forget();
     296             :   }
     297           0 :   if (OggDecoder::IsSupportedType(type)) {
     298           0 :     decoder = new OggDecoder(aInit);
     299           0 :     return decoder.forget();
     300             :   }
     301           0 :   if (WaveDecoder::IsSupportedType(type)) {
     302           0 :     decoder = new WaveDecoder(aInit);
     303           0 :     return decoder.forget();
     304             :   }
     305           0 :   if (FlacDecoder::IsSupportedType(type)) {
     306           0 :     decoder = new FlacDecoder(aInit);
     307           0 :     return decoder.forget();
     308             :   }
     309             : #ifdef MOZ_ANDROID_OMX
     310             :   if (MediaDecoder::IsAndroidMediaPluginEnabled() &&
     311             :       EnsureAndroidMediaPluginHost()->FindDecoder(type, nullptr)) {
     312             :     decoder = new AndroidMediaDecoder(aInit, type);
     313             :     return decoder.forget();
     314             :   }
     315             : #endif
     316             : 
     317           0 :   if (WebMDecoder::IsSupportedType(type)) {
     318           0 :     decoder = new WebMDecoder(aInit);
     319           0 :     return decoder.forget();
     320             :   }
     321             : 
     322           0 :   if (DecoderTraits::IsHttpLiveStreamingType(type)) {
     323             :     // We don't have an HLS decoder.
     324           0 :     Telemetry::Accumulate(Telemetry::MEDIA_HLS_DECODER_SUCCESS, false);
     325             :   }
     326             : 
     327           0 :   return nullptr;
     328             : }
     329             : 
     330             : /* static */
     331             : already_AddRefed<ChannelMediaDecoder>
     332           0 : DecoderTraits::CreateDecoder(MediaDecoderInit& aInit,
     333             :                              DecoderDoctorDiagnostics* aDiagnostics)
     334             : {
     335           0 :   MOZ_ASSERT(NS_IsMainThread());
     336           0 :   return InstantiateDecoder(aInit, aDiagnostics);
     337             : }
     338             : 
     339             : /* static */
     340             : MediaDecoderReader*
     341           0 : DecoderTraits::CreateReader(const MediaContainerType& aType,
     342             :                             const MediaDecoderReaderInit& aInit)
     343             : {
     344           0 :   MOZ_ASSERT(NS_IsMainThread());
     345           0 :   MediaDecoderReader* decoderReader = nullptr;
     346             : 
     347           0 :   if (!aInit.mDecoder) {
     348           0 :     return decoderReader;
     349             :   }
     350             : 
     351           0 :   MediaResource* resource = aInit.mResource;
     352             : 
     353             : #ifdef MOZ_FMP4
     354           0 :   if (MP4Decoder::IsSupportedType(aType,
     355             :                                   /* DecoderDoctorDiagnostics* */ nullptr)) {
     356           0 :     decoderReader = new MediaFormatReader(aInit, new MP4Demuxer(resource));
     357             :   } else
     358             : #endif
     359           0 :   if (MP3Decoder::IsSupportedType(aType)) {
     360           0 :     decoderReader = new MediaFormatReader(aInit, new MP3Demuxer(resource));
     361             :   } else
     362           0 :   if (ADTSDecoder::IsSupportedType(aType)) {
     363           0 :     decoderReader = new MediaFormatReader(aInit, new ADTSDemuxer(resource));
     364             :   } else
     365           0 :   if (WaveDecoder::IsSupportedType(aType)) {
     366           0 :     decoderReader = new MediaFormatReader(aInit, new WAVDemuxer(resource));
     367             :   } else
     368           0 :   if (FlacDecoder::IsSupportedType(aType)) {
     369           0 :     decoderReader = new MediaFormatReader(aInit, new FlacDemuxer(resource));
     370             :   } else
     371           0 :   if (OggDecoder::IsSupportedType(aType)) {
     372           0 :     decoderReader = new MediaFormatReader(aInit, new OggDemuxer(resource));
     373             :   } else
     374             : #ifdef MOZ_ANDROID_OMX
     375             :   if (MediaDecoder::IsAndroidMediaPluginEnabled() &&
     376             :       EnsureAndroidMediaPluginHost()->FindDecoder(aType, nullptr)) {
     377             :     decoderReader = new AndroidMediaReader(aType, aInit);
     378             :   } else
     379             : #endif
     380           0 :   if (WebMDecoder::IsSupportedType(aType)) {
     381           0 :     decoderReader = new MediaFormatReader(aInit, new WebMDemuxer(resource));
     382             :   }
     383             : 
     384           0 :   return decoderReader;
     385             : }
     386             : 
     387             : /* static */
     388           0 : bool DecoderTraits::IsSupportedInVideoDocument(const nsACString& aType)
     389             : {
     390             :   // Forbid playing media in video documents if the user has opted
     391             :   // not to, using either the legacy WMF specific pref, or the newer
     392             :   // catch-all pref.
     393           0 :   if (!Preferences::GetBool("media.windows-media-foundation.play-stand-alone", true) ||
     394           0 :       !Preferences::GetBool("media.play-stand-alone", true)) {
     395           0 :     return false;
     396             :   }
     397             : 
     398           0 :   Maybe<MediaContainerType> type = MakeMediaContainerType(aType);
     399           0 :   if (!type) {
     400           0 :     return false;
     401             :   }
     402             : 
     403             :   return
     404           0 :     OggDecoder::IsSupportedType(*type) ||
     405           0 :     WebMDecoder::IsSupportedType(*type) ||
     406             : #ifdef MOZ_ANDROID_OMX
     407             :     (MediaDecoder::IsAndroidMediaPluginEnabled() && IsAndroidMediaType(*type)) ||
     408             : #endif
     409             : #ifdef MOZ_FMP4
     410           0 :     MP4Decoder::IsSupportedType(*type, /* DecoderDoctorDiagnostics* */ nullptr) ||
     411             : #endif
     412           0 :     MP3Decoder::IsSupportedType(*type) ||
     413           0 :     ADTSDecoder::IsSupportedType(*type) ||
     414           0 :     FlacDecoder::IsSupportedType(*type) ||
     415             : #ifdef MOZ_ANDROID_HLS_SUPPORT
     416             :     HLSDecoder::IsSupportedType(*type) ||
     417             : #endif
     418           0 :     false;
     419             : }
     420             : 
     421             : } // namespace mozilla

Generated by: LCOV version 1.13