mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-03 17:58:55 +02:00 
			
		
		
		
	This patch makes MediaDataEncoder declare its refcounting as virtual. This will allow a future patch in this series to add subclasses that have multiple superclasses using refcounting. Differential Revision: https://phabricator.services.mozilla.com/D211650
		
			
				
	
	
		
			216 lines
		
	
	
	
		
			8.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			216 lines
		
	
	
	
		
			8.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
 | 
						|
/* 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/. */
 | 
						|
 | 
						|
#if !defined(PlatformEncoderModule_h_)
 | 
						|
#  define PlatformEncoderModule_h_
 | 
						|
 | 
						|
#  include "MP4Decoder.h"
 | 
						|
#  include "MediaResult.h"
 | 
						|
#  include "VPXDecoder.h"
 | 
						|
#  include "mozilla/Maybe.h"
 | 
						|
#  include "mozilla/MozPromise.h"
 | 
						|
#  include "mozilla/RefPtr.h"
 | 
						|
#  include "mozilla/TaskQueue.h"
 | 
						|
#  include "mozilla/dom/ImageBitmapBinding.h"
 | 
						|
#  include "nsISupportsImpl.h"
 | 
						|
#  include "VideoUtils.h"
 | 
						|
#  include "EncoderConfig.h"
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
 | 
						|
class MediaDataEncoder;
 | 
						|
class MediaData;
 | 
						|
struct EncoderConfigurationChangeList;
 | 
						|
 | 
						|
class PlatformEncoderModule {
 | 
						|
 public:
 | 
						|
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PlatformEncoderModule)
 | 
						|
 | 
						|
  virtual already_AddRefed<MediaDataEncoder> CreateVideoEncoder(
 | 
						|
      const EncoderConfig& aConfig, const RefPtr<TaskQueue>& aTaskQueue) const {
 | 
						|
    return nullptr;
 | 
						|
  };
 | 
						|
 | 
						|
  virtual already_AddRefed<MediaDataEncoder> CreateAudioEncoder(
 | 
						|
      const EncoderConfig& aConfig, const RefPtr<TaskQueue>& aTaskQueue) const {
 | 
						|
    return nullptr;
 | 
						|
  };
 | 
						|
 | 
						|
  using CreateEncoderPromise = MozPromise<RefPtr<MediaDataEncoder>, MediaResult,
 | 
						|
                                          /* IsExclusive = */ true>;
 | 
						|
 | 
						|
  // Indicates if the PlatformDecoderModule supports encoding of a codec.
 | 
						|
  virtual bool Supports(const EncoderConfig& aConfig) const = 0;
 | 
						|
  virtual bool SupportsCodec(CodecType aCodecType) const = 0;
 | 
						|
 | 
						|
  // Returns a readable name for this Platform Encoder Module
 | 
						|
  virtual const char* GetName() const = 0;
 | 
						|
 | 
						|
  // Asychronously create an encoder
 | 
						|
  RefPtr<PlatformEncoderModule::CreateEncoderPromise> AsyncCreateEncoder(
 | 
						|
      const EncoderConfig& aEncoderConfig, const RefPtr<TaskQueue>& aTaskQueue);
 | 
						|
 | 
						|
 protected:
 | 
						|
  PlatformEncoderModule() = default;
 | 
						|
  virtual ~PlatformEncoderModule() = default;
 | 
						|
};
 | 
						|
 | 
						|
