Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1341)

Unified Diff: ppapi/proxy/video_encoder_resource_unittest.cc

Issue 905023005: Pepper: PPB_VideoEncoder implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Deal with Encode() callbacks in the proxy Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ppapi/proxy/video_encoder_resource_unittest.cc
diff --git a/ppapi/proxy/video_encoder_resource_unittest.cc b/ppapi/proxy/video_encoder_resource_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d01f352f4d11645dd675193ad1656a6c49a2c6ea
--- /dev/null
+++ b/ppapi/proxy/video_encoder_resource_unittest.cc
@@ -0,0 +1,919 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/shared_memory.h"
+#include "base/process/process.h"
+#include "base/synchronization/waitable_event.h"
+#include "ppapi/c/pp_codecs.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_video_encoder.h"
+#include "ppapi/c/ppb_video_frame.h"
+#include "ppapi/proxy/locking_resource_releaser.h"
+#include "ppapi/proxy/plugin_message_filter.h"
+#include "ppapi/proxy/ppapi_message_utils.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/proxy/ppapi_proxy_test.h"
+#include "ppapi/proxy/video_encoder_resource.h"
+#include "ppapi/shared_impl/media_stream_buffer.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/thunk/thunk.h"
+
+using ppapi::proxy::ResourceMessageTestSink;
+
+namespace ppapi {
+namespace proxy {
+
+namespace {
+
+const uint32_t kShmSize = 256;
+const size_t kDecodeBufferSize = 16;
+const uint32_t kDecodeId = 5;
bbudge 2015/02/13 01:45:54 I don't think you need these definitions.
llandwerlin-old 2015/02/13 20:12:26 Done.
+
+class MockCompletionCallback {
+ public:
+ MockCompletionCallback() : called_(false), call_event_(false, false) {}
+
+ bool called() { return called_; }
+ int32_t result() { return result_; }
+
+ void WaitUntilCalled() { call_event_.Wait(); }
+
+ void Reset() {
+ called_ = false;
+ call_event_.Reset();
+ }
+
+ static void Callback(void* user_data, int32_t result) {
+ MockCompletionCallback* that =
+ reinterpret_cast<MockCompletionCallback*>(user_data);
+ that->call_event_.Signal();
+ that->called_ = true;
+ that->result_ = result;
+ }
+
+ private:
+ bool called_;
+ int32_t result_;
+ base::WaitableEvent call_event_;
+};
+
+class VideoEncoderResourceTest : public PluginProxyTest {
+ public:
+ VideoEncoderResourceTest()
+ : encoder_iface_(thunk::GetPPB_VideoEncoder_0_1_Thunk()) {}
+
+ const PPB_VideoEncoder_0_1* encoder_iface() const { return encoder_iface_; }
+
+ const uint32_t kBitstreamBufferSize = 4000;
+ const uint32_t kBitstreamBufferNb = 5;
+ const uint32_t kVideoFrameNb = 3;
bbudge 2015/02/13 01:45:54 It took me a while to get that Nb is 'Count'.
llandwerlin-old 2015/02/13 20:12:26 Done.
+ const uint32_t kBitrate = 200000;
+
+ const PP_Size kSize = {640, 480};
bbudge 2015/02/13 01:45:54 kFrameSize?
llandwerlin-old 2015/02/13 20:12:26 Done.
+
+ void SendReply(const ResourceMessageCallParams& params,
+ int32_t result,
+ const IPC::Message& nested_message) {
+ ResourceMessageReplyParams reply_params(params.pp_resource(),
+ params.sequence());
+ reply_params.set_result(result);
+ PluginMessageFilter::DispatchResourceReplyForTest(reply_params,
+ nested_message);
+ }
+
+ void SendReplyWithHandle(const ResourceMessageCallParams& params,
+ int32_t result,
+ const IPC::Message& nested_message,
+ const SerializedHandle& handle) {
+ ResourceMessageReplyParams reply_params(params.pp_resource(),
+ params.sequence());
+ reply_params.set_result(result);
+ reply_params.AppendHandle(handle);
+ PluginMessageFilter::DispatchResourceReplyForTest(reply_params,
+ nested_message);
+ }
+
+ void SendReplyWithHandles(const ResourceMessageCallParams& params,
+ int32_t result,
+ const IPC::Message& nested_message,
+ const std::vector<SerializedHandle>& handles) {
+ ResourceMessageReplyParams reply_params(params.pp_resource(),
+ params.sequence());
+ reply_params.set_result(result);
+ for (SerializedHandle handle : handles)
+ reply_params.AppendHandle(handle);
+ PluginMessageFilter::DispatchResourceReplyForTest(reply_params,
+ nested_message);
+ }
+
+ PP_Resource CreateEncoder() {
+ PP_Resource result = encoder_iface()->Create(pp_instance());
+ return result;
+ }
+
+ void CreateBitstreamSharedMemory(uint32_t buffer_size, uint32_t nb_buffers) {
+ shared_memory_bitstreams_.clear();
+ for (uint32_t i = 0; i < nb_buffers; ++i) {
+ scoped_ptr<base::SharedMemory> mem(new base::SharedMemory());
+ ASSERT_TRUE(mem->CreateAnonymous(buffer_size));
+ shared_memory_bitstreams_.push_back(mem.Pass());
+ }
+ }
+
+ void CreateVideoFramesSharedMemory(uint32_t frame_length,
+ uint32_t frame_count) {
+ shared_memory_frames_.reset(new base::SharedMemory());
+ uint32_t frame_buffer_length =
+ frame_length + sizeof(ppapi::MediaStreamBuffer::Video) -
+ sizeof(ppapi::MediaStreamBuffer::Video::data);
+ ASSERT_TRUE(shared_memory_frames_->CreateAnonymous(frame_buffer_length *
+ frame_count));
+ }
+
+ PP_Resource CreateAndInitializeEncoder() {
+ PP_Resource encoder = CreateEncoder();
+ PP_Size size = kSize;
+ MockCompletionCallback cb;
+ int32_t result = encoder_iface()->Initialize(
+ encoder, PP_VIDEOFRAME_FORMAT_I420, &size, PP_VIDEOPROFILE_H264MAIN,
+ kBitrate, PP_HARDWAREACCELERATION_WITHFALLBACK,
+ PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback,
+ &cb));
+ if (result != PP_OK_COMPLETIONPENDING)
+ return 0;
+ ResourceMessageCallParams params;
+ IPC::Message msg;
+ if (!sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_VideoEncoder_Initialize::ID, &params, &msg))
+ return 0;
+ sink().ClearMessages();
+
+ CreateBitstreamSharedMemory(kBitstreamBufferSize, kBitstreamBufferNb);
+ SendInitializeReply(params, kBitstreamBufferSize, kVideoFrameNb, size);
+
+ if (!cb.called() || cb.result() != PP_OK)
+ return 0;
+
+ return encoder;
+ }
+
+ int32_t CallGetFramesRequired(PP_Resource pp_encoder) {
+ return encoder_iface()->GetFramesRequired(pp_encoder);
+ }
+
+ int32_t CallGetFrameCodedSize(PP_Resource pp_encoder, PP_Size* coded_size) {
+ return encoder_iface()->GetFrameCodedSize(pp_encoder, coded_size);
+ }
+
+ int32_t CallGetVideoFrame(PP_Resource pp_encoder,
+ PP_Resource* video_frame,
+ MockCompletionCallback* cb) {
+ return encoder_iface()->GetVideoFrame(
+ pp_encoder, video_frame, PP_MakeOptionalCompletionCallback(
+ &MockCompletionCallback::Callback, cb));
+ }
+
+ int32_t CallFirstGetVideoFrame(PP_Resource pp_encoder,
+ PP_Resource* video_frame,
+ MockCompletionCallback* cb) {
+ int32_t result = encoder_iface()->GetVideoFrame(
+ pp_encoder, video_frame, PP_MakeOptionalCompletionCallback(
+ &MockCompletionCallback::Callback, cb));
+ if (result != PP_OK_COMPLETIONPENDING)
+ return result;
+
+ ResourceMessageCallParams params;
+ CheckGetVideoFramesMsg(&params);
+
+ uint32_t frame_length = kSize.width * kSize.height * 2;
+ CreateVideoFramesSharedMemory(frame_length, kVideoFrameNb);
+ SendGetVideoFramesReply(params, kVideoFrameNb, frame_length, kSize);
+
+ return result;
+ }
+
+ int32_t CallEncode(PP_Resource pp_encoder,
+ PP_Resource video_frame,
+ PP_Bool force_keyframe,
+ MockCompletionCallback* cb) {
+ return encoder_iface()->Encode(pp_encoder, video_frame, force_keyframe,
+ PP_MakeOptionalCompletionCallback(
+ &MockCompletionCallback::Callback, cb));
+ }
+
+ int32_t CallCompleteEncode(PP_Resource pp_encoder,
+ PP_Resource video_frame,
+ PP_Bool force_keyframe,
+ MockCompletionCallback* cb) {
+ int32_t result =
+ encoder_iface()->Encode(pp_encoder, video_frame, force_keyframe,
+ PP_MakeOptionalCompletionCallback(
+ &MockCompletionCallback::Callback, cb));
+ if (result != PP_OK_COMPLETIONPENDING)
+ return result;
+
+ ResourceMessageCallParams params;
+ uint32_t frame_id;
+ bool forced_keyframe;
+ if (!CheckEncodeMsg(&params, &frame_id, &forced_keyframe))
+ return PP_ERROR_FAILED;
+
+ SendEncodeReply(params, frame_id);
+
+ return result;
+ }
+
+ int32_t CallGetBitstreamBuffer(PP_Resource pp_encoder,
+ PP_BitstreamBuffer* bitstream_buffer,
+ MockCompletionCallback* cb) {
+ return encoder_iface()->GetBitstreamBuffer(
+ pp_encoder, bitstream_buffer,
+ PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback,
+ cb));
+ }
+
+ void CallRecycleBitstreamBuffer(PP_Resource pp_encoder,
+ const PP_BitstreamBuffer& buffer) {
+ encoder_iface()->RecycleBitstreamBuffer(pp_encoder, &buffer);
+ }
+
+ void CallRequestEncodingParametersChange(PP_Resource pp_encoder,
+ uint32_t bitrate,
+ uint32_t framerate) {
+ encoder_iface()->RequestEncodingParametersChange(pp_encoder, bitrate,
+ framerate);
+ }
+
+ void CallClose(PP_Resource pp_encoder) {
+ encoder_iface()->Close(pp_encoder);
+ }
+
+ void SendGetSupportedProfilesReply(
+ const ResourceMessageCallParams& params,
+ const std::vector<PP_VideoProfileDescription>& profiles) {
+ SendReply(params, PP_OK,
+ PpapiPluginMsg_VideoEncoder_GetSupportedProfilesReply(profiles));
+ }
+
+ void SendInitializeReply(const ResourceMessageCallParams& params,
+ uint32_t buffer_length,
+ uint32_t input_frame_count,
+ const PP_Size& coded_size) {
+ SendReply(params, PP_OK, PpapiPluginMsg_VideoEncoder_InitializeReply());
+ std::vector<SerializedHandle> handles;
+ for (base::SharedMemory* mem : shared_memory_bitstreams_) {
+ ASSERT_EQ(mem->requested_size(), buffer_length);
+ base::SharedMemoryHandle handle;
+
+ ASSERT_TRUE(
+ mem->ShareToProcess(base::Process::Current().Handle(), &handle));
+ handles.push_back(SerializedHandle(handle, buffer_length));
+ }
+ SendReplyWithHandles(params, PP_OK,
+ PpapiPluginMsg_VideoEncoder_BitstreamBuffers(
+ buffer_length, input_frame_count, coded_size),
+ handles);
+ }
+
+ void SendGetVideoFramesReply(const ResourceMessageCallParams& params,
+ uint32_t frame_count,
+ uint32_t frame_length,
+ const PP_Size& size) {
+ base::SharedMemoryHandle handle;
+ ASSERT_TRUE(shared_memory_frames_->ShareToProcess(
+ base::Process::Current().Handle(), &handle));
+ SendReplyWithHandle(
+ params, PP_OK, PpapiPluginMsg_VideoEncoder_GetVideoFramesReply(
+ frame_count, frame_length, size),
+ SerializedHandle(handle, shared_memory_frames_->requested_size()));
+ }
+
+ void SendEncodeReply(const ResourceMessageCallParams& params,
+ uint32_t frame_id) {
+ SendReply(params, PP_OK, PpapiPluginMsg_VideoEncoder_EncodeReply(frame_id));
+ }
+
+ void SendBitstreamBufferReady(const ResourceMessageCallParams& params,
+ uint32_t buffer_id,
+ uint32_t buffer_size,
+ bool keyframe) {
+ SendReply(params, PP_OK,
+ PpapiPluginMsg_VideoEncoder_BitstreamBufferReady(
+ buffer_id, buffer_size, PP_FromBool(keyframe)));
+ }
+
+ void SendNotifyError(const ResourceMessageCallParams& params, int32_t error) {
+ SendReply(params, PP_OK, PpapiPluginMsg_VideoEncoder_NotifyError(error));
+ }
+
+ bool CheckGetSupportedProfilesMsg(ResourceMessageCallParams* params) {
+ IPC::Message msg;
+ if (!sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_VideoEncoder_GetSupportedProfiles::ID, params, &msg))
+ return false;
+ return true;
+ }
+
+ bool CheckInitializeMsg(ResourceMessageCallParams* params,
+ PP_VideoFrame_Format* input_format,
+ struct PP_Size* input_visible_size,
+ PP_VideoProfile* output_profile,
+ uint32_t* bitrate,
+ PP_HardwareAcceleration* acceleration) {
+ IPC::Message msg;
+ if (!sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_VideoEncoder_Initialize::ID, params, &msg))
+ return false;
+ sink().ClearMessages();
+ return UnpackMessage<PpapiHostMsg_VideoEncoder_Initialize>(
+ msg, input_format, input_visible_size, output_profile, bitrate,
+ acceleration);
+ }
+
+ bool CheckGetVideoFramesMsg(ResourceMessageCallParams* params) {
+ IPC::Message msg;
+ if (!sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_VideoEncoder_GetVideoFrames::ID, params, &msg))
+ return false;
+ sink().ClearMessages();
+ return true;
+ }
+
+ bool CheckEncodeMsg(ResourceMessageCallParams* params,
+ uint32_t* frame_id,
+ bool* keyframe) {
+ IPC::Message msg;
+ if (!sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_VideoEncoder_Encode::ID, params, &msg))
+ return false;
+ sink().ClearMessages();
+ return UnpackMessage<PpapiHostMsg_VideoEncoder_Encode>(msg, frame_id,
+ keyframe);
+ }
+
+ bool CheckRecycleBitstreamBufferMsg(ResourceMessageCallParams* params,
+ uint32_t* buffer_id) {
+ IPC::Message msg;
+ if (!sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_VideoEncoder_RecycleBitstreamBuffer::ID, params, &msg))
+ return false;
+ sink().ClearMessages();
+ return UnpackMessage<PpapiHostMsg_VideoEncoder_RecycleBitstreamBuffer>(
+ msg, buffer_id);
+ }
+
+ bool CheckRequestEncodeingParametersChangeMsg(
bbudge 2015/02/13 01:45:53 s/Encodeing/Encoding
llandwerlin-old 2015/02/13 20:12:26 Done.
+ ResourceMessageCallParams* params,
+ uint32_t* bitrate,
+ uint32_t* framerate) {
+ IPC::Message msg;
+ if (!sink().GetFirstResourceCallMatching(
+ PpapiHostMsg_VideoEncoder_RequestEncodingParametersChange::ID,
+ params, &msg))
+ return false;
+ sink().ClearMessages();
+ return UnpackMessage<
+ PpapiHostMsg_VideoEncoder_RequestEncodingParametersChange>(msg, bitrate,
+ framerate);
+ }
+
+ bool CheckIsVideoFrame(PP_Resource video_frame) {
+ return thunk::GetPPB_VideoFrame_0_1_Thunk()->IsVideoFrame(video_frame);
+ }
+
+ private:
+ bool CheckMsg(ResourceMessageCallParams* params, int id) {
bbudge 2015/02/13 01:45:53 Not used
llandwerlin-old 2015/02/13 20:12:26 Done.
+ IPC::Message msg;
+ if (!sink().GetFirstResourceCallMatching(id, params, &msg))
+ return false;
+ sink().ClearMessages();
+ return true;
+ }
+
+ const PPB_VideoEncoder_0_1* encoder_iface_;
+
+ ScopedVector<base::SharedMemory> shared_memory_bitstreams_;
+ scoped_ptr<base::SharedMemory> shared_memory_frames_;
+
+ char decode_buffer_[kDecodeBufferSize];
bbudge 2015/02/13 01:45:54 Not used.
llandwerlin-old 2015/02/13 20:12:26 Done.
+};
+
+void* ForwardUserData(void* user_data,
+ uint32_t element_count,
+ uint32_t element_size) {
+ return user_data;
+}
+
+} // namespace
+
+TEST_F(VideoEncoderResourceTest, GetSupportedProfiles) {
+ // Verifies that GetSupportedProfiles calls into the renderer and
+ // the we get the right results back.
+ {
+ LockingResourceReleaser encoder(CreateEncoder());
+ std::vector<PP_VideoProfileDescription> profiles;
bbudge 2015/02/13 01:45:54 This could just be an array, i.e. PP_VideoProfileD
llandwerlin-old 2015/02/13 20:12:26 Done.
+ profiles.resize(2);
+ PP_ArrayOutput output;
+ output.user_data = &profiles[0];
+ output.GetDataBuffer = ForwardUserData;
+ ResourceMessageCallParams params;
+ MockCompletionCallback cb;
+ int32_t result = encoder_iface()->GetSupportedProfiles(
+ encoder.get(), output, PP_MakeOptionalCompletionCallback(
+ &MockCompletionCallback::Callback, &cb));
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
+ ASSERT_TRUE(CheckGetSupportedProfilesMsg(&params));
+
+ std::vector<PP_VideoProfileDescription> profiles_response;
+ PP_VideoProfileDescription profile;
+ profile.profile = PP_VIDEOPROFILE_H264MAIN;
+ profile.max_resolution.width = 1920;
+ profile.max_resolution.height = 1080;
+ profile.max_framerate_numerator = 30;
+ profile.max_framerate_denominator = 1;
+ profiles_response.push_back(profile);
+ profile.profile = PP_VIDEOPROFILE_VP8_ANY;
+ profile.max_resolution.width = 1920;
+ profile.max_resolution.height = 1080;
+ profile.max_framerate_numerator = 30;
+ profile.max_framerate_denominator = 1;
+ profiles_response.push_back(profile);
+
+ SendGetSupportedProfilesReply(params, profiles_response);
+ ASSERT_EQ(PP_OK, cb.result());
+
+ ASSERT_EQ(profiles_response.size(), profiles.size());
+ ASSERT_EQ(0, memcmp(&profiles[0], &profiles_response[0],
+ sizeof(PP_VideoProfileDescription) * 2));
+ }
+}
+
+TEST_F(VideoEncoderResourceTest, InitializeFailure) {
+ {
+ // Verify the initialize callback is called in case of failure.
+ LockingResourceReleaser encoder(CreateEncoder());
+ ResourceMessageCallParams params;
+ PP_Size size = kSize;
+ MockCompletionCallback cb;
+ int32_t result = encoder_iface()->Initialize(
+ encoder.get(), PP_VIDEOFRAME_FORMAT_BGRA, &size,
+ PP_VIDEOPROFILE_H264MAIN, kBitrate,
+ PP_HARDWAREACCELERATION_WITHFALLBACK,
+ PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback,
+ &cb));
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
+
+ PP_VideoFrame_Format input_format;
+ PP_Size input_visible_size;
+ PP_VideoProfile output_profile;
+ uint32_t bitrate;
+ PP_HardwareAcceleration acceleration;
+ ASSERT_TRUE(CheckInitializeMsg(&params, &input_format, &input_visible_size,
+ &output_profile, &bitrate, &acceleration));
+ ASSERT_EQ(PP_VIDEOFRAME_FORMAT_BGRA, input_format);
+ ASSERT_EQ(size.width, input_visible_size.width);
+ ASSERT_EQ(size.height, input_visible_size.height);
+ ASSERT_EQ(kBitrate, bitrate);
+ ASSERT_EQ(PP_VIDEOPROFILE_H264MAIN, output_profile);
+ ASSERT_EQ(PP_HARDWAREACCELERATION_WITHFALLBACK, acceleration);
+
+ SendReply(params, PP_ERROR_NOTSUPPORTED,
+ PpapiPluginMsg_VideoEncoder_InitializeReply());
+ ASSERT_TRUE(cb.called());
+ ASSERT_EQ(PP_ERROR_NOTSUPPORTED, cb.result());
+ }
+ {
+ // Verify the initialize callback is called in case of error
+ // notification.
+ LockingResourceReleaser encoder(CreateEncoder());
+ ResourceMessageCallParams params;
+ PP_Size size = kSize;
+ MockCompletionCallback cb;
+ int32_t result = encoder_iface()->Initialize(
+ encoder.get(), PP_VIDEOFRAME_FORMAT_BGRA, &size,
+ PP_VIDEOPROFILE_H264MAIN, kBitrate,
+ PP_HARDWAREACCELERATION_WITHFALLBACK,
+ PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback,
+ &cb));
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
+
+ PP_VideoFrame_Format input_format;
+ PP_Size input_visible_size;
+ PP_VideoProfile output_profile;
+ uint32_t bitrate;
+ PP_HardwareAcceleration acceleration;
+ ASSERT_TRUE(CheckInitializeMsg(&params, &input_format, &input_visible_size,
+ &output_profile, &bitrate, &acceleration));
+ ASSERT_EQ(PP_VIDEOFRAME_FORMAT_BGRA, input_format);
+ ASSERT_EQ(kSize.width, input_visible_size.width);
+ ASSERT_EQ(kSize.height, input_visible_size.height);
+ ASSERT_EQ(kBitrate, bitrate);
+ ASSERT_EQ(PP_VIDEOPROFILE_H264MAIN, output_profile);
+ ASSERT_EQ(PP_HARDWAREACCELERATION_WITHFALLBACK, acceleration);
+
+ ResourceMessageCallParams error_params(encoder.get(), 0);
+ SendNotifyError(error_params, PP_ERROR_FAILED);
+ ASSERT_TRUE(cb.called());
+ ASSERT_EQ(PP_ERROR_FAILED, cb.result());
+ }
+}
bbudge 2015/02/13 01:45:54 As discussed, the Initialize callback should alway
llandwerlin-old 2015/02/13 20:12:26 Done.
+
+TEST_F(VideoEncoderResourceTest, InitializeSuccess) {
+ {
+ // Verify the initialize callback is called when initialization is
+ // successfull.
+ LockingResourceReleaser encoder(CreateEncoder());
+ ResourceMessageCallParams params;
+ PP_Size size = kSize;
+ const uint32_t kBitrate = 420000;
+ MockCompletionCallback cb;
+ int32_t result = encoder_iface()->Initialize(
+ encoder.get(), PP_VIDEOFRAME_FORMAT_I420, &size,
+ PP_VIDEOPROFILE_H264MAIN, kBitrate,
+ PP_HARDWAREACCELERATION_WITHFALLBACK,
+ PP_MakeOptionalCompletionCallback(&MockCompletionCallback::Callback,
+ &cb));
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
+
+ PP_VideoFrame_Format input_format;
+ PP_Size input_visible_size;
+ PP_VideoProfile output_profile;
+ uint32_t bitrate;
+ PP_HardwareAcceleration acceleration;
+ ASSERT_TRUE(CheckInitializeMsg(&params, &input_format, &input_visible_size,
+ &output_profile, &bitrate, &acceleration));
+ ASSERT_EQ(PP_VIDEOFRAME_FORMAT_I420, input_format);
+ ASSERT_EQ(kSize.width, input_visible_size.width);
+ ASSERT_EQ(kSize.height, input_visible_size.height);
+ ASSERT_EQ(kBitrate, bitrate);
+ ASSERT_EQ(PP_VIDEOPROFILE_H264MAIN, output_profile);
+ ASSERT_EQ(PP_HARDWAREACCELERATION_WITHFALLBACK, acceleration);
+
+ CreateBitstreamSharedMemory(kBitstreamBufferSize, kBitstreamBufferNb);
+ SendInitializeReply(params, kBitstreamBufferSize, kVideoFrameNb, size);
bbudge 2015/02/13 01:45:54 Again, Initialize completes without getting buffer
llandwerlin-old 2015/02/13 20:12:26 Done.
+
+ ASSERT_TRUE(cb.called());
+ ASSERT_EQ(PP_OK, cb.result());
+
+ PP_Size coded_size;
+ CallGetFrameCodedSize(encoder.get(), &coded_size);
+ ASSERT_EQ(kSize.width, coded_size.width);
+ ASSERT_EQ(kSize.height, coded_size.height);
+ ASSERT_EQ(static_cast<int32_t>(kVideoFrameNb),
+ CallGetFramesRequired(encoder.get()));
+ }
+}
+
+TEST_F(VideoEncoderResourceTest, Uninitialized) {
+ // Operations on uninitialized encoders should fail.
+ LockingResourceReleaser encoder(CreateEncoder());
+
+ ASSERT_EQ(PP_ERROR_FAILED, CallGetFramesRequired(encoder.get()));
+
+ PP_Size size;
+ ASSERT_EQ(PP_ERROR_FAILED, CallGetFrameCodedSize(encoder.get(), &size));
+
+ MockCompletionCallback uncalled_cb;
+ PP_Resource video_frame = 0;
+ ASSERT_EQ(PP_ERROR_FAILED,
+ CallGetVideoFrame(encoder.get(), &video_frame, &uncalled_cb));
+ ASSERT_FALSE(uncalled_cb.called());
+ ASSERT_EQ(0, video_frame);
+
+ ASSERT_EQ(PP_ERROR_FAILED,
+ CallEncode(encoder.get(), video_frame, PP_FALSE, &uncalled_cb));
+ ASSERT_FALSE(uncalled_cb.called());
+
+ PP_BitstreamBuffer bitstream_buffer;
+ ASSERT_EQ(
+ PP_ERROR_FAILED,
+ CallGetBitstreamBuffer(encoder.get(), &bitstream_buffer, &uncalled_cb));
+ ASSERT_FALSE(uncalled_cb.called());
+
+ ResourceMessageCallParams params;
+ uint32_t buffer_id;
+ CallRecycleBitstreamBuffer(encoder.get(), bitstream_buffer);
+ ASSERT_FALSE(CheckRecycleBitstreamBufferMsg(&params, &buffer_id));
+
+ uint32_t bitrate, framerate;
+ CallRequestEncodingParametersChange(encoder.get(), 0, 0);
+ ASSERT_FALSE(
+ CheckRequestEncodeingParametersChangeMsg(&params, &bitrate, &framerate));
+}
+
+TEST_F(VideoEncoderResourceTest, InitializeAndGetVideoFrame) {
+ // Verify that we can pull the right number of video frames before
+ // the proxy makes us wait.
+ LockingResourceReleaser encoder(CreateAndInitializeEncoder());
+ ResourceMessageCallParams params;
+ PP_Resource video_frames[kVideoFrameNb + 1];
+ MockCompletionCallback get_frame_cb;
+
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallGetVideoFrame(encoder.get(), &video_frames[0], &get_frame_cb));
+ ASSERT_FALSE(get_frame_cb.called());
+ ASSERT_TRUE(CheckGetVideoFramesMsg(&params));
+
+ uint32_t frame_length = kSize.width * kSize.height * 2;
+ CreateVideoFramesSharedMemory(frame_length, kVideoFrameNb);
+ SendGetVideoFramesReply(params, kVideoFrameNb, frame_length, kSize);
+
+ for (uint32_t i = 1; i < kVideoFrameNb; ++i) {
+ get_frame_cb.Reset();
+ ASSERT_EQ(PP_OK, CallGetVideoFrame(encoder.get(), &video_frames[i],
+ &get_frame_cb));
+ ASSERT_FALSE(get_frame_cb.called());
+ ASSERT_TRUE(CheckIsVideoFrame(video_frames[i]));
+ }
+
+ get_frame_cb.Reset();
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallGetVideoFrame(encoder.get(), &video_frames[kVideoFrameNb],
+ &get_frame_cb));
+ ASSERT_FALSE(get_frame_cb.called());
+
+ MockCompletionCallback get_frame_fail_cb;
+ ASSERT_EQ(PP_ERROR_INPROGRESS,
+ CallGetVideoFrame(encoder.get(), &video_frames[kVideoFrameNb],
+ &get_frame_fail_cb));
+ ASSERT_FALSE(get_frame_fail_cb.called());
+
+ // Unlock the GetVideoFrame callback.
bbudge 2015/02/13 01:45:53 // Unblock the GetVideoFrame callback by freeing u
llandwerlin-old 2015/02/13 20:12:26 Done.
+ MockCompletionCallback encode_cb;
+ ASSERT_EQ(
+ PP_OK_COMPLETIONPENDING,
+ CallCompleteEncode(encoder.get(), video_frames[0], PP_FALSE, &encode_cb));
+ ASSERT_TRUE(encode_cb.called());
+ ASSERT_EQ(PP_OK, encode_cb.result());
+ ASSERT_TRUE(get_frame_cb.called());
+
+ {
+ ProxyAutoLock lock;
+ for (uint32_t i = 0; i < (kVideoFrameNb + 1); ++i)
+ PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(
+ video_frames[i]);
bbudge 2015/02/13 01:45:54 Could you call encoder.Close() instead?
llandwerlin-old 2015/02/13 20:12:26 Done.
+ }
+}
+
+TEST_F(VideoEncoderResourceTest, Encode) {
+ // Check Encode() calls into the renderer.
+ LockingResourceReleaser encoder(CreateAndInitializeEncoder());
+
+ PP_Resource video_frame;
+ MockCompletionCallback get_frame_cb;
+ ;
bbudge 2015/02/13 01:45:54 empty statement
llandwerlin-old 2015/02/13 20:12:26 Done.
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallFirstGetVideoFrame(encoder.get(), &video_frame, &get_frame_cb));
+ ASSERT_TRUE(get_frame_cb.called());
+ ASSERT_EQ(PP_OK, get_frame_cb.result());
+
+ MockCompletionCallback encode_cb;
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallEncode(encoder.get(), video_frame, PP_TRUE, &encode_cb));
+ ASSERT_FALSE(encode_cb.called());
+
+ ResourceMessageCallParams params;
+ uint32_t frame_id;
+ bool force_frame;
+ ASSERT_TRUE(CheckEncodeMsg(&params, &frame_id, &force_frame));
+
+ SendEncodeReply(params, frame_id);
+
+ ASSERT_TRUE(encode_cb.called());
+ ASSERT_EQ(PP_OK, encode_cb.result());
+}
+
+TEST_F(VideoEncoderResourceTest, EncodeAndGetVideoFrame) {
+ // Check the encoding loop works well.
+ LockingResourceReleaser encoder(CreateAndInitializeEncoder());
+ ResourceMessageCallParams params;
+ PP_Resource video_frame;
+ MockCompletionCallback get_frame_cb, encode_cb;
+
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallFirstGetVideoFrame(encoder.get(), &video_frame, &get_frame_cb));
+ ASSERT_TRUE(get_frame_cb.called());
+ ASSERT_EQ(PP_OK, get_frame_cb.result());
+
+ for (uint32_t i = 1; i < 20 * kVideoFrameNb; ++i) {
+ encode_cb.Reset();
+ ASSERT_EQ(
+ PP_OK_COMPLETIONPENDING,
+ CallCompleteEncode(encoder.get(), video_frame, PP_FALSE, &encode_cb));
+ ASSERT_TRUE(encode_cb.called());
+ ASSERT_EQ(PP_OK, encode_cb.result());
+
+ get_frame_cb.Reset();
+ ASSERT_EQ(PP_OK,
+ CallGetVideoFrame(encoder.get(), &video_frame, &get_frame_cb));
+ ASSERT_FALSE(get_frame_cb.called());
+ ASSERT_TRUE(CheckIsVideoFrame(video_frame));
+ }
+
+ ASSERT_EQ(
+ PP_OK_COMPLETIONPENDING,
+ CallCompleteEncode(encoder.get(), video_frame, PP_FALSE, &encode_cb));
+ ASSERT_TRUE(encode_cb.called());
+ ASSERT_EQ(PP_OK, encode_cb.result());
+}
+
+TEST_F(VideoEncoderResourceTest, GetBitstreamBuffer) {
+ // Verify that the GetBitstreamBuffer callback is fired whenever the
+ // renderer signals a buffer is available.
+ LockingResourceReleaser encoder(CreateAndInitializeEncoder());
+
+ MockCompletionCallback get_bitstream_buffer_cb;
+ PP_BitstreamBuffer bitstream_buffer;
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallGetBitstreamBuffer(encoder.get(), &bitstream_buffer,
+ &get_bitstream_buffer_cb));
+ ASSERT_FALSE(get_bitstream_buffer_cb.called());
+
bbudge 2015/02/13 01:45:54 Test a second call gets INPROGRESS.
llandwerlin-old 2015/02/13 20:12:26 Done.
+ ResourceMessageCallParams buffer_params(encoder.get(), 0);
+ SendBitstreamBufferReady(buffer_params, 0, 10, true);
+
+ ASSERT_TRUE(get_bitstream_buffer_cb.called());
+ ASSERT_EQ(PP_OK, get_bitstream_buffer_cb.result());
+ ASSERT_EQ(static_cast<uint32_t>(10), bitstream_buffer.size);
+ ASSERT_EQ(PP_TRUE, bitstream_buffer.key_frame);
+}
+
+TEST_F(VideoEncoderResourceTest, RecycleBitstreamBuffer) {
+ // Verify that we signal the renderer that a bitstream buffer has been
+ // recycled.
+ LockingResourceReleaser encoder(CreateAndInitializeEncoder());
+
+ MockCompletionCallback get_bitstream_buffer_cb;
+ PP_BitstreamBuffer bitstream_buffer;
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallGetBitstreamBuffer(encoder.get(), &bitstream_buffer,
+ &get_bitstream_buffer_cb));
+ ASSERT_FALSE(get_bitstream_buffer_cb.called());
+
+ ResourceMessageCallParams buffer_params(encoder.get(), 0);
+ SendBitstreamBufferReady(buffer_params, kBitstreamBufferNb - 1, 10, true);
+
+ ASSERT_TRUE(get_bitstream_buffer_cb.called());
+ ASSERT_EQ(PP_OK, get_bitstream_buffer_cb.result());
+
+ CallRecycleBitstreamBuffer(encoder.get(), bitstream_buffer);
+
+ ResourceMessageCallParams recycle_params;
+ uint32_t buffer_id;
+ ASSERT_TRUE(CheckRecycleBitstreamBufferMsg(&recycle_params, &buffer_id));
+ ASSERT_EQ(kBitstreamBufferNb - 1, buffer_id);
+}
+
+TEST_F(VideoEncoderResourceTest, RequestEncodingParametersChange) {
+ // Check encoding parameter changes are correctly sent to the
+ // renderer.
+ LockingResourceReleaser encoder(CreateAndInitializeEncoder());
+
+ CallRequestEncodingParametersChange(encoder.get(), 1, 2);
+ ResourceMessageCallParams params;
+ uint32_t bitrate, framerate;
+ ASSERT_TRUE(
+ CheckRequestEncodeingParametersChangeMsg(&params, &bitrate, &framerate));
+ ASSERT_EQ(static_cast<uint32_t>(1), bitrate);
+ ASSERT_EQ(static_cast<uint32_t>(2), framerate);
+}
+
+TEST_F(VideoEncoderResourceTest, NotifyError) {
+ {
+ // Check an error from the encoder calls back GetVideoFrame and
bbudge 2015/02/13 01:45:53 s/calls back/aborts
+ // GetBitstreamBuffer callbacks.
+ LockingResourceReleaser encoder(CreateAndInitializeEncoder());
+
+ MockCompletionCallback get_frame_cb;
+ PP_Resource video_frame;
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallGetVideoFrame(encoder.get(), &video_frame, &get_frame_cb));
+ ASSERT_FALSE(get_frame_cb.called());
+
+ MockCompletionCallback get_bitstream_buffer_cb;
+ PP_BitstreamBuffer bitstream_buffer;
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallGetBitstreamBuffer(encoder.get(), &bitstream_buffer,
+ &get_bitstream_buffer_cb));
+
+ ResourceMessageCallParams error_params(encoder.get(), 0);
+ SendNotifyError(error_params, PP_ERROR_FAILED);
+
+ ASSERT_TRUE(get_frame_cb.called());
+ ASSERT_EQ(PP_ERROR_FAILED, get_frame_cb.result());
+ ASSERT_TRUE(get_bitstream_buffer_cb.called());
+ ASSERT_EQ(PP_ERROR_FAILED, get_bitstream_buffer_cb.result());
+ }
+ {
+ // Check an error from the encoder calls back Encode and GetBitstreamBuffer
bbudge 2015/02/13 01:45:54 s/calls back/aborts
llandwerlin-old 2015/02/13 20:12:26 Done.
+ // callbacks.
+ LockingResourceReleaser encoder(CreateAndInitializeEncoder());
+
+ MockCompletionCallback get_frame_cb, encode_cb1, encode_cb2;
+ PP_Resource video_frame1, video_frame2;
+ ASSERT_EQ(
+ PP_OK_COMPLETIONPENDING,
+ CallFirstGetVideoFrame(encoder.get(), &video_frame1, &get_frame_cb));
+ ASSERT_TRUE(get_frame_cb.called());
+ ASSERT_EQ(PP_OK, get_frame_cb.result());
+
+ get_frame_cb.Reset();
+ ASSERT_EQ(PP_OK, CallFirstGetVideoFrame(encoder.get(), &video_frame2,
+ &get_frame_cb));
+ ASSERT_FALSE(get_frame_cb.called());
+
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallEncode(encoder.get(), video_frame1, PP_FALSE, &encode_cb1));
+ ASSERT_FALSE(encode_cb1.called());
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallEncode(encoder.get(), video_frame2, PP_FALSE, &encode_cb2));
+ ASSERT_FALSE(encode_cb2.called());
+
+ MockCompletionCallback get_bitstream_buffer_cb;
+ PP_BitstreamBuffer bitstream_buffer;
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallGetBitstreamBuffer(encoder.get(), &bitstream_buffer,
+ &get_bitstream_buffer_cb));
+
+ ResourceMessageCallParams error_params(encoder.get(), 0);
+ SendNotifyError(error_params, PP_ERROR_FAILED);
+
+ ASSERT_TRUE(encode_cb1.called());
+ ASSERT_EQ(PP_ERROR_FAILED, encode_cb1.result());
+ ASSERT_TRUE(encode_cb2.called());
+ ASSERT_EQ(PP_ERROR_FAILED, encode_cb2.result());
+ ASSERT_TRUE(get_bitstream_buffer_cb.called());
+ ASSERT_EQ(PP_ERROR_FAILED, get_bitstream_buffer_cb.result());
+ }
+}
+
+TEST_F(VideoEncoderResourceTest, Close) {
+ {
+ // Check closing the encoder callbacks back GetVideoFrame and
bbudge 2015/02/13 01:45:54 s/callbacks back/aborts
llandwerlin-old 2015/02/13 20:12:26 Done.
+ // GetBitstreamBuffer callbacks.
+ LockingResourceReleaser encoder(CreateAndInitializeEncoder());
+
+ MockCompletionCallback get_frame_cb;
+ PP_Resource video_frame;
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallGetVideoFrame(encoder.get(), &video_frame, &get_frame_cb));
+ ASSERT_FALSE(get_frame_cb.called());
+
+ MockCompletionCallback get_bitstream_buffer_cb;
+ PP_BitstreamBuffer bitstream_buffer;
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallGetBitstreamBuffer(encoder.get(), &bitstream_buffer,
+ &get_bitstream_buffer_cb));
+
+ CallClose(encoder.get());
+
+ ASSERT_TRUE(get_frame_cb.called());
+ ASSERT_EQ(PP_ERROR_ABORTED, get_frame_cb.result());
+ ASSERT_TRUE(get_bitstream_buffer_cb.called());
+ ASSERT_EQ(PP_ERROR_ABORTED, get_bitstream_buffer_cb.result());
+ }
+ {
+ // Check closing the encoder calls back Encode and GetBitstreamBuffer
bbudge 2015/02/13 01:45:53 s/calls back/aborts
llandwerlin-old 2015/02/13 20:12:26 Done.
+ // callbacks.
+ LockingResourceReleaser encoder(CreateAndInitializeEncoder());
+
+ MockCompletionCallback get_frame_cb, encode_cb1, encode_cb2;
+ PP_Resource video_frame1, video_frame2;
+ ASSERT_EQ(
+ PP_OK_COMPLETIONPENDING,
+ CallFirstGetVideoFrame(encoder.get(), &video_frame1, &get_frame_cb));
+ ASSERT_TRUE(get_frame_cb.called());
+ ASSERT_EQ(PP_OK, get_frame_cb.result());
+
+ get_frame_cb.Reset();
+ ASSERT_EQ(PP_OK, CallFirstGetVideoFrame(encoder.get(), &video_frame2,
+ &get_frame_cb));
+ ASSERT_FALSE(get_frame_cb.called());
+
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallEncode(encoder.get(), video_frame1, PP_FALSE, &encode_cb1));
+ ASSERT_FALSE(encode_cb1.called());
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallEncode(encoder.get(), video_frame2, PP_FALSE, &encode_cb2));
+ ASSERT_FALSE(encode_cb2.called());
+
+ MockCompletionCallback get_bitstream_buffer_cb;
+ PP_BitstreamBuffer bitstream_buffer;
+ ASSERT_EQ(PP_OK_COMPLETIONPENDING,
+ CallGetBitstreamBuffer(encoder.get(), &bitstream_buffer,
+ &get_bitstream_buffer_cb));
+
+ CallClose(encoder.get());
+
+ ASSERT_TRUE(encode_cb1.called());
+ ASSERT_EQ(PP_ERROR_ABORTED, encode_cb1.result());
+ ASSERT_TRUE(encode_cb2.called());
+ ASSERT_EQ(PP_ERROR_ABORTED, encode_cb2.result());
+ ASSERT_TRUE(get_bitstream_buffer_cb.called());
+ ASSERT_EQ(PP_ERROR_ABORTED, get_bitstream_buffer_cb.result());
+ }
+}
+
+} // namespace proxy
+} // namespace ppapi

Powered by Google App Engine
This is Rietveld 408576698