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