| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2010 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 "base/message_loop.h" | |
| 6 #include "base/process.h" | |
| 7 #include "chrome/gpu/gpu_video_decoder.h" | |
| 8 #include "content/common/gpu_messages.h" | |
| 9 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" | |
| 10 #include "ipc/ipc_message_utils.h" | |
| 11 #include "media/base/pipeline.h" | |
| 12 #include "media/video/video_mock_objects.h" | |
| 13 #include "testing/gtest/include/gtest/gtest.h" | |
| 14 | |
| 15 using testing::_; | |
| 16 using testing::DoAll; | |
| 17 using testing::NotNull; | |
| 18 using testing::Return; | |
| 19 using testing::SetArgumentPointee; | |
| 20 | |
| 21 static const int32 kFrameId = 10; | |
| 22 static const int32 kDecoderHostId = 50; | |
| 23 static const media::VideoFrame::GlTexture kClientTexture = 101; | |
| 24 static const media::VideoFrame::GlTexture kServiceTexture = 102; | |
| 25 static const size_t kWidth = 320; | |
| 26 static const size_t kHeight = 240; | |
| 27 | |
| 28 class MockGpuVideoDevice : public GpuVideoDevice { | |
| 29 public: | |
| 30 MockGpuVideoDevice() {} | |
| 31 virtual ~MockGpuVideoDevice() {} | |
| 32 | |
| 33 MOCK_METHOD0(GetDevice, void*()); | |
| 34 MOCK_METHOD5(CreateVideoFrameFromGlTextures, | |
| 35 bool(size_t, size_t, media::VideoFrame::Format, | |
| 36 const std::vector<media::VideoFrame::GlTexture>&, | |
| 37 scoped_refptr<media::VideoFrame>*)); | |
| 38 MOCK_METHOD1(ReleaseVideoFrame, | |
| 39 void(const scoped_refptr<media::VideoFrame>& frame)); | |
| 40 MOCK_METHOD2(ConvertToVideoFrame, | |
| 41 bool(void* buffer, scoped_refptr<media::VideoFrame> frame)); | |
| 42 | |
| 43 private: | |
| 44 DISALLOW_COPY_AND_ASSIGN(MockGpuVideoDevice); | |
| 45 }; | |
| 46 | |
| 47 ACTION_P(InitializationDone, handler) { | |
| 48 media::VideoCodecInfo info; | |
| 49 info.success = true; | |
| 50 info.provides_buffers = false; | |
| 51 info.stream_info.surface_format = media::VideoFrame::RGBA; | |
| 52 info.stream_info.surface_type = media::VideoFrame::TYPE_SYSTEM_MEMORY; | |
| 53 info.stream_info.surface_width = kWidth; | |
| 54 info.stream_info.surface_height = kHeight; | |
| 55 handler->OnInitializeComplete(info); | |
| 56 } | |
| 57 | |
| 58 ACTION_P(SendVideoFrameAllocated, handler) { | |
| 59 std::vector<media::VideoFrame::GlTexture> textures; | |
| 60 textures.push_back(kClientTexture); | |
| 61 GpuVideoDecoderMsg_VideoFrameAllocated msg(0, kFrameId, textures); | |
| 62 handler->OnMessageReceived(msg); | |
| 63 } | |
| 64 | |
| 65 ACTION_P2(SendConsumeVideoFrame, handler, frame) { | |
| 66 media::PipelineStatistics statistics; | |
| 67 handler->ConsumeVideoFrame(frame, statistics); | |
| 68 } | |
| 69 | |
| 70 class GpuVideoDecoderTest : public testing::Test, | |
| 71 public IPC::Message::Sender { | |
| 72 public: | |
| 73 GpuVideoDecoderTest() { | |
| 74 // Create the mock objects. | |
| 75 gles2_decoder_.reset(new gpu::gles2::MockGLES2Decoder()); | |
| 76 | |
| 77 gpu_video_decoder_ = new GpuVideoDecoder( | |
| 78 &message_loop_, kDecoderHostId, this, base::kNullProcessHandle, | |
| 79 gles2_decoder_.get()); | |
| 80 | |
| 81 // Create the mock objects. | |
| 82 mock_engine_ = new media::MockVideoDecodeEngine(); | |
| 83 mock_device_ = new MockGpuVideoDevice(); | |
| 84 | |
| 85 // Inject the mock objects. | |
| 86 gpu_video_decoder_->SetVideoDecodeEngine(mock_engine_); | |
| 87 gpu_video_decoder_->SetGpuVideoDevice(mock_device_); | |
| 88 | |
| 89 // VideoFrame for GpuVideoDevice. | |
| 90 media::VideoFrame::GlTexture textures[] = { kServiceTexture, 0, 0 }; | |
| 91 media::VideoFrame::CreateFrameGlTexture(media::VideoFrame::RGBA, | |
| 92 kWidth, kHeight, textures, | |
| 93 &device_frame_); | |
| 94 } | |
| 95 | |
| 96 virtual ~GpuVideoDecoderTest() { | |
| 97 gpu_video_decoder_->SetVideoDecodeEngine(NULL); | |
| 98 gpu_video_decoder_->SetGpuVideoDevice(NULL); | |
| 99 } | |
| 100 | |
| 101 // This method is used to dispatch IPC messages to mock methods. | |
| 102 virtual bool Send(IPC::Message* msg) { | |
| 103 EXPECT_TRUE(msg); | |
| 104 if (!msg) | |
| 105 return false; | |
| 106 | |
| 107 bool handled = true; | |
| 108 IPC_BEGIN_MESSAGE_MAP(GpuVideoDecoderTest, *msg) | |
| 109 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_InitializeACK, | |
| 110 OnInitializeDone) | |
| 111 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_DestroyACK, | |
| 112 OnUninitializeDone) | |
| 113 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_FlushACK, | |
| 114 OnFlushDone) | |
| 115 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_EmptyThisBufferACK, | |
| 116 OnEmptyThisBufferACK) | |
| 117 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_EmptyThisBufferDone, | |
| 118 OnEmptyThisBufferDone) | |
| 119 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_AllocateVideoFrames, | |
| 120 OnAllocateVideoFrames) | |
| 121 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_ReleaseAllVideoFrames, | |
| 122 OnReleaseAllVideoFrames) | |
| 123 IPC_MESSAGE_HANDLER(GpuVideoDecoderHostMsg_ConsumeVideoFrame, | |
| 124 OnConsumeVideoFrame) | |
| 125 IPC_MESSAGE_UNHANDLED_ERROR() | |
| 126 IPC_END_MESSAGE_MAP() | |
| 127 EXPECT_TRUE(handled); | |
| 128 delete msg; | |
| 129 return true; | |
| 130 } | |
| 131 | |
| 132 // Mock methods for handling output IPC messages. | |
| 133 MOCK_METHOD1(OnInitializeDone, | |
| 134 void(const GpuVideoDecoderInitDoneParam& param)); | |
| 135 MOCK_METHOD0(OnUninitializeDone, void()); | |
| 136 MOCK_METHOD0(OnFlushDone, void()); | |
| 137 MOCK_METHOD0(OnEmptyThisBufferDone, void()); | |
| 138 MOCK_METHOD4(OnConsumeVideoFrame, void(int32 device_frame_id, int64 timestamp, | |
| 139 int64 duration, int32 flags)); | |
| 140 MOCK_METHOD0(OnEmptyThisBufferACK, void()); | |
| 141 MOCK_METHOD4(OnAllocateVideoFrames, void(int32 n, uint32 width, | |
| 142 uint32 height, int32 format)); | |
| 143 MOCK_METHOD0(OnReleaseAllVideoFrames, void()); | |
| 144 | |
| 145 // Receive events from GpuVideoDecoder. | |
| 146 MOCK_METHOD0(VideoFramesAllocated, void()); | |
| 147 | |
| 148 void Initialize() { | |
| 149 // VideoDecodeEngine is called. | |
| 150 EXPECT_CALL(*mock_engine_, Initialize(_, _, _, _)) | |
| 151 .WillOnce(InitializationDone(gpu_video_decoder_)); | |
| 152 | |
| 153 // Expect that initialization is completed. | |
| 154 EXPECT_CALL(*this, OnInitializeDone(_)); | |
| 155 | |
| 156 // Send an initialiaze message to GpuVideoDecoder. | |
| 157 GpuVideoDecoderInitParam param; | |
| 158 param.width = kWidth; | |
| 159 param.height = kHeight; | |
| 160 | |
| 161 GpuVideoDecoderMsg_Initialize msg(0, param); | |
| 162 gpu_video_decoder_->OnMessageReceived(msg); | |
| 163 } | |
| 164 | |
| 165 void AllocateVideoFrames() { | |
| 166 // Expect that IPC messages are sent. We'll reply with some GL textures. | |
| 167 EXPECT_CALL(*this, OnAllocateVideoFrames( | |
| 168 1, kWidth, kHeight, static_cast<int32>(media::VideoFrame::RGBA))) | |
| 169 .WillOnce(SendVideoFrameAllocated(gpu_video_decoder_)); | |
| 170 | |
| 171 // Expect that MakeCurrent() is called. | |
| 172 EXPECT_CALL(*gles2_decoder_.get(), MakeCurrent()) | |
| 173 .WillOnce(Return(true)) | |
| 174 .RetiresOnSaturation(); | |
| 175 | |
| 176 // Expect that translate method is called. | |
| 177 EXPECT_CALL(*gles2_decoder_.get(), | |
| 178 GetServiceTextureId(kClientTexture, NotNull())) | |
| 179 .WillOnce(DoAll(SetArgumentPointee<1>(kServiceTexture), Return(true))); | |
| 180 | |
| 181 // And then GpuVideoDevice is called to create VideoFrame from GL textures. | |
| 182 EXPECT_CALL(*mock_device_, | |
| 183 CreateVideoFrameFromGlTextures(kWidth, kHeight, | |
| 184 media::VideoFrame::RGBA, _, | |
| 185 NotNull())) | |
| 186 .WillOnce(DoAll(SetArgumentPointee<4>(device_frame_), Return(true))); | |
| 187 | |
| 188 // Finally the task is called. | |
| 189 EXPECT_CALL(*this, VideoFramesAllocated()); | |
| 190 | |
| 191 // Pretend calling GpuVideoDecoder for allocating frames. | |
| 192 gpu_video_decoder_->AllocateVideoFrames( | |
| 193 1, kWidth, kHeight, media::VideoFrame::RGBA, &decoder_frames_, | |
| 194 NewRunnableMethod(this, &GpuVideoDecoderTest::VideoFramesAllocated)); | |
| 195 } | |
| 196 | |
| 197 void ReleaseVideoFrames() { | |
| 198 // Expect that MakeCurrent() is called. | |
| 199 EXPECT_CALL(*gles2_decoder_.get(), MakeCurrent()) | |
| 200 .WillOnce(Return(true)) | |
| 201 .RetiresOnSaturation(); | |
| 202 | |
| 203 // Expect that video frame is released. | |
| 204 EXPECT_CALL(*mock_device_, ReleaseVideoFrame(device_frame_)); | |
| 205 | |
| 206 // Expect that IPC message is send to release video frame. | |
| 207 EXPECT_CALL(*this, OnReleaseAllVideoFrames()); | |
| 208 | |
| 209 // Call to GpuVideoDecoder to release all video frames. | |
| 210 gpu_video_decoder_->ReleaseAllVideoFrames(); | |
| 211 } | |
| 212 | |
| 213 void BufferExchange() { | |
| 214 // Expect that we call to produce video frame. | |
| 215 EXPECT_CALL(*mock_engine_, ProduceVideoFrame(device_frame_)) | |
| 216 .WillOnce(SendConsumeVideoFrame(gpu_video_decoder_, device_frame_)) | |
| 217 .RetiresOnSaturation(); | |
| 218 | |
| 219 // Expect that consume video frame is called. | |
| 220 EXPECT_CALL(*this, OnConsumeVideoFrame(kFrameId, 0, 0, 0)) | |
| 221 .RetiresOnSaturation(); | |
| 222 | |
| 223 // Ask the GpuVideoDecoder to produce a video frame. | |
| 224 GpuVideoDecoderMsg_ProduceVideoFrame msg(0, kFrameId); | |
| 225 gpu_video_decoder_->OnMessageReceived(msg); | |
| 226 } | |
| 227 | |
| 228 private: | |
| 229 scoped_refptr<GpuVideoDecoder> gpu_video_decoder_; | |
| 230 MockGpuVideoDevice* mock_device_; | |
| 231 media::MockVideoDecodeEngine* mock_engine_; | |
| 232 scoped_ptr<gpu::gles2::MockGLES2Decoder> gles2_decoder_; | |
| 233 std::vector<scoped_refptr<media::VideoFrame> > decoder_frames_; | |
| 234 scoped_refptr<media::VideoFrame> device_frame_; | |
| 235 | |
| 236 MessageLoop message_loop_; | |
| 237 | |
| 238 DISALLOW_COPY_AND_ASSIGN(GpuVideoDecoderTest); | |
| 239 }; | |
| 240 | |
| 241 TEST_F(GpuVideoDecoderTest, Initialize) { | |
| 242 Initialize(); | |
| 243 } | |
| 244 | |
| 245 TEST_F(GpuVideoDecoderTest, AllocateVideoFrames) { | |
| 246 Initialize(); | |
| 247 AllocateVideoFrames(); | |
| 248 } | |
| 249 | |
| 250 TEST_F(GpuVideoDecoderTest, ReleaseVideoFrames) { | |
| 251 Initialize(); | |
| 252 AllocateVideoFrames(); | |
| 253 ReleaseVideoFrames(); | |
| 254 } | |
| 255 | |
| 256 TEST_F(GpuVideoDecoderTest, BufferExchange) { | |
| 257 Initialize(); | |
| 258 AllocateVideoFrames(); | |
| 259 BufferExchange(); | |
| 260 BufferExchange(); | |
| 261 ReleaseVideoFrames(); | |
| 262 } | |
| 263 | |
| 264 DISABLE_RUNNABLE_METHOD_REFCOUNT(GpuVideoDecoderTest); | |
| OLD | NEW |