Bug 1860899 - Allocate/Free AVCodecContext in Init()/Shutdown() r=media-playback-reviewers,padenot

This patch partially implements Init() and Shutdown() to allocate and
release the AVCodecContext respectively. These two functions will be
exectued on the platform's encoder task queue specified in the given
CreateEncoderParams. Thus, the allocated AVCodecContext is a task-queue
only member variable.

Depends on D193952

Differential Revision: https://phabricator.services.mozilla.com/D194580
This commit is contained in:
Chun-Min Chang 2023-12-08 06:17:09 +00:00
parent 994f2860fc
commit 398bee4aa4
3 changed files with 72 additions and 7 deletions

View File

@ -30,7 +30,8 @@ already_AddRefed<MediaDataEncoder> FFmpegEncoderModule<V>::CreateVideoEncoder(
}
// TODO: Properly create a FFmpegVideoDecoder with parameters in aParams.
RefPtr<MediaDataEncoder> encoder = new FFmpegVideoEncoder<V>(mLib);
RefPtr<MediaDataEncoder> encoder =
new FFmpegVideoEncoder<V>(mLib, codecId, aParams.mTaskQueue);
FFMPEGV_LOG("ffmpeg %s encoder: %s has been created",
aParams.mConfig.mMimeType.get(),
encoder->GetDescriptionName().get());

View File

@ -29,9 +29,18 @@ AVCodecID GetFFmpegEncoderCodecId<LIBAV_VER>(const nsACString& aMimeType) {
return AV_CODEC_ID_NONE;
}
FFmpegVideoEncoder<LIBAV_VER>::FFmpegVideoEncoder(const FFmpegLibWrapper* aLib,
AVCodecID aCodecID,
RefPtr<TaskQueue> aTaskQueue)
: mLib(aLib), mCodecID(aCodecID), mTaskQueue(aTaskQueue), mCodecContext(nullptr) {
MOZ_ASSERT(mLib);
MOZ_ASSERT(mTaskQueue);
};
RefPtr<MediaDataEncoder::InitPromise> FFmpegVideoEncoder<LIBAV_VER>::Init() {
FFMPEGV_LOG("Init");
return InitPromise::CreateAndReject(NS_ERROR_NOT_IMPLEMENTED, __func__);
return InvokeAsync(mTaskQueue, this, __func__,
&FFmpegVideoEncoder::ProcessInit);
}
RefPtr<MediaDataEncoder::EncodePromise> FFmpegVideoEncoder<LIBAV_VER>::Encode(
@ -47,7 +56,11 @@ RefPtr<MediaDataEncoder::EncodePromise> FFmpegVideoEncoder<LIBAV_VER>::Drain() {
RefPtr<ShutdownPromise> FFmpegVideoEncoder<LIBAV_VER>::Shutdown() {
FFMPEGV_LOG("Shutdown");
return ShutdownPromise::CreateAndReject(false, __func__);
RefPtr<FFmpegVideoEncoder<LIBAV_VER>> self = this;
return InvokeAsync(mTaskQueue, __func__, [self]() {
self->ProcessShutdown();
return self->mTaskQueue->BeginShutdown();
});
}
RefPtr<GenericPromise> FFmpegVideoEncoder<LIBAV_VER>::SetBitrate(
@ -70,4 +83,46 @@ nsCString FFmpegVideoEncoder<LIBAV_VER>::GetDescriptionName() const {
#endif
}
RefPtr<MediaDataEncoder::InitPromise>
FFmpegVideoEncoder<LIBAV_VER>::ProcessInit() {
MOZ_ASSERT(mTaskQueue->IsOnCurrentThread());
FFMPEGV_LOG("ProcessInit");
AVCodec* codec = mLib->avcodec_find_encoder(mCodecID);
if (!codec) {
FFMPEGV_LOG("failed to find ffmpeg encoder for codec id %d", mCodecID);
return InitPromise::CreateAndReject(
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL("Unable to find codec")),
__func__);
}
FFMPEGV_LOG("find codec: %s", codec->name);
MOZ_ASSERT(!mCodecContext);
if (!(mCodecContext = mLib->avcodec_alloc_context3(codec))) {
FFMPEGV_LOG("failed to allocate ffmpeg context for codec %s", codec->name);
return InitPromise::CreateAndReject(
MediaResult(NS_ERROR_OUT_OF_MEMORY,
RESULT_DETAIL("Failed to initialize ffmpeg context")),
__func__);
}
// TODO: setting mCodecContext.
FFMPEGV_LOG("%s has been initialized", codec->name);
return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__);
}
void FFmpegVideoEncoder<LIBAV_VER>::ProcessShutdown() {
MOZ_ASSERT(mTaskQueue->IsOnCurrentThread());
FFMPEGV_LOG("ProcessShutdown");
if (mCodecContext) {
mLib->av_freep(&mCodecContext);
mCodecContext = nullptr;
}
}
} // namespace mozilla

View File

@ -28,11 +28,11 @@ class FFmpegVideoEncoder {};
template <>
class FFmpegVideoEncoder<LIBAV_VER> final : public MediaDataEncoder {
public:
explicit FFmpegVideoEncoder(const FFmpegLibWrapper* aLib) : mLib(aLib) {
MOZ_ASSERT(mLib);
};
FFmpegVideoEncoder(const FFmpegLibWrapper* aLib, AVCodecID aCodecID,
RefPtr<TaskQueue> aTaskQueue);
/* MediaDataEncoder Methods */
// All methods run on the task queue, except for GetDescriptionName.
RefPtr<InitPromise> Init() override;
RefPtr<EncodePromise> Encode(const MediaData* aSample) override;
RefPtr<EncodePromise> Drain() override;
@ -43,8 +43,17 @@ class FFmpegVideoEncoder<LIBAV_VER> final : public MediaDataEncoder {
private:
~FFmpegVideoEncoder() = default;
// Methods only called on mTaskQueue.
RefPtr<InitPromise> ProcessInit();
void ProcessShutdown();
// This refers to a static FFmpegLibWrapper, so raw pointer is adequate.
const FFmpegLibWrapper* mLib; // set in constructor
const FFmpegLibWrapper* mLib;
const AVCodecID mCodecID;
const RefPtr<TaskQueue> mTaskQueue;
// mTaskQueue only.
AVCodecContext* mCodecContext;
};
} // namespace mozilla