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 namespace { | |
33 const int k90khzTimestampFrameDiff = 3000; // Assuming 30 fps. | |
34 } // namespace | |
35 | |
36 const char* ExcludeFrameTypesToStr(ExcludeFrameTypes e) { | 32 const char* ExcludeFrameTypesToStr(ExcludeFrameTypes e) { |
37 switch (e) { | 33 switch (e) { |
38 case kExcludeOnlyFirstKeyFrame: | 34 case kExcludeOnlyFirstKeyFrame: |
39 return "ExcludeOnlyFirstKeyFrame"; | 35 return "ExcludeOnlyFirstKeyFrame"; |
40 case kExcludeAllKeyFrames: | 36 case kExcludeAllKeyFrames: |
41 return "ExcludeAllKeyFrames"; | 37 return "ExcludeAllKeyFrames"; |
42 default: | 38 default: |
43 RTC_NOTREACHED(); | 39 RTC_NOTREACHED(); |
44 return "Unknown"; | 40 return "Unknown"; |
45 } | 41 } |
(...skipping 11 matching lines...) Expand all Loading... |
57 frame_length_in_bytes(0), | 53 frame_length_in_bytes(0), |
58 use_single_core(false), | 54 use_single_core(false), |
59 keyframe_interval(0), | 55 keyframe_interval(0), |
60 codec_settings(nullptr), | 56 codec_settings(nullptr), |
61 verbose(true) {} | 57 verbose(true) {} |
62 | 58 |
63 TestConfig::~TestConfig() {} | 59 TestConfig::~TestConfig() {} |
64 | 60 |
65 VideoProcessorImpl::VideoProcessorImpl(webrtc::VideoEncoder* encoder, | 61 VideoProcessorImpl::VideoProcessorImpl(webrtc::VideoEncoder* encoder, |
66 webrtc::VideoDecoder* decoder, | 62 webrtc::VideoDecoder* decoder, |
67 FrameReader* analysis_frame_reader, | 63 FrameReader* frame_reader, |
68 FrameWriter* analysis_frame_writer, | 64 FrameWriter* frame_writer, |
69 PacketManipulator* packet_manipulator, | 65 PacketManipulator* packet_manipulator, |
70 const TestConfig& config, | 66 const TestConfig& config, |
71 Stats* stats, | 67 Stats* stats) |
72 FrameWriter* source_frame_writer, | |
73 IvfFileWriter* encoded_frame_writer, | |
74 FrameWriter* decoded_frame_writer) | |
75 : encoder_(encoder), | 68 : encoder_(encoder), |
76 decoder_(decoder), | 69 decoder_(decoder), |
77 analysis_frame_reader_(analysis_frame_reader), | 70 frame_reader_(frame_reader), |
78 analysis_frame_writer_(analysis_frame_writer), | 71 frame_writer_(frame_writer), |
79 packet_manipulator_(packet_manipulator), | 72 packet_manipulator_(packet_manipulator), |
80 config_(config), | 73 config_(config), |
81 stats_(stats), | 74 stats_(stats), |
82 source_frame_writer_(source_frame_writer), | |
83 encoded_frame_writer_(encoded_frame_writer), | |
84 decoded_frame_writer_(decoded_frame_writer), | |
85 first_key_frame_has_been_excluded_(false), | 75 first_key_frame_has_been_excluded_(false), |
86 last_frame_missing_(false), | 76 last_frame_missing_(false), |
87 initialized_(false), | 77 initialized_(false), |
88 encoded_frame_size_(0), | 78 encoded_frame_size_(0), |
89 encoded_frame_type_(kVideoFrameKey), | 79 encoded_frame_type_(kVideoFrameKey), |
90 prev_time_stamp_(0), | 80 prev_time_stamp_(0), |
91 num_dropped_frames_(0), | 81 num_dropped_frames_(0), |
92 num_spatial_resizes_(0), | 82 num_spatial_resizes_(0), |
93 last_encoder_frame_width_(0), | 83 last_encoder_frame_width_(0), |
94 last_encoder_frame_height_(0), | 84 last_encoder_frame_height_(0), |
95 bit_rate_factor_(0.0), | 85 bit_rate_factor_(0.0), |
96 encode_start_ns_(0), | 86 encode_start_ns_(0), |
97 decode_start_ns_(0) { | 87 decode_start_ns_(0) { |
98 std::unique_ptr<TemporalLayersFactory> tl_factory; | 88 std::unique_ptr<TemporalLayersFactory> tl_factory; |
99 if (config_.codec_settings->codecType == VideoCodecType::kVideoCodecVP8) { | 89 if (config_.codec_settings->codecType == VideoCodecType::kVideoCodecVP8) { |
100 tl_factory.reset(new TemporalLayersFactory()); | 90 tl_factory.reset(new TemporalLayersFactory()); |
101 config.codec_settings->VP8()->tl_factory = tl_factory.get(); | 91 config.codec_settings->VP8()->tl_factory = tl_factory.get(); |
102 } | 92 } |
103 bitrate_allocator_ = VideoCodecInitializer::CreateBitrateAllocator( | 93 bitrate_allocator_ = VideoCodecInitializer::CreateBitrateAllocator( |
104 *config.codec_settings, std::move(tl_factory)); | 94 *config.codec_settings, std::move(tl_factory)); |
105 RTC_DCHECK(encoder); | 95 RTC_DCHECK(encoder); |
106 RTC_DCHECK(decoder); | 96 RTC_DCHECK(decoder); |
107 RTC_DCHECK(analysis_frame_reader); | 97 RTC_DCHECK(frame_reader); |
108 RTC_DCHECK(analysis_frame_writer); | 98 RTC_DCHECK(frame_writer); |
109 RTC_DCHECK(packet_manipulator); | 99 RTC_DCHECK(packet_manipulator); |
110 RTC_DCHECK(stats); | 100 RTC_DCHECK(stats); |
111 } | 101 } |
112 | 102 |
113 bool VideoProcessorImpl::Init() { | 103 bool VideoProcessorImpl::Init() { |
114 // Calculate a factor used for bit rate calculations. | 104 // Calculate a factor used for bit rate calculations. |
115 bit_rate_factor_ = config_.codec_settings->maxFramerate * 0.001 * 8; // bits | 105 bit_rate_factor_ = config_.codec_settings->maxFramerate * 0.001 * 8; // bits |
116 | 106 |
117 // Initialize data structures used by the encoder/decoder APIs. | 107 // Initialize data structures used by the encoder/decoder APIs. |
118 size_t frame_length_in_bytes = analysis_frame_reader_->FrameLength(); | 108 size_t frame_length_in_bytes = frame_reader_->FrameLength(); |
119 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]); |
120 | 110 |
121 // Set fixed properties common for all frames. | 111 // Set fixed properties common for all frames. |
122 // To keep track of spatial resize actions by encoder. | 112 // To keep track of spatial resize actions by encoder. |
123 last_encoder_frame_width_ = config_.codec_settings->width; | 113 last_encoder_frame_width_ = config_.codec_settings->width; |
124 last_encoder_frame_height_ = config_.codec_settings->height; | 114 last_encoder_frame_height_ = config_.codec_settings->height; |
125 | 115 |
126 // Setup required callbacks for the encoder/decoder. | 116 // Setup required callbacks for the encoder/decoder. |
127 encode_callback_.reset(new VideoProcessorEncodeCompleteCallback(this)); | 117 encode_callback_.reset(new VideoProcessorEncodeCompleteCallback(this)); |
128 decode_callback_.reset(new VideoProcessorDecodeCompleteCallback(this)); | 118 decode_callback_.reset(new VideoProcessorDecodeCompleteCallback(this)); |
(...skipping 15 matching lines...) Expand all Loading... |
144 WEBRTC_VIDEO_CODEC_OK) | 134 WEBRTC_VIDEO_CODEC_OK) |
145 << "Failed to initialize VideoEncoder"; | 135 << "Failed to initialize VideoEncoder"; |
146 | 136 |
147 RTC_CHECK_EQ(decoder_->InitDecode(config_.codec_settings, num_cores), | 137 RTC_CHECK_EQ(decoder_->InitDecode(config_.codec_settings, num_cores), |
148 WEBRTC_VIDEO_CODEC_OK) | 138 WEBRTC_VIDEO_CODEC_OK) |
149 << "Failed to initialize VideoDecoder"; | 139 << "Failed to initialize VideoDecoder"; |
150 | 140 |
151 if (config_.verbose) { | 141 if (config_.verbose) { |
152 printf("Video Processor:\n"); | 142 printf("Video Processor:\n"); |
153 printf(" #CPU cores used : %d\n", num_cores); | 143 printf(" #CPU cores used : %d\n", num_cores); |
154 printf(" Total # of frames: %d\n", | 144 printf(" Total # of frames: %d\n", frame_reader_->NumberOfFrames()); |
155 analysis_frame_reader_->NumberOfFrames()); | |
156 printf(" Codec settings:\n"); | 145 printf(" Codec settings:\n"); |
157 printf(" Start bitrate : %d kbps\n", | 146 printf(" Start bitrate : %d kbps\n", |
158 config_.codec_settings->startBitrate); | 147 config_.codec_settings->startBitrate); |
159 printf(" Width : %d\n", config_.codec_settings->width); | 148 printf(" Width : %d\n", config_.codec_settings->width); |
160 printf(" Height : %d\n", config_.codec_settings->height); | 149 printf(" Height : %d\n", config_.codec_settings->height); |
161 printf(" Codec type : %s\n", | 150 printf(" Codec type : %s\n", |
162 CodecTypeToPayloadName(config_.codec_settings->codecType) | 151 CodecTypeToPayloadName(config_.codec_settings->codecType) |
163 .value_or("Unknown")); | 152 .value_or("Unknown")); |
164 printf(" Encoder implementation name: %s\n", | 153 printf(" Encoder implementation name: %s\n", |
165 encoder_->ImplementationName()); | 154 encoder_->ImplementationName()); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 } | 200 } |
212 | 201 |
213 int VideoProcessorImpl::NumberSpatialResizes() { | 202 int VideoProcessorImpl::NumberSpatialResizes() { |
214 return num_spatial_resizes_; | 203 return num_spatial_resizes_; |
215 } | 204 } |
216 | 205 |
217 bool VideoProcessorImpl::ProcessFrame(int frame_number) { | 206 bool VideoProcessorImpl::ProcessFrame(int frame_number) { |
218 RTC_DCHECK_GE(frame_number, 0); | 207 RTC_DCHECK_GE(frame_number, 0); |
219 RTC_CHECK(initialized_) << "Attempting to use uninitialized VideoProcessor"; | 208 RTC_CHECK(initialized_) << "Attempting to use uninitialized VideoProcessor"; |
220 | 209 |
221 rtc::scoped_refptr<VideoFrameBuffer> buffer( | 210 // |prev_time_stamp_| is used for getting number of dropped frames. |
222 analysis_frame_reader_->ReadFrame()); | 211 if (frame_number == 0) { |
| 212 prev_time_stamp_ = -1; |
| 213 } |
| 214 |
| 215 rtc::scoped_refptr<VideoFrameBuffer> buffer(frame_reader_->ReadFrame()); |
223 if (buffer) { | 216 if (buffer) { |
224 if (source_frame_writer_) { | 217 // Use the frame number as "timestamp" to identify frames. |
225 // TODO(brandtr): Introduce temp buffer as data member, to avoid | 218 VideoFrame source_frame(buffer, frame_number, 0, webrtc::kVideoRotation_0); |
226 // allocating for every frame. | |
227 size_t length = CalcBufferSize(kI420, buffer->width(), buffer->height()); | |
228 std::unique_ptr<uint8_t[]> extracted_buffer(new uint8_t[length]); | |
229 int extracted_length = | |
230 ExtractBuffer(buffer, length, extracted_buffer.get()); | |
231 RTC_DCHECK_GT(extracted_length, 0); | |
232 source_frame_writer_->WriteFrame(extracted_buffer.get()); | |
233 } | |
234 | |
235 // Use the frame number as basis for timestamp to identify frames. Let the | |
236 // first timestamp be non-zero, to not make the IvfFileWriter believe that | |
237 // we want to use capture timestamps in the IVF files. | |
238 VideoFrame source_frame(buffer, | |
239 (frame_number + 1) * k90khzTimestampFrameDiff, 0, | |
240 webrtc::kVideoRotation_0); | |
241 | 219 |
242 // Ensure we have a new statistics data object we can fill. | 220 // Ensure we have a new statistics data object we can fill. |
243 FrameStatistic& stat = stats_->NewFrame(frame_number); | 221 FrameStatistic& stat = stats_->NewFrame(frame_number); |
244 | 222 |
245 // Decide if we are going to force a keyframe. | 223 // Decide if we are going to force a keyframe. |
246 std::vector<FrameType> frame_types(1, kVideoFrameDelta); | 224 std::vector<FrameType> frame_types(1, kVideoFrameDelta); |
247 if (config_.keyframe_interval > 0 && | 225 if (config_.keyframe_interval > 0 && |
248 frame_number % config_.keyframe_interval == 0) { | 226 frame_number % config_.keyframe_interval == 0) { |
249 frame_types[0] = kVideoFrameKey; | 227 frame_types[0] = kVideoFrameKey; |
250 } | 228 } |
(...skipping 22 matching lines...) Expand all Loading... |
273 } | 251 } |
274 | 252 |
275 void VideoProcessorImpl::FrameEncoded( | 253 void VideoProcessorImpl::FrameEncoded( |
276 webrtc::VideoCodecType codec, | 254 webrtc::VideoCodecType codec, |
277 const EncodedImage& encoded_image, | 255 const EncodedImage& encoded_image, |
278 const webrtc::RTPFragmentationHeader* fragmentation) { | 256 const webrtc::RTPFragmentationHeader* fragmentation) { |
279 // For the highest measurement accuracy of the encode time, the start/stop | 257 // For the highest measurement accuracy of the encode time, the start/stop |
280 // time recordings should wrap the Encode call as tightly as possible. | 258 // time recordings should wrap the Encode call as tightly as possible. |
281 int64_t encode_stop_ns = rtc::TimeNanos(); | 259 int64_t encode_stop_ns = rtc::TimeNanos(); |
282 | 260 |
283 if (encoded_frame_writer_) { | 261 // Timestamp is frame number, so this gives us #dropped frames. |
284 RTC_DCHECK(encoded_frame_writer_->WriteFrame(encoded_image, codec)); | |
285 } | |
286 | |
287 // Timestamp is proportional to frame number, so this gives us number of | |
288 // dropped frames. | |
289 int num_dropped_from_prev_encode = | 262 int num_dropped_from_prev_encode = |
290 (encoded_image._timeStamp - prev_time_stamp_) / k90khzTimestampFrameDiff - | 263 encoded_image._timeStamp - prev_time_stamp_ - 1; |
291 1; | |
292 num_dropped_frames_ += num_dropped_from_prev_encode; | 264 num_dropped_frames_ += num_dropped_from_prev_encode; |
293 prev_time_stamp_ = encoded_image._timeStamp; | 265 prev_time_stamp_ = encoded_image._timeStamp; |
294 if (num_dropped_from_prev_encode > 0) { | 266 if (num_dropped_from_prev_encode > 0) { |
295 // For dropped frames, we write out the last decoded frame to avoid getting | 267 // For dropped frames, we write out the last decoded frame to avoid getting |
296 // out of sync for the computation of PSNR and SSIM. | 268 // out of sync for the computation of PSNR and SSIM. |
297 for (int i = 0; i < num_dropped_from_prev_encode; i++) { | 269 for (int i = 0; i < num_dropped_from_prev_encode; i++) { |
298 RTC_DCHECK(analysis_frame_writer_->WriteFrame( | 270 frame_writer_->WriteFrame(last_successful_frame_buffer_.get()); |
299 last_successful_frame_buffer_.get())); | |
300 if (decoded_frame_writer_) { | |
301 RTC_DCHECK(decoded_frame_writer_->WriteFrame( | |
302 last_successful_frame_buffer_.get())); | |
303 } | |
304 } | 271 } |
305 } | 272 } |
306 | |
307 // Frame is not dropped, so update the encoded frame size | 273 // Frame is not dropped, so update the encoded frame size |
308 // (encoder callback is only called for non-zero length frames). | 274 // (encoder callback is only called for non-zero length frames). |
309 encoded_frame_size_ = encoded_image._length; | 275 encoded_frame_size_ = encoded_image._length; |
310 encoded_frame_type_ = encoded_image._frameType; | 276 encoded_frame_type_ = encoded_image._frameType; |
311 int frame_number = encoded_image._timeStamp / k90khzTimestampFrameDiff - 1; | 277 int frame_number = encoded_image._timeStamp; |
| 278 |
312 FrameStatistic& stat = stats_->stats_[frame_number]; | 279 FrameStatistic& stat = stats_->stats_[frame_number]; |
313 stat.encode_time_in_us = | 280 stat.encode_time_in_us = |
314 GetElapsedTimeMicroseconds(encode_start_ns_, encode_stop_ns); | 281 GetElapsedTimeMicroseconds(encode_start_ns_, encode_stop_ns); |
315 stat.encoding_successful = true; | 282 stat.encoding_successful = true; |
316 stat.encoded_frame_length_in_bytes = encoded_image._length; | 283 stat.encoded_frame_length_in_bytes = encoded_image._length; |
317 stat.frame_number = frame_number; | 284 stat.frame_number = encoded_image._timeStamp; |
318 stat.frame_type = encoded_image._frameType; | 285 stat.frame_type = encoded_image._frameType; |
319 stat.bit_rate_in_kbps = encoded_image._length * bit_rate_factor_; | 286 stat.bit_rate_in_kbps = encoded_image._length * bit_rate_factor_; |
320 stat.total_packets = | 287 stat.total_packets = |
321 encoded_image._length / config_.networking_config.packet_size_in_bytes + | 288 encoded_image._length / config_.networking_config.packet_size_in_bytes + |
322 1; | 289 1; |
323 | 290 |
324 // Simulate packet loss. | 291 // Simulate packet loss. |
325 bool exclude_this_frame = false; | 292 bool exclude_this_frame = false; |
326 // Only keyframes can be excluded. | 293 // Only keyframes can be excluded. |
327 if (encoded_image._frameType == kVideoFrameKey) { | 294 if (encoded_image._frameType == kVideoFrameKey) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 // For the highest measurement accuracy of the decode time, the start/stop | 331 // For the highest measurement accuracy of the decode time, the start/stop |
365 // time recordings should wrap the Decode call as tightly as possible. | 332 // time recordings should wrap the Decode call as tightly as possible. |
366 decode_start_ns_ = rtc::TimeNanos(); | 333 decode_start_ns_ = rtc::TimeNanos(); |
367 int32_t decode_result = | 334 int32_t decode_result = |
368 decoder_->Decode(copied_image, last_frame_missing_, nullptr); | 335 decoder_->Decode(copied_image, last_frame_missing_, nullptr); |
369 stat.decode_return_code = decode_result; | 336 stat.decode_return_code = decode_result; |
370 | 337 |
371 if (decode_result != WEBRTC_VIDEO_CODEC_OK) { | 338 if (decode_result != WEBRTC_VIDEO_CODEC_OK) { |
372 // Write the last successful frame the output file to avoid getting it out | 339 // Write the last successful frame the output file to avoid getting it out |
373 // of sync with the source file for SSIM and PSNR comparisons. | 340 // of sync with the source file for SSIM and PSNR comparisons. |
374 RTC_DCHECK(analysis_frame_writer_->WriteFrame( | 341 frame_writer_->WriteFrame(last_successful_frame_buffer_.get()); |
375 last_successful_frame_buffer_.get())); | |
376 if (decoded_frame_writer_) { | |
377 RTC_DCHECK(decoded_frame_writer_->WriteFrame( | |
378 last_successful_frame_buffer_.get())); | |
379 } | |
380 } | 342 } |
381 | 343 |
382 // Save status for losses so we can inform the decoder for the next frame. | 344 // Save status for losses so we can inform the decoder for the next frame. |
383 last_frame_missing_ = copied_image._length == 0; | 345 last_frame_missing_ = copied_image._length == 0; |
384 } | 346 } |
385 | 347 |
386 void VideoProcessorImpl::FrameDecoded(const VideoFrame& image) { | 348 void VideoProcessorImpl::FrameDecoded(const VideoFrame& image) { |
387 // For the highest measurement accuracy of the decode time, the start/stop | 349 // For the highest measurement accuracy of the decode time, the start/stop |
388 // time recordings should wrap the Decode call as tightly as possible. | 350 // time recordings should wrap the Decode call as tightly as possible. |
389 int64_t decode_stop_ns = rtc::TimeNanos(); | 351 int64_t decode_stop_ns = rtc::TimeNanos(); |
390 | 352 |
391 // Report stats. | 353 // Report stats. |
392 int frame_number = image.timestamp() / k90khzTimestampFrameDiff - 1; | 354 int frame_number = image.timestamp(); |
393 FrameStatistic& stat = stats_->stats_[frame_number]; | 355 FrameStatistic& stat = stats_->stats_[frame_number]; |
394 stat.decode_time_in_us = | 356 stat.decode_time_in_us = |
395 GetElapsedTimeMicroseconds(decode_start_ns_, decode_stop_ns); | 357 GetElapsedTimeMicroseconds(decode_start_ns_, decode_stop_ns); |
396 stat.decoding_successful = true; | 358 stat.decoding_successful = true; |
397 | 359 |
398 // Check for resize action (either down or up). | 360 // Check for resize action (either down or up). |
399 if (static_cast<int>(image.width()) != last_encoder_frame_width_ || | 361 if (static_cast<int>(image.width()) != last_encoder_frame_width_ || |
400 static_cast<int>(image.height()) != last_encoder_frame_height_) { | 362 static_cast<int>(image.height()) != last_encoder_frame_height_) { |
401 ++num_spatial_resizes_; | 363 ++num_spatial_resizes_; |
402 last_encoder_frame_width_ = image.width(); | 364 last_encoder_frame_width_ = image.width(); |
(...skipping 17 matching lines...) Expand all Loading... |
420 | 382 |
421 // TODO(mikhal): Extracting the buffer for now - need to update test. | 383 // TODO(mikhal): Extracting the buffer for now - need to update test. |
422 size_t length = | 384 size_t length = |
423 CalcBufferSize(kI420, up_image->width(), up_image->height()); | 385 CalcBufferSize(kI420, up_image->width(), up_image->height()); |
424 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); | 386 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); |
425 int extracted_length = ExtractBuffer(up_image, length, image_buffer.get()); | 387 int extracted_length = ExtractBuffer(up_image, length, image_buffer.get()); |
426 RTC_DCHECK_GT(extracted_length, 0); | 388 RTC_DCHECK_GT(extracted_length, 0); |
427 // Update our copy of the last successful frame. | 389 // Update our copy of the last successful frame. |
428 memcpy(last_successful_frame_buffer_.get(), image_buffer.get(), | 390 memcpy(last_successful_frame_buffer_.get(), image_buffer.get(), |
429 extracted_length); | 391 extracted_length); |
430 | 392 bool write_success = frame_writer_->WriteFrame(image_buffer.get()); |
431 RTC_DCHECK(analysis_frame_writer_->WriteFrame(image_buffer.get())); | 393 RTC_DCHECK(write_success); |
432 if (decoded_frame_writer_) { | 394 if (!write_success) { |
433 RTC_DCHECK(decoded_frame_writer_->WriteFrame(image_buffer.get())); | 395 fprintf(stderr, "Failed to write frame %d to disk!", frame_number); |
434 } | 396 } |
435 } else { // No resize. | 397 } else { // No resize. |
436 // Update our copy of the last successful frame. | 398 // Update our copy of the last successful frame. |
437 // TODO(mikhal): Add as a member function, so won't be allocated per frame. | 399 // TODO(mikhal): Add as a member function, so won't be allocated per frame. |
438 size_t length = CalcBufferSize(kI420, image.width(), image.height()); | 400 size_t length = CalcBufferSize(kI420, image.width(), image.height()); |
439 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); | 401 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); |
440 int extracted_length; | 402 int extracted_length; |
441 if (image.video_frame_buffer()->native_handle()) { | 403 if (image.video_frame_buffer()->native_handle()) { |
442 extracted_length = | 404 extracted_length = |
443 ExtractBuffer(image.video_frame_buffer()->NativeToI420Buffer(), | 405 ExtractBuffer(image.video_frame_buffer()->NativeToI420Buffer(), |
444 length, image_buffer.get()); | 406 length, image_buffer.get()); |
445 } else { | 407 } else { |
446 extracted_length = | 408 extracted_length = |
447 ExtractBuffer(image.video_frame_buffer(), length, image_buffer.get()); | 409 ExtractBuffer(image.video_frame_buffer(), length, image_buffer.get()); |
448 } | 410 } |
449 RTC_DCHECK_GT(extracted_length, 0); | 411 RTC_DCHECK_GT(extracted_length, 0); |
450 memcpy(last_successful_frame_buffer_.get(), image_buffer.get(), | 412 memcpy(last_successful_frame_buffer_.get(), image_buffer.get(), |
451 extracted_length); | 413 extracted_length); |
452 | 414 |
453 RTC_DCHECK(analysis_frame_writer_->WriteFrame(image_buffer.get())); | 415 bool write_success = frame_writer_->WriteFrame(image_buffer.get()); |
454 if (decoded_frame_writer_) { | 416 RTC_DCHECK(write_success); |
455 RTC_DCHECK(decoded_frame_writer_->WriteFrame(image_buffer.get())); | 417 if (!write_success) { |
| 418 fprintf(stderr, "Failed to write frame %d to disk!", frame_number); |
456 } | 419 } |
457 } | 420 } |
458 } | 421 } |
459 | 422 |
460 int VideoProcessorImpl::GetElapsedTimeMicroseconds(int64_t start, | 423 int VideoProcessorImpl::GetElapsedTimeMicroseconds(int64_t start, |
461 int64_t stop) { | 424 int64_t stop) { |
462 int64_t encode_time = (stop - start) / rtc::kNumNanosecsPerMicrosec; | 425 int64_t encode_time = (stop - start) / rtc::kNumNanosecsPerMicrosec; |
463 RTC_DCHECK_GE(encode_time, std::numeric_limits<int>::min()); | 426 RTC_DCHECK_GE(encode_time, std::numeric_limits<int>::min()); |
464 RTC_DCHECK_LE(encode_time, std::numeric_limits<int>::max()); | 427 RTC_DCHECK_LE(encode_time, std::numeric_limits<int>::max()); |
465 return static_cast<int>(encode_time); | 428 return static_cast<int>(encode_time); |
466 } | 429 } |
467 | 430 |
468 } // namespace test | 431 } // namespace test |
469 } // namespace webrtc | 432 } // namespace webrtc |
OLD | NEW |