class MediaDataEncoder {
 | 
						|
 public:
 | 
						|
  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
 | 
						|
 | 
						|
  static bool IsVideo(const CodecType aCodec) {
 | 
						|
    return aCodec > CodecType::_BeginVideo_ && aCodec < CodecType::_EndVideo_;
 | 
						|
  }
 | 
						|
  static bool IsAudio(const CodecType aCodec) {
 | 
						|
    return aCodec > CodecType::_BeginAudio_ && aCodec < CodecType::_EndAudio_;
 | 
						|
  }
 | 
						|
 | 
						|
  using InitPromise = MozPromise<bool, MediaResult, /* IsExclusive = */ true>;
 | 
						|
  using EncodedData = nsTArray<RefPtr<MediaRawData>>;
 | 
						|
  using EncodePromise =
 | 
						|
      MozPromise<EncodedData, MediaResult, /* IsExclusive = */ true>;
 | 
						|
  using ReconfigurationPromise =
 | 
						|
      MozPromise<bool, MediaResult, /* IsExclusive = */ true>;
 | 
						|
 | 
						|
  // Initialize the encoder. It should be ready to encode once the returned
 | 
						|
  // promise resolves. The encoder should do any initialization here, rather
 | 
						|
  // than in its constructor or PlatformEncoderModule::Create*Encoder(),
 | 
						|
  // so that if the client needs to shutdown during initialization,
 | 
						|
  // it can call Shutdown() to cancel this operation. Any initialization
 | 
						|
  // that requires blocking the calling thread in this function *must*
 | 
						|
  // be done here so that it can be canceled by calling Shutdown()!
 | 
						|
  virtual RefPtr<InitPromise> Init() = 0;
 | 
						|
 | 
						|
  // Inserts a sample into the encoder's encode pipeline. The EncodePromise it
 | 
						|
  // returns will be resolved with already encoded MediaRawData at the moment,
 | 
						|
  // or empty when there is none available yet.
 | 
						|
  virtual RefPtr<EncodePromise> Encode(const MediaData* aSample) = 0;
 | 
						|
 | 
						|
  // Attempt to reconfigure the encoder on the fly. This can fail if the
 | 
						|
  // underlying PEM doesn't support this type of reconfiguration.
 | 
						|
  virtual RefPtr<ReconfigurationPromise> Reconfigure(
 | 
						|
      const RefPtr<const EncoderConfigurationChangeList>&
 | 
						|
          aConfigurationChanges) = 0;
 | 
						|
 | 
						|
  // Causes all complete samples in the pipeline that can be encoded to be
 | 
						|
  // output. It indicates that there is no more input sample to insert.
 | 
						|
  // This function is asynchronous.
 | 
						|
  // The MediaDataEncoder shall resolve the pending EncodePromise with drained
 | 
						|
  // samples. Drain will be called multiple times until the resolved
 | 
						|
  // EncodePromise is empty which indicates that there are no more samples to
 | 
						|
  // drain.
 | 
						|
  virtual RefPtr<EncodePromise> Drain() = 0;
 | 
						|
 | 
						|
  // Cancels all init/encode/drain operations, and shuts down the encoder. The
 | 
						|
  // platform encoder should clean up any resources it's using and release
 | 
						|
  // memory etc. The shutdown promise will be resolved once the encoder has
 | 
						|
  // completed shutdown. The client will delete the decoder once the promise is
 | 
						|
  // resolved.
 | 
						|
  // The ShutdownPromise must only ever be resolved.
 | 
						|
  virtual RefPtr<ShutdownPromise> Shutdown() = 0;
 | 
						|
 | 
						|
  virtual RefPtr<GenericPromise> SetBitrate(uint32_t aBitsPerSec) {
 | 
						|
    return GenericPromise::CreateAndResolve(true, __func__);
 | 
						|
  }
 | 
						|
 | 
						|
  // Decoder needs to decide whether or not hardware acceleration is supported
 | 
						|
  // after creating. It doesn't need to call Init() before calling this
 | 
						|
  // function.
 | 
						|
  virtual bool IsHardwareAccelerated(nsACString& aFailureReason) const {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  // Return the name of the MediaDataEncoder, only used for encoding.
 | 
						|
  // May be accessed in a non thread-safe fashion.
 | 
						|
  virtual nsCString GetDescriptionName() const = 0;
 | 
						|
 | 
						|
  friend class PlatformEncoderModule;
 | 
						|
 | 
						|
 protected:
 | 
						|
  virtual ~MediaDataEncoder() = default;
 | 
						|
};
 | 
						|
 | 
						|
// Wrap a type to make it unique. This allows using ergonomically in the Variant
 | 
						|
// below. Simply aliasing with `using` isn't enough, because typedefs in C++
 | 
						|
// don't produce strong types, so two integer variants result in
 | 
						|
// the same type, making it ambiguous to the Variant code.
 | 
						|
// T is the type to be wrapped. Phantom is a type that is only used to
 | 
						|
// disambiguate and should be unique in the program.
 | 
						|
template <typename T, typename Phantom>
 | 
						|
class StrongTypedef {
 | 
						|
 public:
 | 
						|
  explicit StrongTypedef(T const& value) : mValue(value) {}
 | 
						|
  explicit StrongTypedef(T&& value) : mValue(std::move(value)) {}
 | 
						|
  T& get() { return mValue; }
 | 
						|
  T const& get() const { return mValue; }
 | 
						|
 | 
						|
 private:
 | 
						|
  T mValue;
 | 
						|
};
 | 
						|
 | 
						|
// Dimensions of the video frames
 | 
						|
using DimensionsChange =
 | 
						|
    StrongTypedef<gfx::IntSize, struct DimensionsChangeType>;
 | 
						|
// Expected display size of the encoded frames, can influence encoding
 | 
						|
using DisplayDimensionsChange =
 | 
						|
    StrongTypedef<Maybe<gfx::IntSize>, struct DisplayDimensionsChangeType>;
 | 
						|
// If present, the bitrate in kbps of the encoded stream. If absent, let the
 | 
						|
// platform decide.
 | 
						|
using BitrateChange = StrongTypedef<Maybe<uint32_t>, struct BitrateChangeType>;
 | 
						|
// If present, the expected framerate of the output video stream. If absent,
 | 
						|
// infer from the input frames timestamp.
 | 
						|
using FramerateChange =
 | 
						|
    StrongTypedef<Maybe<double>, struct FramerateChangeType>;
 | 
						|
// The bitrate mode (variable, constant) of the encoding
 | 
						|
using BitrateModeChange =
 | 
						|
    StrongTypedef<BitrateMode, struct BitrateModeChangeType>;
 | 
						|
// The usage for the encoded stream, this influence latency, ordering, etc.
 | 
						|
using UsageChange = StrongTypedef<Usage, struct UsageChangeType>;
 | 
						|
// If present, the expected content of the video frames (screen, movie, etc.).
 | 
						|
// The value the string can have isn't decided just yet. When absent, the
 | 
						|
// encoder uses generic settings.
 | 
						|
using ContentHintChange =
 | 
						|
    StrongTypedef<Maybe<nsString>, struct ContentHintTypeType>;
 | 
						|
// If present, the new sample-rate of the audio
 | 
						|
using SampleRateChange = StrongTypedef<uint32_t, struct SampleRateChangeType>;
 | 
						|
// If present, the new sample-rate of the audio
 | 
						|
using NumberOfChannelsChange =
 | 
						|
    StrongTypedef<uint32_t, struct NumberOfChannelsChangeType>;
 | 
						|
 | 
						|
// A change to a parameter of an encoder instance.
 | 
						|
using EncoderConfigurationItem =
 | 
						|
    Variant<DimensionsChange, DisplayDimensionsChange, BitrateModeChange,
 | 
						|
            BitrateChange, FramerateChange, UsageChange, ContentHintChange,
 | 
						|
            SampleRateChange, NumberOfChannelsChange>;
 | 
						|
 | 
						|
// A list of changes to an encoder configuration, that _might_ be able to change
 | 
						|
// on the fly. Not all encoder modules can adjust their configuration on the
 | 
						|
// fly.
 | 
						|
struct EncoderConfigurationChangeList {
 | 
						|
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(EncoderConfigurationChangeList)
 | 
						|
  bool Empty() const { return mChanges.IsEmpty(); }
 | 
						|
  template <typename T>
 | 
						|
  void Push(const T& aItem) {
 | 
						|
    mChanges.AppendElement(aItem);
 | 
						|
  }
 | 
						|
  nsString ToString() const;
 | 
						|
 | 
						|
  nsTArray<EncoderConfigurationItem> mChanges;
 | 
						|
 | 
						|
 private:
 | 
						|
  ~EncoderConfigurationChangeList() = default;
 | 
						|
};
 | 
						|
 | 
						|
// Just by inspecting the configuration and before asking the PEM, it's
 | 
						|
// sometimes possible to know that a media won't be able to be encoded. For
 | 
						|
// example, VP8 encodes the frame size on 14 bits, so a resolution of more than
 | 
						|
// 16383x16383 pixels cannot work.
 | 
						|
bool CanLikelyEncode(const EncoderConfig& aConfig);
 | 
						|
 | 
						|
}  // namespace mozilla
 | 
						|
 | 
						|
#endif /* PlatformEncoderModule_h_ */
 |