commit 241dcd4b983f27807d1c4b06ee8751e2fa57778a
parent bd392be720e17790cae9bb4423bcddbfd28c5e02
Author: Chun-Min Chang <chun.m.chang@gmail.com>
Date: Tue, 30 Sep 2025 23:39:50 +0000
Bug 1986544 - Ensure minimum keyframe count in MediaDataEncoder's gTests r=padenot
Differential Revision: https://phabricator.services.mozilla.com/D264167
Diffstat:
1 file changed, 45 insertions(+), 8 deletions(-)
diff --git a/dom/media/gtest/TestMediaDataEncoder.cpp b/dom/media/gtest/TestMediaDataEncoder.cpp
@@ -266,21 +266,36 @@ static Result<MediaDataEncoder::EncodedData, MediaResult> Drain(
return output;
}
-static Result<MediaDataEncoder::EncodedData, MediaResult> Encode(
+struct EncodeResult {
+ MediaDataEncoder::EncodedData mEncodedData;
+ size_t mInputKeyframes = 0;
+};
+static Result<EncodeResult, MediaResult> EncodeWithInputStats(
const RefPtr<MediaDataEncoder>& aEncoder, const size_t aNumFrames,
MediaDataEncoderTest::FrameSource& aSource) {
MOZ_RELEASE_ASSERT(aEncoder);
+ size_t inputKeyframes = 0;
MediaDataEncoder::EncodedData output;
for (size_t i = 0; i < aNumFrames; i++) {
RefPtr<MediaData> frame = aSource.GetFrame(i);
+ if (frame->mKeyframe) {
+ inputKeyframes++;
+ }
output.AppendElements(MOZ_TRY(WaitFor(aEncoder->Encode(frame))));
}
output.AppendElements(std::move(MOZ_TRY(Drain(aEncoder))));
- return output;
+ return EncodeResult{std::move(output), inputKeyframes};
+}
+
+static Result<MediaDataEncoder::EncodedData, MediaResult> Encode(
+ const RefPtr<MediaDataEncoder>& aEncoder, const size_t aNumFrames,
+ MediaDataEncoderTest::FrameSource& aSource) {
+ EncodeResult r = MOZ_TRY(EncodeWithInputStats(aEncoder, aNumFrames, aSource));
+ return std::move(r.mEncodedData);
}
-static Result<MediaDataEncoder::EncodedData, MediaResult> EncodeBatch(
+static Result<EncodeResult, MediaResult> EncodeBatchWithInputStats(
const RefPtr<MediaDataEncoder>& aEncoder, const size_t aTotalNumFrames,
MediaDataEncoderTest::FrameSource& aSource, const size_t aBatchSize) {
if (aBatchSize == 0 || aTotalNumFrames == 0) {
@@ -289,10 +304,15 @@ static Result<MediaDataEncoder::EncodedData, MediaResult> EncodeBatch(
"Batch size and total number of frames must be greater than 0"));
}
+ size_t inputKeyframes = 0;
MediaDataEncoder::EncodedData output;
nsTArray<RefPtr<MediaData>> frames;
for (size_t i = 0; i < aTotalNumFrames; i++) {
- frames.AppendElement(aSource.GetFrame(i));
+ RefPtr<MediaData> frame = aSource.GetFrame(i);
+ frames.AppendElement(frame);
+ if (frame->mKeyframe) {
+ inputKeyframes++;
+ }
if (frames.Length() == aBatchSize || i == aTotalNumFrames - 1) {
nsTArray<RefPtr<MediaData>> batch = std::move(frames);
output.AppendElements(
@@ -302,7 +322,18 @@ static Result<MediaDataEncoder::EncodedData, MediaResult> EncodeBatch(
MOZ_RELEASE_ASSERT(frames.IsEmpty());
output.AppendElements(std::move(MOZ_TRY(Drain(aEncoder))));
- return output;
+ return EncodeResult{std::move(output), inputKeyframes};
+}
+
+template <typename T>
+size_t GetKeyFrameCount(const T& aData) {
+ size_t count = 0;
+ for (auto sample : aData) {
+ if (sample->mKeyframe) {
+ count++;
+ }
+ }
+ return count;
}
Result<uint8_t, nsresult> GetNALUSize(const mozilla::MediaRawData* aSample) {
@@ -398,19 +429,23 @@ static void H264EncodesTest(Usage aUsage,
EXPECT_TRUE(isAVCC ? AnnexB::IsAVCC(output[0])
: AnnexB::IsAnnexB(output[0]));
WaitForShutdown(e);
+ output.Clear();
// Encode multiple frames and output in AnnexB/AVCC format.
e = CreateH264Encoder(
aUsage, EncoderConfig::SampleFormat(dom::ImageBitmapFormat::YUV420P),
aFrameSource.GetSize(), ScalabilityMode::None, aSpecific);
EXPECT_TRUE(EnsureInit(e));
- output = GET_OR_RETURN_ON_ERROR(Encode(e, NUM_FRAMES, aFrameSource));
+ EncodeResult r = GET_OR_RETURN_ON_ERROR(
+ EncodeWithInputStats(e, NUM_FRAMES, aFrameSource));
+ output = std::move(r.mEncodedData);
if (aUsage == Usage::Realtime && kImageSize4K <= aFrameSource.GetSize()) {
// Realtime encoding may drop frames for large frame sizes.
EXPECT_LE(output.Length(), NUM_FRAMES);
} else {
EXPECT_EQ(output.Length(), NUM_FRAMES);
}
+ EXPECT_GE(GetKeyFrameCount(output), r.mInputKeyframes);
if (isAVCC) {
uint8_t naluSize = GetNALUSize(output[0]).unwrapOr(0);
EXPECT_GT(naluSize, 0);
@@ -487,14 +522,16 @@ static void H264EncodeBatchTest(
EXPECT_TRUE(EnsureInit(e));
constexpr size_t batchSize = 6;
- MediaDataEncoder::EncodedData output = GET_OR_RETURN_ON_ERROR(
- EncodeBatch(e, NUM_FRAMES, aFrameSource, batchSize));
+ EncodeResult r = GET_OR_RETURN_ON_ERROR(
+ EncodeBatchWithInputStats(e, NUM_FRAMES, aFrameSource, batchSize));
+ MediaDataEncoder::EncodedData output = std::move(r.mEncodedData);
if (aUsage == Usage::Realtime && kImageSize4K <= aFrameSource.GetSize()) {
// Realtime encoding may drop frames for large frame sizes.
EXPECT_LE(output.Length(), NUM_FRAMES);
} else {
EXPECT_EQ(output.Length(), NUM_FRAMES);
}
+ EXPECT_GE(GetKeyFrameCount(output), r.mInputKeyframes);
if (isAVCC) {
uint8_t naluSize = GetNALUSize(output[0]).unwrapOr(0);
EXPECT_GT(naluSize, 0);