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 <algorithm> | 9 #include <algorithm> |
| 10 #include <iostream> | 10 #include <iostream> |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 39 // include-guards), make sure this is the last file #include'd in this file. | 39 // include-guards), make sure this is the last file #include'd in this file. |
| 40 #undef NDEBUG | 40 #undef NDEBUG |
| 41 #include <assert.h> | 41 #include <assert.h> |
| 42 | 42 |
| 43 #define fourcc(a, b, c, d) \ | 43 #define fourcc(a, b, c, d) \ |
| 44 (((uint32_t)(a) << 0) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | \ | 44 (((uint32_t)(a) << 0) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | \ |
| 45 ((uint32_t)(d) << 24)) | 45 ((uint32_t)(d) << 24)) |
| 46 | 46 |
| 47 namespace { | 47 namespace { |
| 48 | 48 |
| 49 double clamp(double min, double max, double value) { | |
| 50 return std::max(std::min(value, max), min); | |
| 51 } | |
| 52 | |
| 49 // IVF container writer. It is possible to parse H264 bitstream using | 53 // IVF container writer. It is possible to parse H264 bitstream using |
| 50 // NAL units but for VP8 we need a container to at least find encoded | 54 // NAL units but for VP8 we need a container to at least find encoded |
| 51 // pictures as well as the picture sizes. | 55 // pictures as well as the picture sizes. |
| 52 class IVFWriter { | 56 class IVFWriter { |
| 53 public: | 57 public: |
| 54 IVFWriter() {} | 58 IVFWriter() {} |
| 55 ~IVFWriter() {} | 59 ~IVFWriter() {} |
| 56 | 60 |
| 57 uint32_t GetFileHeaderSize() const { return 32; } | 61 uint32_t GetFileHeaderSize() const { return 32; } |
| 58 uint32_t GetFrameHeaderSize() const { return 12; } | 62 uint32_t GetFrameHeaderSize() const { return 12; } |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 154 | 158 |
| 155 void PostDataMessage(const void* buffer, uint32_t size); | 159 void PostDataMessage(const void* buffer, uint32_t size); |
| 156 | 160 |
| 157 typedef std::map<std::string, PP_VideoProfile> VideoProfileFromStringMap; | 161 typedef std::map<std::string, PP_VideoProfile> VideoProfileFromStringMap; |
| 158 VideoProfileFromStringMap profile_from_string_; | 162 VideoProfileFromStringMap profile_from_string_; |
| 159 | 163 |
| 160 typedef std::map<PP_VideoProfile, std::string> VideoProfileToStringMap; | 164 typedef std::map<PP_VideoProfile, std::string> VideoProfileToStringMap; |
| 161 VideoProfileToStringMap profile_to_string_; | 165 VideoProfileToStringMap profile_to_string_; |
| 162 | 166 |
| 163 bool is_encoding_; | 167 bool is_encoding_; |
| 168 bool is_encode_ticking_; | |
| 164 bool is_receiving_track_frames_; | 169 bool is_receiving_track_frames_; |
| 165 | 170 |
| 166 pp::VideoEncoder video_encoder_; | 171 pp::VideoEncoder video_encoder_; |
| 167 pp::MediaStreamVideoTrack video_track_; | 172 pp::MediaStreamVideoTrack video_track_; |
| 168 pp::CompletionCallbackFactory<VideoEncoderInstance> callback_factory_; | 173 pp::CompletionCallbackFactory<VideoEncoderInstance> callback_factory_; |
| 169 | 174 |
| 170 PP_VideoProfile video_profile_; | 175 PP_VideoProfile video_profile_; |
| 171 PP_VideoFrame_Format frame_format_; | 176 PP_VideoFrame_Format frame_format_; |
| 172 | 177 |
| 173 pp::Size requested_size_; | 178 pp::Size requested_size_; |
| 174 pp::Size frame_size_; | 179 pp::Size frame_size_; |
| 175 pp::Size encoder_size_; | 180 pp::Size encoder_size_; |
| 176 uint32_t encoded_frames_; | 181 uint32_t encoded_frames_; |
| 177 | 182 |
| 178 pp::VideoFrame current_track_frame_; | 183 pp::VideoFrame current_track_frame_; |
| 179 | 184 |
| 180 IVFWriter ivf_writer_; | 185 IVFWriter ivf_writer_; |
| 181 | 186 |
| 182 PP_Time last_encode_tick_; | 187 PP_Time last_encode_tick_; |
| 183 }; | 188 }; |
| 184 | 189 |
| 185 VideoEncoderInstance::VideoEncoderInstance(PP_Instance instance, | 190 VideoEncoderInstance::VideoEncoderInstance(PP_Instance instance, |
| 186 pp::Module* module) | 191 pp::Module* module) |
| 187 : pp::Instance(instance), | 192 : pp::Instance(instance), |
| 188 is_encoding_(false), | 193 is_encoding_(false), |
| 194 is_encode_ticking_(false), | |
| 189 callback_factory_(this), | 195 callback_factory_(this), |
| 190 #if defined(USE_VP8_INSTEAD_OF_H264) | 196 #if defined(USE_VP8_INSTEAD_OF_H264) |
| 191 video_profile_(PP_VIDEOPROFILE_VP8_ANY), | 197 video_profile_(PP_VIDEOPROFILE_VP8_ANY), |
| 192 #else | 198 #else |
| 193 video_profile_(PP_VIDEOPROFILE_H264MAIN), | 199 video_profile_(PP_VIDEOPROFILE_H264MAIN), |
| 194 #endif | 200 #endif |
| 195 frame_format_(PP_VIDEOFRAME_FORMAT_I420), | 201 frame_format_(PP_VIDEOFRAME_FORMAT_I420), |
| 196 encoded_frames_(0), | 202 encoded_frames_(0), |
| 197 last_encode_tick_(0) { | 203 last_encode_tick_(0) { |
| 198 InitializeVideoProfiles(); | 204 InitializeVideoProfiles(); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 333 | 339 |
| 334 if (encoder_size_ != frame_size_) | 340 if (encoder_size_ != frame_size_) |
| 335 ConfigureTrack(); | 341 ConfigureTrack(); |
| 336 else { | 342 else { |
| 337 StartTrackFrames(); | 343 StartTrackFrames(); |
| 338 ScheduleNextEncode(); | 344 ScheduleNextEncode(); |
| 339 } | 345 } |
| 340 } | 346 } |
| 341 | 347 |
| 342 void VideoEncoderInstance::ScheduleNextEncode() { | 348 void VideoEncoderInstance::ScheduleNextEncode() { |
| 349 // Avoid scheduling more than once at a time. | |
| 350 if (is_encode_ticking_) | |
| 351 return; | |
| 352 | |
| 343 PP_Time now = pp::Module::Get()->core()->GetTime(); | 353 PP_Time now = pp::Module::Get()->core()->GetTime(); |
| 354 PP_Time tick = 1.0 / 30; | |
| 355 // If the callback was triggered late, we need to account for that | |
| 356 // delay for the next tick. | |
| 357 PP_Time delta = tick - clamp(0, tick, now - last_encode_tick_ - tick); | |
|
binji
2015/06/30 18:50:34
Just to be clear: this assumes the callback is nev
llandwerlin-old
2015/06/30 19:14:15
Yes, that's right. I assumed the implementation wo
| |
| 358 | |
| 344 pp::Module::Get()->core()->CallOnMainThread( | 359 pp::Module::Get()->core()->CallOnMainThread( |
| 345 std::min(std::max(now - last_encode_tick_, 0.0), 1000.0 / 30), | 360 delta * 1000, |
| 346 callback_factory_.NewCallback(&VideoEncoderInstance::GetEncoderFrameTick), | 361 callback_factory_.NewCallback(&VideoEncoderInstance::GetEncoderFrameTick), |
| 347 0); | 362 0); |
| 363 | |
| 348 last_encode_tick_ = now; | 364 last_encode_tick_ = now; |
| 365 is_encode_ticking_ = true; | |
| 349 } | 366 } |
| 350 | 367 |
| 351 void VideoEncoderInstance::GetEncoderFrameTick(int32_t result) { | 368 void VideoEncoderInstance::GetEncoderFrameTick(int32_t result) { |
| 369 is_encode_ticking_ = false; | |
| 370 | |
| 352 if (is_encoding_) { | 371 if (is_encoding_) { |
| 353 if (!current_track_frame_.is_null()) { | 372 if (!current_track_frame_.is_null()) { |
| 354 pp::VideoFrame frame = current_track_frame_; | 373 pp::VideoFrame frame = current_track_frame_; |
| 355 current_track_frame_.detach(); | 374 current_track_frame_.detach(); |
| 356 GetEncoderFrame(frame); | 375 GetEncoderFrame(frame); |
| 357 } | 376 } |
| 358 ScheduleNextEncode(); | 377 ScheduleNextEncode(); |
| 359 } | 378 } |
| 360 } | 379 } |
| 361 | 380 |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 571 } | 590 } |
| 572 | 591 |
| 573 } // anonymous namespace | 592 } // anonymous namespace |
| 574 | 593 |
| 575 namespace pp { | 594 namespace pp { |
| 576 // Factory function for your specialization of the Module object. | 595 // Factory function for your specialization of the Module object. |
| 577 Module* CreateModule() { | 596 Module* CreateModule() { |
| 578 return new VideoEncoderModule(); | 597 return new VideoEncoderModule(); |
| 579 } | 598 } |
| 580 } // namespace pp | 599 } // namespace pp |
| OLD | NEW |