OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <stdint.h> |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/single_thread_task_runner.h" |
| 10 #include "base/synchronization/waitable_event.h" |
| 11 #include "base/threading/thread.h" |
| 12 #include "content/renderer/media/gpu/rtc_video_encoder.h" |
| 13 #include "media/renderers/mock_gpu_video_accelerator_factories.h" |
| 14 #include "media/video/mock_video_encode_accelerator.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 #include "third_party/libyuv/include/libyuv/planar_functions.h" |
| 17 #include "third_party/webrtc/modules/video_coding/include/video_codec_interface.
h" |
| 18 |
| 19 using ::testing::_; |
| 20 using ::testing::Invoke; |
| 21 using ::testing::Return; |
| 22 using ::testing::SaveArg; |
| 23 using ::testing::Values; |
| 24 using ::testing::WithArgs; |
| 25 |
| 26 namespace content { |
| 27 |
| 28 namespace { |
| 29 |
| 30 const int kInputFrameFillY = 12; |
| 31 const int kInputFrameFillU = 23; |
| 32 const int kInputFrameFillV = 34; |
| 33 const unsigned short kInputFrameHeight = 234; |
| 34 const unsigned short kInputFrameWidth = 345; |
| 35 const unsigned short kStartBitrate = 100; |
| 36 |
| 37 } // anonymous namespace |
| 38 |
| 39 class RTCVideoEncoderTest |
| 40 : public ::testing::TestWithParam<webrtc::VideoCodecType> { |
| 41 public: |
| 42 RTCVideoEncoderTest() |
| 43 : mock_gpu_factories_( |
| 44 new media::MockGpuVideoAcceleratorFactories(nullptr)), |
| 45 encoder_thread_("vea_thread"), |
| 46 idle_waiter_(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| 47 base::WaitableEvent::InitialState::NOT_SIGNALED) {} |
| 48 |
| 49 void SetUp() override { |
| 50 DVLOG(3) << __FUNCTION__; |
| 51 ASSERT_TRUE(encoder_thread_.Start()); |
| 52 mock_vea_ = new media::MockVideoEncodeAccelerator(); |
| 53 |
| 54 EXPECT_CALL(*mock_gpu_factories_.get(), GetTaskRunner()) |
| 55 .WillRepeatedly(Return(encoder_thread_.task_runner())); |
| 56 EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoEncodeAccelerator()) |
| 57 .WillRepeatedly(Return(mock_vea_)); |
| 58 EXPECT_CALL(*mock_vea_, Initialize(_, _, _, _, _)) |
| 59 .WillOnce(Invoke(this, &RTCVideoEncoderTest::Initialize)); |
| 60 EXPECT_CALL(*mock_vea_, UseOutputBitstreamBuffer(_)).Times(3); |
| 61 EXPECT_CALL(*mock_vea_, Destroy()).Times(1); |
| 62 } |
| 63 |
| 64 void TearDown() override { |
| 65 DVLOG(3) << __FUNCTION__; |
| 66 EXPECT_TRUE(encoder_thread_.IsRunning()); |
| 67 RunUntilIdle(); |
| 68 rtc_encoder_->Release(); |
| 69 RunUntilIdle(); |
| 70 encoder_thread_.Stop(); |
| 71 } |
| 72 |
| 73 void RunUntilIdle() { |
| 74 DVLOG(3) << __FUNCTION__; |
| 75 encoder_thread_.task_runner()->PostTask( |
| 76 FROM_HERE, base::Bind(&base::WaitableEvent::Signal, |
| 77 base::Unretained(&idle_waiter_))); |
| 78 idle_waiter_.Wait(); |
| 79 } |
| 80 |
| 81 void CreateEncoder(webrtc::VideoCodecType codec_type) { |
| 82 DVLOG(3) << __FUNCTION__; |
| 83 rtc_encoder_ = base::WrapUnique( |
| 84 new RTCVideoEncoder(codec_type, mock_gpu_factories_.get())); |
| 85 } |
| 86 |
| 87 // media::VideoEncodeAccelerator implementation. |
| 88 bool Initialize(media::VideoPixelFormat input_format, |
| 89 const gfx::Size& input_visible_size, |
| 90 media::VideoCodecProfile output_profile, |
| 91 uint32_t initial_bitrate, |
| 92 media::VideoEncodeAccelerator::Client* client) { |
| 93 DVLOG(3) << __FUNCTION__; |
| 94 client->RequireBitstreamBuffers(0, input_visible_size, |
| 95 input_visible_size.GetArea()); |
| 96 return true; |
| 97 } |
| 98 |
| 99 webrtc::VideoCodec GetDefaultCodec() { |
| 100 webrtc::VideoCodec codec = {}; |
| 101 memset(&codec, 0, sizeof(codec)); |
| 102 codec.width = kInputFrameWidth; |
| 103 codec.height = kInputFrameHeight; |
| 104 codec.codecType = webrtc::kVideoCodecVP8; |
| 105 codec.startBitrate = kStartBitrate; |
| 106 return codec; |
| 107 } |
| 108 |
| 109 void FillFrameBuffer(rtc::scoped_refptr<webrtc::I420Buffer> frame) { |
| 110 CHECK(libyuv::I420Rect(frame->MutableDataY(), frame->StrideY(), |
| 111 frame->MutableDataU(), frame->StrideU(), |
| 112 frame->MutableDataV(), frame->StrideV(), 0, 0, |
| 113 frame->width(), frame->height(), kInputFrameFillY, |
| 114 kInputFrameFillU, kInputFrameFillV) == 0); |
| 115 } |
| 116 |
| 117 void VerifyEncodedFrame(const scoped_refptr<media::VideoFrame>& frame, |
| 118 bool force_keyframe) { |
| 119 DVLOG(3) << __FUNCTION__; |
| 120 EXPECT_EQ(kInputFrameWidth, frame->visible_rect().width()); |
| 121 EXPECT_EQ(kInputFrameHeight, frame->visible_rect().height()); |
| 122 EXPECT_EQ(kInputFrameFillY, |
| 123 frame->visible_data(media::VideoFrame::kYPlane)[0]); |
| 124 EXPECT_EQ(kInputFrameFillU, |
| 125 frame->visible_data(media::VideoFrame::kUPlane)[0]); |
| 126 EXPECT_EQ(kInputFrameFillV, |
| 127 frame->visible_data(media::VideoFrame::kVPlane)[0]); |
| 128 } |
| 129 |
| 130 protected: |
| 131 media::MockVideoEncodeAccelerator* mock_vea_; |
| 132 std::unique_ptr<RTCVideoEncoder> rtc_encoder_; |
| 133 |
| 134 private: |
| 135 std::unique_ptr<media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_; |
| 136 base::Thread encoder_thread_; |
| 137 base::WaitableEvent idle_waiter_; |
| 138 }; |
| 139 |
| 140 TEST_P(RTCVideoEncoderTest, CreateAndInitSucceeds) { |
| 141 const webrtc::VideoCodecType codec_type = GetParam(); |
| 142 CreateEncoder(codec_type); |
| 143 webrtc::VideoCodec codec = GetDefaultCodec(); |
| 144 codec.codecType = codec_type; |
| 145 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_encoder_->InitEncode(&codec, 1, 12345)); |
| 146 } |
| 147 |
| 148 TEST_F(RTCVideoEncoderTest, EncodeScaledFrame) { |
| 149 const webrtc::VideoCodecType codec_type = webrtc::kVideoCodecVP8; |
| 150 CreateEncoder(codec_type); |
| 151 webrtc::VideoCodec codec = GetDefaultCodec(); |
| 152 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_encoder_->InitEncode(&codec, 1, 12345)); |
| 153 |
| 154 EXPECT_CALL(*mock_vea_, Encode(_, _)) |
| 155 .Times(2) |
| 156 .WillRepeatedly(Invoke(this, &RTCVideoEncoderTest::VerifyEncodedFrame)); |
| 157 |
| 158 const rtc::scoped_refptr<webrtc::I420Buffer> buffer = |
| 159 webrtc::I420Buffer::Create(kInputFrameWidth, kInputFrameHeight); |
| 160 FillFrameBuffer(buffer); |
| 161 std::vector<webrtc::FrameType> frame_types; |
| 162 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| 163 rtc_encoder_->Encode( |
| 164 webrtc::VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0), |
| 165 nullptr, &frame_types)); |
| 166 |
| 167 const rtc::scoped_refptr<webrtc::I420Buffer> upscaled_buffer = |
| 168 webrtc::I420Buffer::Create(2 * kInputFrameWidth, 2 * kInputFrameHeight); |
| 169 FillFrameBuffer(upscaled_buffer); |
| 170 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| 171 rtc_encoder_->Encode(webrtc::VideoFrame(upscaled_buffer, 0, 0, |
| 172 webrtc::kVideoRotation_0), |
| 173 nullptr, &frame_types)); |
| 174 } |
| 175 |
| 176 INSTANTIATE_TEST_CASE_P(CodecProfiles, |
| 177 RTCVideoEncoderTest, |
| 178 Values(webrtc::kVideoCodecVP8, |
| 179 webrtc::kVideoCodecH264)); |
| 180 } // namespace content |
OLD | NEW |