• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include <string.h>
6 #include <iterator>
7 #include <sstream>
8 #include <string>
9 #include <vector>
10 
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"
20 
21 // When compiling natively on Windows, PostMessage can be #define-d to
22 // something else.
23 #ifdef PostMessage
24 #undef PostMessage
25 #endif
26 
27 namespace {
28 
29 // Helper functions
SplitStringBySpace(const std::string & str)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);
34   return tokens;
35 }
36 
37 // This object is the global object representing this plugin library as long
38 // as it is loaded.
39 class VEDemoModule : public pp::Module {
40  public:
VEDemoModule()41   VEDemoModule() : pp::Module() {}
~VEDemoModule()42   virtual ~VEDemoModule() {}
43 
44   virtual pp::Instance* CreateInstance(PP_Instance instance);
45 };
46 
47 class VEDemoInstance : public pp::Instance {
48  public:
49   VEDemoInstance(PP_Instance instance, pp::Module* module);
50   virtual ~VEDemoInstance();
51 
52   // pp::Instance implementation (see PPP_Instance).
53   virtual void HandleMessage(const pp::Var& message_data);
54 
55  private:
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_;
62   bool effect_on_;
63   pp::CompletionCallbackFactory<VEDemoInstance> factory_;
64   pp::MessageLoop message_loop_;
65 };
66 
VEDemoInstance(PP_Instance instance,pp::Module * module)67 VEDemoInstance::VEDemoInstance(PP_Instance instance, pp::Module* module)
68     : pp::Instance(instance),
69       video_source_(this),
70       video_destination_(this),
71       effect_on_(false),
72       message_loop_(pp::MessageLoop::GetCurrent()) {
73   factory_.Initialize(this);
74 }
75 
~VEDemoInstance()76 VEDemoInstance::~VEDemoInstance() {
77   video_source_.Close();
78   video_destination_.Close();
79 }
80 
HandleMessage(const pp::Var & message_data)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."));
87       return;
88     }
89     if (messages[0] == "registerStream") {
90       if (messages.size() < 3) {
91         PostMessage(pp::Var("Got 'registerStream' with incorrect parameters."));
92         return;
93       }
94       // Open destination stream for write.
95       video_destination_.Open(
96           messages[2],
97           factory_.NewCallback(&VEDemoInstance::DestinationOpenDone,
98                                messages[1]));
99     } else if (messages[0] == "effectOn") {
100       effect_on_ = true;
101       PostMessage(pp::Var("Effect ON."));
102     } else if (messages[0] == "effectOff") {
103       effect_on_ = false;
104       PostMessage(pp::Var("Effect OFF."));
105     }
106   }
107 }
108 
DestinationOpenDone(int32_t result,const std::string & src_url)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."));
113     return;
114   }
115   // Open source stream for read.
116   video_source_.Open(src_url,
117                      factory_.NewCallback(&VEDemoInstance::SourceOpenDone));
118 }
119 
SourceOpenDone(int32_t result)120 void VEDemoInstance::SourceOpenDone(int32_t result) {
121   if (result != PP_OK) {
122     PostMessage(pp::Var("Failed to open source stream."));
123     return;
124   }
125   // Done with the stream register.
126   PostMessage(pp::Var("DoneRegistering"));
127 
128   // Kick off the processing loop.
129   message_loop_.PostWork(factory_.NewCallback(&VEDemoInstance::KickoffEffect));
130 }
131 
GetFrameDone(int32_t result,pp::VideoFrame_Private video_frame)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."));
136     return;
137   }
138 
139   // Apply the effect to the received frame.
140   if (effect_on_) {
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());
151     }
152   }
153 
154   // Put frame back to destination stream
155   video_destination_.PutFrame(video_frame);
156 
157   // Trigger for the next frame.
158   message_loop_.PostWork(factory_.NewCallback(&VEDemoInstance::KickoffEffect));
159 }
160 
KickoffEffect(int32_t)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));
166 }
167 
CreateInstance(PP_Instance instance)168 pp::Instance* VEDemoModule::CreateInstance(PP_Instance instance) {
169   return new VEDemoInstance(instance, this);
170 }
171 
172 }  // anonymous namespace
173 
174 namespace pp {
175 // Factory function for your specialization of the Module object.
CreateModule()176 Module* CreateModule() {
177   return new VEDemoModule();
178 }
179 }  // namespace pp
180