commit 20ccceccb14fb410de75a67867434695600d314d
parent 9a220092ae144225bdffb3d0202ed9075949c674
Author: Andreas Pehrson <apehrson@mozilla.com>
Date: Fri, 5 Dec 2025 16:34:21 +0000
Bug 1999970 - Handle dropped-frame callbacks in the GMP PEM. r=media-playback-reviewers,padenot
The OpenH264 encoder may silently drop a frame due to rate control.
If not handled in the GMP PEM, it may risk stalling waiting for an encoded frame
that never arrives.
Differential Revision: https://phabricator.services.mozilla.com/D274755
Diffstat:
2 files changed, 31 insertions(+), 11 deletions(-)
diff --git a/dom/media/platforms/agnostic/gmp/GMPVideoEncoder.cpp b/dom/media/platforms/agnostic/gmp/GMPVideoEncoder.cpp
@@ -448,7 +448,16 @@ void GMPVideoEncoder::Encoded(GMPVideoEncodedFrame* aEncodedFrame,
void GMPVideoEncoder::Dropped(uint64_t aTimestamp) {
MOZ_ASSERT(IsOnGMPThread());
- // TODO: implement
+
+ RefPtr<EncodePromise::Private> promise;
+ if (!mPendingEncodes.Remove(aTimestamp, getter_AddRefs(promise))) {
+ GMP_LOG_WARNING(
+ "[%p] GMPVideoEncoder::Dropped -- no frame matching timestamp %" PRIu64,
+ this, aTimestamp);
+ return;
+ }
+
+ promise->Reject(NS_ERROR_DOM_MEDIA_DROPPED_BY_ENCODER_ERR, __func__);
}
void GMPVideoEncoder::Teardown(const MediaResult& aResult,
@@ -515,19 +524,29 @@ void GMPVideoEncoder::EncodeNextSample(
GetCurrentSerialEventTarget(), __func__,
[self = RefPtr{this}, inputs = std::move(aInputs),
outputs = std::move(aOutputs)](
- MediaDataEncoder::EncodedData&& aData) mutable {
+ EncodePromise::ResolveOrRejectValue&& aValue) mutable {
self->mEncodeBatchRequest.Complete();
+ if (aValue.IsReject() &&
+ aValue.RejectValue().Code() !=
+ NS_ERROR_DOM_MEDIA_DROPPED_BY_ENCODER_ERR) {
+ auto& error = aValue.RejectValue();
+ GMP_LOG_ERROR(
+ "[%p] GMPVideoEncoder::EncodeNextSample -- failed to encode: "
+ "%s",
+ self.get(), error.Description().get());
+ self->mEncodeBatchPromise.Reject(error, __func__);
+ return;
+ }
inputs.RemoveElementAt(0);
- outputs.AppendElements(aData);
+ if (aValue.IsResolve()) {
+ outputs.AppendElements(aValue.ResolveValue());
+ } else {
+ GMP_LOG_WARNING(
+ "[%p] GMPVideoEncoder::EncodeNextSample -- dropped by "
+ "encoder: %s. Continuing.",
+ self.get(), aValue.RejectValue().Description().get());
+ }
self->EncodeNextSample(std::move(inputs), std::move(outputs));
- },
- [self = RefPtr{this}](const MediaResult& aError) {
- self->mEncodeBatchRequest.Complete();
- GMP_LOG_ERROR(
- "[%p] GMPVideoEncoder::EncodeNextSample -- failed to encode: "
- "%s",
- self.get(), aError.Description().get());
- self->mEncodeBatchPromise.Reject(aError, __func__);
})
->Track(mEncodeBatchRequest);
}
diff --git a/xpcom/base/ErrorList.py b/xpcom/base/ErrorList.py
@@ -1191,6 +1191,7 @@ with modules["DOM_MEDIA"]:
errors["NS_ERROR_DOM_MEDIA_RANGE_ERR"] = FAILURE(105)
errors["NS_ERROR_DOM_MEDIA_TYPE_ERR"] = FAILURE(106)
errors["NS_ERROR_DOM_MEDIA_MEDIA_ENGINE_INITIALIZATION_ERR"] = FAILURE(107)
+ errors["NS_ERROR_DOM_MEDIA_DROPPED_BY_ENCODER_ERR"] = FAILURE(108)
# =======================================================================
# 42: NS_ERROR_MODULE_URL_CLASSIFIER