OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "webrtc/base/timeutils.h" | 22 #include "webrtc/base/timeutils.h" |
23 #include "webrtc/common_types.h" | 23 #include "webrtc/common_types.h" |
24 #include "webrtc/modules/video_coding/include/video_codec_initializer.h" | 24 #include "webrtc/modules/video_coding/include/video_codec_initializer.h" |
25 #include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h" | 25 #include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h" |
26 #include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h" | 26 #include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h" |
27 #include "webrtc/system_wrappers/include/cpu_info.h" | 27 #include "webrtc/system_wrappers/include/cpu_info.h" |
28 | 28 |
29 namespace webrtc { | 29 namespace webrtc { |
30 namespace test { | 30 namespace test { |
31 | 31 |
| 32 const char* ExcludeFrameTypesToStr(ExcludeFrameTypes e) { |
| 33 switch (e) { |
| 34 case kExcludeOnlyFirstKeyFrame: |
| 35 return "ExcludeOnlyFirstKeyFrame"; |
| 36 case kExcludeAllKeyFrames: |
| 37 return "ExcludeAllKeyFrames"; |
| 38 default: |
| 39 RTC_NOTREACHED(); |
| 40 return "Unknown"; |
| 41 } |
| 42 } |
| 43 |
32 TestConfig::TestConfig() | 44 TestConfig::TestConfig() |
33 : name(""), | 45 : name(""), |
34 description(""), | 46 description(""), |
35 test_number(0), | 47 test_number(0), |
36 input_filename(""), | 48 input_filename(""), |
37 output_filename(""), | 49 output_filename(""), |
38 output_dir("out"), | 50 output_dir("out"), |
39 networking_config(), | 51 networking_config(), |
40 exclude_frame_types(kExcludeOnlyFirstKeyFrame), | 52 exclude_frame_types(kExcludeOnlyFirstKeyFrame), |
41 frame_length_in_bytes(0), | 53 frame_length_in_bytes(0), |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 *config.codec_settings, std::move(tl_factory)); | 94 *config.codec_settings, std::move(tl_factory)); |
83 RTC_DCHECK(encoder); | 95 RTC_DCHECK(encoder); |
84 RTC_DCHECK(decoder); | 96 RTC_DCHECK(decoder); |
85 RTC_DCHECK(frame_reader); | 97 RTC_DCHECK(frame_reader); |
86 RTC_DCHECK(frame_writer); | 98 RTC_DCHECK(frame_writer); |
87 RTC_DCHECK(packet_manipulator); | 99 RTC_DCHECK(packet_manipulator); |
88 RTC_DCHECK(stats); | 100 RTC_DCHECK(stats); |
89 } | 101 } |
90 | 102 |
91 bool VideoProcessorImpl::Init() { | 103 bool VideoProcessorImpl::Init() { |
92 // Calculate a factor used for bit rate calculations: | 104 // Calculate a factor used for bit rate calculations. |
93 bit_rate_factor_ = config_.codec_settings->maxFramerate * 0.001 * 8; // bits | 105 bit_rate_factor_ = config_.codec_settings->maxFramerate * 0.001 * 8; // bits |
94 | 106 |
95 // Initialize data structures used by the encoder/decoder APIs | 107 // Initialize data structures used by the encoder/decoder APIs. |
96 size_t frame_length_in_bytes = frame_reader_->FrameLength(); | 108 size_t frame_length_in_bytes = frame_reader_->FrameLength(); |
97 last_successful_frame_buffer_.reset(new uint8_t[frame_length_in_bytes]); | 109 last_successful_frame_buffer_.reset(new uint8_t[frame_length_in_bytes]); |
| 110 |
98 // Set fixed properties common for all frames. | 111 // Set fixed properties common for all frames. |
99 // To keep track of spatial resize actions by encoder. | 112 // To keep track of spatial resize actions by encoder. |
100 last_encoder_frame_width_ = config_.codec_settings->width; | 113 last_encoder_frame_width_ = config_.codec_settings->width; |
101 last_encoder_frame_height_ = config_.codec_settings->height; | 114 last_encoder_frame_height_ = config_.codec_settings->height; |
102 | 115 |
103 // Setup required callbacks for the encoder/decoder: | 116 // Setup required callbacks for the encoder/decoder. |
104 encode_callback_.reset(new VideoProcessorEncodeCompleteCallback(this)); | 117 encode_callback_.reset(new VideoProcessorEncodeCompleteCallback(this)); |
105 decode_callback_.reset(new VideoProcessorDecodeCompleteCallback(this)); | 118 decode_callback_.reset(new VideoProcessorDecodeCompleteCallback(this)); |
106 RTC_CHECK_EQ(encoder_->RegisterEncodeCompleteCallback(encode_callback_.get()), | 119 RTC_CHECK_EQ(encoder_->RegisterEncodeCompleteCallback(encode_callback_.get()), |
107 WEBRTC_VIDEO_CODEC_OK) | 120 WEBRTC_VIDEO_CODEC_OK) |
108 << "Failed to register encode complete callback"; | 121 << "Failed to register encode complete callback"; |
109 RTC_CHECK_EQ(decoder_->RegisterDecodeCompleteCallback(decode_callback_.get()), | 122 RTC_CHECK_EQ(decoder_->RegisterDecodeCompleteCallback(decode_callback_.get()), |
110 WEBRTC_VIDEO_CODEC_OK) | 123 WEBRTC_VIDEO_CODEC_OK) |
111 << "Failed to register decode complete callback"; | 124 << "Failed to register decode complete callback"; |
112 | 125 |
113 // Init the encoder and decoder | 126 // Init the encoder and decoder. |
114 uint32_t nbr_of_cores = 1; | 127 uint32_t num_cores = 1; |
115 if (!config_.use_single_core) { | 128 if (!config_.use_single_core) { |
116 nbr_of_cores = CpuInfo::DetectNumberOfCores(); | 129 num_cores = CpuInfo::DetectNumberOfCores(); |
117 } | 130 } |
118 RTC_CHECK_EQ( | 131 RTC_CHECK_EQ( |
119 encoder_->InitEncode(config_.codec_settings, nbr_of_cores, | 132 encoder_->InitEncode(config_.codec_settings, num_cores, |
120 config_.networking_config.max_payload_size_in_bytes), | 133 config_.networking_config.max_payload_size_in_bytes), |
121 WEBRTC_VIDEO_CODEC_OK) | 134 WEBRTC_VIDEO_CODEC_OK) |
122 << "Failed to initialize VideoEncoder"; | 135 << "Failed to initialize VideoEncoder"; |
123 | 136 |
124 RTC_CHECK_EQ(decoder_->InitDecode(config_.codec_settings, nbr_of_cores), | 137 RTC_CHECK_EQ(decoder_->InitDecode(config_.codec_settings, num_cores), |
125 WEBRTC_VIDEO_CODEC_OK) | 138 WEBRTC_VIDEO_CODEC_OK) |
126 << "Failed to initialize VideoDecoder"; | 139 << "Failed to initialize VideoDecoder"; |
127 | 140 |
128 if (config_.verbose) { | 141 if (config_.verbose) { |
129 printf("Video Processor:\n"); | 142 printf("Video Processor:\n"); |
130 printf(" #CPU cores used : %d\n", nbr_of_cores); | 143 printf(" #CPU cores used : %d\n", num_cores); |
131 printf(" Total # of frames: %d\n", frame_reader_->NumberOfFrames()); | 144 printf(" Total # of frames: %d\n", frame_reader_->NumberOfFrames()); |
132 printf(" Codec settings:\n"); | 145 printf(" Codec settings:\n"); |
133 printf(" Start bitrate : %d kbps\n", | 146 printf(" Start bitrate : %d kbps\n", |
134 config_.codec_settings->startBitrate); | 147 config_.codec_settings->startBitrate); |
135 printf(" Width : %d\n", config_.codec_settings->width); | 148 printf(" Width : %d\n", config_.codec_settings->width); |
136 printf(" Height : %d\n", config_.codec_settings->height); | 149 printf(" Height : %d\n", config_.codec_settings->height); |
137 printf(" Codec type : %s\n", | 150 printf(" Codec type : %s\n", |
138 CodecTypeToPayloadName(config_.codec_settings->codecType) | 151 CodecTypeToPayloadName(config_.codec_settings->codecType) |
139 .value_or("Unknown")); | 152 .value_or("Unknown")); |
140 printf(" Encoder implementation name: %s\n", | 153 printf(" Encoder implementation name: %s\n", |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 } | 204 } |
192 | 205 |
193 bool VideoProcessorImpl::ProcessFrame(int frame_number) { | 206 bool VideoProcessorImpl::ProcessFrame(int frame_number) { |
194 RTC_DCHECK_GE(frame_number, 0); | 207 RTC_DCHECK_GE(frame_number, 0); |
195 RTC_CHECK(initialized_) << "Attempting to use uninitialized VideoProcessor"; | 208 RTC_CHECK(initialized_) << "Attempting to use uninitialized VideoProcessor"; |
196 | 209 |
197 // |prev_time_stamp_| is used for getting number of dropped frames. | 210 // |prev_time_stamp_| is used for getting number of dropped frames. |
198 if (frame_number == 0) { | 211 if (frame_number == 0) { |
199 prev_time_stamp_ = -1; | 212 prev_time_stamp_ = -1; |
200 } | 213 } |
| 214 |
201 rtc::scoped_refptr<VideoFrameBuffer> buffer(frame_reader_->ReadFrame()); | 215 rtc::scoped_refptr<VideoFrameBuffer> buffer(frame_reader_->ReadFrame()); |
202 if (buffer) { | 216 if (buffer) { |
203 // Use the frame number as "timestamp" to identify frames | 217 // Use the frame number as "timestamp" to identify frames. |
204 VideoFrame source_frame(buffer, frame_number, 0, webrtc::kVideoRotation_0); | 218 VideoFrame source_frame(buffer, frame_number, 0, webrtc::kVideoRotation_0); |
205 | 219 |
206 // Ensure we have a new statistics data object we can fill: | 220 // Ensure we have a new statistics data object we can fill. |
207 FrameStatistic& stat = stats_->NewFrame(frame_number); | 221 FrameStatistic& stat = stats_->NewFrame(frame_number); |
208 | 222 |
209 encode_start_ns_ = rtc::TimeNanos(); | 223 encode_start_ns_ = rtc::TimeNanos(); |
210 | 224 |
211 // Decide if we're going to force a keyframe: | 225 // Decide if we are going to force a keyframe. |
212 std::vector<FrameType> frame_types(1, kVideoFrameDelta); | 226 std::vector<FrameType> frame_types(1, kVideoFrameDelta); |
213 if (config_.keyframe_interval > 0 && | 227 if (config_.keyframe_interval > 0 && |
214 frame_number % config_.keyframe_interval == 0) { | 228 frame_number % config_.keyframe_interval == 0) { |
215 frame_types[0] = kVideoFrameKey; | 229 frame_types[0] = kVideoFrameKey; |
216 } | 230 } |
217 | 231 |
218 // For dropped frames, we regard them as zero size encoded frames. | 232 // For dropped frames, we regard them as zero size encoded frames. |
219 encoded_frame_size_ = 0; | 233 encoded_frame_size_ = 0; |
220 encoded_frame_type_ = kVideoFrameDelta; | 234 encoded_frame_type_ = kVideoFrameDelta; |
221 | 235 |
222 int32_t encode_result = | 236 int32_t encode_result = |
223 encoder_->Encode(source_frame, nullptr, &frame_types); | 237 encoder_->Encode(source_frame, nullptr, &frame_types); |
224 | 238 |
225 if (encode_result != WEBRTC_VIDEO_CODEC_OK) { | 239 if (encode_result != WEBRTC_VIDEO_CODEC_OK) { |
226 fprintf(stderr, "Failed to encode frame %d, return code: %d\n", | 240 fprintf(stderr, "Failed to encode frame %d, return code: %d\n", |
227 frame_number, encode_result); | 241 frame_number, encode_result); |
228 } | 242 } |
229 stat.encode_return_code = encode_result; | 243 stat.encode_return_code = encode_result; |
| 244 |
230 return true; | 245 return true; |
231 } else { | 246 } else { |
232 return false; // we've reached the last frame | 247 // Last frame has been reached. |
| 248 return false; |
233 } | 249 } |
234 } | 250 } |
235 | 251 |
236 void VideoProcessorImpl::FrameEncoded( | 252 void VideoProcessorImpl::FrameEncoded( |
237 webrtc::VideoCodecType codec, | 253 webrtc::VideoCodecType codec, |
238 const EncodedImage& encoded_image, | 254 const EncodedImage& encoded_image, |
239 const webrtc::RTPFragmentationHeader* fragmentation) { | 255 const webrtc::RTPFragmentationHeader* fragmentation) { |
240 // Timestamp is frame number, so this gives us #dropped frames. | 256 // Timestamp is frame number, so this gives us #dropped frames. |
241 int num_dropped_from_prev_encode = | 257 int num_dropped_from_prev_encode = |
242 encoded_image._timeStamp - prev_time_stamp_ - 1; | 258 encoded_image._timeStamp - prev_time_stamp_ - 1; |
243 num_dropped_frames_ += num_dropped_from_prev_encode; | 259 num_dropped_frames_ += num_dropped_from_prev_encode; |
244 prev_time_stamp_ = encoded_image._timeStamp; | 260 prev_time_stamp_ = encoded_image._timeStamp; |
245 if (num_dropped_from_prev_encode > 0) { | 261 if (num_dropped_from_prev_encode > 0) { |
246 // For dropped frames, we write out the last decoded frame to avoid getting | 262 // For dropped frames, we write out the last decoded frame to avoid getting |
247 // out of sync for the computation of PSNR and SSIM. | 263 // out of sync for the computation of PSNR and SSIM. |
248 for (int i = 0; i < num_dropped_from_prev_encode; i++) { | 264 for (int i = 0; i < num_dropped_from_prev_encode; i++) { |
249 frame_writer_->WriteFrame(last_successful_frame_buffer_.get()); | 265 frame_writer_->WriteFrame(last_successful_frame_buffer_.get()); |
250 } | 266 } |
251 } | 267 } |
252 // Frame is not dropped, so update the encoded frame size | 268 // Frame is not dropped, so update the encoded frame size |
253 // (encoder callback is only called for non-zero length frames). | 269 // (encoder callback is only called for non-zero length frames). |
254 encoded_frame_size_ = encoded_image._length; | 270 encoded_frame_size_ = encoded_image._length; |
255 | |
256 encoded_frame_type_ = encoded_image._frameType; | 271 encoded_frame_type_ = encoded_image._frameType; |
257 | 272 |
258 int64_t encode_stop_ns = rtc::TimeNanos(); | 273 int64_t encode_stop_ns = rtc::TimeNanos(); |
259 int frame_number = encoded_image._timeStamp; | 274 int frame_number = encoded_image._timeStamp; |
| 275 |
260 FrameStatistic& stat = stats_->stats_[frame_number]; | 276 FrameStatistic& stat = stats_->stats_[frame_number]; |
261 stat.encode_time_in_us = | 277 stat.encode_time_in_us = |
262 GetElapsedTimeMicroseconds(encode_start_ns_, encode_stop_ns); | 278 GetElapsedTimeMicroseconds(encode_start_ns_, encode_stop_ns); |
263 stat.encoding_successful = true; | 279 stat.encoding_successful = true; |
264 stat.encoded_frame_length_in_bytes = encoded_image._length; | 280 stat.encoded_frame_length_in_bytes = encoded_image._length; |
265 stat.frame_number = encoded_image._timeStamp; | 281 stat.frame_number = encoded_image._timeStamp; |
266 stat.frame_type = encoded_image._frameType; | 282 stat.frame_type = encoded_image._frameType; |
267 stat.bit_rate_in_kbps = encoded_image._length * bit_rate_factor_; | 283 stat.bit_rate_in_kbps = encoded_image._length * bit_rate_factor_; |
268 stat.total_packets = | 284 stat.total_packets = |
269 encoded_image._length / config_.networking_config.packet_size_in_bytes + | 285 encoded_image._length / config_.networking_config.packet_size_in_bytes + |
270 1; | 286 1; |
271 | 287 |
272 // Perform packet loss if criteria is fullfilled: | 288 // Simulate packet loss. |
273 bool exclude_this_frame = false; | 289 bool exclude_this_frame = false; |
274 // Only keyframes can be excluded | 290 // Only keyframes can be excluded. |
275 if (encoded_image._frameType == kVideoFrameKey) { | 291 if (encoded_image._frameType == kVideoFrameKey) { |
276 switch (config_.exclude_frame_types) { | 292 switch (config_.exclude_frame_types) { |
277 case kExcludeOnlyFirstKeyFrame: | 293 case kExcludeOnlyFirstKeyFrame: |
278 if (!first_key_frame_has_been_excluded_) { | 294 if (!first_key_frame_has_been_excluded_) { |
279 first_key_frame_has_been_excluded_ = true; | 295 first_key_frame_has_been_excluded_ = true; |
280 exclude_this_frame = true; | 296 exclude_this_frame = true; |
281 } | 297 } |
282 break; | 298 break; |
283 case kExcludeAllKeyFrames: | 299 case kExcludeAllKeyFrames: |
284 exclude_this_frame = true; | 300 exclude_this_frame = true; |
(...skipping 13 matching lines...) Expand all Loading... |
298 memcpy(&copied_image, &encoded_image, sizeof(copied_image)); | 314 memcpy(&copied_image, &encoded_image, sizeof(copied_image)); |
299 copied_image._size = copied_buffer_size; | 315 copied_image._size = copied_buffer_size; |
300 copied_image._buffer = copied_buffer.get(); | 316 copied_image._buffer = copied_buffer.get(); |
301 | 317 |
302 if (!exclude_this_frame) { | 318 if (!exclude_this_frame) { |
303 stat.packets_dropped = | 319 stat.packets_dropped = |
304 packet_manipulator_->ManipulatePackets(&copied_image); | 320 packet_manipulator_->ManipulatePackets(&copied_image); |
305 } | 321 } |
306 | 322 |
307 // Keep track of if frames are lost due to packet loss so we can tell | 323 // Keep track of if frames are lost due to packet loss so we can tell |
308 // this to the encoder (this is handled by the RTP logic in the full stack) | 324 // this to the encoder (this is handled by the RTP logic in the full stack). |
309 decode_start_ns_ = rtc::TimeNanos(); | 325 decode_start_ns_ = rtc::TimeNanos(); |
310 // TODO(kjellander): Pass fragmentation header to the decoder when | 326 // TODO(kjellander): Pass fragmentation header to the decoder when |
311 // CL 172001 has been submitted and PacketManipulator supports this. | 327 // CL 172001 has been submitted and PacketManipulator supports this. |
312 int32_t decode_result = | 328 int32_t decode_result = |
313 decoder_->Decode(copied_image, last_frame_missing_, nullptr); | 329 decoder_->Decode(copied_image, last_frame_missing_, nullptr); |
314 stat.decode_return_code = decode_result; | 330 stat.decode_return_code = decode_result; |
| 331 |
315 if (decode_result != WEBRTC_VIDEO_CODEC_OK) { | 332 if (decode_result != WEBRTC_VIDEO_CODEC_OK) { |
316 // Write the last successful frame the output file to avoid getting it out | 333 // Write the last successful frame the output file to avoid getting it out |
317 // of sync with the source file for SSIM and PSNR comparisons: | 334 // of sync with the source file for SSIM and PSNR comparisons. |
318 frame_writer_->WriteFrame(last_successful_frame_buffer_.get()); | 335 frame_writer_->WriteFrame(last_successful_frame_buffer_.get()); |
319 } | 336 } |
320 // save status for losses so we can inform the decoder for the next frame: | 337 |
| 338 // Save status for losses so we can inform the decoder for the next frame. |
321 last_frame_missing_ = copied_image._length == 0; | 339 last_frame_missing_ = copied_image._length == 0; |
322 } | 340 } |
323 | 341 |
324 void VideoProcessorImpl::FrameDecoded(const VideoFrame& image) { | 342 void VideoProcessorImpl::FrameDecoded(const VideoFrame& image) { |
325 int64_t decode_stop_ns = rtc::TimeNanos(); | 343 int64_t decode_stop_ns = rtc::TimeNanos(); |
| 344 |
| 345 // Report stats. |
326 int frame_number = image.timestamp(); | 346 int frame_number = image.timestamp(); |
327 // Report stats | |
328 FrameStatistic& stat = stats_->stats_[frame_number]; | 347 FrameStatistic& stat = stats_->stats_[frame_number]; |
329 stat.decode_time_in_us = | 348 stat.decode_time_in_us = |
330 GetElapsedTimeMicroseconds(decode_start_ns_, decode_stop_ns); | 349 GetElapsedTimeMicroseconds(decode_start_ns_, decode_stop_ns); |
331 stat.decoding_successful = true; | 350 stat.decoding_successful = true; |
332 | 351 |
333 // Check for resize action (either down or up): | 352 // Check for resize action (either down or up). |
334 if (static_cast<int>(image.width()) != last_encoder_frame_width_ || | 353 if (static_cast<int>(image.width()) != last_encoder_frame_width_ || |
335 static_cast<int>(image.height()) != last_encoder_frame_height_) { | 354 static_cast<int>(image.height()) != last_encoder_frame_height_) { |
336 ++num_spatial_resizes_; | 355 ++num_spatial_resizes_; |
337 last_encoder_frame_width_ = image.width(); | 356 last_encoder_frame_width_ = image.width(); |
338 last_encoder_frame_height_ = image.height(); | 357 last_encoder_frame_height_ = image.height(); |
339 } | 358 } |
340 // Check if codec size is different from native/original size, and if so, | 359 // Check if codec size is different from native/original size, and if so, |
341 // upsample back to original size: needed for PSNR and SSIM computations. | 360 // upsample back to original size. This is needed for PSNR and SSIM |
| 361 // calculations. |
342 if (image.width() != config_.codec_settings->width || | 362 if (image.width() != config_.codec_settings->width || |
343 image.height() != config_.codec_settings->height) { | 363 image.height() != config_.codec_settings->height) { |
344 rtc::scoped_refptr<I420Buffer> up_image( | 364 rtc::scoped_refptr<I420Buffer> up_image( |
345 I420Buffer::Create(config_.codec_settings->width, | 365 I420Buffer::Create(config_.codec_settings->width, |
346 config_.codec_settings->height)); | 366 config_.codec_settings->height)); |
347 | 367 |
348 // Should be the same aspect ratio, no cropping needed. | 368 // Should be the same aspect ratio, no cropping needed. |
349 up_image->ScaleFrom(*image.video_frame_buffer()); | 369 up_image->ScaleFrom(*image.video_frame_buffer()); |
350 | 370 |
351 // TODO(mikhal): Extracting the buffer for now - need to update test. | 371 // TODO(mikhal): Extracting the buffer for now - need to update test. |
352 size_t length = | 372 size_t length = |
353 CalcBufferSize(kI420, up_image->width(), up_image->height()); | 373 CalcBufferSize(kI420, up_image->width(), up_image->height()); |
354 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); | 374 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); |
355 int extracted_length = ExtractBuffer(up_image, length, image_buffer.get()); | 375 int extracted_length = ExtractBuffer(up_image, length, image_buffer.get()); |
356 RTC_DCHECK_GT(extracted_length, 0); | 376 RTC_DCHECK_GT(extracted_length, 0); |
357 // Update our copy of the last successful frame: | 377 // Update our copy of the last successful frame. |
358 memcpy(last_successful_frame_buffer_.get(), image_buffer.get(), | 378 memcpy(last_successful_frame_buffer_.get(), image_buffer.get(), |
359 extracted_length); | 379 extracted_length); |
360 bool write_success = frame_writer_->WriteFrame(image_buffer.get()); | 380 bool write_success = frame_writer_->WriteFrame(image_buffer.get()); |
361 RTC_DCHECK(write_success); | 381 RTC_DCHECK(write_success); |
362 if (!write_success) { | 382 if (!write_success) { |
363 fprintf(stderr, "Failed to write frame %d to disk!", frame_number); | 383 fprintf(stderr, "Failed to write frame %d to disk!", frame_number); |
364 } | 384 } |
365 } else { // No resize. | 385 } else { // No resize. |
366 // Update our copy of the last successful frame: | 386 // Update our copy of the last successful frame. |
367 // TODO(mikhal): Add as a member function, so won't be allocated per frame. | 387 // TODO(mikhal): Add as a member function, so won't be allocated per frame. |
368 size_t length = CalcBufferSize(kI420, image.width(), image.height()); | 388 size_t length = CalcBufferSize(kI420, image.width(), image.height()); |
369 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); | 389 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); |
370 int extracted_length = ExtractBuffer(image, length, image_buffer.get()); | 390 int extracted_length = ExtractBuffer(image, length, image_buffer.get()); |
371 RTC_DCHECK_GT(extracted_length, 0); | 391 RTC_DCHECK_GT(extracted_length, 0); |
372 memcpy(last_successful_frame_buffer_.get(), image_buffer.get(), | 392 memcpy(last_successful_frame_buffer_.get(), image_buffer.get(), |
373 extracted_length); | 393 extracted_length); |
374 | 394 |
375 bool write_success = frame_writer_->WriteFrame(image_buffer.get()); | 395 bool write_success = frame_writer_->WriteFrame(image_buffer.get()); |
376 RTC_DCHECK(write_success); | 396 RTC_DCHECK(write_success); |
377 if (!write_success) { | 397 if (!write_success) { |
378 fprintf(stderr, "Failed to write frame %d to disk!", frame_number); | 398 fprintf(stderr, "Failed to write frame %d to disk!", frame_number); |
379 } | 399 } |
380 } | 400 } |
381 } | 401 } |
382 | 402 |
383 int VideoProcessorImpl::GetElapsedTimeMicroseconds(int64_t start, | 403 int VideoProcessorImpl::GetElapsedTimeMicroseconds(int64_t start, |
384 int64_t stop) { | 404 int64_t stop) { |
385 int64_t encode_time = (stop - start) / rtc::kNumNanosecsPerMicrosec; | 405 int64_t encode_time = (stop - start) / rtc::kNumNanosecsPerMicrosec; |
386 RTC_DCHECK_GE(encode_time, std::numeric_limits<int>::min()); | 406 RTC_DCHECK_GE(encode_time, std::numeric_limits<int>::min()); |
387 RTC_DCHECK_LE(encode_time, std::numeric_limits<int>::max()); | 407 RTC_DCHECK_LE(encode_time, std::numeric_limits<int>::max()); |
388 return static_cast<int>(encode_time); | 408 return static_cast<int>(encode_time); |
389 } | 409 } |
390 | 410 |
391 const char* ExcludeFrameTypesToStr(ExcludeFrameTypes e) { | |
392 switch (e) { | |
393 case kExcludeOnlyFirstKeyFrame: | |
394 return "ExcludeOnlyFirstKeyFrame"; | |
395 case kExcludeAllKeyFrames: | |
396 return "ExcludeAllKeyFrames"; | |
397 default: | |
398 RTC_NOTREACHED(); | |
399 return "Unknown"; | |
400 } | |
401 } | |
402 | |
403 // Callbacks | |
404 EncodedImageCallback::Result | |
405 VideoProcessorImpl::VideoProcessorEncodeCompleteCallback::OnEncodedImage( | |
406 const EncodedImage& encoded_image, | |
407 const webrtc::CodecSpecificInfo* codec_specific_info, | |
408 const webrtc::RTPFragmentationHeader* fragmentation) { | |
409 // Forward to parent class. | |
410 RTC_CHECK(codec_specific_info); | |
411 video_processor_->FrameEncoded(codec_specific_info->codecType, | |
412 encoded_image, | |
413 fragmentation); | |
414 return Result(Result::OK, 0); | |
415 } | |
416 int32_t VideoProcessorImpl::VideoProcessorDecodeCompleteCallback::Decoded( | |
417 VideoFrame& image) { | |
418 // Forward to parent class. | |
419 video_processor_->FrameDecoded(image); | |
420 return 0; | |
421 } | |
422 | |
423 } // namespace test | 411 } // namespace test |
424 } // namespace webrtc | 412 } // namespace webrtc |
OLD | NEW |