#include "third_party/blink/renderer/modules/mediarecorder/audio_track_recorder.h"
#include <stdint.h>
#include <optional>
#include <string>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/test/gmock_callback_support.h"
#include "base/time/time.h"
#include "media/audio/simple_sources.h"
#include "media/base/audio_buffer.h"
#include "media/base/audio_decoder.h"
#include "media/base/audio_encoder.h"
#include "media/base/audio_sample_types.h"
#include "media/base/channel_layout.h"
#include "media/base/decoder_status.h"
#include "media/base/mock_media_log.h"
#include "media/media_buildflags.h"
#include "media/mojo/buildflags.h"
#include "media/mojo/mojom/audio_encoder.mojom.h"
#include "media/mojo/mojom/interface_factory.mojom.h"
#include "media/mojo/services/mojo_audio_encoder_service.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/web/web_heap.h"
#include "third_party/blink/renderer/modules/mediarecorder/audio_track_mojo_encoder.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/heap/weak_cell.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_component_impl.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/testing/task_environment.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/opus/src/include/opus.h"
#if BUILDFLAG(IS_WIN)
#include <objbase.h>
#include "media/gpu/windows/mf_audio_encoder.h"
#define HAS_AAC_ENCODER …
#endif
#if BUILDFLAG(IS_MAC) && BUILDFLAG(USE_PROPRIETARY_CODECS)
#include "media/filters/mac/audio_toolbox_audio_encoder.h"
#define HAS_AAC_ENCODER …
#endif
#if BUILDFLAG(ENABLE_FFMPEG) && BUILDFLAG(USE_PROPRIETARY_CODECS)
#include "media/filters/ffmpeg_audio_decoder.h"
#define HAS_AAC_DECODER …
#endif
TimeTicks;
RunOnceClosure;
_;
Invoke;
namespace {
constexpr int kExpectedNumOutputs = …;
constexpr int kDefaultSampleRate = …;
constexpr int kMediaStreamAudioTrackBufferDurationMs = …;
constexpr int kOpusBufferDurationMs = …;
constexpr int kAacFramesPerBuffer = …;
int FramesPerInputBuffer(int sample_rate) { … }
#if HAS_AAC_ENCODER
class TestInterfaceFactory : public media::mojom::InterfaceFactory {
public:
TestInterfaceFactory() = default;
~TestInterfaceFactory() override {
#if BUILDFLAG(IS_WIN)
::CoUninitialize();
#endif
}
void BindRequest(mojo::ScopedMessagePipeHandle handle) {
receiver_.Bind(mojo::PendingReceiver<media::mojom::InterfaceFactory>(
std::move(handle)));
receiver_.set_disconnect_handler(WTF::BindOnce(
&TestInterfaceFactory::OnConnectionError, base::Unretained(this)));
}
void OnConnectionError() { receiver_.reset(); }
void CreateAudioEncoder(
mojo::PendingReceiver<media::mojom::AudioEncoder> receiver) override {
#if BUILDFLAG(IS_MAC)
auto platform_audio_encoder =
std::make_unique<media::AudioToolboxAudioEncoder>();
#elif BUILDFLAG(IS_WIN)
HRESULT hr = ::CoInitializeEx(
nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
DCHECK(SUCCEEDED(hr));
auto platform_audio_encoder = std::make_unique<media::MFAudioEncoder>(
blink::scheduler::GetSequencedTaskRunnerForTesting());
#else
#error "Unknown platform encoder."
#endif
audio_encoder_receivers_.Add(
std::make_unique<media::MojoAudioEncoderService>(
std::move(platform_audio_encoder)),
std::move(receiver));
}
void CreateVideoDecoder(
mojo::PendingReceiver<media::mojom::VideoDecoder> receiver,
mojo::PendingRemote<media::stable::mojom::StableVideoDecoder>
dst_video_decoder) override {}
void CreateAudioDecoder(
mojo::PendingReceiver<media::mojom::AudioDecoder> receiver) override {}
void CreateDefaultRenderer(
const std::string& audio_device_id,
mojo::PendingReceiver<media::mojom::Renderer> receiver) override {}
#if BUILDFLAG(ENABLE_CAST_RENDERER)
void CreateCastRenderer(
const base::UnguessableToken& overlay_plane_id,
mojo::PendingReceiver<media::mojom::Renderer> receiver) override {}
#endif
#if BUILDFLAG(IS_ANDROID)
void CreateMediaPlayerRenderer(
mojo::PendingRemote<media::mojom::MediaPlayerRendererClientExtension>
client_extension_remote,
mojo::PendingReceiver<media::mojom::Renderer> receiver,
mojo::PendingReceiver<media::mojom::MediaPlayerRendererExtension>
renderer_extension_receiver) override {}
void CreateFlingingRenderer(
const std::string& presentation_id,
mojo::PendingRemote<media::mojom::FlingingRendererClientExtension>
client_extension,
mojo::PendingReceiver<media::mojom::Renderer> receiver) override {}
#endif
void CreateCdm(const media::CdmConfig& cdm_config,
CreateCdmCallback callback) override {
std::move(callback).Run(mojo::NullRemote(), nullptr,
media::CreateCdmStatus::kCdmNotSupported);
}
#if BUILDFLAG(IS_WIN)
void CreateMediaFoundationRenderer(
mojo::PendingRemote<media::mojom::MediaLog> media_log_remote,
mojo::PendingReceiver<media::mojom::Renderer> receiver,
mojo::PendingReceiver<media::mojom::MediaFoundationRendererExtension>
renderer_extension_receiver,
mojo::PendingRemote<
::media::mojom::MediaFoundationRendererClientExtension>
client_extension_remote) override {}
#endif
private:
mojo::Receiver<media::mojom::InterfaceFactory> receiver_{this};
mojo::UniqueReceiverSet<media::mojom::AudioEncoder> audio_encoder_receivers_;
};
#endif
}
namespace blink {
struct ATRTestParams { … };
const ATRTestParams kATRTestParams[] = …;
std::string ParamsToString(
const ::testing::TestParamInfo<ATRTestParams>& info) { … }
class MockAudioTrackRecorderCallbackInterface
: public GarbageCollected<MockAudioTrackRecorderCallbackInterface>,
public AudioTrackRecorder::CallbackInterface { … };
class AudioTrackRecorderTest : public testing::TestWithParam<ATRTestParams> { … };
TEST_P(AudioTrackRecorderTest, RecordAndValidate) { … }
TEST_P(AudioTrackRecorderTest, ChangeFormatMidRecording) { … }
TEST_P(AudioTrackRecorderTest, ChangeFormatWhilePaused) { … }
TEST_P(AudioTrackRecorderTest, SameFormat) { … }
TEST_P(AudioTrackRecorderTest, PacketSize) { … }
TEST_P(AudioTrackRecorderTest, PauseResume) { … }
TEST_P(AudioTrackRecorderTest, PauseMidStream) { … }
#if BUILDFLAG(IS_MAC)
#define MAYBE_PauseTwice …
#else
#define MAYBE_PauseTwice …
#endif
TEST_P(AudioTrackRecorderTest, MAYBE_PauseTwice) { … }
TEST_P(AudioTrackRecorderTest, ResumeWithoutPausing) { … }
INSTANTIATE_TEST_SUITE_P(…);
}