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