From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- dom/media/gtest/TestMuxer.cpp | 212 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 dom/media/gtest/TestMuxer.cpp (limited to 'dom/media/gtest/TestMuxer.cpp') diff --git a/dom/media/gtest/TestMuxer.cpp b/dom/media/gtest/TestMuxer.cpp new file mode 100644 index 0000000000..1c6c128eef --- /dev/null +++ b/dom/media/gtest/TestMuxer.cpp @@ -0,0 +1,212 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include + +#include "ContainerWriter.h" +#include "EncodedFrame.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "Muxer.h" +#include "OpusTrackEncoder.h" +#include "WebMWriter.h" + +using namespace mozilla; +using media::TimeUnit; +using testing::_; +using testing::ElementsAre; +using testing::Return; +using testing::StaticAssertTypeEq; + +static RefPtr CreateOpusMetadata(int32_t aChannels, + float aSamplingFrequency, + size_t aIdHeaderSize, + size_t aCommentHeaderSize) { + auto opusMetadata = MakeRefPtr(); + opusMetadata->mChannels = aChannels; + opusMetadata->mSamplingFrequency = aSamplingFrequency; + opusMetadata->mIdHeader.SetLength(aIdHeaderSize); + for (size_t i = 0; i < opusMetadata->mIdHeader.Length(); i++) { + opusMetadata->mIdHeader[i] = 0; + } + opusMetadata->mCommentHeader.SetLength(aCommentHeaderSize); + for (size_t i = 0; i < opusMetadata->mCommentHeader.Length(); i++) { + opusMetadata->mCommentHeader[i] = 0; + } + return opusMetadata; +} + +static RefPtr CreateVP8Metadata(int32_t aWidth, + int32_t aHeight) { + auto vp8Metadata = MakeRefPtr(); + vp8Metadata->mWidth = aWidth; + vp8Metadata->mDisplayWidth = aWidth; + vp8Metadata->mHeight = aHeight; + vp8Metadata->mDisplayHeight = aHeight; + return vp8Metadata; +} + +static RefPtr CreateFrame(EncodedFrame::FrameType aType, + const TimeUnit& aTime, + const TimeUnit& aDuration, + size_t aDataSize) { + auto data = MakeRefPtr(); + data->SetLength(aDataSize); + if (aType == EncodedFrame::OPUS_AUDIO_FRAME) { + // Opus duration is in samples, so figure out how many samples will put us + // closest to aDurationUs without going over. + return MakeRefPtr(aTime, + TimeUnitToFrames(aDuration, 48000).value(), + 48000, aType, std::move(data)); + } + return MakeRefPtr( + aTime, TimeUnitToFrames(aDuration, USECS_PER_S).value(), USECS_PER_S, + aType, std::move(data)); +} + +class MockContainerWriter : public ContainerWriter { + public: + MOCK_METHOD2(WriteEncodedTrack, + nsresult(const nsTArray>&, uint32_t)); + MOCK_METHOD1(SetMetadata, + nsresult(const nsTArray>&)); + MOCK_METHOD0(IsWritingComplete, bool()); + MOCK_METHOD2(GetContainerData, + nsresult(nsTArray>*, uint32_t)); +}; + +TEST(MuxerTest, AudioOnly) +{ + MediaQueue audioQueue; + MediaQueue videoQueue; + videoQueue.Finish(); + MockContainerWriter* writer = new MockContainerWriter(); + Muxer muxer(WrapUnique(writer), audioQueue, videoQueue); + + // Prepare data + + auto opusMeta = CreateOpusMetadata(1, 48000, 16, 16); + auto audioFrame = + CreateFrame(EncodedFrame::OPUS_AUDIO_FRAME, TimeUnit::FromSeconds(0), + TimeUnit::FromSeconds(0.2), 4096); + + // Expectations + + EXPECT_CALL(*writer, SetMetadata(ElementsAre(opusMeta))) + .WillOnce(Return(NS_OK)); + EXPECT_CALL(*writer, WriteEncodedTrack(ElementsAre(audioFrame), + ContainerWriter::END_OF_STREAM)) + .WillOnce(Return(NS_OK)); + EXPECT_CALL(*writer, GetContainerData(_, ContainerWriter::GET_HEADER)) + .WillOnce(Return(NS_OK)); + EXPECT_CALL(*writer, GetContainerData(_, ContainerWriter::FLUSH_NEEDED)) + .WillOnce(Return(NS_OK)); + EXPECT_CALL(*writer, IsWritingComplete()).Times(0); + + // Test + + EXPECT_EQ(muxer.SetMetadata(nsTArray>({opusMeta})), + NS_OK); + audioQueue.Push(audioFrame); + audioQueue.Finish(); + nsTArray> buffers; + EXPECT_EQ(muxer.GetData(&buffers), NS_OK); +} + +TEST(MuxerTest, AudioVideo) +{ + MediaQueue audioQueue; + MediaQueue videoQueue; + MockContainerWriter* writer = new MockContainerWriter(); + Muxer muxer(WrapUnique(writer), audioQueue, videoQueue); + + // Prepare data + + auto opusMeta = CreateOpusMetadata(1, 48000, 16, 16); + auto vp8Meta = CreateVP8Metadata(640, 480); + auto audioFrame = + CreateFrame(EncodedFrame::OPUS_AUDIO_FRAME, TimeUnit::FromSeconds(0), + TimeUnit::FromSeconds(0.2), 4096); + auto videoFrame = + CreateFrame(EncodedFrame::VP8_I_FRAME, TimeUnit::FromSeconds(0), + TimeUnit::FromSeconds(0.05), 65536); + + // Expectations + + EXPECT_CALL(*writer, SetMetadata(ElementsAre(opusMeta, vp8Meta))) + .WillOnce(Return(NS_OK)); + EXPECT_CALL(*writer, WriteEncodedTrack(ElementsAre(videoFrame, audioFrame), + ContainerWriter::END_OF_STREAM)) + .WillOnce(Return(NS_OK)); + EXPECT_CALL(*writer, GetContainerData(_, ContainerWriter::GET_HEADER)) + .WillOnce(Return(NS_OK)); + EXPECT_CALL(*writer, GetContainerData(_, ContainerWriter::FLUSH_NEEDED)) + .WillOnce(Return(NS_OK)); + EXPECT_CALL(*writer, IsWritingComplete()).Times(0); + + // Test + + EXPECT_EQ(muxer.SetMetadata( + nsTArray>({opusMeta, vp8Meta})), + NS_OK); + audioQueue.Push(audioFrame); + audioQueue.Finish(); + videoQueue.Push(videoFrame); + videoQueue.Finish(); + nsTArray> buffers; + EXPECT_EQ(muxer.GetData(&buffers), NS_OK); +} + +TEST(MuxerTest, AudioVideoOutOfOrder) +{ + MediaQueue audioQueue; + MediaQueue videoQueue; + MockContainerWriter* writer = new MockContainerWriter(); + Muxer muxer(WrapUnique(writer), audioQueue, videoQueue); + + // Prepare data + + auto opusMeta = CreateOpusMetadata(1, 48000, 16, 16); + auto vp8Meta = CreateVP8Metadata(640, 480); + auto a0 = + CreateFrame(EncodedFrame::OPUS_AUDIO_FRAME, TimeUnit::FromMicroseconds(0), + TimeUnit::FromMicroseconds(48), 4096); + auto v0 = + CreateFrame(EncodedFrame::VP8_I_FRAME, TimeUnit::FromMicroseconds(0), + TimeUnit::FromMicroseconds(50), 65536); + auto a48 = CreateFrame(EncodedFrame::OPUS_AUDIO_FRAME, + TimeUnit::FromMicroseconds(48), + TimeUnit::FromMicroseconds(48), 4096); + auto v50 = + CreateFrame(EncodedFrame::VP8_I_FRAME, TimeUnit::FromMicroseconds(50), + TimeUnit::FromMicroseconds(50), 65536); + + // Expectations + + EXPECT_CALL(*writer, SetMetadata(ElementsAre(opusMeta, vp8Meta))) + .WillOnce(Return(NS_OK)); + EXPECT_CALL(*writer, WriteEncodedTrack(ElementsAre(v0, a0, a48, v50), + ContainerWriter::END_OF_STREAM)) + .WillOnce(Return(NS_OK)); + EXPECT_CALL(*writer, GetContainerData(_, ContainerWriter::GET_HEADER)) + .WillOnce(Return(NS_OK)); + EXPECT_CALL(*writer, GetContainerData(_, ContainerWriter::FLUSH_NEEDED)) + .WillOnce(Return(NS_OK)); + EXPECT_CALL(*writer, IsWritingComplete()).Times(0); + + // Test + + EXPECT_EQ(muxer.SetMetadata( + nsTArray>({opusMeta, vp8Meta})), + NS_OK); + audioQueue.Push(a0); + videoQueue.Push(v0); + videoQueue.Push(v50); + videoQueue.Finish(); + audioQueue.Push(a48); + audioQueue.Finish(); + nsTArray> buffers; + EXPECT_EQ(muxer.GetData(&buffers), NS_OK); +} -- cgit v1.2.3