Chromium Code Reviews| 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 |