OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <math.h> | 5 #include <math.h> |
6 #include <stdio.h> | 6 #include <stdio.h> |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <iostream> | 9 #include <iostream> |
10 #include <map> | |
10 #include <sstream> | 11 #include <sstream> |
11 #include <vector> | 12 #include <vector> |
12 | 13 |
13 #include "ppapi/c/pp_errors.h" | 14 #include "ppapi/c/pp_errors.h" |
14 #include "ppapi/c/ppb_console.h" | 15 #include "ppapi/c/ppb_console.h" |
15 #include "ppapi/cpp/input_event.h" | 16 #include "ppapi/cpp/input_event.h" |
16 #include "ppapi/cpp/instance.h" | 17 #include "ppapi/cpp/instance.h" |
17 #include "ppapi/cpp/media_stream_video_track.h" | 18 #include "ppapi/cpp/media_stream_video_track.h" |
18 #include "ppapi/cpp/module.h" | 19 #include "ppapi/cpp/module.h" |
19 #include "ppapi/cpp/rect.h" | 20 #include "ppapi/cpp/rect.h" |
20 #include "ppapi/cpp/var.h" | 21 #include "ppapi/cpp/var.h" |
21 #include "ppapi/cpp/var_array_buffer.h" | 22 #include "ppapi/cpp/var_array_buffer.h" |
22 #include "ppapi/cpp/var_dictionary.h" | 23 #include "ppapi/cpp/var_dictionary.h" |
23 #include "ppapi/cpp/video_encoder.h" | 24 #include "ppapi/cpp/video_encoder.h" |
24 #include "ppapi/cpp/video_frame.h" | 25 #include "ppapi/cpp/video_frame.h" |
25 #include "ppapi/utility/completion_callback_factory.h" | 26 #include "ppapi/utility/completion_callback_factory.h" |
26 | 27 |
27 // TODO(llandwerlin): turn on by default when we have software encode. | |
28 // #define USE_VP8_INSTEAD_OF_H264 | |
29 | |
30 // When compiling natively on Windows, PostMessage can be #define-d to | 28 // When compiling natively on Windows, PostMessage can be #define-d to |
31 // something else. | 29 // something else. |
32 #ifdef PostMessage | 30 #ifdef PostMessage |
33 #undef PostMessage | 31 #undef PostMessage |
34 #endif | 32 #endif |
35 | 33 |
36 // Use assert as a poor-man's CHECK, even in non-debug mode. | 34 // Use assert as a poor-man's CHECK, even in non-debug mode. |
37 // Since <assert.h> redefines assert on every inclusion (it doesn't use | 35 // Since <assert.h> redefines assert on every inclusion (it doesn't use |
38 // include-guards), make sure this is the last file #include'd in this file. | 36 // include-guards), make sure this is the last file #include'd in this file. |
39 #undef NDEBUG | 37 #undef NDEBUG |
40 #include <assert.h> | 38 #include <assert.h> |
41 | 39 |
40 #define fourcc(a, b, c, d) \ | |
41 (((uint32_t)(a) << 0) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | \ | |
42 ((uint32_t)(d) << 24)) | |
43 | |
42 namespace { | 44 namespace { |
43 | 45 |
44 std::string VideoProfileToString(PP_VideoProfile profile) { | 46 class IVFWriter { |
bbudge
2015/03/16 18:27:48
Since this is an example, some general comments ab
llandwerlin-old
2015/03/16 19:08:09
Done.
| |
45 switch (profile) { | 47 public: |
46 case PP_VIDEOPROFILE_H264BASELINE: | 48 IVFWriter() {} |
47 return "h264baseline"; | 49 ~IVFWriter() {} |
48 case PP_VIDEOPROFILE_H264MAIN: | 50 |
49 return "h264main"; | 51 uint32_t GetFileHeaderSize() const { return 32; } |
50 case PP_VIDEOPROFILE_H264EXTENDED: | 52 uint32_t GetFrameHeaderSize() const { return 12; } |
51 return "h264extended"; | 53 uint32_t WriteFileHeader(uint8_t* mem, int32_t width, int32_t height); |
52 case PP_VIDEOPROFILE_H264HIGH: | 54 uint32_t WriteFrameHeader(uint8_t* mem, uint64_t pts, size_t frame_size); |
53 return "h264high"; | 55 |
54 case PP_VIDEOPROFILE_H264HIGH10PROFILE: | 56 private: |
55 return "h264high10"; | 57 void PutLE16(uint8_t* mem, int val) const { |
56 case PP_VIDEOPROFILE_H264HIGH422PROFILE: | 58 mem[0] = (val >> 0) & 0xff; |
57 return "h264high422"; | 59 mem[1] = (val >> 8) & 0xff; |
58 case PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE: | |
59 return "h264high444predictive"; | |
60 case PP_VIDEOPROFILE_H264SCALABLEBASELINE: | |
61 return "h264scalablebaseline"; | |
62 case PP_VIDEOPROFILE_H264SCALABLEHIGH: | |
63 return "h264scalablehigh"; | |
64 case PP_VIDEOPROFILE_H264STEREOHIGH: | |
65 return "h264stereohigh"; | |
66 case PP_VIDEOPROFILE_H264MULTIVIEWHIGH: | |
67 return "h264multiviewhigh"; | |
68 case PP_VIDEOPROFILE_VP8_ANY: | |
69 return "vp8"; | |
70 case PP_VIDEOPROFILE_VP9_ANY: | |
71 return "vp9"; | |
72 // No default to catch unhandled profiles. | |
73 } | 60 } |
74 return "unknown"; | 61 void PutLE32(uint8_t* mem, int val) const { |
62 mem[0] = (val >> 0) & 0xff; | |
63 mem[1] = (val >> 8) & 0xff; | |
64 mem[2] = (val >> 16) & 0xff; | |
65 mem[3] = (val >> 24) & 0xff; | |
66 } | |
67 }; | |
68 | |
69 uint32_t IVFWriter::WriteFileHeader(uint8_t* mem, | |
70 int32_t width, | |
71 int32_t height) { | |
72 mem[0] = 'D'; | |
73 mem[1] = 'K'; | |
74 mem[2] = 'I'; | |
75 mem[3] = 'F'; | |
76 PutLE16(mem + 4, 0); // version | |
77 PutLE16(mem + 6, 32); // header size | |
78 PutLE32(mem + 8, fourcc('V', 'P', '8', '0')); // fourcc | |
79 PutLE16(mem + 12, static_cast<uint16_t>(width)); // width | |
80 PutLE16(mem + 14, static_cast<uint16_t>(height)); // height | |
81 PutLE32(mem + 16, 30); // rate | |
82 PutLE32(mem + 20, 1); // scale | |
83 PutLE32(mem + 24, 0xffffffff); // length | |
84 PutLE32(mem + 28, 0); // unused | |
85 | |
86 return 32; | |
75 } | 87 } |
76 | 88 |
77 std::string HardwareAccelerationToString(PP_HardwareAcceleration acceleration) { | 89 uint32_t IVFWriter::WriteFrameHeader(uint8_t* mem, |
78 switch (acceleration) { | 90 uint64_t pts, |
79 case PP_HARDWAREACCELERATION_ONLY: | 91 size_t frame_size) { |
80 return "hardware"; | 92 PutLE32(mem, (int)frame_size); |
81 case PP_HARDWAREACCELERATION_WITHFALLBACK: | 93 PutLE32(mem + 4, (int)(pts & 0xFFFFFFFF)); |
82 return "hardware/software"; | 94 PutLE32(mem + 8, (int)(pts >> 32)); |
83 case PP_HARDWAREACCELERATION_NONE: | 95 |
84 return "software"; | 96 return 12; |
85 // No default to catch unhandled accelerations. | |
86 } | |
87 return "unknown"; | |
88 } | 97 } |
89 | 98 |
90 // This object is the global object representing this plugin library as long | 99 // This object is the global object representing this plugin library as long |
91 // as it is loaded. | 100 // as it is loaded. |
92 class VideoEncoderModule : public pp::Module { | 101 class VideoEncoderModule : public pp::Module { |
93 public: | 102 public: |
94 VideoEncoderModule() : pp::Module() {} | 103 VideoEncoderModule() : pp::Module() {} |
95 virtual ~VideoEncoderModule() {} | 104 virtual ~VideoEncoderModule() {} |
96 | 105 |
97 virtual pp::Instance* CreateInstance(PP_Instance instance); | 106 virtual pp::Instance* CreateInstance(PP_Instance instance); |
98 }; | 107 }; |
99 | 108 |
100 class VideoEncoderInstance : public pp::Instance { | 109 class VideoEncoderInstance : public pp::Instance { |
101 public: | 110 public: |
102 VideoEncoderInstance(PP_Instance instance, pp::Module* module); | 111 VideoEncoderInstance(PP_Instance instance, pp::Module* module); |
103 virtual ~VideoEncoderInstance(); | 112 virtual ~VideoEncoderInstance(); |
104 | 113 |
105 // pp::Instance implementation. | 114 // pp::Instance implementation. |
106 virtual void HandleMessage(const pp::Var& var_message); | 115 virtual void HandleMessage(const pp::Var& var_message); |
107 | 116 |
108 private: | 117 private: |
118 void AddVideoProfile(PP_VideoProfile profile, const std::string& profile_str); | |
119 void InitializeVideoProfiles(); | |
120 PP_VideoProfile VideoProfileFromString(const std::string& str); | |
121 std::string VideoProfileToString(PP_VideoProfile profile); | |
122 | |
109 void ConfigureTrack(); | 123 void ConfigureTrack(); |
110 void OnConfiguredTrack(int32_t result); | 124 void OnConfiguredTrack(int32_t result); |
111 void ProbeEncoder(); | 125 void ProbeEncoder(); |
112 void OnEncoderProbed(int32_t result, | 126 void OnEncoderProbed(int32_t result, |
113 const std::vector<PP_VideoProfileDescription> profiles); | 127 const std::vector<PP_VideoProfileDescription> profiles); |
128 void StartEncoder(); | |
114 void OnInitializedEncoder(int32_t result); | 129 void OnInitializedEncoder(int32_t result); |
115 void ScheduleNextEncode(); | 130 void ScheduleNextEncode(); |
116 void GetEncoderFrameTick(int32_t result); | 131 void GetEncoderFrameTick(int32_t result); |
117 void GetEncoderFrame(const pp::VideoFrame& track_frame); | 132 void GetEncoderFrame(const pp::VideoFrame& track_frame); |
118 void OnEncoderFrame(int32_t result, | 133 void OnEncoderFrame(int32_t result, |
119 pp::VideoFrame encoder_frame, | 134 pp::VideoFrame encoder_frame, |
120 pp::VideoFrame track_frame); | 135 pp::VideoFrame track_frame); |
121 int32_t CopyVideoFrame(pp::VideoFrame dest, pp::VideoFrame src); | 136 int32_t CopyVideoFrame(pp::VideoFrame dest, pp::VideoFrame src); |
122 void EncodeFrame(const pp::VideoFrame& frame); | 137 void EncodeFrame(const pp::VideoFrame& frame); |
123 void OnEncodeDone(int32_t result); | 138 void OnEncodeDone(int32_t result); |
124 void OnGetBitstreamBuffer(int32_t result, PP_BitstreamBuffer buffer); | 139 void OnGetBitstreamBuffer(int32_t result, PP_BitstreamBuffer buffer); |
125 void StartTrackFrames(); | 140 void StartTrackFrames(); |
126 void StopTrackFrames(); | 141 void StopTrackFrames(); |
127 void OnTrackFrame(int32_t result, pp::VideoFrame frame); | 142 void OnTrackFrame(int32_t result, pp::VideoFrame frame); |
128 | 143 |
129 void StopEncode(); | 144 void StopEncode(); |
130 | 145 |
131 void LogError(int32_t error, const std::string& message); | 146 void LogError(int32_t error, const std::string& message); |
132 void Log(const std::string& message); | 147 void Log(const std::string& message); |
133 | 148 |
134 void PostDataMessage(const void* buffer, uint32_t size); | 149 void PostDataMessage(const void* buffer, uint32_t size); |
135 void PostSignalMessage(const char* name); | 150 void PostSignalMessage(const char* name); |
136 | 151 |
152 typedef std::map<std::string, PP_VideoProfile> VideoProfileFromStringMap; | |
153 VideoProfileFromStringMap profile_from_string_; | |
154 | |
155 typedef std::map<PP_VideoProfile, std::string> VideoProfileToStringMap; | |
156 VideoProfileToStringMap profile_to_string_; | |
157 | |
137 bool is_encoding_; | 158 bool is_encoding_; |
138 bool is_receiving_track_frames_; | 159 bool is_receiving_track_frames_; |
139 | 160 |
140 pp::VideoEncoder video_encoder_; | 161 pp::VideoEncoder video_encoder_; |
141 pp::MediaStreamVideoTrack video_track_; | 162 pp::MediaStreamVideoTrack video_track_; |
142 pp::CompletionCallbackFactory<VideoEncoderInstance> callback_factory_; | 163 pp::CompletionCallbackFactory<VideoEncoderInstance> callback_factory_; |
143 | 164 |
144 PP_VideoProfile video_profile_; | 165 PP_VideoProfile video_profile_; |
145 PP_VideoFrame_Format frame_format_; | 166 PP_VideoFrame_Format frame_format_; |
146 | 167 |
147 pp::Size requested_size_; | 168 pp::Size requested_size_; |
148 pp::Size frame_size_; | 169 pp::Size frame_size_; |
149 pp::Size encoder_size_; | 170 pp::Size encoder_size_; |
150 uint32_t encoded_frames_; | 171 uint32_t encoded_frames_; |
151 | 172 |
152 pp::VideoFrame current_track_frame_; | 173 pp::VideoFrame current_track_frame_; |
174 | |
175 IVFWriter ivf_writer_; | |
153 }; | 176 }; |
154 | 177 |
155 VideoEncoderInstance::VideoEncoderInstance(PP_Instance instance, | 178 VideoEncoderInstance::VideoEncoderInstance(PP_Instance instance, |
156 pp::Module* module) | 179 pp::Module* module) |
157 : pp::Instance(instance), | 180 : pp::Instance(instance), |
158 is_encoding_(false), | 181 is_encoding_(false), |
159 callback_factory_(this), | 182 callback_factory_(this), |
160 #if defined(USE_VP8_INSTEAD_OF_H264) | 183 #if defined(USE_VP8_INSTEAD_OF_H264) |
161 video_profile_(PP_VIDEOPROFILE_VP8_ANY), | 184 video_profile_(PP_VIDEOPROFILE_VP8_ANY), |
162 #else | 185 #else |
163 video_profile_(PP_VIDEOPROFILE_H264MAIN), | 186 video_profile_(PP_VIDEOPROFILE_H264MAIN), |
164 #endif | 187 #endif |
165 frame_format_(PP_VIDEOFRAME_FORMAT_I420), | 188 frame_format_(PP_VIDEOFRAME_FORMAT_I420), |
166 encoded_frames_(0) { | 189 encoded_frames_(0) { |
190 InitializeVideoProfiles(); | |
191 ProbeEncoder(); | |
167 } | 192 } |
168 | 193 |
169 VideoEncoderInstance::~VideoEncoderInstance() { | 194 VideoEncoderInstance::~VideoEncoderInstance() { |
170 } | 195 } |
171 | 196 |
197 void VideoEncoderInstance::AddVideoProfile(PP_VideoProfile profile, | |
198 const std::string& profile_str) { | |
199 profile_to_string_.insert(std::make_pair(profile, profile_str)); | |
200 profile_from_string_.insert(std::make_pair(profile_str, profile)); | |
201 } | |
202 | |
203 void VideoEncoderInstance::InitializeVideoProfiles() { | |
204 AddVideoProfile(PP_VIDEOPROFILE_H264BASELINE, "h264baseline"); | |
205 AddVideoProfile(PP_VIDEOPROFILE_H264MAIN, "h264main"); | |
206 AddVideoProfile(PP_VIDEOPROFILE_H264EXTENDED, "h264extended"); | |
207 AddVideoProfile(PP_VIDEOPROFILE_H264HIGH, "h264high"); | |
208 AddVideoProfile(PP_VIDEOPROFILE_H264HIGH10PROFILE, "h264high10"); | |
209 AddVideoProfile(PP_VIDEOPROFILE_H264HIGH422PROFILE, "h264high422"); | |
210 AddVideoProfile(PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE, | |
211 "h264high444predictive"); | |
212 AddVideoProfile(PP_VIDEOPROFILE_H264SCALABLEBASELINE, "h264scalablebaseline"); | |
213 AddVideoProfile(PP_VIDEOPROFILE_H264SCALABLEHIGH, "h264scalablehigh"); | |
214 AddVideoProfile(PP_VIDEOPROFILE_H264STEREOHIGH, "h264stereohigh"); | |
215 AddVideoProfile(PP_VIDEOPROFILE_H264MULTIVIEWHIGH, "h264multiviewhigh"); | |
216 AddVideoProfile(PP_VIDEOPROFILE_VP8_ANY, "vp8"); | |
217 AddVideoProfile(PP_VIDEOPROFILE_VP9_ANY, "vp9"); | |
218 } | |
219 | |
220 PP_VideoProfile VideoEncoderInstance::VideoProfileFromString( | |
221 const std::string& str) { | |
222 VideoProfileFromStringMap::iterator it = profile_from_string_.find(str); | |
223 if (it == profile_from_string_.end()) | |
224 return PP_VIDEOPROFILE_VP8_ANY; | |
225 return it->second; | |
226 } | |
227 | |
228 std::string VideoEncoderInstance::VideoProfileToString( | |
229 PP_VideoProfile profile) { | |
230 VideoProfileToStringMap::iterator it = profile_to_string_.find(profile); | |
231 if (it == profile_to_string_.end()) | |
232 return "unknown"; | |
233 return it->second; | |
234 } | |
235 | |
172 void VideoEncoderInstance::ConfigureTrack() { | 236 void VideoEncoderInstance::ConfigureTrack() { |
173 if (encoder_size_.IsEmpty()) | 237 if (encoder_size_.IsEmpty()) |
174 frame_size_ = requested_size_; | 238 frame_size_ = requested_size_; |
175 else | 239 else |
176 frame_size_ = encoder_size_; | 240 frame_size_ = encoder_size_; |
177 | 241 |
178 int32_t attrib_list[] = {PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT, | 242 int32_t attrib_list[] = {PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT, |
179 frame_format_, | 243 frame_format_, |
180 PP_MEDIASTREAMVIDEOTRACK_ATTRIB_WIDTH, | 244 PP_MEDIASTREAMVIDEOTRACK_ATTRIB_WIDTH, |
181 frame_size_.width(), | 245 frame_size_.width(), |
(...skipping 15 matching lines...) Expand all Loading... | |
197 void VideoEncoderInstance::OnConfiguredTrack(int32_t result) { | 261 void VideoEncoderInstance::OnConfiguredTrack(int32_t result) { |
198 if (result != PP_OK) { | 262 if (result != PP_OK) { |
199 LogError(result, "Cannot configure track"); | 263 LogError(result, "Cannot configure track"); |
200 return; | 264 return; |
201 } | 265 } |
202 | 266 |
203 if (is_encoding_) { | 267 if (is_encoding_) { |
204 StartTrackFrames(); | 268 StartTrackFrames(); |
205 ScheduleNextEncode(); | 269 ScheduleNextEncode(); |
206 } else | 270 } else |
207 ProbeEncoder(); | 271 StartEncoder(); |
208 } | 272 } |
209 | 273 |
210 void VideoEncoderInstance::ProbeEncoder() { | 274 void VideoEncoderInstance::ProbeEncoder() { |
211 video_encoder_ = pp::VideoEncoder(this); | 275 video_encoder_ = pp::VideoEncoder(this); |
212 video_encoder_.GetSupportedProfiles(callback_factory_.NewCallbackWithOutput( | 276 video_encoder_.GetSupportedProfiles(callback_factory_.NewCallbackWithOutput( |
213 &VideoEncoderInstance::OnEncoderProbed)); | 277 &VideoEncoderInstance::OnEncoderProbed)); |
214 } | 278 } |
215 | 279 |
216 void VideoEncoderInstance::OnEncoderProbed( | 280 void VideoEncoderInstance::OnEncoderProbed( |
217 int32_t result, | 281 int32_t result, |
218 const std::vector<PP_VideoProfileDescription> profiles) { | 282 const std::vector<PP_VideoProfileDescription> profiles) { |
219 bool has_required_profile = false; | 283 pp::VarDictionary dict; |
284 dict.Set(pp::Var("name"), pp::Var("supportedProfiles")); | |
285 pp::VarArray js_profiles; | |
286 dict.Set(pp::Var("profiles"), js_profiles); | |
220 | 287 |
221 Log("Available profiles:"); | 288 if (result != PP_OK) { |
222 for (const PP_VideoProfileDescription& profile : profiles) { | 289 LogError(result, "Cannot get supported profiles"); |
223 std::ostringstream oss; | 290 PostMessage(dict); |
224 oss << " profile=" << VideoProfileToString(profile.profile) | |
225 << " max_resolution=" << profile.max_resolution.width << "x" | |
226 << profile.max_resolution.height | |
227 << " max_framerate=" << profile.max_framerate_numerator << "/" | |
228 << profile.max_framerate_denominator << " acceleration=" | |
229 << HardwareAccelerationToString(profile.acceleration); | |
230 Log(oss.str()); | |
231 | |
232 has_required_profile |= profile.profile == video_profile_; | |
233 } | 291 } |
234 | 292 |
235 if (!has_required_profile) { | 293 int32_t idx = 0; |
236 std::ostringstream oss; | 294 for (const PP_VideoProfileDescription& profile : profiles) |
237 oss << "Cannot find required video profile: "; | 295 js_profiles.Set(idx++, pp::Var(VideoProfileToString(profile.profile))); |
238 oss << VideoProfileToString(video_profile_); | 296 PostMessage(dict); |
239 LogError(PP_ERROR_FAILED, oss.str()); | 297 } |
240 return; | |
241 } | |
242 | 298 |
299 void VideoEncoderInstance::StartEncoder() { | |
243 video_encoder_ = pp::VideoEncoder(this); | 300 video_encoder_ = pp::VideoEncoder(this); |
244 | 301 |
245 pp::VarDictionary dict; | |
246 dict.Set(pp::Var("status"), pp::Var("initializing encoder")); | |
247 dict.Set(pp::Var("width"), pp::Var(encoder_size_.width())); | |
248 dict.Set(pp::Var("height"), pp::Var(encoder_size_.height())); | |
249 PostMessage(dict); | |
250 | |
251 int32_t error = video_encoder_.Initialize( | 302 int32_t error = video_encoder_.Initialize( |
252 frame_format_, frame_size_, video_profile_, 2000000, | 303 frame_format_, frame_size_, video_profile_, 2000000, |
253 PP_HARDWAREACCELERATION_WITHFALLBACK, | 304 PP_HARDWAREACCELERATION_WITHFALLBACK, |
254 callback_factory_.NewCallback( | 305 callback_factory_.NewCallback( |
255 &VideoEncoderInstance::OnInitializedEncoder)); | 306 &VideoEncoderInstance::OnInitializedEncoder)); |
256 if (error != PP_OK_COMPLETIONPENDING) { | 307 if (error != PP_OK_COMPLETIONPENDING) { |
257 LogError(error, "Cannot initialize encoder"); | 308 LogError(error, "Cannot initialize encoder"); |
258 return; | 309 return; |
259 } | 310 } |
260 } | 311 } |
261 | 312 |
262 void VideoEncoderInstance::OnInitializedEncoder(int32_t result) { | 313 void VideoEncoderInstance::OnInitializedEncoder(int32_t result) { |
263 if (result != PP_OK) { | 314 if (result != PP_OK) { |
264 LogError(result, "Encoder initialization failed"); | 315 LogError(result, "Encoder initialization failed"); |
265 return; | 316 return; |
266 } | 317 } |
267 | 318 |
268 is_encoding_ = true; | 319 is_encoding_ = true; |
320 PostSignalMessage("started"); | |
269 | 321 |
270 if (video_encoder_.GetFrameCodedSize(&encoder_size_) != PP_OK) { | 322 if (video_encoder_.GetFrameCodedSize(&encoder_size_) != PP_OK) { |
271 LogError(result, "Cannot get encoder coded frame size"); | 323 LogError(result, "Cannot get encoder coded frame size"); |
272 return; | 324 return; |
273 } | 325 } |
274 | 326 |
275 pp::VarDictionary dict; | |
276 dict.Set(pp::Var("status"), pp::Var("encoder initialized")); | |
277 dict.Set(pp::Var("width"), pp::Var(encoder_size_.width())); | |
278 dict.Set(pp::Var("height"), pp::Var(encoder_size_.height())); | |
279 PostMessage(dict); | |
280 | |
281 video_encoder_.GetBitstreamBuffer(callback_factory_.NewCallbackWithOutput( | 327 video_encoder_.GetBitstreamBuffer(callback_factory_.NewCallbackWithOutput( |
282 &VideoEncoderInstance::OnGetBitstreamBuffer)); | 328 &VideoEncoderInstance::OnGetBitstreamBuffer)); |
283 | 329 |
284 if (encoder_size_ != frame_size_) | 330 if (encoder_size_ != frame_size_) |
285 ConfigureTrack(); | 331 ConfigureTrack(); |
286 else { | 332 else { |
287 StartTrackFrames(); | 333 StartTrackFrames(); |
288 ScheduleNextEncode(); | 334 ScheduleNextEncode(); |
289 } | 335 } |
290 } | 336 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
341 int32_t VideoEncoderInstance::CopyVideoFrame(pp::VideoFrame dest, | 387 int32_t VideoEncoderInstance::CopyVideoFrame(pp::VideoFrame dest, |
342 pp::VideoFrame src) { | 388 pp::VideoFrame src) { |
343 if (dest.GetDataBufferSize() < src.GetDataBufferSize()) { | 389 if (dest.GetDataBufferSize() < src.GetDataBufferSize()) { |
344 std::ostringstream oss; | 390 std::ostringstream oss; |
345 oss << "Incorrect destination video frame buffer size : " | 391 oss << "Incorrect destination video frame buffer size : " |
346 << dest.GetDataBufferSize() << " < " << src.GetDataBufferSize(); | 392 << dest.GetDataBufferSize() << " < " << src.GetDataBufferSize(); |
347 LogError(PP_ERROR_FAILED, oss.str()); | 393 LogError(PP_ERROR_FAILED, oss.str()); |
348 return PP_ERROR_FAILED; | 394 return PP_ERROR_FAILED; |
349 } | 395 } |
350 | 396 |
397 dest.SetTimestamp(src.GetTimestamp()); | |
351 memcpy(dest.GetDataBuffer(), src.GetDataBuffer(), src.GetDataBufferSize()); | 398 memcpy(dest.GetDataBuffer(), src.GetDataBuffer(), src.GetDataBufferSize()); |
352 return PP_OK; | 399 return PP_OK; |
353 } | 400 } |
354 | 401 |
355 void VideoEncoderInstance::EncodeFrame(const pp::VideoFrame& frame) { | 402 void VideoEncoderInstance::EncodeFrame(const pp::VideoFrame& frame) { |
356 video_encoder_.Encode( | 403 video_encoder_.Encode( |
357 frame, PP_FALSE, | 404 frame, PP_FALSE, |
358 callback_factory_.NewCallback(&VideoEncoderInstance::OnEncodeDone)); | 405 callback_factory_.NewCallback(&VideoEncoderInstance::OnEncodeDone)); |
359 } | 406 } |
360 | 407 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
439 requested_size_ = pp::Size(dict_message.Get("width").AsInt(), | 486 requested_size_ = pp::Size(dict_message.Get("width").AsInt(), |
440 dict_message.Get("height").AsInt()); | 487 dict_message.Get("height").AsInt()); |
441 pp::Var var_track = dict_message.Get("track"); | 488 pp::Var var_track = dict_message.Get("track"); |
442 if (!var_track.is_resource()) { | 489 if (!var_track.is_resource()) { |
443 LogToConsole(PP_LOGLEVEL_ERROR, pp::Var("Given track is not a resource")); | 490 LogToConsole(PP_LOGLEVEL_ERROR, pp::Var("Given track is not a resource")); |
444 return; | 491 return; |
445 } | 492 } |
446 pp::Resource resource_track = var_track.AsResource(); | 493 pp::Resource resource_track = var_track.AsResource(); |
447 video_track_ = pp::MediaStreamVideoTrack(resource_track); | 494 video_track_ = pp::MediaStreamVideoTrack(resource_track); |
448 video_encoder_ = pp::VideoEncoder(); | 495 video_encoder_ = pp::VideoEncoder(); |
496 video_profile_ = VideoProfileFromString( | |
497 dict_message.Get("profile").AsString()); | |
449 ConfigureTrack(); | 498 ConfigureTrack(); |
450 } else if (command == "stop") { | 499 } else if (command == "stop") { |
451 StopEncode(); | 500 StopEncode(); |
452 PostSignalMessage("stopped"); | 501 PostSignalMessage("stopped"); |
453 } else { | 502 } else { |
454 LogToConsole(PP_LOGLEVEL_ERROR, pp::Var("Invalid command!")); | 503 LogToConsole(PP_LOGLEVEL_ERROR, pp::Var("Invalid command!")); |
455 } | 504 } |
456 } | 505 } |
457 | 506 |
458 void VideoEncoderInstance::PostDataMessage(const void* buffer, uint32_t size) { | 507 void VideoEncoderInstance::PostDataMessage(const void* buffer, uint32_t size) { |
459 pp::VarDictionary dictionary; | 508 pp::VarDictionary dictionary; |
460 | 509 |
461 dictionary.Set(pp::Var("name"), pp::Var("data")); | 510 dictionary.Set(pp::Var("name"), pp::Var("data")); |
462 | 511 |
463 pp::VarArrayBuffer array_buffer(size); | 512 pp::VarArrayBuffer array_buffer; |
464 void* data_ptr = array_buffer.Map(); | 513 uint8_t* data_ptr; |
465 memcpy(data_ptr, buffer, size); | 514 uint32_t data_offset = 0; |
515 if (video_profile_ == PP_VIDEOPROFILE_VP8_ANY || | |
516 video_profile_ == PP_VIDEOPROFILE_VP9_ANY) { | |
517 uint32_t frame_offset = 0; | |
518 if (encoded_frames_ == 1) { | |
519 array_buffer = pp::VarArrayBuffer( | |
520 size + ivf_writer_.GetFileHeaderSize() + | |
521 ivf_writer_.GetFrameHeaderSize()); | |
522 data_ptr = static_cast<uint8_t*>(array_buffer.Map()); | |
523 frame_offset = ivf_writer_.WriteFileHeader( | |
524 data_ptr, frame_size_.width(), frame_size_.height()); | |
525 } else { | |
526 array_buffer = pp::VarArrayBuffer( | |
527 size + ivf_writer_.GetFrameHeaderSize()); | |
528 data_ptr = static_cast<uint8_t*>(array_buffer.Map()); | |
529 } | |
530 data_offset = frame_offset + | |
531 ivf_writer_.WriteFrameHeader(data_ptr + frame_offset, | |
532 encoded_frames_, | |
533 size); | |
534 } else { | |
535 array_buffer = pp::VarArrayBuffer(size); | |
536 data_ptr = static_cast<uint8_t*>(array_buffer.Map()); | |
537 } | |
538 | |
539 memcpy(data_ptr + data_offset, buffer, size); | |
466 array_buffer.Unmap(); | 540 array_buffer.Unmap(); |
467 dictionary.Set(pp::Var("data"), array_buffer); | 541 dictionary.Set(pp::Var("data"), array_buffer); |
468 | 542 |
469 PostMessage(dictionary); | 543 PostMessage(dictionary); |
470 } | 544 } |
471 | 545 |
472 void VideoEncoderInstance::PostSignalMessage(const char* name) { | 546 void VideoEncoderInstance::PostSignalMessage(const char* name) { |
473 pp::VarDictionary dictionary; | 547 pp::VarDictionary dictionary; |
474 dictionary.Set(pp::Var("name"), pp::Var(name)); | 548 dictionary.Set(pp::Var("name"), pp::Var(name)); |
475 | 549 |
(...skipping 17 matching lines...) Expand all Loading... | |
493 } | 567 } |
494 | 568 |
495 } // anonymous namespace | 569 } // anonymous namespace |
496 | 570 |
497 namespace pp { | 571 namespace pp { |
498 // Factory function for your specialization of the Module object. | 572 // Factory function for your specialization of the Module object. |
499 Module* CreateModule() { | 573 Module* CreateModule() { |
500 return new VideoEncoderModule(); | 574 return new VideoEncoderModule(); |
501 } | 575 } |
502 } // namespace pp | 576 } // namespace pp |
OLD | NEW |