PlatformDecoderModule.h (27409B)
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 #if !defined(PlatformDecoderModule_h_) 8 # define PlatformDecoderModule_h_ 9 10 # include "DecoderDoctorLogger.h" 11 # include "GMPCrashHelper.h" 12 # include "MediaCodecsSupport.h" 13 # include "MediaEventSource.h" 14 # include "MediaInfo.h" 15 # include "MediaResult.h" 16 # include "PerformanceRecorder.h" 17 # include "mozilla/EnumSet.h" 18 # include "mozilla/EnumTypeTraits.h" 19 # include "mozilla/MozPromise.h" 20 # include "mozilla/PRemoteCDMActor.h" 21 # include "mozilla/RefPtr.h" 22 # include "mozilla/TaskQueue.h" 23 # include "mozilla/ipc/UtilityMediaService.h" 24 # include "mozilla/layers/KnowsCompositor.h" 25 # include "mozilla/layers/LayersTypes.h" 26 # include "nsTArray.h" 27 28 namespace mozilla { 29 class TrackInfo; 30 class AudioInfo; 31 class VideoInfo; 32 class MediaRawData; 33 class DecoderDoctorDiagnostics; 34 35 namespace layers { 36 class ImageContainer; 37 } // namespace layers 38 39 class MediaDataDecoder; 40 class RemoteDecoderModule; 41 class CDMProxy; 42 43 static LazyLogModule sPDMLog("PlatformDecoderModule"); 44 45 namespace media { 46 47 template <typename T> 48 static nsCString EnumSetToString(const EnumSet<T>& aSet) { 49 nsCString str; 50 for (const auto e : aSet) { 51 if (!str.IsEmpty()) { 52 str.AppendLiteral("|"); 53 } 54 str.AppendPrintf("%s", EnumValueToString(e)); 55 } 56 if (str.IsEmpty()) { 57 str.AppendLiteral("Empty"); 58 } 59 return str; 60 } 61 62 MOZ_DEFINE_ENUM_CLASS_WITH_TOSTRING( 63 Option, 64 (Default, LowLatency, HardwareDecoderNotAllowed, FullH264Parsing, 65 ErrorIfNoInitializationData, // By default frames delivered before 66 // initialization data are dropped. Pass this 67 // option to raise an error if frames are 68 // delivered before initialization data. 69 DefaultPlaybackDeviceMono, // Currently only used by Opus on RDD to avoid 70 // initialization of audio backends on RDD 71 KeepOriginalPts, // It can be that the decoder mangles the pts of decoded 72 // frames, this forces using the input PTS. 73 Output8BitPerChannel, // Convert decoded data to 8-bit per channel format. 74 // Useful when the consumer (webrender, WebGL, ...) 75 // doesn't support inputs higher than 8-bit. ONLY 76 // SUPPORTED BY DAV1DDecoder and FFmpegVideoDecoder. 77 78 SENTINEL // one past the last valid value 79 )); 80 81 using OptionSet = EnumSet<Option>; 82 83 struct UseNullDecoder { 84 UseNullDecoder() = default; 85 explicit UseNullDecoder(bool aUseNullDecoder) : mUse(aUseNullDecoder) {} 86 bool mUse = false; 87 }; 88 89 // Do not wrap H264 decoder in a H264Converter. 90 MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AND_TOSTRING(Wrapper, uint8_t, 91 (AudioTrimmer, 92 MediaChangeMonitor)); 93 using WrapperSet = EnumSet<Wrapper>; 94 static WrapperSet GetDefaultWrapperSet(const TrackInfo& aInfo) { 95 // MediaChangeMonitor can work with some audio codecs like AAC but only 96 // WebCodecs needs it, so it's only enabled for video by default. 97 WrapperSet set; 98 if (aInfo.IsVideo()) { 99 set += Wrapper::MediaChangeMonitor; 100 } 101 if (aInfo.IsAudio()) { 102 set += Wrapper::AudioTrimmer; 103 } 104 return set; 105 } 106 107 struct VideoFrameRate { 108 VideoFrameRate() = default; 109 explicit VideoFrameRate(float aFramerate) : mValue(aFramerate) {} 110 float mValue = 0.0f; 111 }; 112 113 } // namespace media 114 115 struct CreateDecoderParams; 116 struct CreateDecoderParamsForAsync { 117 using Option = media::Option; 118 using OptionSet = media::OptionSet; 119 explicit CreateDecoderParamsForAsync(const CreateDecoderParams& aParams); 120 CreateDecoderParamsForAsync(CreateDecoderParamsForAsync&& aParams); 121 122 const VideoInfo& VideoConfig() const { 123 MOZ_ASSERT(mConfig->IsVideo()); 124 return *mConfig->GetAsVideoInfo(); 125 } 126 127 const AudioInfo& AudioConfig() const { 128 MOZ_ASSERT(mConfig->IsAudio()); 129 return *mConfig->GetAsAudioInfo(); 130 } 131 132 UniquePtr<TrackInfo> mConfig; 133 const RefPtr<layers::ImageContainer> mImageContainer; 134 const RefPtr<layers::KnowsCompositor> mKnowsCompositor; 135 const RefPtr<GMPCrashHelper> mCrashHelper; 136 const RefPtr<PRemoteCDMActor> mCDM; 137 const media::UseNullDecoder mUseNullDecoder; 138 const media::WrapperSet mWrappers; 139 const TrackInfo::TrackType mType = TrackInfo::kUndefinedTrack; 140 std::function<MediaEventProducer<TrackInfo::TrackType>*()> 141 mOnWaitingForKeyEvent; 142 const OptionSet mOptions = OptionSet(Option::Default); 143 const media::VideoFrameRate mRate; 144 const Maybe<uint64_t> mMediaEngineId; 145 const Maybe<TrackingId> mTrackingId; 146 }; 147 148 struct MOZ_STACK_CLASS CreateDecoderParams final { 149 using Option = media::Option; 150 using OptionSet = media::OptionSet; 151 using UseNullDecoder = media::UseNullDecoder; 152 using WrapperSet = media::WrapperSet; 153 using VideoFrameRate = media::VideoFrameRate; 154 enum class EncryptedCustomIdent : bool { 155 False, 156 True, 157 }; 158 159 explicit CreateDecoderParams(const TrackInfo& aConfig) 160 : mConfig(aConfig), mWrappers(media::GetDefaultWrapperSet(aConfig)) {} 161 CreateDecoderParams(const CreateDecoderParams& aParams) = default; 162 163 MOZ_IMPLICIT CreateDecoderParams(const CreateDecoderParamsForAsync& aParams) 164 : mConfig(*aParams.mConfig), 165 mImageContainer(aParams.mImageContainer), 166 mKnowsCompositor(aParams.mKnowsCompositor), 167 mCrashHelper(aParams.mCrashHelper), 168 mCDM(aParams.mCDM), 169 mUseNullDecoder(aParams.mUseNullDecoder), 170 mWrappers(aParams.mWrappers), 171 mType(aParams.mType), 172 mOnWaitingForKeyEvent(aParams.mOnWaitingForKeyEvent), 173 mOptions(aParams.mOptions), 174 mRate(aParams.mRate), 175 mMediaEngineId(aParams.mMediaEngineId), 176 mTrackingId(aParams.mTrackingId) {} 177 178 template <typename T1, typename... Ts> 179 CreateDecoderParams(const TrackInfo& aConfig, T1&& a1, Ts&&... args) 180 : mConfig(aConfig), mWrappers(media::GetDefaultWrapperSet(aConfig)) { 181 Set(std::forward<T1>(a1), std::forward<Ts>(args)...); 182 } 183 184 template <typename T1, typename... Ts> 185 CreateDecoderParams(const CreateDecoderParams& aParams, T1&& a1, Ts&&... args) 186 : CreateDecoderParams(aParams) { 187 Set(std::forward<T1>(a1), std::forward<Ts>(args)...); 188 } 189 190 const VideoInfo& VideoConfig() const { 191 MOZ_ASSERT(mConfig.IsVideo()); 192 return *mConfig.GetAsVideoInfo(); 193 } 194 195 const AudioInfo& AudioConfig() const { 196 MOZ_ASSERT(mConfig.IsAudio()); 197 return *mConfig.GetAsAudioInfo(); 198 } 199 200 bool IsVideo() const { return mConfig.IsVideo(); } 201 202 bool IsAudio() const { return mConfig.IsAudio(); } 203 204 layers::LayersBackend GetLayersBackend() const { 205 if (mKnowsCompositor) { 206 return mKnowsCompositor->GetCompositorBackendType(); 207 } 208 return layers::LayersBackend::LAYERS_NONE; 209 } 210 211 nsCString ToString() const { 212 nsPrintfCString str("CreateDecoderParams @ %p: ", this); 213 str.AppendPrintf("mConfig = %s", mConfig.ToString().get()); 214 str.AppendPrintf(", mImageContainer = %p", mImageContainer); 215 str.AppendPrintf(", mError = %s", 216 mError ? mError->Description().get() : "null"); 217 str.AppendPrintf(", mKnowsCompositor = %p", mKnowsCompositor); 218 str.AppendPrintf(", mCrashHelper = %p", mCrashHelper); 219 str.AppendPrintf(", mCDM = %p", mCDM); 220 str.AppendPrintf(", mUseNullDecoder = %s", 221 mUseNullDecoder.mUse ? "yes" : "no"); 222 str.AppendPrintf(", mWrappers = %s", EnumSetToString(mWrappers).get()); 223 str.AppendPrintf(", mType = %d", static_cast<int32_t>(mType)); 224 str.AppendPrintf(", mOnWaitingForKeyEvent = %s", 225 mOnWaitingForKeyEvent ? "yes" : "no"); 226 str.AppendPrintf(", mOptions = %s", EnumSetToString(mOptions).get()); 227 str.AppendPrintf(", mRate = %f", mRate.mValue); 228 str.AppendPrintf( 229 ", mMediaEngineId = %s", 230 mMediaEngineId ? std::to_string(*mMediaEngineId).c_str() : "None"); 231 str.AppendPrintf(", mTrackingId = %s", 232 mTrackingId ? mTrackingId->ToString().get() : "None"); 233 str.AppendPrintf( 234 ", mEncryptedCustomIdent = %s", 235 mEncryptedCustomIdent == EncryptedCustomIdent::True ? "true" : "false"); 236 return {std::move(str)}; 237 } 238 239 // CreateDecoderParams is a MOZ_STACK_CLASS, it is only used to 240 // simplify the passing of arguments to Create*Decoder. 241 // It is safe to use references and raw pointers. 242 const TrackInfo& mConfig; 243 layers::ImageContainer* mImageContainer = nullptr; 244 MediaResult* mError = nullptr; 245 layers::KnowsCompositor* mKnowsCompositor = nullptr; 246 GMPCrashHelper* mCrashHelper = nullptr; 247 PRemoteCDMActor* mCDM = nullptr; 248 media::UseNullDecoder mUseNullDecoder; 249 WrapperSet mWrappers; 250 TrackInfo::TrackType mType = TrackInfo::kUndefinedTrack; 251 std::function<MediaEventProducer<TrackInfo::TrackType>*()> 252 mOnWaitingForKeyEvent; 253 OptionSet mOptions = OptionSet(Option::Default); 254 media::VideoFrameRate mRate; 255 // Used on Windows when the MF media engine playback is enabled. 256 Maybe<uint64_t> mMediaEngineId; 257 Maybe<TrackingId> mTrackingId; 258 EncryptedCustomIdent mEncryptedCustomIdent = EncryptedCustomIdent::False; 259 260 private: 261 void Set(layers::ImageContainer* aImageContainer) { 262 mImageContainer = aImageContainer; 263 } 264 void Set(MediaResult* aError) { mError = aError; } 265 void Set(GMPCrashHelper* aCrashHelper) { mCrashHelper = aCrashHelper; } 266 void Set(PRemoteCDMActor* aCDM) { mCDM = aCDM; } 267 void Set(UseNullDecoder aUseNullDecoder) { 268 mUseNullDecoder = aUseNullDecoder; 269 } 270 void Set(const WrapperSet& aWrappers) { mWrappers = aWrappers; } 271 void Set(const OptionSet& aOptions) { mOptions = aOptions; } 272 void Set(VideoFrameRate aRate) { mRate = aRate; } 273 void Set(layers::KnowsCompositor* aKnowsCompositor) { 274 if (aKnowsCompositor) { 275 mKnowsCompositor = aKnowsCompositor; 276 MOZ_ASSERT(aKnowsCompositor->IsThreadSafe()); 277 } 278 } 279 void Set(TrackInfo::TrackType aType) { mType = aType; } 280 void Set(std::function<MediaEventProducer<TrackInfo::TrackType>*()>&& 281 aOnWaitingForKey) { 282 mOnWaitingForKeyEvent = std::move(aOnWaitingForKey); 283 } 284 void Set(const std::function<MediaEventProducer<TrackInfo::TrackType>*()>& 285 aOnWaitingForKey) { 286 mOnWaitingForKeyEvent = aOnWaitingForKey; 287 } 288 void Set(const Maybe<uint64_t>& aMediaEngineId) { 289 mMediaEngineId = aMediaEngineId; 290 } 291 void Set(const Maybe<TrackingId>& aTrackingId) { mTrackingId = aTrackingId; } 292 void Set(const EncryptedCustomIdent aEncryptedCustomIdent) { 293 mEncryptedCustomIdent = aEncryptedCustomIdent; 294 } 295 void Set(const CreateDecoderParams& aParams) { 296 // Set all but mTrackInfo; 297 mImageContainer = aParams.mImageContainer; 298 mError = aParams.mError; 299 mKnowsCompositor = aParams.mKnowsCompositor; 300 mCrashHelper = aParams.mCrashHelper; 301 mCDM = aParams.mCDM; 302 mUseNullDecoder = aParams.mUseNullDecoder; 303 mWrappers = aParams.mWrappers; 304 mType = aParams.mType; 305 mOnWaitingForKeyEvent = aParams.mOnWaitingForKeyEvent; 306 mOptions = aParams.mOptions; 307 mRate = aParams.mRate; 308 mMediaEngineId = aParams.mMediaEngineId; 309 mTrackingId = aParams.mTrackingId; 310 } 311 template <typename T1, typename T2, typename... Ts> 312 void Set(T1&& a1, T2&& a2, Ts&&... args) { 313 Set(std::forward<T1>(a1)); 314 Set(std::forward<T2>(a2), std::forward<Ts>(args)...); 315 } 316 }; 317 318 struct MOZ_STACK_CLASS SupportDecoderParams final { 319 using Option = media::Option; 320 using OptionSet = media::OptionSet; 321 using UseNullDecoder = media::UseNullDecoder; 322 using WrapperSet = media::WrapperSet; 323 using VideoFrameRate = media::VideoFrameRate; 324 325 explicit SupportDecoderParams(const TrackInfo& aConfig) 326 : mConfig(aConfig), mWrappers(media::GetDefaultWrapperSet(aConfig)) {} 327 328 explicit SupportDecoderParams(const CreateDecoderParams& aParams) 329 : mConfig(aParams.mConfig), 330 mError(aParams.mError), 331 mKnowsCompositor(aParams.mKnowsCompositor), 332 mCDM(aParams.mCDM), 333 mUseNullDecoder(aParams.mUseNullDecoder), 334 mWrappers(aParams.mWrappers), 335 mOptions(aParams.mOptions), 336 mRate(aParams.mRate), 337 mMediaEngineId(aParams.mMediaEngineId) {} 338 339 template <typename T1, typename... Ts> 340 SupportDecoderParams(const TrackInfo& aConfig, T1&& a1, Ts&&... args) 341 : mConfig(aConfig), mWrappers(media::GetDefaultWrapperSet(aConfig)) { 342 Set(std::forward<T1>(a1), std::forward<Ts>(args)...); 343 } 344 345 const nsCString& MimeType() const { return mConfig.mMimeType; } 346 347 const TrackInfo& mConfig; 348 DecoderDoctorDiagnostics* mDiagnostics = nullptr; 349 MediaResult* mError = nullptr; 350 RefPtr<layers::KnowsCompositor> mKnowsCompositor; 351 PRemoteCDMActor* mCDM = nullptr; 352 UseNullDecoder mUseNullDecoder; 353 WrapperSet mWrappers; 354 OptionSet mOptions = OptionSet(Option::Default); 355 VideoFrameRate mRate; 356 Maybe<uint64_t> mMediaEngineId; 357 358 private: 359 void Set(DecoderDoctorDiagnostics* aDiagnostics) { 360 mDiagnostics = aDiagnostics; 361 } 362 void Set(MediaResult* aError) { mError = aError; } 363 void Set(PRemoteCDMActor* aCDM) { mCDM = aCDM; } 364 void Set(media::UseNullDecoder aUseNullDecoder) { 365 mUseNullDecoder = aUseNullDecoder; 366 } 367 void Set(const WrapperSet& aWrappers) { mWrappers = aWrappers; } 368 void Set(const media::OptionSet& aOptions) { mOptions = aOptions; } 369 void Set(media::VideoFrameRate aRate) { mRate = aRate; } 370 void Set(layers::KnowsCompositor* aKnowsCompositor) { 371 if (aKnowsCompositor) { 372 mKnowsCompositor = aKnowsCompositor; 373 MOZ_ASSERT(aKnowsCompositor->IsThreadSafe()); 374 } 375 } 376 void Set(const Maybe<uint64_t>& aMediaEngineId) { 377 mMediaEngineId = aMediaEngineId; 378 } 379 380 template <typename T1, typename T2, typename... Ts> 381 void Set(T1&& a1, T2&& a2, Ts&&... args) { 382 Set(std::forward<T1>(a1)); 383 Set(std::forward<T2>(a2), std::forward<Ts>(args)...); 384 } 385 }; 386 387 // Used for IPDL serialization. 388 // The 'value' have to be the biggest enum from CreateDecoderParams::Option. 389 template <> 390 struct MaxEnumValue<::mozilla::CreateDecoderParams::Option> { 391 static constexpr unsigned int value = 392 static_cast<unsigned int>(CreateDecoderParams::Option::SENTINEL); 393 }; 394 395 // The PlatformDecoderModule interface is used by the MediaFormatReader to 396 // abstract access to decoders provided by various 397 // platforms. 398 // Each platform (Windows, MacOSX, Linux, B2G etc) must implement a 399 // PlatformDecoderModule to provide access to its decoders in order to get 400 // decompressed H.264/AAC from the MediaFormatReader. 401 // 402 // Decoding is asynchronous, and should be performed on the task queue 403 // provided if the underlying platform isn't already exposing an async API. 404 // 405 // A cross-platform decoder module that discards input and produces "blank" 406 // output samples exists for testing, and is created when the pref 407 // "media.use-blank-decoder" is true. 408 409 class PlatformDecoderModule { 410 public: 411 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PlatformDecoderModule) 412 413 virtual const char* Name() const = 0; 414 415 // Perform any per-instance initialization. 416 // This is called on the decode task queue. 417 virtual nsresult Startup() { return NS_OK; } 418 419 // Indicates if the PlatformDecoderModule supports decoding of aMimeType, 420 // and whether or not hardware-accelerated decoding is supported. 421 // The answer to both SupportsMimeType and Supports doesn't guarantee that 422 // creation of a decoder will actually succeed. 423 virtual media::DecodeSupportSet SupportsMimeType( 424 const nsACString& aMimeType, 425 DecoderDoctorDiagnostics* aDiagnostics) const = 0; 426 427 virtual media::DecodeSupportSet Supports( 428 const SupportDecoderParams& aParams, 429 DecoderDoctorDiagnostics* aDiagnostics) const { 430 const TrackInfo& trackInfo = aParams.mConfig; 431 const media::DecodeSupportSet support = 432 SupportsMimeType(trackInfo.mMimeType, aDiagnostics); 433 434 // Bail early if we don't support this format at all 435 if (support.isEmpty()) { 436 return support; 437 } 438 439 const auto* videoInfo = trackInfo.GetAsVideoInfo(); 440 441 if (!videoInfo) { 442 // No video stream = software decode only 443 return media::DecodeSupport::SoftwareDecode; 444 } 445 446 // Check whether we support the desired color depth 447 if (!SupportsColorDepth(videoInfo->mColorDepth, aDiagnostics)) { 448 return media::DecodeSupportSet{}; 449 } 450 return support; 451 } 452 453 using CreateDecoderPromise = MozPromise<RefPtr<MediaDataDecoder>, MediaResult, 454 /* IsExclusive = */ true>; 455 456 protected: 457 PlatformDecoderModule() = default; 458 virtual ~PlatformDecoderModule() = default; 459 460 friend class MediaChangeMonitor; 461 friend class PDMFactory; 462 friend class EMEDecoderModule; 463 friend class RemoteDecoderModule; 464 465 // Indicates if the PlatformDecoderModule supports decoding of aColorDepth. 466 // Should override this method when the platform can support color depth != 8. 467 virtual bool SupportsColorDepth( 468 gfx::ColorDepth aColorDepth, 469 DecoderDoctorDiagnostics* aDiagnostics) const { 470 return aColorDepth == gfx::ColorDepth::COLOR_8; 471 } 472 473 // Creates a Video decoder. The layers backend is passed in so that 474 // decoders can determine whether hardware accelerated decoding can be used. 475 // On Windows the task queue's threads in have MSCOM initialized with 476 // COINIT_MULTITHREADED. 477 // Returns nullptr if the decoder can't be created. 478 // It is not safe to store a reference to aParams or aParams.mConfig as the 479 // object isn't guaranteed to live after the call. 480 // CreateVideoDecoder may need to make additional checks if the 481 // CreateDecoderParams argument is actually supported and return nullptr if 482 // not to allow for fallback PDMs to be tried. 483 virtual already_AddRefed<MediaDataDecoder> CreateVideoDecoder( 484 const CreateDecoderParams& aParams) = 0; 485 486 // Creates an Audio decoder with the specified properties. 487 // Returns nullptr if the decoder can't be created. 488 // On Windows the task queue's threads in have MSCOM initialized with 489 // COINIT_MULTITHREADED. 490 // It is not safe to store a reference to aParams or aParams.mConfig as the 491 // object isn't guaranteed to live after the call. 492 // CreateAudioDecoder may need to make additional checks if the 493 // CreateDecoderParams argument is actually supported and return nullptr if 494 // not to allow for fallback PDMs to be tried. 495 virtual already_AddRefed<MediaDataDecoder> CreateAudioDecoder( 496 const CreateDecoderParams& aParams) = 0; 497 498 // Asychronously create a decoder. 499 virtual RefPtr<CreateDecoderPromise> AsyncCreateDecoder( 500 const CreateDecoderParams& aParams); 501 }; 502 503 DDLoggedTypeDeclName(MediaDataDecoder); 504 505 // MediaDataDecoder is the interface exposed by decoders created by the 506 // PlatformDecoderModule's Create*Decoder() functions. The type of 507 // media data that the decoder accepts as valid input and produces as 508 // output is determined when the MediaDataDecoder is created. 509 // 510 // Unless otherwise noted, all functions are only called on the decode task 511 // queue. An exception is the MediaDataDecoder in 512 // MediaFormatReader::IsVideoAccelerated() for which all calls (Init(), 513 // IsHardwareAccelerated(), and Shutdown()) are from the main thread. 514 // 515 // Don't block inside these functions, unless it's explicitly noted that you 516 // should (like in Flush()). 517 // 518 // Decoding is done asynchronously. 519 class MediaDataDecoder : public DecoderDoctorLifeLogger<MediaDataDecoder> { 520 protected: 521 virtual ~MediaDataDecoder() = default; 522 523 public: 524 using TrackType = TrackInfo::TrackType; 525 using DecodedData = nsTArray<RefPtr<MediaData>>; 526 using InitPromise = MozPromise<TrackType, MediaResult, true>; 527 using DecodePromise = MozPromise<DecodedData, MediaResult, true>; 528 using FlushPromise = MozPromise<bool, MediaResult, true>; 529 530 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING 531 532 // Initialize the decoder. The decoder should be ready to decode once 533 // the promise resolves. The decoder should do any initialization here, rather 534 // than in its constructor or PlatformDecoderModule::Create*Decoder(), 535 // so that if the MediaFormatReader needs to shutdown during initialization, 536 // it can call Shutdown() to cancel this operation. Any initialization 537 // that requires blocking the calling thread in this function *must* 538 // be done here so that it can be canceled by calling Shutdown()! 539 // Methods Decode, DecodeBatch, Drain, Flush, Shutdown are guaranteed to be 540 // called on the thread where Init() first ran. 541 virtual RefPtr<InitPromise> Init() = 0; 542 543 // Inserts a sample into the decoder's decode pipeline. The DecodePromise will 544 // be resolved with the decoded MediaData. In case the decoder needs more 545 // input, the DecodePromise may be resolved with an empty array of samples to 546 // indicate that Decode should be called again before a MediaData is returned. 547 virtual RefPtr<DecodePromise> Decode(MediaRawData* aSample) = 0; 548 549 // This could probably be implemented as a wrapper that takes a 550 // generic MediaDataDecoder and manages batching as needed. For now 551 // only AudioTrimmer with RemoteMediaDataDecoder supports batch 552 // decoding. 553 // Inserts an array of samples into the decoder's decode pipeline. The 554 // DecodePromise will be resolved with the decoded MediaData. In case 555 // the decoder needs more input, the DecodePromise may be resolved 556 // with an empty array of samples to indicate that Decode should be 557 // called again before a MediaData is returned. 558 virtual bool CanDecodeBatch() const { return false; } 559 virtual RefPtr<DecodePromise> DecodeBatch( 560 nsTArray<RefPtr<MediaRawData>>&& aSamples) { 561 MOZ_CRASH("DecodeBatch not implemented yet"); 562 return MediaDataDecoder::DecodePromise::CreateAndReject( 563 NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__); 564 } 565 566 // Causes all complete samples in the pipeline that can be decoded to be 567 // output. If the decoder can't produce samples from the current output, 568 // it drops the input samples. The decoder may be holding onto samples 569 // that are required to decode samples that it expects to get in future. 570 // This is called when the demuxer reaches end of stream. 571 // This function is asynchronous. 572 // The MediaDataDecoder shall resolve the pending DecodePromise with drained 573 // samples. Drain will be called multiple times until the resolved 574 // DecodePromise is empty which indicates that there are no more samples to 575 // drain. 576 virtual RefPtr<DecodePromise> Drain() = 0; 577 578 // Causes all samples in the decoding pipeline to be discarded. When this 579 // promise resolves, the decoder must be ready to accept new data for 580 // decoding. This function is called when the demuxer seeks, before decoding 581 // resumes after the seek. The current DecodePromise if any shall be rejected 582 // with NS_ERROR_DOM_MEDIA_CANCELED 583 virtual RefPtr<FlushPromise> Flush() = 0; 584 585 // Cancels all init/decode/drain operations, and shuts down the decoder. The 586 // platform decoder should clean up any resources it's using and release 587 // memory etc. The shutdown promise will be resolved once the decoder has 588 // completed shutdown. The reader calls Flush() before calling Shutdown(). The 589 // reader will delete the decoder once the promise is resolved. 590 // The ShutdownPromise must only ever be resolved. 591 // Shutdown() may not be called if init hasn't been called first. It is 592 // possible under some circumstances for the decoder to be deleted without 593 // Init having been called first. 594 virtual RefPtr<ShutdownPromise> Shutdown() = 0; 595 596 // Called from the state machine task queue or main thread. Decoder needs to 597 // decide whether or not hardware acceleration is supported after creating. 598 // It doesn't need to call Init() before calling this function. 599 virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const { 600 return false; 601 } 602 603 // Return the name of the MediaDataDecoder, only used for decoding. 604 // May be accessed in a non thread-safe fashion. 605 virtual nsCString GetDescriptionName() const = 0; 606 607 virtual nsCString GetProcessName() const { 608 nsCString rv = nsCString(XRE_GetProcessTypeString()); 609 if (XRE_IsUtilityProcess()) { 610 rv += "+"_ns + mozilla::ipc::GetChildAudioActorName(); 611 } 612 return rv; 613 }; 614 virtual nsCString GetCodecName() const = 0; 615 616 // Set a hint of seek target time to decoder. Decoder will drop any decoded 617 // data which pts is smaller than this value. This threshold needs to be clear 618 // after reset decoder. To clear it explicitly, call this method with 619 // TimeUnit::Invalid(). 620 // Decoder may not honor this value. However, it'd be better that 621 // video decoder implements this API to improve seek performance. 622 // Note: it should be called before Input() or after Flush(). 623 virtual void SetSeekThreshold(const media::TimeUnit& aTime) {} 624 625 // When playing adaptive playback, recreating an Android video decoder will 626 // cause the transition not smooth during resolution change. 627 // Reuse the decoder if the decoder support recycling. 628 // Currently, only Android video decoder will return true. 629 virtual bool SupportDecoderRecycling() const { return false; } 630 631 // Recycling decoder is controlled by the pref and other different conditions 632 // in our media pipeloine. True if the decoder should always be reused no 633 // matter what situation is. 634 virtual bool ShouldDecoderAlwaysBeRecycled() const { return false; } 635 636 enum class ConversionRequired { 637 kNeedNone = 0, 638 kNeedAVCC = 1, 639 kNeedAnnexB = 2, 640 kNeedHVCC = 3, 641 }; 642 643 // Indicates that the decoder requires a specific format. 644 // The demuxed data will be converted accordingly before feeding it to 645 // Decode(). 646 virtual ConversionRequired NeedsConversion() const { 647 return ConversionRequired::kNeedNone; 648 } 649 650 // Properties specific to platform decoders. They can be consulted by the 651 // client to improve playback smoothness. When not defined by the decoder, the 652 // client can choose its own. 653 // MaxNumVideoBuffers: some platform decoders have limited output buffers. 654 // This specifies how many (output) video buffers can be held at most by the 655 // client. Holding more will exhaust the deocder buffer pool and block further 656 // decoding. 657 // MinNumVideoBuffers: some platform decoders have decoding time longer than 658 // frame duration. To avoid frame dropping in this case, the client queues 659 // frames before starting to play. This value tells the client the least 660 // amount of frames it should queue. 661 // MaxNumCurrentImages: specifies how many (output) video buffers are current 662 // (renderable) at a time. 663 // The result is not accurated until Init() is resolved. 664 MOZ_DEFINE_ENUM_CLASS_WITH_TOSTRING_AT_CLASS_SCOPE(PropertyName, 665 (MaxNumVideoBuffers, 666 MinNumVideoBuffers, 667 MaxNumCurrentImages)); 668 // Generic type for property values to avoid breaking existing client code in 669 // the future. 670 using PropertyValue = Variant<uint32_t>; 671 virtual Maybe<PropertyValue> GetDecodeProperty(PropertyName aName) const { 672 return Nothing(); 673 } 674 }; 675 676 } // namespace mozilla 677 678 #endif