/* 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/. */ #ifndef DOM_MEDIA_PLATFORMS_ANDROID_ANDROIDDATAENCODER_H_ #define DOM_MEDIA_PLATFORMS_ANDROID_ANDROIDDATAENCODER_H_ #include "MediaData.h" #include "PlatformEncoderModule.h" #include "JavaCallbacksSupport.h" #include "mozilla/Maybe.h" #include "mozilla/Mutex.h" namespace mozilla { class AndroidDataEncoder final : public MediaDataEncoder { public: AndroidDataEncoder(const EncoderConfig& aConfig, const RefPtr& aTaskQueue) : mConfig(aConfig), mTaskQueue(aTaskQueue) { MOZ_ASSERT(mConfig.mSize.width > 0 && mConfig.mSize.height > 0); MOZ_ASSERT(mTaskQueue); } ~AndroidDataEncoder() { MOZ_ASSERT(!mJavaEncoder); } RefPtr Init() override; RefPtr Encode(const MediaData* aSample) override; RefPtr Drain() override; RefPtr Shutdown() override; RefPtr SetBitrate(uint32_t aBitsPerSec) override; RefPtr Reconfigure( const RefPtr& aConfigurationChanges) override { // General reconfiguration interface not implemented right now return MediaDataEncoder::ReconfigurationPromise::CreateAndReject( NS_ERROR_DOM_MEDIA_FATAL_ERR, __func__); }; nsCString GetDescriptionName() const override { return "Android Encoder"_ns; } private: class CallbacksSupport final : public JavaCallbacksSupport { public: explicit CallbacksSupport(AndroidDataEncoder* aEncoder) : mMutex("AndroidDataEncoder::CallbacksSupport") { MutexAutoLock lock(mMutex); mEncoder = aEncoder; } ~CallbacksSupport() { MutexAutoLock lock(mMutex); mEncoder = nullptr; } void HandleInput(int64_t aTimestamp, bool aProcessed) override; void HandleOutput(java::Sample::Param aSample, java::SampleBuffer::Param aBuffer) override; void HandleOutputFormatChanged( java::sdk::MediaFormat::Param aFormat) override; void HandleError(const MediaResult& aError) override; private: Mutex mMutex; AndroidDataEncoder* mEncoder MOZ_GUARDED_BY(mMutex); }; friend class CallbacksSupport; // Methods only called on mTaskQueue. RefPtr ProcessInit(); RefPtr ProcessEncode(const RefPtr& aSample); RefPtr ProcessDrain(); RefPtr ProcessShutdown(); void ProcessInput(); void ProcessOutput(java::Sample::GlobalRef&& aSample, java::SampleBuffer::GlobalRef&& aBuffer); RefPtr GetOutputData(java::SampleBuffer::Param aBuffer, const int32_t aOffset, const int32_t aSize, const bool aIsKeyFrame); RefPtr GetOutputDataH264(java::SampleBuffer::Param aBuffer, const int32_t aOffset, const int32_t aSize, const bool aIsKeyFrame); void Error(const MediaResult& aError); void AssertOnTaskQueue() const { MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); } EncoderConfig mConfig; RefPtr mTaskQueue; // Can be accessed on any thread, but only written on during init. bool mIsHardwareAccelerated = false; java::CodecProxy::GlobalRef mJavaEncoder; java::CodecProxy::NativeCallbacks::GlobalRef mJavaCallbacks; java::sdk::MediaFormat::GlobalRef mFormat; // Preallocated Java object used as a reusable storage for input buffer // information. Contents must be changed only on mTaskQueue. java::sdk::MediaCodec::BufferInfo::GlobalRef mInputBufferInfo; MozPromiseHolder mDrainPromise; // Accessed on mTaskqueue only. RefPtr mYUVBuffer; EncodedData mEncodedData; // SPS/PPS NALUs for realtime usage, avcC otherwise. RefPtr mConfigData; enum class DrainState { DRAINABLE, DRAINING, DRAINED }; DrainState mDrainState = DrainState::DRAINABLE; Maybe mError; }; } // namespace mozilla #endif