Skip to content

Commit 6d9fcd3

Browse files
committed
Bug 1978232 - Add batch endoing API to WMFMediaDataEncoder r=media-playback-reviewers,jolin
This patch introduces a new API in `MediaDataEncoder` for batch encoding and implement it for `WMFMediaDataEncoder`. Differential Revision: https://phabricator.services.mozilla.com/D261493
1 parent ed66df4 commit 6d9fcd3

File tree

5 files changed

+81
-0
lines changed

5 files changed

+81
-0
lines changed

dom/media/ipc/RemoteMediaDataEncoderChild.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ void RemoteMediaDataEncoderChild::DoSendInit() {
123123

124124
self->mIsHardwareAccelerated = initResponse.hardware();
125125
self->mHardwareAcceleratedReason = initResponse.hardwareReason();
126+
// TODO: Get batch-encoding capability.
126127
self->mInitPromise.ResolveIfExists(true, __func__);
127128
},
128129
[self = RefPtr{this}](const mozilla::ipc::ResponseRejectReason& aReason) {

dom/media/ipc/RemoteMediaDataEncoderParent.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ IPCResult RemoteMediaDataEncoderParent::RecvInit(InitResolver&& aResolver) {
7272
return;
7373
}
7474

75+
// TODO: Pass batch-encoding capability.
7576
nsCString hardwareReason;
7677
bool hardware = encoder->IsHardwareAccelerated(hardwareReason);
7778
resolver(EncodeInitCompletionIPDL{encoder->GetDescriptionName(),

dom/media/platforms/PlatformEncoderModule.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,17 @@ class MediaDataEncoder {
8686
// or empty when there is none available yet.
8787
virtual RefPtr<EncodePromise> Encode(const MediaData* aSample) = 0;
8888

89+
// Inserts a batch of samples into the encoder's encode pipeline. The
90+
// EncodePromise it returns will be resolved with already encoded MediaRawData
91+
// at the moment, or empty when there is none available yet.
92+
virtual RefPtr<EncodePromise> Encode(nsTArray<RefPtr<MediaData>>&& aSamples) {
93+
MOZ_ASSERT_UNREACHABLE("Encode samples in a batch is not implemented");
94+
return EncodePromise::CreateAndReject(
95+
MediaResult(NS_ERROR_NOT_IMPLEMENTED,
96+
"Encode samples in a batch is not implemented"),
97+
__func__);
98+
}
99+
89100
// Attempt to reconfigure the encoder on the fly. This can fail if the
90101
// underlying PEM doesn't support this type of reconfiguration.
91102
virtual RefPtr<ReconfigurationPromise> Reconfigure(

dom/media/platforms/wmf/WMFMediaDataEncoder.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,20 @@ RefPtr<EncodePromise> WMFMediaDataEncoder::Encode(const MediaData* aSample) {
5151
mTaskQueue, this, __func__, &WMFMediaDataEncoder::ProcessEncode,
5252
std::move(sample));
5353
}
54+
RefPtr<EncodePromise> WMFMediaDataEncoder::Encode(
55+
nsTArray<RefPtr<MediaData>>&& aSamples) {
56+
WMF_ENC_LOGD("Encode: num of samples=%zu", aSamples.Length());
57+
MOZ_ASSERT(!aSamples.IsEmpty());
58+
59+
nsTArray<RefPtr<const VideoData>> videoSamples;
60+
for (auto& sample : aSamples) {
61+
videoSamples.AppendElement(sample->As<const VideoData>());
62+
}
63+
64+
return InvokeAsync(mTaskQueue, this, __func__,
65+
&WMFMediaDataEncoder::ProcessEncodeBatch,
66+
std::move(videoSamples));
67+
}
5468
RefPtr<EncodePromise> WMFMediaDataEncoder::Drain() {
5569
WMF_ENC_LOGD("Drain");
5670
return InvokeAsync(mTaskQueue, this, __func__,
@@ -249,6 +263,55 @@ RefPtr<EncodePromise> WMFMediaDataEncoder::ProcessEncode(
249263
return p;
250264
}
251265

266+
RefPtr<EncodePromise> WMFMediaDataEncoder::ProcessEncodeBatch(
267+
nsTArray<RefPtr<const VideoData>>&& aSamples) {
268+
AssertOnTaskQueue();
269+
MOZ_ASSERT(mEncoder);
270+
MOZ_ASSERT(!aSamples.IsEmpty());
271+
MOZ_ASSERT(mEncodePromise.IsEmpty());
272+
MOZ_ASSERT(!mEncodeRequest.Exists());
273+
274+
WMF_ENC_LOGD("ProcessEncodeBatch: num of samples=%zu", aSamples.Length());
275+
276+
nsTArray<MFTEncoder::InputSample> inputs;
277+
for (auto& sample : aSamples) {
278+
RefPtr<IMFSample> nv12 = ConvertToNV12InputSample(std::move(sample));
279+
if (!nv12) {
280+
WMF_ENC_LOGE(
281+
"failed to convert samples(ts=%s duration=%s) into NV12 format",
282+
sample->mTime.ToString().get(), sample->mDuration.ToString().get());
283+
return EncodePromise::CreateAndReject(
284+
MediaResult(
285+
NS_ERROR_DOM_MEDIA_FATAL_ERR,
286+
RESULT_DETAIL("Failed to convert sample into NV12 format")),
287+
__func__);
288+
}
289+
inputs.AppendElement(MFTEncoder::InputSample{
290+
.mSample = std::move(nv12), .mKeyFrameRequested = sample->mKeyframe});
291+
}
292+
293+
RefPtr<EncodePromise> p = mEncodePromise.Ensure(__func__);
294+
295+
mEncoder->Encode(std::move(inputs))
296+
->Then(
297+
GetCurrentSerialEventTarget(), __func__,
298+
[self = RefPtr<WMFMediaDataEncoder>(this)](
299+
MFTEncoder::EncodedData&& aOutput) {
300+
self->mEncodeRequest.Complete();
301+
self->mEncodePromise.Resolve(
302+
self->ProcessOutputSamples(std::move(aOutput)), __func__);
303+
},
304+
[self =
305+
RefPtr<WMFMediaDataEncoder>(this)](const MediaResult& aError) {
306+
WMF_ENC_SLOGE("Encode failed: %s", aError.Description().get());
307+
self->mEncodeRequest.Complete();
308+
self->mEncodePromise.Reject(aError, __func__);
309+
})
310+
->Track(mEncodeRequest);
311+
312+
return p;
313+
}
314+
252315
RefPtr<EncodePromise> WMFMediaDataEncoder::ProcessDrain() {
253316
AssertOnTaskQueue();
254317
MOZ_ASSERT(mEncoder);

dom/media/platforms/wmf/WMFMediaDataEncoder.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class WMFMediaDataEncoder final : public MediaDataEncoder {
2626

2727
RefPtr<InitPromise> Init() override;
2828
RefPtr<EncodePromise> Encode(const MediaData* aSample) override;
29+
RefPtr<EncodePromise> Encode(nsTArray<RefPtr<MediaData>>&& aSamples) override;
2930
RefPtr<EncodePromise> Drain() override;
3031
RefPtr<ShutdownPromise> Shutdown() override;
3132
RefPtr<GenericPromise> SetBitrate(uint32_t aBitsPerSec) override;
@@ -74,6 +75,8 @@ class WMFMediaDataEncoder final : public MediaDataEncoder {
7475
void SetConfigData(const nsTArray<UINT8>& aHeader);
7576

7677
RefPtr<EncodePromise> ProcessEncode(RefPtr<const VideoData>&& aSample);
78+
RefPtr<EncodePromise> ProcessEncodeBatch(
79+
nsTArray<RefPtr<const VideoData>>&& aSamples);
7780
RefPtr<EncodePromise> ProcessDrain();
7881

7982
already_AddRefed<IMFSample> ConvertToNV12InputSample(
@@ -101,6 +104,8 @@ class WMFMediaDataEncoder final : public MediaDataEncoder {
101104
// Can be accessed on any thread, but only written on during init.
102105
Atomic<bool> mIsHardwareAccelerated;
103106

107+
// Both Encode and EncodeBatch share mEncodePromise and mEncodeRequest, as
108+
// concurrent calls are not allowed.
104109
MozPromiseHolder<EncodePromise> mEncodePromise;
105110
MozPromiseRequestHolder<MFTEncoder::EncodePromise> mEncodeRequest;
106111

0 commit comments

Comments
 (0)