Calculate and report PSNR for Y, U, V planes separately.
Bug: webrtc:8448 Change-Id: Ia5b2b2f3ebac9ea7d1efbb3079b0bc3438a54a09 Reviewed-on: https://webrtc-review.googlesource.com/61324 Commit-Queue: Sergey Silkin <ssilkin@webrtc.org> Reviewed-by: Rasmus Brandt <brandtr@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22420}
This commit is contained in:
committed by
Commit Bot
parent
16cba5c18d
commit
8d3758e610
@ -230,6 +230,9 @@ VideoStatistics Stats::SliceAndCalcVideoStatistic(
|
||||
Statistics frame_encoding_time_us;
|
||||
Statistics frame_decoding_time_us;
|
||||
|
||||
Statistics psnr_y;
|
||||
Statistics psnr_u;
|
||||
Statistics psnr_v;
|
||||
Statistics psnr;
|
||||
Statistics ssim;
|
||||
Statistics qp;
|
||||
@ -290,6 +293,9 @@ VideoStatistics Stats::SliceAndCalcVideoStatistic(
|
||||
video_stat.width = frame_stat.decoded_width;
|
||||
video_stat.height = frame_stat.decoded_height;
|
||||
|
||||
psnr_y.AddSample(frame_stat.psnr_y);
|
||||
psnr_u.AddSample(frame_stat.psnr_u);
|
||||
psnr_v.AddSample(frame_stat.psnr_v);
|
||||
psnr.AddSample(frame_stat.psnr);
|
||||
ssim.AddSample(frame_stat.ssim);
|
||||
|
||||
@ -359,6 +365,9 @@ VideoStatistics Stats::SliceAndCalcVideoStatistic(
|
||||
video_stat.avg_delta_frame_size_bytes = delta_frame_size_bytes.Mean();
|
||||
video_stat.avg_qp = qp.Mean();
|
||||
|
||||
video_stat.avg_psnr_y = psnr_y.Mean();
|
||||
video_stat.avg_psnr_u = psnr_u.Mean();
|
||||
video_stat.avg_psnr_v = psnr_v.Mean();
|
||||
video_stat.avg_psnr = psnr.Mean();
|
||||
video_stat.min_psnr = psnr.Min();
|
||||
video_stat.avg_ssim = ssim.Mean();
|
||||
|
||||
@ -59,8 +59,11 @@ struct FrameStatistics {
|
||||
int qp = -1;
|
||||
|
||||
// Quality.
|
||||
float psnr = 0.0;
|
||||
float ssim = 0.0;
|
||||
float psnr_y = 0.0f;
|
||||
float psnr_u = 0.0f;
|
||||
float psnr_v = 0.0f;
|
||||
float psnr = 0.0f; // 10 * log10(255^2 / (mse_y + mse_u + mse_v)).
|
||||
float ssim = 0.0f; // 0.8 * ssim_y + 0.1 * (ssim_u + ssim_v).
|
||||
};
|
||||
|
||||
struct VideoStatistics {
|
||||
@ -91,6 +94,9 @@ struct VideoStatistics {
|
||||
float avg_delta_frame_size_bytes = 0.0f;
|
||||
float avg_qp = 0.0f;
|
||||
|
||||
float avg_psnr_y = 0.0f;
|
||||
float avg_psnr_u = 0.0f;
|
||||
float avg_psnr_v = 0.0f;
|
||||
float avg_psnr = 0.0f;
|
||||
float min_psnr = 0.0f;
|
||||
float avg_ssim = 0.0f;
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/timeutils.h"
|
||||
#include "test/gtest.h"
|
||||
#include "third_party/libyuv/include/libyuv/compare.h"
|
||||
#include "third_party/libyuv/include/libyuv/scale.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -115,23 +116,16 @@ void ExtractI420BufferWithSize(const VideoFrame& image,
|
||||
RTC_CHECK_NE(ExtractBuffer(image, length, buffer->data()), -1);
|
||||
}
|
||||
|
||||
void CalculateFrameQuality(const VideoFrame& ref_frame,
|
||||
const VideoFrame& dec_frame,
|
||||
void CalculateFrameQuality(const I420BufferInterface& ref_buffer,
|
||||
const I420BufferInterface& dec_buffer,
|
||||
FrameStatistics* frame_stat) {
|
||||
if (ref_frame.width() == dec_frame.width() ||
|
||||
ref_frame.height() == dec_frame.height()) {
|
||||
frame_stat->psnr = I420PSNR(&ref_frame, &dec_frame);
|
||||
frame_stat->ssim = I420SSIM(&ref_frame, &dec_frame);
|
||||
} else {
|
||||
RTC_CHECK_GE(ref_frame.width(), dec_frame.width());
|
||||
RTC_CHECK_GE(ref_frame.height(), dec_frame.height());
|
||||
// Downscale reference frame. Use bilinear interpolation since it is used
|
||||
// to get lowres inputs for encoder at simulcasting.
|
||||
// TODO(ssilkin): Sync with VP9 SVC which uses 8-taps polyphase.
|
||||
if (ref_buffer.width() != dec_buffer.width() ||
|
||||
ref_buffer.height() != dec_buffer.height()) {
|
||||
RTC_CHECK_GE(ref_buffer.width(), dec_buffer.width());
|
||||
RTC_CHECK_GE(ref_buffer.height(), dec_buffer.height());
|
||||
// Downscale reference frame.
|
||||
rtc::scoped_refptr<I420Buffer> scaled_buffer =
|
||||
I420Buffer::Create(dec_frame.width(), dec_frame.height());
|
||||
const I420BufferInterface& ref_buffer =
|
||||
*ref_frame.video_frame_buffer()->ToI420();
|
||||
I420Buffer::Create(dec_buffer.width(), dec_buffer.height());
|
||||
I420Scale(ref_buffer.DataY(), ref_buffer.StrideY(), ref_buffer.DataU(),
|
||||
ref_buffer.StrideU(), ref_buffer.DataV(), ref_buffer.StrideV(),
|
||||
ref_buffer.width(), ref_buffer.height(),
|
||||
@ -140,10 +134,31 @@ void CalculateFrameQuality(const VideoFrame& ref_frame,
|
||||
scaled_buffer->MutableDataV(), scaled_buffer->StrideV(),
|
||||
scaled_buffer->width(), scaled_buffer->height(),
|
||||
libyuv::kFilterBox);
|
||||
frame_stat->psnr =
|
||||
I420PSNR(*scaled_buffer, *dec_frame.video_frame_buffer()->ToI420());
|
||||
frame_stat->ssim =
|
||||
I420SSIM(*scaled_buffer, *dec_frame.video_frame_buffer()->ToI420());
|
||||
|
||||
CalculateFrameQuality(*scaled_buffer, dec_buffer, frame_stat);
|
||||
} else {
|
||||
const uint64_t sse_y = libyuv::ComputeSumSquareErrorPlane(
|
||||
dec_buffer.DataY(), dec_buffer.StrideY(), ref_buffer.DataY(),
|
||||
ref_buffer.StrideY(), dec_buffer.width(), dec_buffer.height());
|
||||
|
||||
const uint64_t sse_u = libyuv::ComputeSumSquareErrorPlane(
|
||||
dec_buffer.DataU(), dec_buffer.StrideU(), ref_buffer.DataU(),
|
||||
ref_buffer.StrideU(), dec_buffer.width() / 2, dec_buffer.height() / 2);
|
||||
|
||||
const uint64_t sse_v = libyuv::ComputeSumSquareErrorPlane(
|
||||
dec_buffer.DataV(), dec_buffer.StrideV(), ref_buffer.DataV(),
|
||||
ref_buffer.StrideV(), dec_buffer.width() / 2, dec_buffer.height() / 2);
|
||||
|
||||
const size_t num_y_samples = dec_buffer.width() * dec_buffer.height();
|
||||
const size_t num_u_samples =
|
||||
dec_buffer.width() / 2 * dec_buffer.height() / 2;
|
||||
|
||||
frame_stat->psnr_y = libyuv::SumSquareErrorToPsnr(sse_y, num_y_samples);
|
||||
frame_stat->psnr_u = libyuv::SumSquareErrorToPsnr(sse_u, num_u_samples);
|
||||
frame_stat->psnr_v = libyuv::SumSquareErrorToPsnr(sse_v, num_u_samples);
|
||||
frame_stat->psnr = libyuv::SumSquareErrorToPsnr(
|
||||
sse_y + sse_u + sse_v, num_y_samples + 2 * num_u_samples);
|
||||
frame_stat->ssim = I420SSIM(ref_buffer, dec_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -411,7 +426,9 @@ void VideoProcessor::FrameDecoded(const VideoFrame& decoded_frame) {
|
||||
RTC_CHECK(reference_frame != input_frames_.cend())
|
||||
<< "The codecs are either buffering too much, dropping too much, or "
|
||||
"being too slow relative the input frame rate.";
|
||||
CalculateFrameQuality(reference_frame->second, decoded_frame, frame_stat);
|
||||
CalculateFrameQuality(
|
||||
*reference_frame->second.video_frame_buffer()->ToI420(),
|
||||
*decoded_frame.video_frame_buffer()->ToI420(), frame_stat);
|
||||
}
|
||||
|
||||
// Erase all buffered input frames that we have moved past for all
|
||||
|
||||
@ -49,17 +49,20 @@ class VideoProcessorIntegrationTestLibvpx
|
||||
|
||||
void PrintRdPerf(std::map<size_t, std::vector<VideoStatistics>> rd_stats) {
|
||||
printf("--> Summary\n");
|
||||
printf("%13s %7s %7s %13s %13s %7s %13s %13s\n", "uplink_kbps", "width",
|
||||
"height", "downlink_kbps", "framerate_fps", "psnr", "enc_speed_fps",
|
||||
"dec_speed_fps");
|
||||
printf("%11s %5s %6s %13s %13s %5s %7s %7s %7s %13s %13s\n", "uplink_kbps",
|
||||
"width", "height", "downlink_kbps", "framerate_fps", "psnr",
|
||||
"psnr_y", "psnr_u", "psnr_v", "enc_speed_fps", "dec_speed_fps");
|
||||
for (const auto& rd_stat : rd_stats) {
|
||||
const size_t bitrate_kbps = rd_stat.first;
|
||||
for (const auto& layer_stat : rd_stat.second) {
|
||||
printf("%13zu %7zu %7zu %13zu %13.2f %7.2f %13.2f %13.2f\n",
|
||||
bitrate_kbps, layer_stat.width, layer_stat.height,
|
||||
layer_stat.bitrate_kbps, layer_stat.framerate_fps,
|
||||
layer_stat.avg_psnr, layer_stat.enc_speed_fps,
|
||||
layer_stat.dec_speed_fps);
|
||||
printf(
|
||||
"%11zu %5zu %6zu %13zu %13.2f %5.2f %7.2f %7.2f %7.2f %13.2f "
|
||||
"%13.2f\n",
|
||||
bitrate_kbps, layer_stat.width, layer_stat.height,
|
||||
layer_stat.bitrate_kbps, layer_stat.framerate_fps,
|
||||
layer_stat.avg_psnr, layer_stat.avg_psnr_y, layer_stat.avg_psnr_u,
|
||||
layer_stat.avg_psnr_v, layer_stat.enc_speed_fps,
|
||||
layer_stat.dec_speed_fps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user