| Index: media/cast/sender/video_encoder_unittest.cc
|
| diff --git a/media/cast/sender/video_encoder_impl_unittest.cc b/media/cast/sender/video_encoder_unittest.cc
|
| similarity index 29%
|
| rename from media/cast/sender/video_encoder_impl_unittest.cc
|
| rename to media/cast/sender/video_encoder_unittest.cc
|
| index dab16eace30273c17b2fe39993cf14dfe883cb0d..a528e287cf0a5e787076c42b99744d4ae997e083 100644
|
| --- a/media/cast/sender/video_encoder_impl_unittest.cc
|
| +++ b/media/cast/sender/video_encoder_unittest.cc
|
| @@ -3,6 +3,7 @@
|
| // found in the LICENSE file.
|
|
|
| #include <vector>
|
| +#include <utility>
|
|
|
| #include "base/bind.h"
|
| #include "base/memory/ref_counted.h"
|
| @@ -10,18 +11,25 @@
|
| #include "media/base/video_frame.h"
|
| #include "media/cast/cast_defines.h"
|
| #include "media/cast/cast_environment.h"
|
| -#include "media/cast/sender/video_encoder_impl.h"
|
| +#include "media/cast/sender/fake_video_encode_accelerator_factory.h"
|
| +#include "media/cast/sender/video_frame_factory.h"
|
| +#include "media/cast/sender/video_encoder.h"
|
| #include "media/cast/test/fake_single_thread_task_runner.h"
|
| #include "media/cast/test/utility/default_config.h"
|
| #include "media/cast/test/utility/video_utility.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| +#if defined(OS_MACOSX)
|
| +#include "media/cast/sender/h264_vt_encoder.h"
|
| +#endif
|
| +
|
| namespace media {
|
| namespace cast {
|
|
|
| -class VideoEncoderImplTest : public ::testing::TestWithParam<Codec> {
|
| +class VideoEncoderTest
|
| + : public ::testing::TestWithParam<std::pair<Codec, bool>> {
|
| protected:
|
| - VideoEncoderImplTest()
|
| + VideoEncoderTest()
|
| : testing_clock_(new base::SimpleTestTickClock()),
|
| task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
|
| cast_environment_(new CastEnvironment(
|
| @@ -36,101 +44,213 @@ class VideoEncoderImplTest : public ::testing::TestWithParam<Codec> {
|
| first_frame_time_ = testing_clock_->NowTicks();
|
| }
|
|
|
| - ~VideoEncoderImplTest() override {}
|
| + ~VideoEncoderTest() override {}
|
|
|
| void SetUp() override {
|
| - video_config_.codec = GetParam();
|
| + video_config_.codec = GetParam().first;
|
| + video_config_.use_external_encoder = GetParam().second;
|
| +
|
| + if (video_config_.use_external_encoder)
|
| + vea_factory_.reset(new FakeVideoEncodeAcceleratorFactory(task_runner_));
|
| }
|
|
|
| void TearDown() override {
|
| video_encoder_.reset();
|
| - task_runner_->RunTasks();
|
| + RunTasksAndAdvanceClock();
|
| }
|
|
|
| void CreateEncoder(bool three_buffer_mode) {
|
| ASSERT_EQ(STATUS_UNINITIALIZED, operational_status_);
|
| video_config_.max_number_of_video_buffers_used =
|
| (three_buffer_mode ? 3 : 1);
|
| - video_encoder_.reset(new VideoEncoderImpl(
|
| + video_encoder_ = VideoEncoder::Create(
|
| cast_environment_,
|
| video_config_,
|
| - base::Bind(&VideoEncoderImplTest::OnOperationalStatusChange,
|
| - base::Unretained(this))));
|
| - task_runner_->RunTasks();
|
| - ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
|
| + base::Bind(&VideoEncoderTest::OnOperationalStatusChange,
|
| + base::Unretained(this)),
|
| + base::Bind(
|
| + &FakeVideoEncodeAcceleratorFactory::CreateVideoEncodeAccelerator,
|
| + base::Unretained(vea_factory_.get())),
|
| + base::Bind(&FakeVideoEncodeAcceleratorFactory::CreateSharedMemory,
|
| + base::Unretained(vea_factory_.get()))).Pass();
|
| + RunTasksAndAdvanceClock();
|
| + if (is_encoder_present())
|
| + ASSERT_EQ(STATUS_INITIALIZED, operational_status_);
|
| + }
|
| +
|
| + bool is_encoder_present() const {
|
| + return !!video_encoder_;
|
| + }
|
| +
|
| + bool is_testing_software_vp8_encoder() const {
|
| + return video_config_.codec == CODEC_VIDEO_VP8 &&
|
| + !video_config_.use_external_encoder;
|
| + }
|
| +
|
| + bool is_testing_video_toolbox_encoder() const {
|
| + return
|
| +#if defined(OS_MACOSX)
|
| + (!video_config_.use_external_encoder &&
|
| + H264VideoToolboxEncoder::IsSupported(video_config_)) ||
|
| +#endif
|
| + false;
|
| + }
|
| +
|
| + bool is_testing_platform_encoder() const {
|
| + return video_config_.use_external_encoder ||
|
| + is_testing_video_toolbox_encoder();
|
| }
|
|
|
| VideoEncoder* video_encoder() const {
|
| return video_encoder_.get();
|
| }
|
|
|
| - void AdvanceClock() {
|
| - testing_clock_->Advance(base::TimeDelta::FromMilliseconds(33));
|
| + void DestroyEncoder() {
|
| + video_encoder_.reset();
|
| }
|
|
|
| base::TimeTicks Now() const {
|
| return testing_clock_->NowTicks();
|
| }
|
|
|
| - void RunTasks() const {
|
| - return task_runner_->RunTasks();
|
| + void RunTasksAndAdvanceClock() const {
|
| + const base::TimeDelta frame_duration = base::TimeDelta::FromMicroseconds(
|
| + 1000000.0 / video_config_.max_frame_rate);
|
| +#if defined(OS_MACOSX)
|
| + if (is_testing_video_toolbox_encoder()) {
|
| + // The H264VideoToolboxEncoder (on MAC_OSX and IOS) is not a faked
|
| + // implementation in these tests, and performs its encoding asynchronously
|
| + // on an unknown set of threads. Therefore, sleep the current thread for
|
| + // the real amount of time to avoid excessively spinning the CPU while
|
| + // waiting for something to happen.
|
| + base::PlatformThread::Sleep(frame_duration);
|
| + }
|
| +#endif
|
| + task_runner_->RunTasks();
|
| + testing_clock_->Advance(frame_duration);
|
| }
|
|
|
| int count_frames_delivered() const {
|
| return count_frames_delivered_;
|
| }
|
|
|
| - // Return a callback that, when run, expects the EncodedFrame to have the
|
| - // given properties.
|
| - VideoEncoder::FrameEncodedCallback CreateFrameDeliverCallback(
|
| - uint32 expected_frame_id,
|
| - uint32 expected_last_referenced_frame_id,
|
| - uint32 expected_rtp_timestamp,
|
| - const base::TimeTicks& expected_reference_time) {
|
| - return base::Bind(&VideoEncoderImplTest::DeliverEncodedVideoFrame,
|
| - base::Unretained(this),
|
| - expected_frame_id,
|
| - expected_last_referenced_frame_id,
|
| - expected_rtp_timestamp,
|
| - expected_reference_time);
|
| + void WaitForAllFramesToBeDelivered(int total_expected) const {
|
| + video_encoder_->EmitFrames();
|
| + while (count_frames_delivered_ < total_expected)
|
| + RunTasksAndAdvanceClock();
|
| }
|
|
|
| // Creates a new VideoFrame of the given |size|, filled with a test pattern.
|
| - scoped_refptr<media::VideoFrame> CreateTestVideoFrame(
|
| - const gfx::Size& size) const {
|
| - const scoped_refptr<media::VideoFrame> frame =
|
| - media::VideoFrame::CreateFrame(
|
| - VideoFrame::I420, size, gfx::Rect(size), size,
|
| - testing_clock_->NowTicks() - first_frame_time_);
|
| + // When available, it attempts to use the VideoFrameFactory provided by the
|
| + // encoder.
|
| + scoped_refptr<media::VideoFrame> CreateTestVideoFrame(const gfx::Size& size) {
|
| + const base::TimeDelta timestamp =
|
| + testing_clock_->NowTicks() - first_frame_time_;
|
| + scoped_refptr<media::VideoFrame> frame;
|
| + if (video_frame_factory_)
|
| + frame = video_frame_factory_->MaybeCreateFrame(size, timestamp);
|
| + if (!frame) {
|
| + frame = media::VideoFrame::CreateFrame(
|
| + VideoFrame::I420, size, gfx::Rect(size), size, timestamp);
|
| + }
|
| PopulateVideoFrame(frame.get(), 123);
|
| return frame;
|
| }
|
|
|
| + // Requests encoding the |video_frame| and has the resulting frame delivered
|
| + // via a callback that checks for expected results. Returns false if the
|
| + // encoder rejected the request.
|
| + bool EncodeAndCheckDelivery(
|
| + const scoped_refptr<media::VideoFrame>& video_frame,
|
| + uint32 frame_id,
|
| + uint32 reference_frame_id) {
|
| + return video_encoder_->EncodeVideoFrame(
|
| + video_frame,
|
| + Now(),
|
| + base::Bind(&VideoEncoderTest::DeliverEncodedVideoFrame,
|
| + base::Unretained(this),
|
| + frame_id,
|
| + reference_frame_id,
|
| + TimeDeltaToRtpDelta(video_frame->timestamp(),
|
| + kVideoFrequency),
|
| + Now()));
|
| + }
|
| +
|
| + // If the implementation of |video_encoder_| is ExternalVideoEncoder, check
|
| + // that the VEA factory has responded (by running the callbacks) a specific
|
| + // number of times. Otherwise, check that the VEA factory is inactive.
|
| + void ExpectVEAResponsesForExternalVideoEncoder(
|
| + int vea_response_count,
|
| + int shm_response_count) const {
|
| + if (!vea_factory_)
|
| + return;
|
| + EXPECT_EQ(vea_response_count, vea_factory_->vea_response_count());
|
| + EXPECT_EQ(shm_response_count, vea_factory_->shm_response_count());
|
| + }
|
| +
|
| + void SetVEAFactoryAutoRespond(bool auto_respond) {
|
| + if (vea_factory_)
|
| + vea_factory_->SetAutoRespond(auto_respond);
|
| + }
|
| +
|
| private:
|
| void OnOperationalStatusChange(OperationalStatus status) {
|
| + DVLOG(1) << "OnOperationalStatusChange: from " << operational_status_
|
| + << " to " << status;
|
| operational_status_ = status;
|
| +
|
| + EXPECT_TRUE(operational_status_ == STATUS_CODEC_REINIT_PENDING ||
|
| + operational_status_ == STATUS_INITIALIZED);
|
| +
|
| + // Create the VideoFrameFactory the first time status changes to
|
| + // STATUS_INITIALIZED.
|
| + if (operational_status_ == STATUS_INITIALIZED && !video_frame_factory_)
|
| + video_frame_factory_ = video_encoder_->CreateVideoFrameFactory().Pass();
|
| }
|
|
|
| // Checks that |encoded_frame| matches expected values. This is the method
|
| - // bound in the callback returned from CreateFrameDeliverCallback().
|
| + // bound in the callback returned from EncodeAndCheckDelivery().
|
| void DeliverEncodedVideoFrame(
|
| uint32 expected_frame_id,
|
| uint32 expected_last_referenced_frame_id,
|
| uint32 expected_rtp_timestamp,
|
| const base::TimeTicks& expected_reference_time,
|
| scoped_ptr<EncodedFrame> encoded_frame) {
|
| - if (expected_frame_id != expected_last_referenced_frame_id) {
|
| - EXPECT_EQ(EncodedFrame::DEPENDENT, encoded_frame->dependency);
|
| - } else if (video_config_.max_number_of_video_buffers_used == 1) {
|
| - EXPECT_EQ(EncodedFrame::KEY, encoded_frame->dependency);
|
| - }
|
| + EXPECT_TRUE(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
|
| +
|
| EXPECT_EQ(expected_frame_id, encoded_frame->frame_id);
|
| - EXPECT_EQ(expected_last_referenced_frame_id,
|
| - encoded_frame->referenced_frame_id)
|
| - << "frame id: " << expected_frame_id;
|
| EXPECT_EQ(expected_rtp_timestamp, encoded_frame->rtp_timestamp);
|
| EXPECT_EQ(expected_reference_time, encoded_frame->reference_time);
|
| - EXPECT_FALSE(encoded_frame->data.empty());
|
| +
|
| + // The platform encoders are "black boxes" and may choose to vend key frames
|
| + // and/or empty data at any time. The software encoders, however, should
|
| + // strictly adhere to expected behavior.
|
| + if (is_testing_platform_encoder()) {
|
| + const bool expected_key_frame =
|
| + expected_frame_id == expected_last_referenced_frame_id;
|
| + const bool have_key_frame =
|
| + encoded_frame->dependency == EncodedFrame::KEY;
|
| + EXPECT_EQ(have_key_frame,
|
| + encoded_frame->frame_id == encoded_frame->referenced_frame_id);
|
| + LOG_IF(WARNING, expected_key_frame != have_key_frame)
|
| + << "Platform encoder chose to emit a "
|
| + << (have_key_frame ? "key" : "delta")
|
| + << " frame instead of the expected kind @ frame_id="
|
| + << encoded_frame->frame_id;
|
| + LOG_IF(WARNING, encoded_frame->data.empty())
|
| + << "Platform encoder returned an empty frame @ frame_id="
|
| + << encoded_frame->frame_id;
|
| + } else {
|
| + if (expected_frame_id != expected_last_referenced_frame_id) {
|
| + EXPECT_EQ(EncodedFrame::DEPENDENT, encoded_frame->dependency);
|
| + } else if (video_config_.max_number_of_video_buffers_used == 1) {
|
| + EXPECT_EQ(EncodedFrame::KEY, encoded_frame->dependency);
|
| + }
|
| + EXPECT_EQ(expected_last_referenced_frame_id,
|
| + encoded_frame->referenced_frame_id);
|
| + EXPECT_FALSE(encoded_frame->data.empty());
|
| + }
|
| +
|
| ++count_frames_delivered_;
|
| }
|
|
|
| @@ -138,103 +258,82 @@ class VideoEncoderImplTest : public ::testing::TestWithParam<Codec> {
|
| const scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
|
| const scoped_refptr<CastEnvironment> cast_environment_;
|
| VideoSenderConfig video_config_;
|
| + scoped_ptr<FakeVideoEncodeAcceleratorFactory> vea_factory_;
|
| base::TimeTicks first_frame_time_;
|
| OperationalStatus operational_status_;
|
| scoped_ptr<VideoEncoder> video_encoder_;
|
| + scoped_ptr<VideoFrameFactory> video_frame_factory_;
|
|
|
| int count_frames_delivered_;
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(VideoEncoderImplTest);
|
| + DISALLOW_COPY_AND_ASSIGN(VideoEncoderTest);
|
| };
|
|
|
| // A simple test to encode ten frames of video, expecting to see one key frame
|
| // followed by nine delta frames.
|
| -TEST_P(VideoEncoderImplTest, GeneratesKeyFrameThenOnlyDeltaFrames) {
|
| +TEST_P(VideoEncoderTest, GeneratesKeyFrameThenOnlyDeltaFrames) {
|
| CreateEncoder(false);
|
| + SetVEAFactoryAutoRespond(true);
|
|
|
| EXPECT_EQ(0, count_frames_delivered());
|
| + ExpectVEAResponsesForExternalVideoEncoder(0, 0);
|
|
|
| - scoped_refptr<media::VideoFrame> video_frame =
|
| - CreateTestVideoFrame(gfx::Size(1280, 720));
|
| - EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
|
| - video_frame,
|
| - Now(),
|
| - CreateFrameDeliverCallback(
|
| - 0, 0, TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
|
| - Now())));
|
| - RunTasks();
|
| -
|
| - for (uint32 frame_id = 1; frame_id < 10; ++frame_id) {
|
| - AdvanceClock();
|
| - video_frame = CreateTestVideoFrame(gfx::Size(1280, 720));
|
| - EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
|
| - video_frame,
|
| - Now(),
|
| - CreateFrameDeliverCallback(
|
| - frame_id, frame_id - 1,
|
| - TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
|
| - Now())));
|
| - RunTasks();
|
| + uint32 frame_id = 0;
|
| + uint32 reference_frame_id = 0;
|
| + const gfx::Size frame_size(1280, 720);
|
| +
|
| + // For the platform encoders, the first one or more frames is dropped while
|
| + // the encoder initializes. Then, for all encoders, expect one key frame is
|
| + // delivered.
|
| + bool accepted_first_frame = false;
|
| + do {
|
| + accepted_first_frame = EncodeAndCheckDelivery(
|
| + CreateTestVideoFrame(frame_size), frame_id, reference_frame_id);
|
| + if (!is_testing_platform_encoder())
|
| + EXPECT_TRUE(accepted_first_frame);
|
| + RunTasksAndAdvanceClock();
|
| + } while (!accepted_first_frame);
|
| + ExpectVEAResponsesForExternalVideoEncoder(1, 3);
|
| +
|
| + // Expect the remaining frames are encoded as delta frames.
|
| + for (++frame_id; frame_id < 10; ++frame_id, ++reference_frame_id) {
|
| + EXPECT_TRUE(EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size),
|
| + frame_id,
|
| + reference_frame_id));
|
| + RunTasksAndAdvanceClock();
|
| }
|
|
|
| - EXPECT_EQ(10, count_frames_delivered());
|
| + WaitForAllFramesToBeDelivered(10);
|
| + ExpectVEAResponsesForExternalVideoEncoder(1, 3);
|
| }
|
|
|
| // Tests basic frame dependency rules when using the VP8 encoder in multi-buffer
|
| // mode.
|
| -TEST_P(VideoEncoderImplTest,
|
| - FramesDoNotDependOnUnackedFramesInMultiBufferMode) {
|
| - if (GetParam() != CODEC_VIDEO_VP8)
|
| - return; // Only test multibuffer mode for the VP8 encoder.
|
| +TEST_P(VideoEncoderTest, FramesDoNotDependOnUnackedFramesInMultiBufferMode) {
|
| + if (!is_testing_software_vp8_encoder())
|
| + return; // Only test multibuffer mode for the software VP8 encoder.
|
| CreateEncoder(true);
|
|
|
| EXPECT_EQ(0, count_frames_delivered());
|
|
|
| - scoped_refptr<media::VideoFrame> video_frame =
|
| - CreateTestVideoFrame(gfx::Size(1280, 720));
|
| - EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
|
| - video_frame,
|
| - Now(),
|
| - CreateFrameDeliverCallback(
|
| - 0, 0, TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
|
| - Now())));
|
| - RunTasks();
|
| -
|
| - AdvanceClock();
|
| + const gfx::Size frame_size(1280, 720);
|
| + EXPECT_TRUE(EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), 0, 0));
|
| + RunTasksAndAdvanceClock();
|
| +
|
| video_encoder()->LatestFrameIdToReference(0);
|
| - video_frame = CreateTestVideoFrame(gfx::Size(1280, 720));
|
| - EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
|
| - video_frame,
|
| - Now(),
|
| - CreateFrameDeliverCallback(
|
| - 1, 0, TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
|
| - Now())));
|
| - RunTasks();
|
| -
|
| - AdvanceClock();
|
| + EXPECT_TRUE(EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), 1, 0));
|
| + RunTasksAndAdvanceClock();
|
| +
|
| video_encoder()->LatestFrameIdToReference(1);
|
| - video_frame = CreateTestVideoFrame(gfx::Size(1280, 720));
|
| - EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
|
| - video_frame,
|
| - Now(),
|
| - CreateFrameDeliverCallback(
|
| - 2, 1, TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
|
| - Now())));
|
| - RunTasks();
|
| + EXPECT_TRUE(EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), 2, 1));
|
| + RunTasksAndAdvanceClock();
|
|
|
| video_encoder()->LatestFrameIdToReference(2);
|
|
|
| for (uint32 frame_id = 3; frame_id < 10; ++frame_id) {
|
| - AdvanceClock();
|
| - video_frame = CreateTestVideoFrame(gfx::Size(1280, 720));
|
| - EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
|
| - video_frame,
|
| - Now(),
|
| - CreateFrameDeliverCallback(
|
| - frame_id, 2,
|
| - TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
|
| - Now())));
|
| - RunTasks();
|
| + EXPECT_TRUE(EncodeAndCheckDelivery(
|
| + CreateTestVideoFrame(frame_size), frame_id, 2));
|
| + RunTasksAndAdvanceClock();
|
| }
|
|
|
| EXPECT_EQ(10, count_frames_delivered());
|
| @@ -244,11 +343,12 @@ TEST_P(VideoEncoderImplTest,
|
| // changes. See media/cast/receiver/video_decoder_unittest.cc for a complete
|
| // encode/decode cycle of varied frame sizes that actually checks the frame
|
| // content.
|
| -TEST_P(VideoEncoderImplTest, EncodesVariedFrameSizes) {
|
| +TEST_P(VideoEncoderTest, EncodesVariedFrameSizes) {
|
| CreateEncoder(false);
|
| - ASSERT_TRUE(video_encoder()->CanEncodeVariedFrameSizes());
|
| + SetVEAFactoryAutoRespond(true);
|
|
|
| EXPECT_EQ(0, count_frames_delivered());
|
| + ExpectVEAResponsesForExternalVideoEncoder(0, 0);
|
|
|
| std::vector<gfx::Size> frame_sizes;
|
| frame_sizes.push_back(gfx::Size(1280, 720));
|
| @@ -265,49 +365,90 @@ TEST_P(VideoEncoderImplTest, EncodesVariedFrameSizes) {
|
|
|
| uint32 frame_id = 0;
|
|
|
| - // Encode one frame at each size. Expect nothing but key frames to come out.
|
| + // Encode one frame at each size. For the platform encoders, expect no frames
|
| + // to be delivered since each frame size change will sprun re-initialization
|
| + // of the underlying encoder. Otherwise, expect all key frames to come out.
|
| for (const auto& frame_size : frame_sizes) {
|
| - AdvanceClock();
|
| - const scoped_refptr<media::VideoFrame> video_frame =
|
| - CreateTestVideoFrame(frame_size);
|
| - EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
|
| - video_frame,
|
| - Now(),
|
| - CreateFrameDeliverCallback(
|
| - frame_id,
|
| - frame_id,
|
| - TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
|
| - Now())));
|
| - RunTasks();
|
| - ++frame_id;
|
| + EXPECT_EQ(!is_testing_platform_encoder(),
|
| + EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size),
|
| + frame_id,
|
| + frame_id));
|
| + RunTasksAndAdvanceClock();
|
| + if (!is_testing_platform_encoder())
|
| + ++frame_id;
|
| }
|
|
|
| - // Encode 10 frames at each size. Expect one key frame followed by nine delta
|
| - // frames for each frame size.
|
| + // Encode 10+ frames at each size. For the platform decoders, expect the
|
| + // first one or more frames are dropped while the encoder re-inits. Then, for
|
| + // all encoders, expect one key frame followed by all delta frames.
|
| for (const auto& frame_size : frame_sizes) {
|
| - for (int i = 0; i < 10; ++i) {
|
| - AdvanceClock();
|
| - const scoped_refptr<media::VideoFrame> video_frame =
|
| - CreateTestVideoFrame(frame_size);
|
| - EXPECT_TRUE(video_encoder()->EncodeVideoFrame(
|
| - video_frame,
|
| - Now(),
|
| - CreateFrameDeliverCallback(
|
| - frame_id,
|
| - i == 0 ? frame_id : frame_id - 1,
|
| - TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency),
|
| - Now())));
|
| - RunTasks();
|
| - ++frame_id;
|
| + bool accepted_first_frame = false;
|
| + do {
|
| + accepted_first_frame = EncodeAndCheckDelivery(
|
| + CreateTestVideoFrame(frame_size), frame_id, frame_id);
|
| + if (!is_testing_platform_encoder())
|
| + EXPECT_TRUE(accepted_first_frame);
|
| + RunTasksAndAdvanceClock();
|
| + } while (!accepted_first_frame);
|
| + ++frame_id;
|
| + for (int i = 1; i < 10; ++i, ++frame_id) {
|
| + EXPECT_TRUE(EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size),
|
| + frame_id,
|
| + frame_id - 1));
|
| + RunTasksAndAdvanceClock();
|
| }
|
| }
|
|
|
| - EXPECT_EQ(static_cast<int>(frame_id), count_frames_delivered());
|
| + WaitForAllFramesToBeDelivered(10 * frame_sizes.size());
|
| + ExpectVEAResponsesForExternalVideoEncoder(
|
| + 2 * frame_sizes.size(), 6 * frame_sizes.size());
|
| +}
|
| +
|
| +// Verify that everything goes well even if ExternalVideoEncoder is destroyed
|
| +// before it has a chance to receive the VEA creation callback. For all other
|
| +// encoders, this tests that the encoder can be safely destroyed before the task
|
| +// is run that delivers the first EncodedFrame.
|
| +TEST_P(VideoEncoderTest, CanBeDestroyedBeforeVEAIsCreated) {
|
| + CreateEncoder(false);
|
| +
|
| + // Send a frame to spawn creation of the ExternalVideoEncoder instance.
|
| + EncodeAndCheckDelivery(CreateTestVideoFrame(gfx::Size(1280, 720)), 0, 0);
|
| +
|
| + // Destroy the encoder, and confirm the VEA Factory did not respond yet.
|
| + DestroyEncoder();
|
| + ExpectVEAResponsesForExternalVideoEncoder(0, 0);
|
| +
|
| + // Allow the VEA Factory to respond by running the creation callback. When
|
| + // the task runs, it will be a no-op since the weak pointers to the
|
| + // ExternalVideoEncoder were invalidated.
|
| + SetVEAFactoryAutoRespond(true);
|
| + RunTasksAndAdvanceClock();
|
| + ExpectVEAResponsesForExternalVideoEncoder(1, 0);
|
| +}
|
| +
|
| +namespace {
|
| +std::vector<std::pair<Codec, bool>> DetermineEncodersToTest() {
|
| + std::vector<std::pair<Codec, bool>> values;
|
| + // Fake encoder.
|
| + values.push_back(std::make_pair(CODEC_VIDEO_FAKE, false));
|
| + // Software VP8 encoder.
|
| + values.push_back(std::make_pair(CODEC_VIDEO_VP8, false));
|
| + // Hardware-accelerated encoder (faked).
|
| + values.push_back(std::make_pair(CODEC_VIDEO_VP8, true));
|
| +#if defined(OS_MACOSX)
|
| + // VideoToolbox encoder (when VideoToolbox is present).
|
| + VideoSenderConfig video_config = GetDefaultVideoSenderConfig();
|
| + video_config.use_external_encoder = false;
|
| + video_config.codec = CODEC_VIDEO_H264;
|
| + if (H264VideoToolboxEncoder::IsSupported(video_config))
|
| + values.push_back(std::make_pair(CODEC_VIDEO_H264, false));
|
| +#endif
|
| + return values;
|
| }
|
| +} // namespace
|
|
|
| -INSTANTIATE_TEST_CASE_P(,
|
| - VideoEncoderImplTest,
|
| - ::testing::Values(CODEC_VIDEO_FAKE, CODEC_VIDEO_VP8));
|
| +INSTANTIATE_TEST_CASE_P(
|
| + , VideoEncoderTest, ::testing::ValuesIn(DetermineEncodersToTest()));
|
|
|
| } // namespace cast
|
| } // namespace media
|
|
|