Skip to content

Commit ae28af6

Browse files
committed
Bug 1978232 - Add batch encoding tests for H264 encoders r=jolin
This patch adds tests for batch encoding for H264 encoders with different parameters sets, including both AVCC and AnnexB formats. These tests ensure that batch encoding produces expected outputs under varying configurations. Differential Revision: https://phabricator.services.mozilla.com/D262212
1 parent d35966d commit ae28af6

File tree

1 file changed

+110
-2
lines changed

1 file changed

+110
-2
lines changed

dom/media/gtest/TestMediaDataEncoder.cpp

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,13 +274,37 @@ static Result<MediaDataEncoder::EncodedData, MediaResult> Encode(
274274
MediaDataEncoder::EncodedData output;
275275
for (size_t i = 0; i < aNumFrames; i++) {
276276
RefPtr<MediaData> frame = aSource.GetFrame(i);
277-
output.AppendElements(MOZ_TRY(
278-
WaitFor(aEncoder->Encode(frame))));
277+
output.AppendElements(MOZ_TRY(WaitFor(aEncoder->Encode(frame))));
279278
}
280279
output.AppendElements(std::move(MOZ_TRY(Drain(aEncoder))));
281280
return output;
282281
}
283282

283+
static Result<MediaDataEncoder::EncodedData, MediaResult> EncodeBatch(
284+
const RefPtr<MediaDataEncoder>& aEncoder, const size_t aTotalNumFrames,
285+
MediaDataEncoderTest::FrameSource& aSource, const size_t aBatchSize) {
286+
if (aBatchSize == 0 || aTotalNumFrames == 0) {
287+
return Err(MediaResult(
288+
NS_ERROR_INVALID_ARG,
289+
"Batch size and total number of frames must be greater than 0"));
290+
}
291+
292+
MediaDataEncoder::EncodedData output;
293+
nsTArray<RefPtr<MediaData>> frames;
294+
for (size_t i = 0; i < aTotalNumFrames; i++) {
295+
frames.AppendElement(aSource.GetFrame(i));
296+
if (frames.Length() == aBatchSize || i == aTotalNumFrames - 1) {
297+
nsTArray<RefPtr<MediaData>> batch = std::move(frames);
298+
output.AppendElements(
299+
MOZ_TRY(WaitFor(aEncoder->Encode(std::move(batch)))));
300+
}
301+
}
302+
MOZ_RELEASE_ASSERT(frames.IsEmpty());
303+
304+
output.AppendElements(std::move(MOZ_TRY(Drain(aEncoder))));
305+
return output;
306+
}
307+
284308
Result<uint8_t, nsresult> GetNALUSize(const mozilla::MediaRawData* aSample) {
285309
return AVCCConfig::Parse(aSample).map(
286310
[](AVCCConfig config) { return config.NALUSize(); });
@@ -445,6 +469,90 @@ TEST_F(MediaDataEncoderTest, H264Encodes4KAVCCRealtime) {
445469
H264EncodesTest(Usage::Realtime, AsVariant(kH264SpecificAVCC), mData4K);
446470
}
447471

472+
static void H264EncodeBatchTest(
473+
Usage aUsage, const EncoderConfig::CodecSpecific& aSpecific,
474+
MediaDataEncoderTest::FrameSource& aFrameSource) {
475+
ASSERT_TRUE(aSpecific.is<H264Specific>());
476+
ASSERT_TRUE(aSpecific.as<H264Specific>().mFormat ==
477+
H264BitStreamFormat::ANNEXB ||
478+
aSpecific.as<H264Specific>().mFormat == H264BitStreamFormat::AVC);
479+
480+
RUN_IF_SUPPORTED(CodecType::H264, [&]() {
481+
bool isAVCC =
482+
aSpecific.as<H264Specific>().mFormat == H264BitStreamFormat::AVC;
483+
484+
RefPtr<MediaDataEncoder> e = CreateH264Encoder(
485+
aUsage, EncoderConfig::SampleFormat(dom::ImageBitmapFormat::YUV420P),
486+
aFrameSource.GetSize(), ScalabilityMode::None, aSpecific);
487+
EnsureInit(e);
488+
489+
constexpr size_t batchSize = 6;
490+
MediaDataEncoder::EncodedData output = GET_OR_RETURN_ON_ERROR(
491+
EncodeBatch(e, NUM_FRAMES, aFrameSource, batchSize));
492+
if (aUsage == Usage::Realtime && kImageSize4K <= aFrameSource.GetSize()) {
493+
// Realtime encoding may drop frames for large frame sizes.
494+
EXPECT_LE(output.Length(), NUM_FRAMES);
495+
} else {
496+
EXPECT_EQ(output.Length(), NUM_FRAMES);
497+
}
498+
if (isAVCC) {
499+
uint8_t naluSize = GetNALUSize(output[0]).unwrapOr(0);
500+
EXPECT_GT(naluSize, 0);
501+
EXPECT_LE(naluSize, 4);
502+
for (auto frame : output) {
503+
if (frame->mExtraData && !frame->mExtraData->IsEmpty()) {
504+
naluSize = GetNALUSize(frame).unwrapOr(0);
505+
EXPECT_GT(naluSize, 0);
506+
EXPECT_LE(naluSize, 4);
507+
}
508+
EXPECT_TRUE(IsValidAVCC(frame, naluSize).isOk());
509+
}
510+
} else {
511+
for (auto frame : output) {
512+
EXPECT_TRUE(AnnexB::IsAnnexB(frame));
513+
}
514+
}
515+
516+
WaitForShutdown(e);
517+
});
518+
};
519+
520+
TEST_F(MediaDataEncoderTest, H264EncodeBatchAnnexBRecord) {
521+
H264EncodeBatchTest(Usage::Record, AsVariant(kH264SpecificAnnexB), mData);
522+
}
523+
524+
TEST_F(MediaDataEncoderTest, H264EncodeBatchAnnexBRealtime) {
525+
H264EncodeBatchTest(Usage::Realtime, AsVariant(kH264SpecificAnnexB), mData);
526+
}
527+
528+
TEST_F(MediaDataEncoderTest, H264EncodeBatchAVCCRecord) {
529+
H264EncodeBatchTest(Usage::Record, AsVariant(kH264SpecificAVCC), mData);
530+
}
531+
532+
TEST_F(MediaDataEncoderTest, H264EncodeBatchAVCCRealtime) {
533+
H264EncodeBatchTest(Usage::Realtime, AsVariant(kH264SpecificAVCC), mData);
534+
}
535+
536+
TEST_F(MediaDataEncoderTest, H264EncodeBatch4KAnnexBRecord) {
537+
SKIP_IF_ANDROID_SW(); // Android SW can't encode 4K.
538+
H264EncodeBatchTest(Usage::Record, AsVariant(kH264SpecificAnnexB), mData4K);
539+
}
540+
541+
TEST_F(MediaDataEncoderTest, H264EncodeBatch4KAnnexBRealtime) {
542+
SKIP_IF_ANDROID_SW(); // Android SW can't encode 4K.
543+
H264EncodeBatchTest(Usage::Realtime, AsVariant(kH264SpecificAnnexB), mData4K);
544+
}
545+
546+
TEST_F(MediaDataEncoderTest, H264EncodeBatch4KAVCCRecord) {
547+
SKIP_IF_ANDROID_SW(); // Android SW can't encode 4K.
548+
H264EncodeBatchTest(Usage::Record, AsVariant(kH264SpecificAVCC), mData4K);
549+
}
550+
551+
TEST_F(MediaDataEncoderTest, H264EncodeBatch4KAVCCRealtime) {
552+
SKIP_IF_ANDROID_SW(); // Android SW can't encode 4K.
553+
H264EncodeBatchTest(Usage::Realtime, AsVariant(kH264SpecificAVCC), mData4K);
554+
}
555+
448556
#if !defined(ANDROID)
449557
static void H264EncodeAfterDrainTest(
450558
Usage aUsage, const EncoderConfig::CodecSpecific& aSpecific,

0 commit comments

Comments
 (0)