1 // Copyright (c) 2013 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.
11 #include "ppapi/c/pp_errors.h"
12 #include "ppapi/cpp/instance.h"
13 #include "ppapi/cpp/message_loop.h"
14 #include "ppapi/cpp/module.h"
15 #include "ppapi/cpp/private/video_destination_private.h"
16 #include "ppapi/cpp/private/video_frame_private.h"
17 #include "ppapi/cpp/private/video_source_private.h"
18 #include "ppapi/cpp/var.h"
19 #include "ppapi/utility/completion_callback_factory.h"
21 // When compiling natively on Windows, PostMessage can be #define-d to
30 std::vector
<std::string
> SplitStringBySpace(const std::string
& str
) {
31 std::istringstream
buf(str
);
32 std::istream_iterator
<std::string
> begin(buf
), end
;
33 std::vector
<std::string
> tokens(begin
, end
);
37 // This object is the global object representing this plugin library as long
39 class VEDemoModule
: public pp::Module
{
41 VEDemoModule() : pp::Module() {}
42 virtual ~VEDemoModule() {}
44 virtual pp::Instance
* CreateInstance(PP_Instance instance
);
47 class VEDemoInstance
: public pp::Instance
{
49 VEDemoInstance(PP_Instance instance
, pp::Module
* module
);
50 virtual ~VEDemoInstance();
52 // pp::Instance implementation (see PPP_Instance).
53 virtual void HandleMessage(const pp::Var
& message_data
);
56 void DestinationOpenDone(int32_t result
, const std::string
& src_url
);
57 void SourceOpenDone(int32_t result
);
58 void GetFrameDone(int32_t result
, pp::VideoFrame_Private video_frame
);
59 void KickoffEffect(int32_t result
);
60 pp::VideoSource_Private video_source_
;
61 pp::VideoDestination_Private video_destination_
;
63 pp::CompletionCallbackFactory
<VEDemoInstance
> factory_
;
64 pp::MessageLoop message_loop_
;
67 VEDemoInstance::VEDemoInstance(PP_Instance instance
, pp::Module
* module
)
68 : pp::Instance(instance
),
70 video_destination_(this),
72 message_loop_(pp::MessageLoop::GetCurrent()) {
73 factory_
.Initialize(this);
76 VEDemoInstance::~VEDemoInstance() {
77 video_source_
.Close();
78 video_destination_
.Close();
81 void VEDemoInstance::HandleMessage(const pp::Var
& message_data
) {
82 if (message_data
.is_string()) {
83 std::vector
<std::string
> messages
;
84 messages
= SplitStringBySpace(message_data
.AsString());
85 if (messages
.empty()) {
86 PostMessage(pp::Var("Ignored empty message."));
89 if (messages
[0] == "registerStream") {
90 if (messages
.size() < 3) {
91 PostMessage(pp::Var("Got 'registerStream' with incorrect parameters."));
94 // Open destination stream for write.
95 video_destination_
.Open(
97 factory_
.NewCallback(&VEDemoInstance::DestinationOpenDone
,
99 } else if (messages
[0] == "effectOn") {
101 PostMessage(pp::Var("Effect ON."));
102 } else if (messages
[0] == "effectOff") {
104 PostMessage(pp::Var("Effect OFF."));
109 void VEDemoInstance::DestinationOpenDone(int32_t result
,
110 const std::string
& src_url
) {
111 if (result
!= PP_OK
) {
112 PostMessage(pp::Var("Failed to open destination stream."));
115 // Open source stream for read.
116 video_source_
.Open(src_url
,
117 factory_
.NewCallback(&VEDemoInstance::SourceOpenDone
));
120 void VEDemoInstance::SourceOpenDone(int32_t result
) {
121 if (result
!= PP_OK
) {
122 PostMessage(pp::Var("Failed to open source stream."));
125 // Done with the stream register.
126 PostMessage(pp::Var("DoneRegistering"));
128 // Kick off the processing loop.
129 message_loop_
.PostWork(factory_
.NewCallback(&VEDemoInstance::KickoffEffect
));
132 void VEDemoInstance::GetFrameDone(int32_t result
,
133 pp::VideoFrame_Private video_frame
) {
134 if (result
!= PP_OK
) {
135 PostMessage(pp::Var("Failed to get frame."));
139 // Apply the effect to the received frame.
141 pp::ImageData image_data
= video_frame
.image_data();
142 pp::Size size
= image_data
.size();
143 std::vector
<uint8_t> tmp_row(image_data
.stride());
144 uint8_t* image
= static_cast<uint8_t*>(image_data
.data());
145 for (int i
= 0; i
< size
.height() / 2; ++i
) {
146 uint8_t* top
= image
+ i
* image_data
.stride();
147 uint8_t* bottom
= image
+ (size
.height() - 1 - i
) * image_data
.stride();
148 memcpy(&tmp_row
[0], top
, image_data
.stride());
149 memcpy(top
, bottom
, image_data
.stride());
150 memcpy(bottom
, &tmp_row
[0], image_data
.stride());
154 // Put frame back to destination stream
155 video_destination_
.PutFrame(video_frame
);
157 // Trigger for the next frame.
158 message_loop_
.PostWork(factory_
.NewCallback(&VEDemoInstance::KickoffEffect
));
161 void VEDemoInstance::KickoffEffect(int32_t /* result */) {
162 // Get the frame from the source stream.
163 video_source_
.GetFrame(
164 factory_
.NewCallbackWithOutput
<pp::VideoFrame_Private
>(
165 &VEDemoInstance::GetFrameDone
));
168 pp::Instance
* VEDemoModule::CreateInstance(PP_Instance instance
) {
169 return new VEDemoInstance(instance
, this);
172 } // anonymous namespace
175 // Factory function for your specialization of the Module object.
176 Module
* CreateModule() {
177 return new VEDemoModule();