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 |
11 #include "webrtc/test/testsupport/metrics/video_metrics.h" | 11 #include "webrtc/test/testsupport/metrics/video_metrics.h" |
12 | 12 |
13 #include <assert.h> | 13 #include <assert.h> |
14 #include <stdio.h> | 14 #include <stdio.h> |
15 | 15 |
16 #include <algorithm> // min_element, max_element | 16 #include <algorithm> // min_element, max_element |
17 #include <memory> | 17 #include <memory> |
18 | 18 |
19 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | 19 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
20 #include "webrtc/video_frame.h" | 20 #include "webrtc/video_frame.h" |
21 #include "libyuv/convert.h" | |
22 | 21 |
23 namespace webrtc { | 22 namespace webrtc { |
24 namespace test { | 23 namespace test { |
25 | 24 |
26 // Copy here so our callers won't need to include libyuv for this constant. | 25 // Copy here so our callers won't need to include libyuv for this constant. |
27 double kMetricsPerfectPSNR = kPerfectPSNR; | 26 double kMetricsPerfectPSNR = kPerfectPSNR; |
28 | 27 |
29 // Used for calculating min and max values. | 28 // Used for calculating min and max values. |
30 static bool LessForFrameResultValue(const FrameResult& s1, | 29 static bool LessForFrameResultValue(const FrameResult& s1, |
31 const FrameResult& s2) { | 30 const FrameResult& s2) { |
32 return s1.value < s2.value; | 31 return s1.value < s2.value; |
33 } | 32 } |
34 | 33 |
35 enum VideoMetricsType { kPSNR, kSSIM, kBoth }; | 34 enum VideoMetricsType { kPSNR, kSSIM, kBoth }; |
36 | 35 |
37 // Calculates metrics for a frame and adds statistics to the result for it. | 36 // Calculates metrics for a frame and adds statistics to the result for it. |
38 void CalculateFrame(VideoMetricsType video_metrics_type, | 37 void CalculateFrame(VideoMetricsType video_metrics_type, |
39 const VideoFrameBuffer& ref, | 38 const VideoFrame* ref, |
40 const VideoFrameBuffer& test, | 39 const VideoFrame* test, |
41 int frame_number, | 40 int frame_number, |
42 QualityMetricsResult* result) { | 41 QualityMetricsResult* result) { |
43 FrameResult frame_result = {0, 0}; | 42 FrameResult frame_result = {0, 0}; |
44 frame_result.frame_number = frame_number; | 43 frame_result.frame_number = frame_number; |
45 switch (video_metrics_type) { | 44 switch (video_metrics_type) { |
46 case kPSNR: | 45 case kPSNR: |
47 frame_result.value = I420PSNR(ref, test); | 46 frame_result.value = I420PSNR(ref, test); |
48 break; | 47 break; |
49 case kSSIM: | 48 case kSSIM: |
50 frame_result.value = I420SSIM(ref, test); | 49 frame_result.value = I420SSIM(ref, test); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 if (test_fp == NULL) { | 103 if (test_fp == NULL) { |
105 // Cannot open test file. | 104 // Cannot open test file. |
106 fprintf(stderr, "Cannot open file %s\n", test_filename); | 105 fprintf(stderr, "Cannot open file %s\n", test_filename); |
107 fclose(ref_fp); | 106 fclose(ref_fp); |
108 return -2; | 107 return -2; |
109 } | 108 } |
110 int frame_number = 0; | 109 int frame_number = 0; |
111 | 110 |
112 // Read reference and test frames. | 111 // Read reference and test frames. |
113 const size_t frame_length = 3 * width * height >> 1; | 112 const size_t frame_length = 3 * width * height >> 1; |
114 rtc::scoped_refptr<I420Buffer> ref_i420_buffer; | 113 VideoFrame ref_frame; |
115 rtc::scoped_refptr<I420Buffer> test_i420_buffer; | 114 VideoFrame test_frame; |
116 std::unique_ptr<uint8_t[]> ref_buffer(new uint8_t[frame_length]); | 115 std::unique_ptr<uint8_t[]> ref_buffer(new uint8_t[frame_length]); |
117 std::unique_ptr<uint8_t[]> test_buffer(new uint8_t[frame_length]); | 116 std::unique_ptr<uint8_t[]> test_buffer(new uint8_t[frame_length]); |
118 | 117 |
119 // Set decoded image parameters. | 118 // Set decoded image parameters. |
120 int half_width = (width + 1) / 2; | 119 int half_width = (width + 1) / 2; |
121 ref_i420_buffer = | 120 ref_frame.CreateEmptyFrame(width, height, width, half_width, half_width); |
122 I420Buffer::Create(width, height, width, half_width, half_width); | 121 test_frame.CreateEmptyFrame(width, height, width, half_width, half_width); |
123 test_i420_buffer = | |
124 I420Buffer::Create(width, height, width, half_width, half_width); | |
125 | 122 |
126 // TODO(nisse): Have a frame reader in one place. And read directly | |
127 // into the planes of an I420Buffer, the extra copying below is silly. | |
128 size_t ref_bytes = fread(ref_buffer.get(), 1, frame_length, ref_fp); | 123 size_t ref_bytes = fread(ref_buffer.get(), 1, frame_length, ref_fp); |
129 size_t test_bytes = fread(test_buffer.get(), 1, frame_length, test_fp); | 124 size_t test_bytes = fread(test_buffer.get(), 1, frame_length, test_fp); |
130 while (ref_bytes == frame_length && test_bytes == frame_length) { | 125 while (ref_bytes == frame_length && test_bytes == frame_length) { |
131 // Converting from buffer to plane representation. | 126 // Converting from buffer to plane representation. |
132 size_t size_y = width * height; | 127 ConvertToI420(kI420, ref_buffer.get(), 0, 0, width, height, 0, |
133 size_t size_uv = half_width * ((height + 1) / 2); | 128 kVideoRotation_0, &ref_frame); |
134 libyuv::I420Copy( | 129 ConvertToI420(kI420, test_buffer.get(), 0, 0, width, height, 0, |
135 ref_buffer.get(), width, | 130 kVideoRotation_0, &test_frame); |
136 ref_buffer.get() + size_y, half_width, | |
137 ref_buffer.get() + size_y + size_uv, half_width, | |
138 ref_i420_buffer->MutableDataY(), ref_i420_buffer->StrideY(), | |
139 ref_i420_buffer->MutableDataU(), ref_i420_buffer->StrideU(), | |
140 ref_i420_buffer->MutableDataV(), ref_i420_buffer->StrideV(), | |
141 width, height); | |
142 | |
143 libyuv::I420Copy( | |
144 test_buffer.get(), width, | |
145 test_buffer.get() + size_y, half_width, | |
146 test_buffer.get() + size_y + size_uv, half_width, | |
147 test_i420_buffer->MutableDataY(), test_i420_buffer->StrideY(), | |
148 test_i420_buffer->MutableDataU(), test_i420_buffer->StrideU(), | |
149 test_i420_buffer->MutableDataV(), test_i420_buffer->StrideV(), | |
150 width, height); | |
151 | |
152 switch (video_metrics_type) { | 131 switch (video_metrics_type) { |
153 case kPSNR: | 132 case kPSNR: |
154 CalculateFrame(kPSNR, *ref_i420_buffer, *test_i420_buffer, frame_number, | 133 CalculateFrame(kPSNR, &ref_frame, &test_frame, frame_number, |
155 psnr_result); | 134 psnr_result); |
156 break; | 135 break; |
157 case kSSIM: | 136 case kSSIM: |
158 CalculateFrame(kSSIM, *ref_i420_buffer, *test_i420_buffer, frame_number, | 137 CalculateFrame(kSSIM, &ref_frame, &test_frame, frame_number, |
159 ssim_result); | 138 ssim_result); |
160 break; | 139 break; |
161 case kBoth: | 140 case kBoth: |
162 CalculateFrame(kPSNR, *ref_i420_buffer, *test_i420_buffer, frame_number, | 141 CalculateFrame(kPSNR, &ref_frame, &test_frame, frame_number, |
163 psnr_result); | 142 psnr_result); |
164 CalculateFrame(kSSIM, *ref_i420_buffer, *test_i420_buffer, frame_number, | 143 CalculateFrame(kSSIM, &ref_frame, &test_frame, frame_number, |
165 ssim_result); | 144 ssim_result); |
166 break; | 145 break; |
167 } | 146 } |
168 frame_number++; | 147 frame_number++; |
169 ref_bytes = fread(ref_buffer.get(), 1, frame_length, ref_fp); | 148 ref_bytes = fread(ref_buffer.get(), 1, frame_length, ref_fp); |
170 test_bytes = fread(test_buffer.get(), 1, frame_length, test_fp); | 149 test_bytes = fread(test_buffer.get(), 1, frame_length, test_fp); |
171 } | 150 } |
172 int return_code = 0; | 151 int return_code = 0; |
173 if (frame_number == 0) { | 152 if (frame_number == 0) { |
174 fprintf(stderr, "Tried to measure video metrics from empty files " | 153 fprintf(stderr, "Tried to measure video metrics from empty files " |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 int width, | 190 int width, |
212 int height, | 191 int height, |
213 QualityMetricsResult* result) { | 192 QualityMetricsResult* result) { |
214 assert(result != NULL); | 193 assert(result != NULL); |
215 return CalculateMetrics(kSSIM, ref_filename, test_filename, width, height, | 194 return CalculateMetrics(kSSIM, ref_filename, test_filename, width, height, |
216 NULL, result); | 195 NULL, result); |
217 } | 196 } |
218 | 197 |
219 } // namespace test | 198 } // namespace test |
220 } // namespace webrtc | 199 } // namespace webrtc |
OLD | NEW |