Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Side by Side Diff: ppapi/examples/video_encode/video_encode.cc

Issue 1132833002: pepper: add software vp9 encoder support to PPB_VideoEncoder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Additional comments Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <algorithm> 9 #include <algorithm>
10 #include <deque> 10 #include <deque>
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 #define fourcc(a, b, c, d) \ 42 #define fourcc(a, b, c, d) \
43 (((uint32_t)(a) << 0) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | \ 43 (((uint32_t)(a) << 0) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | \
44 ((uint32_t)(d) << 24)) 44 ((uint32_t)(d) << 24))
45 45
46 namespace { 46 namespace {
47 47
48 double clamp(double min, double max, double value) { 48 double clamp(double min, double max, double value) {
49 return std::max(std::min(value, max), min); 49 return std::max(std::min(value, max), min);
50 } 50 }
51 51
52 std::string ToUpperString(const std::string& str) {
53 std::string ret;
54 for (uint32_t i = 0; i < str.size(); i++)
55 ret.push_back(static_cast<char>(toupper(str[i])));
56 return ret;
57 }
58
52 // IVF container writer. It is possible to parse H264 bitstream using 59 // IVF container writer. It is possible to parse H264 bitstream using
53 // NAL units but for VP8 we need a container to at least find encoded 60 // NAL units but for VP8 we need a container to at least find encoded
54 // pictures as well as the picture sizes. 61 // pictures as well as the picture sizes.
55 class IVFWriter { 62 class IVFWriter {
56 public: 63 public:
57 IVFWriter() {} 64 IVFWriter() {}
58 ~IVFWriter() {} 65 ~IVFWriter() {}
59 66
60 uint32_t GetFileHeaderSize() const { return 32; } 67 uint32_t GetFileHeaderSize() const { return 32; }
61 uint32_t GetFrameHeaderSize() const { return 12; } 68 uint32_t GetFrameHeaderSize() const { return 12; }
62 uint32_t WriteFileHeader(uint8_t* mem, int32_t width, int32_t height); 69 uint32_t WriteFileHeader(uint8_t* mem,
70 const std::string& codec,
71 int32_t width,
72 int32_t height);
63 uint32_t WriteFrameHeader(uint8_t* mem, uint64_t pts, size_t frame_size); 73 uint32_t WriteFrameHeader(uint8_t* mem, uint64_t pts, size_t frame_size);
64 74
65 private: 75 private:
66 void PutLE16(uint8_t* mem, int val) const { 76 void PutLE16(uint8_t* mem, int val) const {
67 mem[0] = (val >> 0) & 0xff; 77 mem[0] = (val >> 0) & 0xff;
68 mem[1] = (val >> 8) & 0xff; 78 mem[1] = (val >> 8) & 0xff;
69 } 79 }
70 void PutLE32(uint8_t* mem, int val) const { 80 void PutLE32(uint8_t* mem, int val) const {
71 mem[0] = (val >> 0) & 0xff; 81 mem[0] = (val >> 0) & 0xff;
72 mem[1] = (val >> 8) & 0xff; 82 mem[1] = (val >> 8) & 0xff;
73 mem[2] = (val >> 16) & 0xff; 83 mem[2] = (val >> 16) & 0xff;
74 mem[3] = (val >> 24) & 0xff; 84 mem[3] = (val >> 24) & 0xff;
75 } 85 }
76 }; 86 };
77 87
78 uint32_t IVFWriter::WriteFileHeader(uint8_t* mem, 88 uint32_t IVFWriter::WriteFileHeader(uint8_t* mem,
89 const std::string& codec,
79 int32_t width, 90 int32_t width,
80 int32_t height) { 91 int32_t height) {
81 mem[0] = 'D'; 92 mem[0] = 'D';
82 mem[1] = 'K'; 93 mem[1] = 'K';
83 mem[2] = 'I'; 94 mem[2] = 'I';
84 mem[3] = 'F'; 95 mem[3] = 'F';
85 PutLE16(mem + 4, 0); // version 96 PutLE16(mem + 4, 0); // version
86 PutLE16(mem + 6, 32); // header size 97 PutLE16(mem + 6, 32); // header size
87 PutLE32(mem + 8, fourcc('V', 'P', '8', '0')); // fourcc 98 PutLE32(mem + 8, fourcc(codec[0], codec[1], codec[2], '0')); // fourcc
88 PutLE16(mem + 12, static_cast<uint16_t>(width)); // width 99 PutLE16(mem + 12, static_cast<uint16_t>(width)); // width
89 PutLE16(mem + 14, static_cast<uint16_t>(height)); // height 100 PutLE16(mem + 14, static_cast<uint16_t>(height)); // height
90 PutLE32(mem + 16, 1000); // rate 101 PutLE32(mem + 16, 1000); // rate
91 PutLE32(mem + 20, 1); // scale 102 PutLE32(mem + 20, 1); // scale
92 PutLE32(mem + 24, 0xffffffff); // length 103 PutLE32(mem + 24, 0xffffffff); // length
93 PutLE32(mem + 28, 0); // unused 104 PutLE32(mem + 28, 0); // unused
94 105
95 return 32; 106 return 32;
96 } 107 }
97 108
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 void StartTrackFrames(); 160 void StartTrackFrames();
150 void StopTrackFrames(); 161 void StopTrackFrames();
151 void OnTrackFrame(int32_t result, pp::VideoFrame frame); 162 void OnTrackFrame(int32_t result, pp::VideoFrame frame);
152 163
153 void StopEncode(); 164 void StopEncode();
154 165
155 void LogError(int32_t error, const std::string& message); 166 void LogError(int32_t error, const std::string& message);
156 void Log(const std::string& message); 167 void Log(const std::string& message);
157 168
158 void PostDataMessage(const void* buffer, uint32_t size); 169 void PostDataMessage(const void* buffer, uint32_t size);
159 void PostSignalMessage(const char* name);
160 170
161 typedef std::map<std::string, PP_VideoProfile> VideoProfileFromStringMap; 171 typedef std::map<std::string, PP_VideoProfile> VideoProfileFromStringMap;
162 VideoProfileFromStringMap profile_from_string_; 172 VideoProfileFromStringMap profile_from_string_;
163 173
164 typedef std::map<PP_VideoProfile, std::string> VideoProfileToStringMap; 174 typedef std::map<PP_VideoProfile, std::string> VideoProfileToStringMap;
165 VideoProfileToStringMap profile_to_string_; 175 VideoProfileToStringMap profile_to_string_;
166 176
167 bool is_encoding_; 177 bool is_encoding_;
168 bool is_encode_ticking_; 178 bool is_encode_ticking_;
169 bool is_receiving_track_frames_; 179 bool is_receiving_track_frames_;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 frame_size_ = encoder_size_; 266 frame_size_ = encoder_size_;
257 267
258 int32_t attrib_list[] = {PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT, 268 int32_t attrib_list[] = {PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT,
259 frame_format_, 269 frame_format_,
260 PP_MEDIASTREAMVIDEOTRACK_ATTRIB_WIDTH, 270 PP_MEDIASTREAMVIDEOTRACK_ATTRIB_WIDTH,
261 frame_size_.width(), 271 frame_size_.width(),
262 PP_MEDIASTREAMVIDEOTRACK_ATTRIB_HEIGHT, 272 PP_MEDIASTREAMVIDEOTRACK_ATTRIB_HEIGHT,
263 frame_size_.height(), 273 frame_size_.height(),
264 PP_MEDIASTREAMVIDEOTRACK_ATTRIB_NONE}; 274 PP_MEDIASTREAMVIDEOTRACK_ATTRIB_NONE};
265 275
266 pp::VarDictionary dict;
267 dict.Set(pp::Var("status"), pp::Var("configuring video track"));
268 dict.Set(pp::Var("width"), pp::Var(frame_size_.width()));
269 dict.Set(pp::Var("height"), pp::Var(frame_size_.height()));
270 PostMessage(dict);
271
272 video_track_.Configure( 276 video_track_.Configure(
273 attrib_list, 277 attrib_list,
274 callback_factory_.NewCallback(&VideoEncoderInstance::OnConfiguredTrack)); 278 callback_factory_.NewCallback(&VideoEncoderInstance::OnConfiguredTrack));
275 } 279 }
276 280
277 void VideoEncoderInstance::OnConfiguredTrack(int32_t result) { 281 void VideoEncoderInstance::OnConfiguredTrack(int32_t result) {
278 if (result != PP_OK) { 282 if (result != PP_OK) {
279 LogError(result, "Cannot configure track"); 283 LogError(result, "Cannot configure track");
280 return; 284 return;
281 } 285 }
(...skipping 18 matching lines...) Expand all
300 dict.Set(pp::Var("name"), pp::Var("supportedProfiles")); 304 dict.Set(pp::Var("name"), pp::Var("supportedProfiles"));
301 pp::VarArray js_profiles; 305 pp::VarArray js_profiles;
302 dict.Set(pp::Var("profiles"), js_profiles); 306 dict.Set(pp::Var("profiles"), js_profiles);
303 307
304 if (result < 0) { 308 if (result < 0) {
305 LogError(result, "Cannot get supported profiles"); 309 LogError(result, "Cannot get supported profiles");
306 PostMessage(dict); 310 PostMessage(dict);
307 } 311 }
308 312
309 int32_t idx = 0; 313 int32_t idx = 0;
310 for (const PP_VideoProfileDescription& profile : profiles) 314 for (uint32_t i = 0; i < profiles.size(); i++) {
315 const PP_VideoProfileDescription& profile = profiles[i];
311 js_profiles.Set(idx++, pp::Var(VideoProfileToString(profile.profile))); 316 js_profiles.Set(idx++, pp::Var(VideoProfileToString(profile.profile)));
317 }
312 PostMessage(dict); 318 PostMessage(dict);
313 } 319 }
314 320
315 void VideoEncoderInstance::StartEncoder() { 321 void VideoEncoderInstance::StartEncoder() {
316 video_encoder_ = pp::VideoEncoder(this); 322 video_encoder_ = pp::VideoEncoder(this);
317 frames_timestamps_.clear(); 323 frames_timestamps_.clear();
318 324
319 int32_t error = video_encoder_.Initialize( 325 int32_t error = video_encoder_.Initialize(
320 frame_format_, frame_size_, video_profile_, 2000000, 326 frame_format_, frame_size_, video_profile_, 2000000,
321 PP_HARDWAREACCELERATION_WITHFALLBACK, 327 PP_HARDWAREACCELERATION_WITHFALLBACK,
322 callback_factory_.NewCallback( 328 callback_factory_.NewCallback(
323 &VideoEncoderInstance::OnInitializedEncoder)); 329 &VideoEncoderInstance::OnInitializedEncoder));
324 if (error != PP_OK_COMPLETIONPENDING) { 330 if (error != PP_OK_COMPLETIONPENDING) {
325 LogError(error, "Cannot initialize encoder"); 331 LogError(error, "Cannot initialize encoder");
326 return; 332 return;
327 } 333 }
328 } 334 }
329 335
330 void VideoEncoderInstance::OnInitializedEncoder(int32_t result) { 336 void VideoEncoderInstance::OnInitializedEncoder(int32_t result) {
331 if (result != PP_OK) { 337 if (result != PP_OK) {
332 LogError(result, "Encoder initialization failed"); 338 LogError(result, "Encoder initialization failed");
333 return; 339 return;
334 } 340 }
335 341
336 is_encoding_ = true; 342 is_encoding_ = true;
337 PostSignalMessage("started"); 343 Log("started");
338 344
339 if (video_encoder_.GetFrameCodedSize(&encoder_size_) != PP_OK) { 345 if (video_encoder_.GetFrameCodedSize(&encoder_size_) != PP_OK) {
340 LogError(result, "Cannot get encoder coded frame size"); 346 LogError(result, "Cannot get encoder coded frame size");
341 return; 347 return;
342 } 348 }
343 349
344 video_encoder_.GetBitstreamBuffer(callback_factory_.NewCallbackWithOutput( 350 video_encoder_.GetBitstreamBuffer(callback_factory_.NewCallbackWithOutput(
345 &VideoEncoderInstance::OnGetBitstreamBuffer)); 351 &VideoEncoderInstance::OnGetBitstreamBuffer));
346 352
347 if (encoder_size_ != frame_size_) 353 if (encoder_size_ != frame_size_)
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 return; 531 return;
526 } 532 }
527 pp::Resource resource_track = var_track.AsResource(); 533 pp::Resource resource_track = var_track.AsResource();
528 video_track_ = pp::MediaStreamVideoTrack(resource_track); 534 video_track_ = pp::MediaStreamVideoTrack(resource_track);
529 video_encoder_ = pp::VideoEncoder(); 535 video_encoder_ = pp::VideoEncoder();
530 video_profile_ = VideoProfileFromString( 536 video_profile_ = VideoProfileFromString(
531 dict_message.Get("profile").AsString()); 537 dict_message.Get("profile").AsString());
532 ConfigureTrack(); 538 ConfigureTrack();
533 } else if (command == "stop") { 539 } else if (command == "stop") {
534 StopEncode(); 540 StopEncode();
535 PostSignalMessage("stopped"); 541 Log("stopped");
536 } else { 542 } else {
537 LogToConsole(PP_LOGLEVEL_ERROR, pp::Var("Invalid command!")); 543 LogToConsole(PP_LOGLEVEL_ERROR, pp::Var("Invalid command!"));
538 } 544 }
539 } 545 }
540 546
541 void VideoEncoderInstance::PostDataMessage(const void* buffer, uint32_t size) { 547 void VideoEncoderInstance::PostDataMessage(const void* buffer, uint32_t size) {
542 pp::VarDictionary dictionary; 548 pp::VarDictionary dictionary;
543 549
544 dictionary.Set(pp::Var("name"), pp::Var("data")); 550 dictionary.Set(pp::Var("name"), pp::Var("data"));
545 551
546 pp::VarArrayBuffer array_buffer; 552 pp::VarArrayBuffer array_buffer;
547 uint8_t* data_ptr; 553 uint8_t* data_ptr;
548 uint32_t data_offset = 0; 554 uint32_t data_offset = 0;
549 if (video_profile_ == PP_VIDEOPROFILE_VP8_ANY || 555 if (video_profile_ == PP_VIDEOPROFILE_VP8_ANY ||
550 video_profile_ == PP_VIDEOPROFILE_VP9_ANY) { 556 video_profile_ == PP_VIDEOPROFILE_VP9_ANY) {
551 uint32_t frame_offset = 0; 557 uint32_t frame_offset = 0;
552 if (encoded_frames_ == 1) { 558 if (encoded_frames_ == 1) {
553 array_buffer = pp::VarArrayBuffer( 559 array_buffer = pp::VarArrayBuffer(
554 size + ivf_writer_.GetFileHeaderSize() + 560 size + ivf_writer_.GetFileHeaderSize() +
555 ivf_writer_.GetFrameHeaderSize()); 561 ivf_writer_.GetFrameHeaderSize());
556 data_ptr = static_cast<uint8_t*>(array_buffer.Map()); 562 data_ptr = static_cast<uint8_t*>(array_buffer.Map());
557 frame_offset = ivf_writer_.WriteFileHeader( 563 frame_offset = ivf_writer_.WriteFileHeader(
558 data_ptr, frame_size_.width(), frame_size_.height()); 564 data_ptr, ToUpperString(VideoProfileToString(video_profile_)),
565 frame_size_.width(), frame_size_.height());
559 } else { 566 } else {
560 array_buffer = pp::VarArrayBuffer( 567 array_buffer = pp::VarArrayBuffer(
561 size + ivf_writer_.GetFrameHeaderSize()); 568 size + ivf_writer_.GetFrameHeaderSize());
562 data_ptr = static_cast<uint8_t*>(array_buffer.Map()); 569 data_ptr = static_cast<uint8_t*>(array_buffer.Map());
563 } 570 }
564 uint64_t timestamp = frames_timestamps_.front(); 571 uint64_t timestamp = frames_timestamps_.front();
565 frames_timestamps_.pop_front(); 572 frames_timestamps_.pop_front();
566 data_offset = 573 data_offset =
567 frame_offset + 574 frame_offset +
568 ivf_writer_.WriteFrameHeader(data_ptr + frame_offset, timestamp, size); 575 ivf_writer_.WriteFrameHeader(data_ptr + frame_offset, timestamp, size);
569 } else { 576 } else {
570 array_buffer = pp::VarArrayBuffer(size); 577 array_buffer = pp::VarArrayBuffer(size);
571 data_ptr = static_cast<uint8_t*>(array_buffer.Map()); 578 data_ptr = static_cast<uint8_t*>(array_buffer.Map());
572 } 579 }
573 580
574 memcpy(data_ptr + data_offset, buffer, size); 581 memcpy(data_ptr + data_offset, buffer, size);
575 array_buffer.Unmap(); 582 array_buffer.Unmap();
576 dictionary.Set(pp::Var("data"), array_buffer); 583 dictionary.Set(pp::Var("data"), array_buffer);
577 584
578 PostMessage(dictionary); 585 PostMessage(dictionary);
579 } 586 }
580 587
581 void VideoEncoderInstance::PostSignalMessage(const char* name) {
582 pp::VarDictionary dictionary;
583 dictionary.Set(pp::Var("name"), pp::Var(name));
584
585 PostMessage(dictionary);
586 }
587
588 void VideoEncoderInstance::LogError(int32_t error, const std::string& message) { 588 void VideoEncoderInstance::LogError(int32_t error, const std::string& message) {
589 std::string msg("Error: "); 589 std::string msg("Error: ");
590 msg.append(pp::Var(error).DebugString()); 590 msg.append(pp::Var(error).DebugString());
591 msg.append(" : "); 591 msg.append(" : ");
592 msg.append(message); 592 msg.append(message);
593 LogToConsole(PP_LOGLEVEL_ERROR, pp::Var(msg)); 593
594 Log(msg);
594 } 595 }
595 596
596 void VideoEncoderInstance::Log(const std::string& message) { 597 void VideoEncoderInstance::Log(const std::string& message) {
597 LogToConsole(PP_LOGLEVEL_LOG, pp::Var(message)); 598 pp::VarDictionary dictionary;
599 dictionary.Set(pp::Var("name"), pp::Var("log"));
600 dictionary.Set(pp::Var("message"), pp::Var(message));
601
602 PostMessage(dictionary);
598 } 603 }
599 604
600 pp::Instance* VideoEncoderModule::CreateInstance(PP_Instance instance) { 605 pp::Instance* VideoEncoderModule::CreateInstance(PP_Instance instance) {
601 return new VideoEncoderInstance(instance, this); 606 return new VideoEncoderInstance(instance, this);
602 } 607 }
603 608
604 } // anonymous namespace 609 } // anonymous namespace
605 610
606 namespace pp { 611 namespace pp {
607 // Factory function for your specialization of the Module object. 612 // Factory function for your specialization of the Module object.
608 Module* CreateModule() { 613 Module* CreateModule() {
609 return new VideoEncoderModule(); 614 return new VideoEncoderModule();
610 } 615 }
611 } // namespace pp 616 } // namespace pp
OLDNEW
« no previous file with comments | « native_client_sdk/src/examples/api/video_encode/video_encode.cc ('k') | ppapi/examples/video_encode/video_encode.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698