1 // Copyright 2015 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 "ppapi/cpp/video_encoder.h"
6 
7 #include <stddef.h>
8 
9 #include "ppapi/c/pp_errors.h"
10 #include "ppapi/c/ppb_video_encoder.h"
11 #include "ppapi/cpp/completion_callback.h"
12 #include "ppapi/cpp/instance_handle.h"
13 #include "ppapi/cpp/module.h"
14 #include "ppapi/cpp/module_impl.h"
15 
16 namespace pp {
17 
18 namespace {
19 
20 template <>
interface_name()21 const char* interface_name<PPB_VideoEncoder_0_1>() {
22   return PPB_VIDEOENCODER_INTERFACE_0_1;
23 }
24 
25 template <>
interface_name()26 const char* interface_name<PPB_VideoEncoder_0_2>() {
27   return PPB_VIDEOENCODER_INTERFACE_0_2;
28 }
29 
30 // This struct is used to adapt
31 // CompletionCallbackWithOutput<std::vector<PP_VideoProfileDescription>>
32 // to the pre-0.2 APIs, which return PP_VideoProfileDescription_0_1.
33 // This struct is allocated on the heap, and deleted in
34 // CallbackProfileDescriptionConverter.
35 struct CallbackProfileDescription_0_1 {
CallbackProfileDescription_0_1pp::__anone1218aaa0111::CallbackProfileDescription_0_136   explicit CallbackProfileDescription_0_1(const CompletionCallbackWithOutput<
37       std::vector<PP_VideoProfileDescription> >& cc)
38       : output_profiles(&profiles),
39         original_output_profiles(cc.output()),
40         original_callback(cc.pp_completion_callback()) {}
41   std::vector<PP_VideoProfileDescription_0_1> profiles;
42   ArrayOutputAdapter<PP_VideoProfileDescription_0_1> output_profiles;
43   PP_ArrayOutput original_output_profiles;
44   PP_CompletionCallback original_callback;
45 };
46 
47 // Converts data from a 0.1 style callback to 0.2 callback.
CallbackProfileDescriptionConverter(void * user_data,int32_t result)48 void CallbackProfileDescriptionConverter(void* user_data, int32_t result) {
49   CallbackProfileDescription_0_1* data =
50       static_cast<CallbackProfileDescription_0_1*>(user_data);
51   if (result >= 0) {
52     PP_VideoProfileDescription* original_profiles =
53         static_cast<PP_VideoProfileDescription*>(
54             data->original_output_profiles.GetDataBuffer(
55                 data->original_output_profiles.user_data,
56                 static_cast<uint32_t>(data->profiles.size()),
57                 static_cast<uint32_t>(sizeof(PP_VideoProfileDescription))));
58 
59     for (size_t i = 0; i < data->profiles.size(); i++) {
60       const PP_VideoProfileDescription_0_1& profile = data->profiles[i];
61 
62       original_profiles[i].profile = profile.profile;
63       original_profiles[i].max_resolution = profile.max_resolution;
64       original_profiles[i].max_framerate_numerator =
65           profile.max_framerate_numerator;
66       original_profiles[i].max_framerate_denominator =
67           profile.max_framerate_denominator;
68       original_profiles[i].hardware_accelerated =
69           PP_FromBool(profile.acceleration == PP_HARDWAREACCELERATION_ONLY);
70     }
71   }
72 
73   // Now execute the original callback.
74   PP_RunCompletionCallback(&data->original_callback, result);
75   delete data;
76 }
77 
78 }  // namespace
79 
VideoEncoder()80 VideoEncoder::VideoEncoder() {
81 }
82 
VideoEncoder(const InstanceHandle & instance)83 VideoEncoder::VideoEncoder(const InstanceHandle& instance) {
84   if (has_interface<PPB_VideoEncoder_0_2>()) {
85     PassRefFromConstructor(
86         get_interface<PPB_VideoEncoder_0_2>()->Create(instance.pp_instance()));
87   } else if (has_interface<PPB_VideoEncoder_0_1>()) {
88     PassRefFromConstructor(
89         get_interface<PPB_VideoEncoder_0_1>()->Create(instance.pp_instance()));
90   }
91 }
92 
VideoEncoder(const VideoEncoder & other)93 VideoEncoder::VideoEncoder(const VideoEncoder& other) : Resource(other) {
94 }
95 
GetSupportedProfiles(const CompletionCallbackWithOutput<std::vector<PP_VideoProfileDescription>> & cc)96 int32_t VideoEncoder::GetSupportedProfiles(const CompletionCallbackWithOutput<
97     std::vector<PP_VideoProfileDescription> >& cc) {
98   if (has_interface<PPB_VideoEncoder_0_2>()) {
99     return get_interface<PPB_VideoEncoder_0_2>()->GetSupportedProfiles(
100         pp_resource(), cc.output(), cc.pp_completion_callback());
101   } else if (has_interface<PPB_VideoEncoder_0_1>()) {
102     // Data for our callback wrapper. The callback handler will delete it.
103     CallbackProfileDescription_0_1* data =
104         new CallbackProfileDescription_0_1(cc);
105     return get_interface<PPB_VideoEncoder_0_1>()->GetSupportedProfiles(
106         pp_resource(), data->output_profiles.pp_array_output(),
107         PP_MakeCompletionCallback(&CallbackProfileDescriptionConverter, data));
108   }
109   return cc.MayForce(PP_ERROR_NOINTERFACE);
110 }
111 
Initialize(const PP_VideoFrame_Format & input_format,const Size & input_visible_size,const PP_VideoProfile & output_profile,const uint32_t initial_bitrate,PP_HardwareAcceleration acceleration,const CompletionCallback & cc)112 int32_t VideoEncoder::Initialize(const PP_VideoFrame_Format& input_format,
113                                  const Size& input_visible_size,
114                                  const PP_VideoProfile& output_profile,
115                                  const uint32_t initial_bitrate,
116                                  PP_HardwareAcceleration acceleration,
117                                  const CompletionCallback& cc) {
118   if (has_interface<PPB_VideoEncoder_0_2>()) {
119     return get_interface<PPB_VideoEncoder_0_2>()->Initialize(
120         pp_resource(), input_format, &input_visible_size.pp_size(),
121         output_profile, initial_bitrate, acceleration,
122         cc.pp_completion_callback());
123   } else if (has_interface<PPB_VideoEncoder_0_1>()) {
124     return get_interface<PPB_VideoEncoder_0_1>()->Initialize(
125         pp_resource(), input_format, &input_visible_size.pp_size(),
126         output_profile, initial_bitrate, acceleration,
127         cc.pp_completion_callback());
128   }
129   return cc.MayForce(PP_ERROR_NOINTERFACE);
130 }
131 
GetFramesRequired()132 int32_t VideoEncoder::GetFramesRequired() {
133   if (has_interface<PPB_VideoEncoder_0_2>()) {
134     return get_interface<PPB_VideoEncoder_0_2>()->GetFramesRequired(
135         pp_resource());
136   } else if (has_interface<PPB_VideoEncoder_0_1>()) {
137     return get_interface<PPB_VideoEncoder_0_1>()->GetFramesRequired(
138         pp_resource());
139   }
140   return PP_ERROR_NOINTERFACE;
141 }
142 
GetFrameCodedSize(Size * coded_size)143 int32_t VideoEncoder::GetFrameCodedSize(Size* coded_size) {
144   if (has_interface<PPB_VideoEncoder_0_2>()) {
145     return get_interface<PPB_VideoEncoder_0_2>()->GetFrameCodedSize(
146         pp_resource(), &coded_size->pp_size());
147   } else if (has_interface<PPB_VideoEncoder_0_1>()) {
148     return get_interface<PPB_VideoEncoder_0_1>()->GetFrameCodedSize(
149         pp_resource(), &coded_size->pp_size());
150   }
151   return PP_ERROR_NOINTERFACE;
152 }
153 
GetVideoFrame(const CompletionCallbackWithOutput<VideoFrame> & cc)154 int32_t VideoEncoder::GetVideoFrame(
155     const CompletionCallbackWithOutput<VideoFrame>& cc) {
156   if (has_interface<PPB_VideoEncoder_0_2>()) {
157     return get_interface<PPB_VideoEncoder_0_2>()->GetVideoFrame(
158         pp_resource(), cc.output(), cc.pp_completion_callback());
159   } else if (has_interface<PPB_VideoEncoder_0_1>()) {
160     return get_interface<PPB_VideoEncoder_0_1>()->GetVideoFrame(
161         pp_resource(), cc.output(), cc.pp_completion_callback());
162   }
163   return cc.MayForce(PP_ERROR_NOINTERFACE);
164 }
165 
Encode(const VideoFrame & video_frame,bool force_keyframe,const CompletionCallback & cc)166 int32_t VideoEncoder::Encode(const VideoFrame& video_frame,
167                              bool force_keyframe,
168                              const CompletionCallback& cc) {
169   if (has_interface<PPB_VideoEncoder_0_2>()) {
170     return get_interface<PPB_VideoEncoder_0_2>()->Encode(
171         pp_resource(), video_frame.pp_resource(), PP_FromBool(force_keyframe),
172         cc.pp_completion_callback());
173   } else if (has_interface<PPB_VideoEncoder_0_1>()) {
174     return get_interface<PPB_VideoEncoder_0_1>()->Encode(
175         pp_resource(), video_frame.pp_resource(), PP_FromBool(force_keyframe),
176         cc.pp_completion_callback());
177   }
178   return cc.MayForce(PP_ERROR_NOINTERFACE);
179 }
180 
GetBitstreamBuffer(const CompletionCallbackWithOutput<PP_BitstreamBuffer> & cc)181 int32_t VideoEncoder::GetBitstreamBuffer(
182     const CompletionCallbackWithOutput<PP_BitstreamBuffer>& cc) {
183   if (has_interface<PPB_VideoEncoder_0_2>()) {
184     return get_interface<PPB_VideoEncoder_0_2>()->GetBitstreamBuffer(
185         pp_resource(), cc.output(), cc.pp_completion_callback());
186   } else if (has_interface<PPB_VideoEncoder_0_1>()) {
187     return get_interface<PPB_VideoEncoder_0_1>()->GetBitstreamBuffer(
188         pp_resource(), cc.output(), cc.pp_completion_callback());
189   }
190   return cc.MayForce(PP_ERROR_NOINTERFACE);
191 }
192 
RecycleBitstreamBuffer(const PP_BitstreamBuffer & bitstream_buffer)193 void VideoEncoder::RecycleBitstreamBuffer(
194     const PP_BitstreamBuffer& bitstream_buffer) {
195   if (has_interface<PPB_VideoEncoder_0_2>()) {
196     get_interface<PPB_VideoEncoder_0_2>()->RecycleBitstreamBuffer(
197         pp_resource(), &bitstream_buffer);
198   } else if (has_interface<PPB_VideoEncoder_0_1>()) {
199     get_interface<PPB_VideoEncoder_0_1>()->RecycleBitstreamBuffer(
200         pp_resource(), &bitstream_buffer);
201   }
202 }
203 
RequestEncodingParametersChange(uint32_t bitrate,uint32_t framerate)204 void VideoEncoder::RequestEncodingParametersChange(uint32_t bitrate,
205                                                    uint32_t framerate) {
206   if (has_interface<PPB_VideoEncoder_0_2>()) {
207     get_interface<PPB_VideoEncoder_0_2>()->RequestEncodingParametersChange(
208         pp_resource(), bitrate, framerate);
209   } else if (has_interface<PPB_VideoEncoder_0_1>()) {
210     get_interface<PPB_VideoEncoder_0_1>()->RequestEncodingParametersChange(
211         pp_resource(), bitrate, framerate);
212   }
213 }
214 
Close()215 void VideoEncoder::Close() {
216   if (has_interface<PPB_VideoEncoder_0_2>()) {
217     get_interface<PPB_VideoEncoder_0_2>()->Close(pp_resource());
218   } else if (has_interface<PPB_VideoEncoder_0_1>()) {
219     get_interface<PPB_VideoEncoder_0_1>()->Close(pp_resource());
220   }
221 }
222 
223 }  // namespace pp
224