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 13 matching lines...) Expand all Loading... |
132 WEBRTC_VIDEO_CODEC_OK) | 142 WEBRTC_VIDEO_CODEC_OK) |
133 << "Failed to initialize VideoEncoder"; | 143 << "Failed to initialize VideoEncoder"; |
134 | 144 |
135 RTC_CHECK_EQ(decoder_->InitDecode(config_.codec_settings, num_cores), | 145 RTC_CHECK_EQ(decoder_->InitDecode(config_.codec_settings, num_cores), |
136 WEBRTC_VIDEO_CODEC_OK) | 146 WEBRTC_VIDEO_CODEC_OK) |
137 << "Failed to initialize VideoDecoder"; | 147 << "Failed to initialize VideoDecoder"; |
138 | 148 |
139 if (config_.verbose) { | 149 if (config_.verbose) { |
140 printf("Video Processor:\n"); | 150 printf("Video Processor:\n"); |
141 printf(" #CPU cores used : %d\n", num_cores); | 151 printf(" #CPU cores used : %d\n", num_cores); |
142 printf(" Total # of frames: %d\n", frame_reader_->NumberOfFrames()); | 152 printf(" Total # of frames: %d\n", |
| 153 analysis_frame_reader_->NumberOfFrames()); |
143 printf(" Codec settings:\n"); | 154 printf(" Codec settings:\n"); |
144 printf(" Start bitrate : %d kbps\n", | 155 printf(" Start bitrate : %d kbps\n", |
145 config_.codec_settings->startBitrate); | 156 config_.codec_settings->startBitrate); |
146 printf(" Width : %d\n", config_.codec_settings->width); | 157 printf(" Width : %d\n", config_.codec_settings->width); |
147 printf(" Height : %d\n", config_.codec_settings->height); | 158 printf(" Height : %d\n", config_.codec_settings->height); |
148 printf(" Codec type : %s\n", | 159 printf(" Codec type : %s\n", |
149 CodecTypeToPayloadName(config_.codec_settings->codecType) | 160 CodecTypeToPayloadName(config_.codec_settings->codecType) |
150 .value_or("Unknown")); | 161 .value_or("Unknown")); |
151 printf(" Encoder implementation name: %s\n", | 162 printf(" Encoder implementation name: %s\n", |
152 encoder_->ImplementationName()); | 163 encoder_->ImplementationName()); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 | 206 |
196 int VideoProcessorImpl::NumberDroppedFrames() { | 207 int VideoProcessorImpl::NumberDroppedFrames() { |
197 return num_dropped_frames_; | 208 return num_dropped_frames_; |
198 } | 209 } |
199 | 210 |
200 int VideoProcessorImpl::NumberSpatialResizes() { | 211 int VideoProcessorImpl::NumberSpatialResizes() { |
201 return num_spatial_resizes_; | 212 return num_spatial_resizes_; |
202 } | 213 } |
203 | 214 |
204 bool VideoProcessorImpl::ProcessFrame(int frame_number) { | 215 bool VideoProcessorImpl::ProcessFrame(int frame_number) { |
205 RTC_DCHECK_GE(frame_number, 0); | 216 RTC_CHECK_GE(frame_number, 0); |
206 RTC_CHECK(initialized_) << "Attempting to use uninitialized VideoProcessor"; | 217 RTC_CHECK(initialized_) << "Attempting to use uninitialized VideoProcessor"; |
207 | 218 |
208 // |prev_time_stamp_| is used for getting number of dropped frames. | 219 rtc::scoped_refptr<VideoFrameBuffer> buffer( |
209 if (frame_number == 0) { | 220 analysis_frame_reader_->ReadFrame()); |
210 prev_time_stamp_ = -1; | 221 if (buffer) { |
211 } | 222 if (source_frame_writer_) { |
| 223 // TODO(brandtr): Introduce temp buffer as data member, to avoid |
| 224 // allocating for every frame. |
| 225 size_t length = CalcBufferSize(kI420, buffer->width(), buffer->height()); |
| 226 std::unique_ptr<uint8_t[]> extracted_buffer(new uint8_t[length]); |
| 227 int extracted_length = |
| 228 ExtractBuffer(buffer, length, extracted_buffer.get()); |
| 229 RTC_CHECK_EQ(extracted_length, source_frame_writer_->FrameLength()); |
| 230 source_frame_writer_->WriteFrame(extracted_buffer.get()); |
| 231 } |
212 | 232 |
213 rtc::scoped_refptr<VideoFrameBuffer> buffer(frame_reader_->ReadFrame()); | 233 // Use the frame number as basis for timestamp to identify frames. Let the |
214 if (buffer) { | 234 // first timestamp be non-zero, to not make the IvfFileWriter believe that |
215 // Use the frame number as "timestamp" to identify frames. | 235 // we want to use capture timestamps in the IVF files. |
216 VideoFrame source_frame(buffer, frame_number, 0, webrtc::kVideoRotation_0); | 236 VideoFrame source_frame(buffer, |
| 237 (frame_number + 1) * k90khzTimestampFrameDiff, 0, |
| 238 webrtc::kVideoRotation_0); |
217 | 239 |
218 // Ensure we have a new statistics data object we can fill. | 240 // Ensure we have a new statistics data object we can fill. |
219 FrameStatistic& stat = stats_->NewFrame(frame_number); | 241 FrameStatistic& stat = stats_->NewFrame(frame_number); |
220 | 242 |
221 // Decide if we are going to force a keyframe. | 243 // Decide if we are going to force a keyframe. |
222 std::vector<FrameType> frame_types(1, kVideoFrameDelta); | 244 std::vector<FrameType> frame_types(1, kVideoFrameDelta); |
223 if (config_.keyframe_interval > 0 && | 245 if (config_.keyframe_interval > 0 && |
224 frame_number % config_.keyframe_interval == 0) { | 246 frame_number % config_.keyframe_interval == 0) { |
225 frame_types[0] = kVideoFrameKey; | 247 frame_types[0] = kVideoFrameKey; |
226 } | 248 } |
(...skipping 22 matching lines...) Expand all Loading... |
249 } | 271 } |
250 | 272 |
251 void VideoProcessorImpl::FrameEncoded( | 273 void VideoProcessorImpl::FrameEncoded( |
252 webrtc::VideoCodecType codec, | 274 webrtc::VideoCodecType codec, |
253 const EncodedImage& encoded_image, | 275 const EncodedImage& encoded_image, |
254 const webrtc::RTPFragmentationHeader* fragmentation) { | 276 const webrtc::RTPFragmentationHeader* fragmentation) { |
255 // For the highest measurement accuracy of the encode time, the start/stop | 277 // For the highest measurement accuracy of the encode time, the start/stop |
256 // time recordings should wrap the Encode call as tightly as possible. | 278 // time recordings should wrap the Encode call as tightly as possible. |
257 int64_t encode_stop_ns = rtc::TimeNanos(); | 279 int64_t encode_stop_ns = rtc::TimeNanos(); |
258 | 280 |
259 // Timestamp is frame number, so this gives us #dropped frames. | 281 if (encoded_frame_writer_) { |
| 282 RTC_CHECK(encoded_frame_writer_->WriteFrame(encoded_image, codec)); |
| 283 } |
| 284 |
| 285 // Timestamp is proportional to frame number, so this gives us number of |
| 286 // dropped frames. |
260 int num_dropped_from_prev_encode = | 287 int num_dropped_from_prev_encode = |
261 encoded_image._timeStamp - prev_time_stamp_ - 1; | 288 (encoded_image._timeStamp - prev_time_stamp_) / k90khzTimestampFrameDiff - |
| 289 1; |
262 num_dropped_frames_ += num_dropped_from_prev_encode; | 290 num_dropped_frames_ += num_dropped_from_prev_encode; |
263 prev_time_stamp_ = encoded_image._timeStamp; | 291 prev_time_stamp_ = encoded_image._timeStamp; |
264 if (num_dropped_from_prev_encode > 0) { | 292 if (num_dropped_from_prev_encode > 0) { |
265 // For dropped frames, we write out the last decoded frame to avoid getting | 293 // For dropped frames, we write out the last decoded frame to avoid getting |
266 // out of sync for the computation of PSNR and SSIM. | 294 // out of sync for the computation of PSNR and SSIM. |
267 for (int i = 0; i < num_dropped_from_prev_encode; i++) { | 295 for (int i = 0; i < num_dropped_from_prev_encode; i++) { |
268 frame_writer_->WriteFrame(last_successful_frame_buffer_.get()); | 296 RTC_CHECK(analysis_frame_writer_->WriteFrame( |
| 297 last_successful_frame_buffer_.get())); |
| 298 if (decoded_frame_writer_) { |
| 299 RTC_CHECK(decoded_frame_writer_->WriteFrame( |
| 300 last_successful_frame_buffer_.get())); |
| 301 } |
269 } | 302 } |
270 } | 303 } |
| 304 |
271 // Frame is not dropped, so update the encoded frame size | 305 // Frame is not dropped, so update the encoded frame size |
272 // (encoder callback is only called for non-zero length frames). | 306 // (encoder callback is only called for non-zero length frames). |
273 encoded_frame_size_ = encoded_image._length; | 307 encoded_frame_size_ = encoded_image._length; |
274 encoded_frame_type_ = encoded_image._frameType; | 308 encoded_frame_type_ = encoded_image._frameType; |
275 int frame_number = encoded_image._timeStamp; | 309 int frame_number = encoded_image._timeStamp / k90khzTimestampFrameDiff - 1; |
276 | |
277 FrameStatistic& stat = stats_->stats_[frame_number]; | 310 FrameStatistic& stat = stats_->stats_[frame_number]; |
278 stat.encode_time_in_us = | 311 stat.encode_time_in_us = |
279 GetElapsedTimeMicroseconds(encode_start_ns_, encode_stop_ns); | 312 GetElapsedTimeMicroseconds(encode_start_ns_, encode_stop_ns); |
280 stat.encoding_successful = true; | 313 stat.encoding_successful = true; |
281 stat.encoded_frame_length_in_bytes = encoded_image._length; | 314 stat.encoded_frame_length_in_bytes = encoded_image._length; |
282 stat.frame_number = encoded_image._timeStamp; | 315 stat.frame_number = frame_number; |
283 stat.frame_type = encoded_image._frameType; | 316 stat.frame_type = encoded_image._frameType; |
284 stat.bit_rate_in_kbps = encoded_image._length * bit_rate_factor_; | 317 stat.bit_rate_in_kbps = encoded_image._length * bit_rate_factor_; |
285 stat.total_packets = | 318 stat.total_packets = |
286 encoded_image._length / config_.networking_config.packet_size_in_bytes + | 319 encoded_image._length / config_.networking_config.packet_size_in_bytes + |
287 1; | 320 1; |
288 | 321 |
289 // Simulate packet loss. | 322 // Simulate packet loss. |
290 bool exclude_this_frame = false; | 323 bool exclude_this_frame = false; |
291 // Only keyframes can be excluded. | 324 // Only keyframes can be excluded. |
292 if (encoded_image._frameType == kVideoFrameKey) { | 325 if (encoded_image._frameType == kVideoFrameKey) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 // For the highest measurement accuracy of the decode time, the start/stop | 362 // For the highest measurement accuracy of the decode time, the start/stop |
330 // time recordings should wrap the Decode call as tightly as possible. | 363 // time recordings should wrap the Decode call as tightly as possible. |
331 decode_start_ns_ = rtc::TimeNanos(); | 364 decode_start_ns_ = rtc::TimeNanos(); |
332 int32_t decode_result = | 365 int32_t decode_result = |
333 decoder_->Decode(copied_image, last_frame_missing_, nullptr); | 366 decoder_->Decode(copied_image, last_frame_missing_, nullptr); |
334 stat.decode_return_code = decode_result; | 367 stat.decode_return_code = decode_result; |
335 | 368 |
336 if (decode_result != WEBRTC_VIDEO_CODEC_OK) { | 369 if (decode_result != WEBRTC_VIDEO_CODEC_OK) { |
337 // Write the last successful frame the output file to avoid getting it out | 370 // Write the last successful frame the output file to avoid getting it out |
338 // of sync with the source file for SSIM and PSNR comparisons. | 371 // of sync with the source file for SSIM and PSNR comparisons. |
339 frame_writer_->WriteFrame(last_successful_frame_buffer_.get()); | 372 RTC_CHECK(analysis_frame_writer_->WriteFrame( |
| 373 last_successful_frame_buffer_.get())); |
| 374 if (decoded_frame_writer_) { |
| 375 RTC_CHECK(decoded_frame_writer_->WriteFrame( |
| 376 last_successful_frame_buffer_.get())); |
| 377 } |
340 } | 378 } |
341 | 379 |
342 // Save status for losses so we can inform the decoder for the next frame. | 380 // Save status for losses so we can inform the decoder for the next frame. |
343 last_frame_missing_ = copied_image._length == 0; | 381 last_frame_missing_ = copied_image._length == 0; |
344 } | 382 } |
345 | 383 |
346 void VideoProcessorImpl::FrameDecoded(const VideoFrame& image) { | 384 void VideoProcessorImpl::FrameDecoded(const VideoFrame& image) { |
347 // For the highest measurement accuracy of the decode time, the start/stop | 385 // For the highest measurement accuracy of the decode time, the start/stop |
348 // time recordings should wrap the Decode call as tightly as possible. | 386 // time recordings should wrap the Decode call as tightly as possible. |
349 int64_t decode_stop_ns = rtc::TimeNanos(); | 387 int64_t decode_stop_ns = rtc::TimeNanos(); |
350 | 388 |
351 // Report stats. | 389 // Report stats. |
352 int frame_number = image.timestamp(); | 390 int frame_number = image.timestamp() / k90khzTimestampFrameDiff - 1; |
353 FrameStatistic& stat = stats_->stats_[frame_number]; | 391 FrameStatistic& stat = stats_->stats_[frame_number]; |
354 stat.decode_time_in_us = | 392 stat.decode_time_in_us = |
355 GetElapsedTimeMicroseconds(decode_start_ns_, decode_stop_ns); | 393 GetElapsedTimeMicroseconds(decode_start_ns_, decode_stop_ns); |
356 stat.decoding_successful = true; | 394 stat.decoding_successful = true; |
357 | 395 |
358 // Check for resize action (either down or up). | 396 // Check for resize action (either down or up). |
359 if (static_cast<int>(image.width()) != last_encoder_frame_width_ || | 397 if (static_cast<int>(image.width()) != last_encoder_frame_width_ || |
360 static_cast<int>(image.height()) != last_encoder_frame_height_) { | 398 static_cast<int>(image.height()) != last_encoder_frame_height_) { |
361 ++num_spatial_resizes_; | 399 ++num_spatial_resizes_; |
362 last_encoder_frame_width_ = image.width(); | 400 last_encoder_frame_width_ = image.width(); |
(...skipping 13 matching lines...) Expand all Loading... |
376 up_image->ScaleFrom(*image.video_frame_buffer()->NativeToI420Buffer()); | 414 up_image->ScaleFrom(*image.video_frame_buffer()->NativeToI420Buffer()); |
377 } else { | 415 } else { |
378 up_image->ScaleFrom(*image.video_frame_buffer()); | 416 up_image->ScaleFrom(*image.video_frame_buffer()); |
379 } | 417 } |
380 | 418 |
381 // TODO(mikhal): Extracting the buffer for now - need to update test. | 419 // TODO(mikhal): Extracting the buffer for now - need to update test. |
382 size_t length = | 420 size_t length = |
383 CalcBufferSize(kI420, up_image->width(), up_image->height()); | 421 CalcBufferSize(kI420, up_image->width(), up_image->height()); |
384 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); | 422 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); |
385 int extracted_length = ExtractBuffer(up_image, length, image_buffer.get()); | 423 int extracted_length = ExtractBuffer(up_image, length, image_buffer.get()); |
386 RTC_DCHECK_GT(extracted_length, 0); | 424 RTC_CHECK_GT(extracted_length, 0); |
387 // Update our copy of the last successful frame. | 425 // Update our copy of the last successful frame. |
388 memcpy(last_successful_frame_buffer_.get(), image_buffer.get(), | 426 memcpy(last_successful_frame_buffer_.get(), image_buffer.get(), |
389 extracted_length); | 427 extracted_length); |
390 bool write_success = frame_writer_->WriteFrame(image_buffer.get()); | 428 |
391 RTC_DCHECK(write_success); | 429 RTC_CHECK(analysis_frame_writer_->WriteFrame(image_buffer.get())); |
392 if (!write_success) { | 430 if (decoded_frame_writer_) { |
393 fprintf(stderr, "Failed to write frame %d to disk!", frame_number); | 431 RTC_CHECK(decoded_frame_writer_->WriteFrame(image_buffer.get())); |
394 } | 432 } |
395 } else { // No resize. | 433 } else { // No resize. |
396 // Update our copy of the last successful frame. | 434 // Update our copy of the last successful frame. |
397 // TODO(mikhal): Add as a member function, so won't be allocated per frame. | 435 // TODO(mikhal): Add as a member function, so won't be allocated per frame. |
398 size_t length = CalcBufferSize(kI420, image.width(), image.height()); | 436 size_t length = CalcBufferSize(kI420, image.width(), image.height()); |
399 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); | 437 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); |
400 int extracted_length; | 438 int extracted_length; |
401 if (image.video_frame_buffer()->native_handle()) { | 439 if (image.video_frame_buffer()->native_handle()) { |
402 extracted_length = | 440 extracted_length = |
403 ExtractBuffer(image.video_frame_buffer()->NativeToI420Buffer(), | 441 ExtractBuffer(image.video_frame_buffer()->NativeToI420Buffer(), |
404 length, image_buffer.get()); | 442 length, image_buffer.get()); |
405 } else { | 443 } else { |
406 extracted_length = | 444 extracted_length = |
407 ExtractBuffer(image.video_frame_buffer(), length, image_buffer.get()); | 445 ExtractBuffer(image.video_frame_buffer(), length, image_buffer.get()); |
408 } | 446 } |
409 RTC_DCHECK_GT(extracted_length, 0); | 447 RTC_CHECK_GT(extracted_length, 0); |
410 memcpy(last_successful_frame_buffer_.get(), image_buffer.get(), | 448 memcpy(last_successful_frame_buffer_.get(), image_buffer.get(), |
411 extracted_length); | 449 extracted_length); |
412 | 450 |
413 bool write_success = frame_writer_->WriteFrame(image_buffer.get()); | 451 RTC_CHECK(analysis_frame_writer_->WriteFrame(image_buffer.get())); |
414 RTC_DCHECK(write_success); | 452 if (decoded_frame_writer_) { |
415 if (!write_success) { | 453 RTC_CHECK(decoded_frame_writer_->WriteFrame(image_buffer.get())); |
416 fprintf(stderr, "Failed to write frame %d to disk!", frame_number); | |
417 } | 454 } |
418 } | 455 } |
419 } | 456 } |
420 | 457 |
421 int VideoProcessorImpl::GetElapsedTimeMicroseconds(int64_t start, | 458 int VideoProcessorImpl::GetElapsedTimeMicroseconds(int64_t start, |
422 int64_t stop) { | 459 int64_t stop) { |
423 int64_t encode_time = (stop - start) / rtc::kNumNanosecsPerMicrosec; | 460 int64_t encode_time = (stop - start) / rtc::kNumNanosecsPerMicrosec; |
424 RTC_DCHECK_GE(encode_time, std::numeric_limits<int>::min()); | 461 RTC_DCHECK_GE(encode_time, std::numeric_limits<int>::min()); |
425 RTC_DCHECK_LE(encode_time, std::numeric_limits<int>::max()); | 462 RTC_DCHECK_LE(encode_time, std::numeric_limits<int>::max()); |
426 return static_cast<int>(encode_time); | 463 return static_cast<int>(encode_time); |
427 } | 464 } |
428 | 465 |
429 } // namespace test | 466 } // namespace test |
430 } // namespace webrtc | 467 } // namespace webrtc |
OLD | NEW |