diff --git a/webrtc/common_video/libyuv/include/webrtc_libyuv.h b/webrtc/common_video/libyuv/include/webrtc_libyuv.h index ce1da3d859..ec3720e442 100644 --- a/webrtc/common_video/libyuv/include/webrtc_libyuv.h +++ b/webrtc/common_video/libyuv/include/webrtc_libyuv.h @@ -94,8 +94,6 @@ int ExtractBuffer(const VideoFrame& input_frame, size_t size, uint8_t* buffer); // - dst_frame : Reference to a destination frame. // Return value: 0 if OK, < 0 otherwise. -// TODO(nisse): Deprecated, see -// https://bugs.chromium.org/p/webrtc/issues/detail?id=5921. int ConvertToI420(VideoType src_video_type, const uint8_t* src_frame, int crop_x, @@ -122,13 +120,8 @@ int ConvertFromI420(const VideoFrame& src_frame, // Compute PSNR for an I420 frame (all planes). // Returns the PSNR in decibel, to a maximum of kInfinitePSNR. double I420PSNR(const VideoFrame* ref_frame, const VideoFrame* test_frame); -double I420PSNR(const VideoFrameBuffer& ref_buffer, - const VideoFrameBuffer& test_buffer); - // Compute SSIM for an I420 frame (all planes). double I420SSIM(const VideoFrame* ref_frame, const VideoFrame* test_frame); -double I420SSIM(const VideoFrameBuffer& ref_buffer, - const VideoFrameBuffer& test_buffer); } // namespace webrtc diff --git a/webrtc/common_video/libyuv/webrtc_libyuv.cc b/webrtc/common_video/libyuv/webrtc_libyuv.cc index 961b213981..44577e9ac8 100644 --- a/webrtc/common_video/libyuv/webrtc_libyuv.cc +++ b/webrtc/common_video/libyuv/webrtc_libyuv.cc @@ -290,55 +290,55 @@ int ConvertFromI420(const VideoFrame& src_frame, } // Compute PSNR for an I420 frame (all planes) -double I420PSNR(const VideoFrameBuffer& ref_buffer, - const VideoFrameBuffer& test_buffer) { - if ((ref_buffer.width() != test_buffer.width()) || - (ref_buffer.height() != test_buffer.height())) +double I420PSNR(const VideoFrame* ref_frame, const VideoFrame* test_frame) { + if (!ref_frame || !test_frame) return -1; - else if (ref_buffer.width() < 0 || ref_buffer.height() < 0) + else if ((ref_frame->width() != test_frame->width()) || + (ref_frame->height() != test_frame->height())) + return -1; + else if (ref_frame->width() < 0 || ref_frame->height() < 0) return -1; - double psnr = libyuv::I420Psnr(ref_buffer.DataY(), ref_buffer.StrideY(), - ref_buffer.DataU(), ref_buffer.StrideU(), - ref_buffer.DataV(), ref_buffer.StrideV(), - test_buffer.DataY(), test_buffer.StrideY(), - test_buffer.DataU(), test_buffer.StrideU(), - test_buffer.DataV(), test_buffer.StrideV(), - test_buffer.width(), test_buffer.height()); + double psnr = libyuv::I420Psnr(ref_frame->video_frame_buffer()->DataY(), + ref_frame->video_frame_buffer()->StrideY(), + ref_frame->video_frame_buffer()->DataU(), + ref_frame->video_frame_buffer()->StrideU(), + ref_frame->video_frame_buffer()->DataV(), + ref_frame->video_frame_buffer()->StrideV(), + test_frame->video_frame_buffer()->DataY(), + test_frame->video_frame_buffer()->StrideY(), + test_frame->video_frame_buffer()->DataU(), + test_frame->video_frame_buffer()->StrideU(), + test_frame->video_frame_buffer()->DataV(), + test_frame->video_frame_buffer()->StrideV(), + test_frame->width(), test_frame->height()); // LibYuv sets the max psnr value to 128, we restrict it here. // In case of 0 mse in one frame, 128 can skew the results significantly. return (psnr > kPerfectPSNR) ? kPerfectPSNR : psnr; } -// Compute PSNR for an I420 frame (all planes) -double I420PSNR(const VideoFrame* ref_frame, const VideoFrame* test_frame) { - if (!ref_frame || !test_frame) - return -1; - return I420PSNR(*ref_frame->video_frame_buffer(), - *test_frame->video_frame_buffer()); -} - // Compute SSIM for an I420 frame (all planes) -double I420SSIM(const VideoFrameBuffer& ref_buffer, - const VideoFrameBuffer& test_buffer) { - if ((ref_buffer.width() != test_buffer.width()) || - (ref_buffer.height() != test_buffer.height())) - return -1; - else if (ref_buffer.width() < 0 || ref_buffer.height() < 0) - return -1; - - return libyuv::I420Ssim(ref_buffer.DataY(), ref_buffer.StrideY(), - ref_buffer.DataU(), ref_buffer.StrideU(), - ref_buffer.DataV(), ref_buffer.StrideV(), - test_buffer.DataY(), test_buffer.StrideY(), - test_buffer.DataU(), test_buffer.StrideU(), - test_buffer.DataV(), test_buffer.StrideV(), - test_buffer.width(), test_buffer.height()); -} double I420SSIM(const VideoFrame* ref_frame, const VideoFrame* test_frame) { if (!ref_frame || !test_frame) return -1; - return I420SSIM(*ref_frame->video_frame_buffer(), - *test_frame->video_frame_buffer()); + else if ((ref_frame->width() != test_frame->width()) || + (ref_frame->height() != test_frame->height())) + return -1; + else if (ref_frame->width() < 0 || ref_frame->height() < 0) + return -1; + + return libyuv::I420Ssim(ref_frame->video_frame_buffer()->DataY(), + ref_frame->video_frame_buffer()->StrideY(), + ref_frame->video_frame_buffer()->DataU(), + ref_frame->video_frame_buffer()->StrideU(), + ref_frame->video_frame_buffer()->DataV(), + ref_frame->video_frame_buffer()->StrideV(), + test_frame->video_frame_buffer()->DataY(), + test_frame->video_frame_buffer()->StrideY(), + test_frame->video_frame_buffer()->DataU(), + test_frame->video_frame_buffer()->StrideU(), + test_frame->video_frame_buffer()->DataV(), + test_frame->video_frame_buffer()->StrideV(), + test_frame->width(), test_frame->height()); } } // namespace webrtc diff --git a/webrtc/test/fake_texture_frame.h b/webrtc/test/fake_texture_frame.h index 5e7571d87b..23b2954460 100644 --- a/webrtc/test/fake_texture_frame.h +++ b/webrtc/test/fake_texture_frame.h @@ -38,7 +38,8 @@ class FakeNativeHandleBuffer : public NativeHandleBuffer { private: rtc::scoped_refptr NativeToI420Buffer() override { - rtc::scoped_refptr buffer = I420Buffer::Create(width_, height_); + rtc::scoped_refptr buffer( + I420Buffer::Create(width_, height_)); int half_height = (height_ + 1) / 2; int half_width = (width_ + 1) / 2; memset(buffer->MutableDataY(), 0, height_ * width_); diff --git a/webrtc/test/frame_generator.cc b/webrtc/test/frame_generator.cc index 4bfb9ea01f..ed7e95a126 100644 --- a/webrtc/test/frame_generator.cc +++ b/webrtc/test/frame_generator.cc @@ -18,7 +18,6 @@ #include "webrtc/base/checks.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/system_wrappers/include/clock.h" -#include "libyuv/convert.h" namespace webrtc { namespace test { @@ -27,41 +26,35 @@ namespace { class ChromaGenerator : public FrameGenerator { public: ChromaGenerator(size_t width, size_t height) - : width_(width), height_(height), angle_(0.0) { - RTC_CHECK(width_ > 0); - RTC_CHECK(height_ > 0); - half_width_ = (width_ + 1) / 2; - y_size_ = width_ * height_; - uv_size_ = half_width_ * ((height_ + 1) / 2); + : angle_(0.0), width_(width), height_(height) { + assert(width > 0); + assert(height > 0); } VideoFrame* NextFrame() override { + frame_.CreateEmptyFrame(static_cast(width_), + static_cast(height_), + static_cast(width_), + static_cast((width_ + 1) / 2), + static_cast((width_ + 1) / 2)); angle_ += 30.0; uint8_t u = fabs(sin(angle_)) * 0xFF; uint8_t v = fabs(cos(angle_)) * 0xFF; - // Ensure stride == width. - rtc::scoped_refptr buffer(I420Buffer::Create( - static_cast(width_), static_cast(height_), - static_cast(width_), static_cast(half_width_), - static_cast(half_width_))); - - memset(buffer->MutableDataY(), 0x80, y_size_); - memset(buffer->MutableDataU(), u, uv_size_); - memset(buffer->MutableDataV(), v, uv_size_); - - frame_.reset(new VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0)); - return frame_.get(); + memset(frame_.video_frame_buffer()->MutableDataY(), 0x80, + frame_.allocated_size(kYPlane)); + memset(frame_.video_frame_buffer()->MutableDataU(), u, + frame_.allocated_size(kUPlane)); + memset(frame_.video_frame_buffer()->MutableDataV(), v, + frame_.allocated_size(kVPlane)); + return &frame_; } private: double angle_; size_t width_; size_t height_; - size_t half_width_; - size_t y_size_; - size_t uv_size_; - std::unique_ptr frame_; + VideoFrame frame_; }; class YuvFileGenerator : public FrameGenerator { @@ -96,13 +89,15 @@ class YuvFileGenerator : public FrameGenerator { if (++current_display_count_ >= frame_display_count_) current_display_count_ = 0; - temp_frame_.reset( - new VideoFrame(last_read_buffer_, 0, 0, webrtc::kVideoRotation_0)); - return temp_frame_.get(); + // If this is the last repeatition of this frame, it's OK to use the + // original instance, otherwise use a copy. + if (current_display_count_ == frame_display_count_) + return &last_read_frame_; + + temp_frame_copy_.CopyFrame(last_read_frame_); + return &temp_frame_copy_; } - // TODO(nisse): Have a frame reader in one place. And read directly - // into the planes of an I420Buffer, the extra copying below is silly. void ReadNextFrame() { size_t bytes_read = fread(frame_buffer_.get(), 1, frame_size_, files_[file_index_]); @@ -115,21 +110,14 @@ class YuvFileGenerator : public FrameGenerator { assert(bytes_read >= frame_size_); } - size_t half_width = (width_ + 1) / 2; - size_t size_y = width_ * height_; - size_t size_uv = half_width * ((height_ + 1) / 2); - last_read_buffer_ = I420Buffer::Create( + last_read_frame_.CreateEmptyFrame( static_cast(width_), static_cast(height_), - static_cast(width_), static_cast(half_width), - static_cast(half_width)); - libyuv::I420Copy( - frame_buffer_.get(), static_cast(width_), - frame_buffer_.get() + size_y, static_cast(half_width), - frame_buffer_.get() + size_y + size_uv, static_cast(half_width), - last_read_buffer_->MutableDataY(), last_read_buffer_->StrideY(), - last_read_buffer_->MutableDataU(), last_read_buffer_->StrideU(), - last_read_buffer_->MutableDataV(), last_read_buffer_->StrideV(), - static_cast(width_), static_cast(height_)); + static_cast(width_), static_cast((width_ + 1) / 2), + static_cast((width_ + 1) / 2)); + + ConvertToI420(kI420, frame_buffer_.get(), 0, 0, static_cast(width_), + static_cast(height_), 0, kVideoRotation_0, + &last_read_frame_); } private: @@ -141,8 +129,8 @@ class YuvFileGenerator : public FrameGenerator { const std::unique_ptr frame_buffer_; const int frame_display_count_; int current_display_count_; - rtc::scoped_refptr last_read_buffer_; - std::unique_ptr temp_frame_; + VideoFrame last_read_frame_; + VideoFrame temp_frame_copy_; }; class ScrollingImageFrameGenerator : public FrameGenerator { diff --git a/webrtc/test/testsupport/metrics/video_metrics.cc b/webrtc/test/testsupport/metrics/video_metrics.cc index 75bbc61fce..ee9aa340ff 100644 --- a/webrtc/test/testsupport/metrics/video_metrics.cc +++ b/webrtc/test/testsupport/metrics/video_metrics.cc @@ -18,7 +18,6 @@ #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/video_frame.h" -#include "libyuv/convert.h" namespace webrtc { namespace test { @@ -36,8 +35,8 @@ enum VideoMetricsType { kPSNR, kSSIM, kBoth }; // Calculates metrics for a frame and adds statistics to the result for it. void CalculateFrame(VideoMetricsType video_metrics_type, - const VideoFrameBuffer& ref, - const VideoFrameBuffer& test, + const VideoFrame* ref, + const VideoFrame* test, int frame_number, QualityMetricsResult* result) { FrameResult frame_result = {0, 0}; @@ -111,57 +110,37 @@ int CalculateMetrics(VideoMetricsType video_metrics_type, // Read reference and test frames. const size_t frame_length = 3 * width * height >> 1; - rtc::scoped_refptr ref_i420_buffer; - rtc::scoped_refptr test_i420_buffer; + VideoFrame ref_frame; + VideoFrame test_frame; std::unique_ptr ref_buffer(new uint8_t[frame_length]); std::unique_ptr test_buffer(new uint8_t[frame_length]); // Set decoded image parameters. int half_width = (width + 1) / 2; - ref_i420_buffer = - I420Buffer::Create(width, height, width, half_width, half_width); - test_i420_buffer = - I420Buffer::Create(width, height, width, half_width, half_width); + ref_frame.CreateEmptyFrame(width, height, width, half_width, half_width); + test_frame.CreateEmptyFrame(width, height, width, half_width, half_width); - // TODO(nisse): Have a frame reader in one place. And read directly - // into the planes of an I420Buffer, the extra copying below is silly. size_t ref_bytes = fread(ref_buffer.get(), 1, frame_length, ref_fp); size_t test_bytes = fread(test_buffer.get(), 1, frame_length, test_fp); while (ref_bytes == frame_length && test_bytes == frame_length) { // Converting from buffer to plane representation. - size_t size_y = width * height; - size_t size_uv = half_width * ((height + 1) / 2); - libyuv::I420Copy( - ref_buffer.get(), width, - ref_buffer.get() + size_y, half_width, - ref_buffer.get() + size_y + size_uv, half_width, - ref_i420_buffer->MutableDataY(), ref_i420_buffer->StrideY(), - ref_i420_buffer->MutableDataU(), ref_i420_buffer->StrideU(), - ref_i420_buffer->MutableDataV(), ref_i420_buffer->StrideV(), - width, height); - - libyuv::I420Copy( - test_buffer.get(), width, - test_buffer.get() + size_y, half_width, - test_buffer.get() + size_y + size_uv, half_width, - test_i420_buffer->MutableDataY(), test_i420_buffer->StrideY(), - test_i420_buffer->MutableDataU(), test_i420_buffer->StrideU(), - test_i420_buffer->MutableDataV(), test_i420_buffer->StrideV(), - width, height); - + ConvertToI420(kI420, ref_buffer.get(), 0, 0, width, height, 0, + kVideoRotation_0, &ref_frame); + ConvertToI420(kI420, test_buffer.get(), 0, 0, width, height, 0, + kVideoRotation_0, &test_frame); switch (video_metrics_type) { case kPSNR: - CalculateFrame(kPSNR, *ref_i420_buffer, *test_i420_buffer, frame_number, + CalculateFrame(kPSNR, &ref_frame, &test_frame, frame_number, psnr_result); break; case kSSIM: - CalculateFrame(kSSIM, *ref_i420_buffer, *test_i420_buffer, frame_number, + CalculateFrame(kSSIM, &ref_frame, &test_frame, frame_number, ssim_result); break; case kBoth: - CalculateFrame(kPSNR, *ref_i420_buffer, *test_i420_buffer, frame_number, + CalculateFrame(kPSNR, &ref_frame, &test_frame, frame_number, psnr_result); - CalculateFrame(kSSIM, *ref_i420_buffer, *test_i420_buffer, frame_number, + CalculateFrame(kSSIM, &ref_frame, &test_frame, frame_number, ssim_result); break; }