bool AndroidDecoderModule::SupportsMimeType(const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const { if (!AndroidBridge::Bridge() || AndroidBridge::Bridge()->GetAPIVersion() < 16) { return false; } if (aMimeType.EqualsLiteral("video/mp4") || aMimeType.EqualsLiteral("video/avc")) { return true; } // When checking "audio/x-wav", CreateDecoder can cause a JNI ERROR by // Accessing a stale local reference leading to a SIGSEGV crash. // To avoid this we check for wav types here. if (aMimeType.EqualsLiteral("audio/x-wav") || aMimeType.EqualsLiteral("audio/wave; codecs=1") || aMimeType.EqualsLiteral("audio/wave; codecs=6") || aMimeType.EqualsLiteral("audio/wave; codecs=7") || aMimeType.EqualsLiteral("audio/wave; codecs=65534")) { return false; } if ((VPXDecoder::IsVPX(aMimeType, VPXDecoder::VP8) && !GetFeatureStatus(nsIGfxInfo::FEATURE_VP8_HW_DECODE)) || (VPXDecoder::IsVPX(aMimeType, VPXDecoder::VP9) && !GetFeatureStatus(nsIGfxInfo::FEATURE_VP9_HW_DECODE))) { return false; } return java::HardwareCodecCapabilityUtils::FindDecoderCodecInfoForMimeType( nsCString(TranslateMimeType(aMimeType))); }
nsresult MediaCodecDataDecoder::InitDecoder(Surface::Param aSurface) { mDecoder = CreateDecoder(mMimeType); if (!mDecoder) { INVOKE_CALLBACK(Error, MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__)); return NS_ERROR_FAILURE; } // Check if the video codec supports adaptive playback or not. if (aSurface && java::HardwareCodecCapabilityUtils::CheckSupportsAdaptivePlayback( mDecoder, nsCString(TranslateMimeType(mMimeType)))) { // TODO: may need to find a way to not use hard code to decide the max w/h. mFormat->SetInteger(MediaFormat::KEY_MAX_WIDTH, 1920); mFormat->SetInteger(MediaFormat::KEY_MAX_HEIGHT, 1080); } MediaCrypto::LocalRef crypto = MediaDrmProxy::GetMediaCrypto(mDrmStubId); bool hascrypto = !!crypto; LOG("Has(%d) MediaCrypto (%s)", hascrypto, NS_ConvertUTF16toUTF8(mDrmStubId).get()); nsresult rv; NS_ENSURE_SUCCESS(rv = mDecoder->Configure(mFormat, aSurface, crypto, 0), rv); NS_ENSURE_SUCCESS(rv = mDecoder->Start(), rv); NS_ENSURE_SUCCESS(rv = ResetInputBuffers(), rv); NS_ENSURE_SUCCESS(rv = ResetOutputBuffers(), rv); nsCOMPtr<nsIRunnable> r = NewRunnableMethod(this, &MediaCodecDataDecoder::DecoderLoop); rv = NS_NewNamedThread("MC Decoder", getter_AddRefs(mThread), r); return rv; }
static MediaCodec::LocalRef CreateDecoder(const nsACString& aMimeType) { MediaCodec::LocalRef codec; NS_ENSURE_SUCCESS(MediaCodec::CreateDecoderByType(TranslateMimeType(aMimeType), &codec), nullptr); return codec; }
bool AndroidDecoderModule::SupportsMimeType(const nsACString& aMimeType) { if (jni::GetAPIVersion() < 16) { return false; } if (aMimeType.EqualsLiteral("video/mp4") || aMimeType.EqualsLiteral("video/avc")) { return true; } // When checking "audio/x-wav", CreateDecoder can cause a JNI ERROR by // Accessing a stale local reference leading to a SIGSEGV crash. // To avoid this we check for wav types here. if (aMimeType.EqualsLiteral("audio/x-wav") || aMimeType.EqualsLiteral("audio/wave; codecs=1") || aMimeType.EqualsLiteral("audio/wave; codecs=6") || aMimeType.EqualsLiteral("audio/wave; codecs=7") || aMimeType.EqualsLiteral("audio/wave; codecs=65534")) { return false; } if ((VPXDecoder::IsVPX(aMimeType, VPXDecoder::VP8) && !GetFeatureStatus(nsIGfxInfo::FEATURE_VP8_HW_DECODE)) || (VPXDecoder::IsVPX(aMimeType, VPXDecoder::VP9) && !GetFeatureStatus(nsIGfxInfo::FEATURE_VP9_HW_DECODE))) { return false; } // Prefer the gecko decoder for opus and vorbis; stagefright crashes // on content demuxed from mp4. // Not all android devices support FLAC even when they say they do. if (OpusDataDecoder::IsOpus(aMimeType) || VorbisDataDecoder::IsVorbis(aMimeType) || aMimeType.EqualsLiteral("audio/flac")) { SLOG("Rejecting audio of type %s", aMimeType.Data()); return false; } // Prefer the gecko decoder for Theora. // Not all android devices support Theora even when they say they do. if (TheoraDecoder::IsTheora(aMimeType)) { SLOG("Rejecting video of type %s", aMimeType.Data()); return false; } return java::HardwareCodecCapabilityUtils::FindDecoderCodecInfoForMimeType( TranslateMimeType(aMimeType)); }
bool AndroidDecoderModule::SupportsMimeType(const nsACString& aMimeType) const { if (!AndroidBridge::Bridge() || AndroidBridge::Bridge()->GetAPIVersion() < 16) { return false; } if (aMimeType.EqualsLiteral("video/mp4") || aMimeType.EqualsLiteral("video/avc")) { return true; } return widget::HardwareCodecCapabilityUtils::FindDecoderCodecInfoForMimeType( nsCString(TranslateMimeType(aMimeType))); }
already_AddRefed<MediaDataDecoder> AndroidDecoderModule::CreateVideoDecoder( const VideoInfo& aConfig, layers::LayersBackend aLayersBackend, layers::ImageContainer* aImageContainer, FlushableTaskQueue* aVideoTaskQueue, MediaDataDecoderCallback* aCallback) { MediaFormat::LocalRef format; NS_ENSURE_SUCCESS(MediaFormat::CreateVideoFormat( TranslateMimeType(aConfig.mMimeType), aConfig.mDisplay.width, aConfig.mDisplay.height, &format), nullptr); RefPtr<MediaDataDecoder> decoder = new VideoDataDecoder(aConfig, format, aCallback, aImageContainer); return decoder.forget(); }
already_AddRefed<MediaDataDecoder> AndroidDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams) { MediaFormat::LocalRef format; const VideoInfo& config = aParams.VideoConfig(); NS_ENSURE_SUCCESS(MediaFormat::CreateVideoFormat( TranslateMimeType(config.mMimeType), config.mDisplay.width, config.mDisplay.height, &format), nullptr); RefPtr<MediaDataDecoder> decoder = MediaPrefs::PDMAndroidRemoteCodecEnabled() ? RemoteDataDecoder::CreateVideoDecoder(config, format, aParams.mCallback, aParams.mImageContainer) : MediaCodecDataDecoder::CreateVideoDecoder(config, format, aParams.mCallback, aParams.mImageContainer); return decoder.forget(); }