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