mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-25 09:57:32 +09:00
Issue #2101 - Part 3: Update libyuv
Updated to version 1861, git revision 88b050f337cc0ca2a51800fe7bf4737222c87344 from https://chromium.googlesource.com/libyuv/libyuv/
This commit is contained in:
parent
42f3296899
commit
a4d1f57b9e
222 changed files with 111006 additions and 37106 deletions
|
|
@ -4,3 +4,6 @@ ifeq ($(CXX),icl)
|
|||
else
|
||||
$(CXX) -msse2 -O3 -fopenmp -static -o psnr psnr.cc ssim.cc psnr_main.cc -Wl,--strip-all
|
||||
endif
|
||||
|
||||
# for MacOS
|
||||
# /usr/local/bin/g++-7 -msse2 -O3 -fopenmp -Bstatic -o psnr psnr.cc ssim.cc psnr_main.cc
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# Copyright 2014 The LibYuv Project Authors. All rights reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
"""
|
||||
Runs tests on Android devices.
|
||||
|
||||
This script exists to avoid Libyuv being broken by changes in the Chrome Android
|
||||
test execution toolchain. It also conveniently sets the CHECKOUT_SOURCE_ROOT
|
||||
environment variable.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
SCRIPT_DIR = os.path.dirname(__file__)
|
||||
ROOT_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir, os.pardir))
|
||||
CHROMIUM_BUILD_ANDROID_DIR = os.path.join(ROOT_DIR, 'build', 'android')
|
||||
sys.path.insert(0, CHROMIUM_BUILD_ANDROID_DIR)
|
||||
|
||||
|
||||
import test_runner # pylint: disable=W0406
|
||||
|
||||
def main():
|
||||
# Override environment variable to make it possible for the scripts to find
|
||||
# the root directory (our symlinking of the Chromium build toolchain would
|
||||
# otherwise make them fail to do so).
|
||||
os.environ['CHECKOUT_SOURCE_ROOT'] = ROOT_DIR
|
||||
return test_runner.main()
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
120
media/libyuv/util/color.cc
Normal file
120
media/libyuv/util/color.cc
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright 2021 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// This utility computes values needed to generate yuvconstants based on
|
||||
// white point values.
|
||||
// The yuv formulas are tuned for 8 bit YUV channels.
|
||||
|
||||
// For those MCs that can be represented as kr and kb:
|
||||
// Full range
|
||||
// float M[3][3]
|
||||
// {{1,0,2*(1-kr)},{1,-((2*kb)/((2-kb)*(1-kb-kr))),-((2*kr)/((2-kr)*(1-kb-kr)))},{1,2*(1-kb),0}};
|
||||
// float B[3]
|
||||
// {1+(256*(1-kr))/255,1-(256*kb)/(255*(2-kb)*(1-kb-kr))-(256*kr)/(255*(2-kr)*(1-kb-kr)),1+(256*(1-kb))/255};
|
||||
// Limited range
|
||||
// float M[3][3]
|
||||
// {{85/73,0,255/112-(255*kr)/112},{85/73,-((255*kb)/(112*(2-kb)*(1-kb-kr))),-((255*kr)/(112*(2-kr)*(1-kb-kr)))},{85/73,255/112-(255*kb)/112,0}};
|
||||
// float B[3]
|
||||
// {77662/43435-(1537*kr)/1785,203/219-(1537*kb)/(1785*(2-kb)*(1-kb-kr))-(1537*kr)/(1785*(2-kr)*(1-kb-kr)),77662/43435-(1537*kb)/1785};
|
||||
|
||||
// mc bt
|
||||
// 1 bt.709 KR = 0.2126; KB = 0.0722
|
||||
// 4 fcc KR = 0.30; KB = 0.11
|
||||
// 6 bt.601 KR = 0.299; KB = 0.114
|
||||
// 7 SMPTE 240M KR = 0.212; KB = 0.087
|
||||
// 10 bt2020 KR = 0.2627; KB = 0.0593
|
||||
|
||||
// BT.709 full range YUV to RGB reference
|
||||
// R = Y + V * 1.5748
|
||||
// G = Y - U * 0.18732 - V * 0.46812
|
||||
// B = Y + U * 1.8556
|
||||
// KR = 0.2126
|
||||
// KB = 0.0722
|
||||
|
||||
// https://mymusing.co/bt601-yuv-to-rgb-conversion-color/
|
||||
|
||||
// // Y contribution to R,G,B. Scale and bias.
|
||||
// #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */
|
||||
// #define YB 32 /* 64 / 2 */
|
||||
//
|
||||
// // U and V contributions to R,G,B.
|
||||
// #define UB 113 /* round(1.77200 * 64) */
|
||||
// #define UG 22 /* round(0.34414 * 64) */
|
||||
// #define VG 46 /* round(0.71414 * 64) */
|
||||
// #define VR 90 /* round(1.40200 * 64) */
|
||||
//
|
||||
// // Bias values to round, and subtract 128 from U and V.
|
||||
// #define BB (-UB * 128 + YB)
|
||||
// #define BG (UG * 128 + VG * 128 + YB)
|
||||
// #define BR (-VR * 128 + YB)
|
||||
|
||||
int round(float v) {
|
||||
return (int)(v + 0.5);
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (argc < 2) {
|
||||
printf("color kr kb\n");
|
||||
return -1;
|
||||
}
|
||||
float kr = atof(argv[1]);
|
||||
float kb = atof(argv[2]);
|
||||
float kg = 1 - kr - kb;
|
||||
|
||||
float vr = 2 * (1 - kr);
|
||||
float ug = 2 * ((1 - kb) * kb / kg);
|
||||
float vg = 2 * ((1 - kr) * kr / kg);
|
||||
float ub = 2 * (1 - kb);
|
||||
|
||||
printf("Full range\n");
|
||||
printf("R = Y + V * %5f\n", vr);
|
||||
printf("G = Y - U * %6f - V * %6f\n", ug, vg);
|
||||
printf("B = Y + U * %5f\n", ub);
|
||||
|
||||
printf("KR = %4f; ", kr);
|
||||
printf("KB = %4f\n", kb);
|
||||
// printf("KG = %4f\n", kg);
|
||||
// #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */
|
||||
// #define YB 32 /* 64 / 2 */
|
||||
//
|
||||
// // U and V contributions to R,G,B.
|
||||
|
||||
printf("UB %-3d /* round(%f * 64) */\n", round(ub * 64), ub);
|
||||
printf("UG %-3d /* round(%f * 64) */\n", round(ug * 64), ug);
|
||||
printf("VG %-3d /* round(%f * 64) */\n", round(vg * 64), vg);
|
||||
printf("VR %-3d /* round(%f * 64) */\n", round(vr * 64), vr);
|
||||
|
||||
vr = 255.f / 224.f * 2 * (1 - kr);
|
||||
ug = 255.f / 224.f * 2 * ((1 - kb) * kb / kg);
|
||||
vg = 255.f / 224.f * 2 * ((1 - kr) * kr / kg);
|
||||
ub = 255.f / 224.f * 2 * (1 - kb);
|
||||
|
||||
printf("Limited range\n");
|
||||
printf("R = (Y - 16) * 1.164 + V * %5f\n", vr);
|
||||
printf("G = (Y - 16) * 1.164 - U * %6f - V * %6f\n", ug, vg);
|
||||
printf("B = (Y - 16) * 1.164 + U * %5f\n", ub);
|
||||
|
||||
// printf("KG = %4f\n", kg);
|
||||
// #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */
|
||||
// #define YB 32 /* 64 / 2 */
|
||||
//
|
||||
// // U and V contributions to R,G,B.
|
||||
|
||||
printf("UB %-3d /* round(%f * 64) */\n", round(ub * 64), ub);
|
||||
printf("UG %-3d /* round(%f * 64) */\n", round(ug * 64), ug);
|
||||
printf("VG %-3d /* round(%f * 64) */\n", round(vg * 64), vg);
|
||||
printf("VR %-3d /* round(%f * 64) */\n", round(vr * 64), vr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -29,20 +29,24 @@ int main(int argc, char** argv) {
|
|||
FILE* fin2 = name2 ? fopen(name2, "rb") : NULL;
|
||||
|
||||
const int kBlockSize = 32768;
|
||||
uint8 buf1[kBlockSize];
|
||||
uint8 buf2[kBlockSize];
|
||||
uint32 hash1 = 5381;
|
||||
uint32 hash2 = 5381;
|
||||
uint64 sum_square_err = 0;
|
||||
uint64 size_min = 0;
|
||||
uint8_t buf1[kBlockSize];
|
||||
uint8_t buf2[kBlockSize];
|
||||
uint32_t hash1 = 5381;
|
||||
uint32_t hash2 = 5381;
|
||||
uint64_t sum_square_err = 0;
|
||||
uint64_t size_min = 0;
|
||||
int amt1 = 0;
|
||||
int amt2 = 0;
|
||||
do {
|
||||
amt1 = static_cast<int>(fread(buf1, 1, kBlockSize, fin1));
|
||||
if (amt1 > 0) hash1 = libyuv::HashDjb2(buf1, amt1, hash1);
|
||||
if (amt1 > 0) {
|
||||
hash1 = libyuv::HashDjb2(buf1, amt1, hash1);
|
||||
}
|
||||
if (fin2) {
|
||||
amt2 = static_cast<int>(fread(buf2, 1, kBlockSize, fin2));
|
||||
if (amt2 > 0) hash2 = libyuv::HashDjb2(buf2, amt2, hash2);
|
||||
if (amt2 > 0) {
|
||||
hash2 = libyuv::HashDjb2(buf2, amt2, hash2);
|
||||
}
|
||||
int amt_min = (amt1 < amt2) ? amt1 : amt2;
|
||||
size_min += amt_min;
|
||||
sum_square_err += libyuv::ComputeSumSquareError(buf1, buf2, amt_min);
|
||||
|
|
@ -52,8 +56,8 @@ int main(int argc, char** argv) {
|
|||
printf("hash1 %x", hash1);
|
||||
if (fin2) {
|
||||
printf(", hash2 %x", hash2);
|
||||
double mse = static_cast<double>(sum_square_err) /
|
||||
static_cast<double>(size_min);
|
||||
double mse =
|
||||
static_cast<double>(sum_square_err) / static_cast<double>(size_min);
|
||||
printf(", mse %.2f", mse);
|
||||
double psnr = libyuv::SumSquareErrorToPsnr(sum_square_err, size_min);
|
||||
printf(", psnr %.2f\n", psnr);
|
||||
|
|
|
|||
|
|
@ -12,20 +12,25 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define INCLUDE_LIBYUV_COMPARE_H_
|
||||
#include "libyuv.h"
|
||||
#include "./psnr.h"
|
||||
#include "./ssim.h"
|
||||
#include "libyuv/cpu_id.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
using namespace libyuv;
|
||||
#endif
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
int cpu_flags = TestCpuFlag(-1);
|
||||
int has_arm = TestCpuFlag(kCpuHasARM);
|
||||
int has_mips = TestCpuFlag(kCpuHasMIPS);
|
||||
int has_x86 = TestCpuFlag(kCpuHasX86);
|
||||
int has_loongarch = TestCpuFlag(kCpuHasLOONGARCH);
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__) || \
|
||||
defined(_M_IX86) || defined(_M_X64)
|
||||
if (has_x86) {
|
||||
uint32 family, model, cpu_info[4];
|
||||
int family, model, cpu_info[4];
|
||||
// Vendor ID:
|
||||
// AuthenticAMD AMD processor
|
||||
// CentaurHauls Centaur processor
|
||||
|
|
@ -61,13 +66,20 @@ int main(int argc, const char* argv[]) {
|
|||
printf("Has ARM %x\n", has_arm);
|
||||
printf("Has MIPS %x\n", has_mips);
|
||||
printf("Has X86 %x\n", has_x86);
|
||||
printf("Has LOONGARCH %x\n", has_loongarch);
|
||||
if (has_arm) {
|
||||
int has_neon = TestCpuFlag(kCpuHasNEON);
|
||||
printf("Has NEON %x\n", has_neon);
|
||||
}
|
||||
if (has_mips) {
|
||||
int has_dspr2 = TestCpuFlag(kCpuHasDSPR2);
|
||||
printf("Has DSPR2 %x\n", has_dspr2);
|
||||
int has_msa = TestCpuFlag(kCpuHasMSA);
|
||||
printf("Has MSA %x\n", has_msa);
|
||||
}
|
||||
if (has_loongarch) {
|
||||
int has_lsx = TestCpuFlag(kCpuHasLSX);
|
||||
printf("Has LSX %x\n", has_lsx);
|
||||
int has_lasx = TestCpuFlag(kCpuHasLASX);
|
||||
printf("Has LASX %x\n", has_lasx);
|
||||
}
|
||||
if (has_x86) {
|
||||
int has_sse2 = TestCpuFlag(kCpuHasSSE2);
|
||||
|
|
@ -76,18 +88,34 @@ int main(int argc, const char* argv[]) {
|
|||
int has_sse42 = TestCpuFlag(kCpuHasSSE42);
|
||||
int has_avx = TestCpuFlag(kCpuHasAVX);
|
||||
int has_avx2 = TestCpuFlag(kCpuHasAVX2);
|
||||
int has_avx3 = TestCpuFlag(kCpuHasAVX3);
|
||||
int has_erms = TestCpuFlag(kCpuHasERMS);
|
||||
int has_fma3 = TestCpuFlag(kCpuHasFMA3);
|
||||
int has_f16c = TestCpuFlag(kCpuHasF16C);
|
||||
int has_gfni = TestCpuFlag(kCpuHasGFNI);
|
||||
int has_avx512bw = TestCpuFlag(kCpuHasAVX512BW);
|
||||
int has_avx512vl = TestCpuFlag(kCpuHasAVX512VL);
|
||||
int has_avx512vnni = TestCpuFlag(kCpuHasAVX512VNNI);
|
||||
int has_avx512vbmi = TestCpuFlag(kCpuHasAVX512VBMI);
|
||||
int has_avx512vbmi2 = TestCpuFlag(kCpuHasAVX512VBMI2);
|
||||
int has_avx512vbitalg = TestCpuFlag(kCpuHasAVX512VBITALG);
|
||||
int has_avx512vpopcntdq = TestCpuFlag(kCpuHasAVX512VPOPCNTDQ);
|
||||
printf("Has SSE2 %x\n", has_sse2);
|
||||
printf("Has SSSE3 %x\n", has_ssse3);
|
||||
printf("Has SSE4.1 %x\n", has_sse41);
|
||||
printf("Has SSE4.2 %x\n", has_sse42);
|
||||
printf("Has AVX %x\n", has_avx);
|
||||
printf("Has AVX2 %x\n", has_avx2);
|
||||
printf("Has AVX3 %x\n", has_avx3);
|
||||
printf("Has ERMS %x\n", has_erms);
|
||||
printf("Has FMA3 %x\n", has_fma3);
|
||||
printf("Has F16C %x\n", has_f16c);
|
||||
printf("Has GFNI %x\n", has_gfni);
|
||||
printf("Has AVX512BW %x\n", has_avx512bw);
|
||||
printf("Has AVX512VL %x\n", has_avx512vl);
|
||||
printf("Has AVX512VNNI %x\n", has_avx512vnni);
|
||||
printf("Has AVX512VBMI %x\n", has_avx512vbmi);
|
||||
printf("Has AVX512VBMI2 %x\n", has_avx512vbmi2);
|
||||
printf("Has AVX512VBITALG %x\n", has_avx512vbitalg);
|
||||
printf("Has AVX512VPOPCNTDQ %x\n", has_avx512vpopcntdq);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
28
media/libyuv/util/i444tonv12_eg.cc
Normal file
28
media/libyuv/util/i444tonv12_eg.cc
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
#include "libyuv/convert.h"
|
||||
|
||||
#include <stdio.h> // for printf
|
||||
#include <string.h> // for memset
|
||||
|
||||
int main(int, char**) {
|
||||
unsigned char src_i444[640 * 400 * 3];
|
||||
unsigned char dst_nv12[640 * 400 * 3 / 2];
|
||||
|
||||
for (size_t i = 0; i < sizeof(src_i444); ++i) {
|
||||
src_i444[i] = i & 255;
|
||||
}
|
||||
memset(dst_nv12, 0, sizeof(dst_nv12));
|
||||
libyuv::I444ToNV12(&src_i444[0], 640, // source Y
|
||||
&src_i444[640 * 400], 640, // source U
|
||||
&src_i444[640 * 400 * 2], 640, // source V
|
||||
&dst_nv12[0], 640, // dest Y
|
||||
&dst_nv12[640 * 400], 640, // dest UV
|
||||
640, 400); // width and height
|
||||
|
||||
int checksum = 0;
|
||||
for (size_t i = 0; i < sizeof(dst_nv12); ++i) {
|
||||
checksum += dst_nv12[i];
|
||||
}
|
||||
printf("checksum %x %s\n", checksum, checksum == 0x2ec0c00 ? "PASS" : "FAIL");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -21,14 +21,14 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned int uint32; // NOLINT
|
||||
typedef unsigned int uint32_t; // NOLINT
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int64 uint64;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else // COMPILER_MSVC
|
||||
#if defined(__LP64__) && !defined(__OpenBSD__) && !defined(__APPLE__)
|
||||
typedef unsigned long uint64; // NOLINT
|
||||
#else // defined(__LP64__) && !defined(__OpenBSD__) && !defined(__APPLE__)
|
||||
typedef unsigned long long uint64; // NOLINT
|
||||
typedef unsigned long uint64_t; // NOLINT
|
||||
#else // defined(__LP64__) && !defined(__OpenBSD__) && !defined(__APPLE__)
|
||||
typedef unsigned long long uint64_t; // NOLINT
|
||||
#endif // __LP64__
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
|
@ -38,86 +38,82 @@ typedef unsigned long long uint64; // NOLINT
|
|||
#if !defined(LIBYUV_DISABLE_NEON) && defined(__ARM_NEON__) && \
|
||||
!defined(__aarch64__)
|
||||
#define HAS_SUMSQUAREERROR_NEON
|
||||
static uint32 SumSquareError_NEON(const uint8* src_a,
|
||||
const uint8* src_b, int count) {
|
||||
volatile uint32 sse;
|
||||
asm volatile (
|
||||
"vmov.u8 q7, #0 \n"
|
||||
"vmov.u8 q9, #0 \n"
|
||||
"vmov.u8 q8, #0 \n"
|
||||
"vmov.u8 q10, #0 \n"
|
||||
static uint32_t SumSquareError_NEON(const uint8_t* src_a,
|
||||
const uint8_t* src_b,
|
||||
int count) {
|
||||
volatile uint32_t sse;
|
||||
asm volatile(
|
||||
"vmov.u8 q7, #0 \n"
|
||||
"vmov.u8 q9, #0 \n"
|
||||
"vmov.u8 q8, #0 \n"
|
||||
"vmov.u8 q10, #0 \n"
|
||||
|
||||
"1: \n"
|
||||
"vld1.u8 {q0}, [%0]! \n"
|
||||
"vld1.u8 {q1}, [%1]! \n"
|
||||
"vsubl.u8 q2, d0, d2 \n"
|
||||
"vsubl.u8 q3, d1, d3 \n"
|
||||
"vmlal.s16 q7, d4, d4 \n"
|
||||
"vmlal.s16 q8, d6, d6 \n"
|
||||
"vmlal.s16 q8, d5, d5 \n"
|
||||
"vmlal.s16 q10, d7, d7 \n"
|
||||
"subs %2, %2, #16 \n"
|
||||
"bhi 1b \n"
|
||||
"1: \n"
|
||||
"vld1.u8 {q0}, [%0]! \n"
|
||||
"vld1.u8 {q1}, [%1]! \n"
|
||||
"vsubl.u8 q2, d0, d2 \n"
|
||||
"vsubl.u8 q3, d1, d3 \n"
|
||||
"vmlal.s16 q7, d4, d4 \n"
|
||||
"vmlal.s16 q8, d6, d6 \n"
|
||||
"vmlal.s16 q8, d5, d5 \n"
|
||||
"vmlal.s16 q10, d7, d7 \n"
|
||||
"subs %2, %2, #16 \n"
|
||||
"bhi 1b \n"
|
||||
|
||||
"vadd.u32 q7, q7, q8 \n"
|
||||
"vadd.u32 q9, q9, q10 \n"
|
||||
"vadd.u32 q10, q7, q9 \n"
|
||||
"vpaddl.u32 q1, q10 \n"
|
||||
"vadd.u64 d0, d2, d3 \n"
|
||||
"vmov.32 %3, d0[0] \n"
|
||||
: "+r"(src_a),
|
||||
"+r"(src_b),
|
||||
"+r"(count),
|
||||
"=r"(sse)
|
||||
:
|
||||
: "memory", "cc", "q0", "q1", "q2", "q3", "q7", "q8", "q9", "q10");
|
||||
"vadd.u32 q7, q7, q8 \n"
|
||||
"vadd.u32 q9, q9, q10 \n"
|
||||
"vadd.u32 q10, q7, q9 \n"
|
||||
"vpaddl.u32 q1, q10 \n"
|
||||
"vadd.u64 d0, d2, d3 \n"
|
||||
"vmov.32 %3, d0[0] \n"
|
||||
: "+r"(src_a), "+r"(src_b), "+r"(count), "=r"(sse)
|
||||
:
|
||||
: "memory", "cc", "q0", "q1", "q2", "q3", "q7", "q8", "q9", "q10");
|
||||
return sse;
|
||||
}
|
||||
#elif !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__)
|
||||
#define HAS_SUMSQUAREERROR_NEON
|
||||
static uint32 SumSquareError_NEON(const uint8* src_a,
|
||||
const uint8* src_b, int count) {
|
||||
volatile uint32 sse;
|
||||
asm volatile (
|
||||
"eor v16.16b, v16.16b, v16.16b \n"
|
||||
"eor v18.16b, v18.16b, v18.16b \n"
|
||||
"eor v17.16b, v17.16b, v17.16b \n"
|
||||
"eor v19.16b, v19.16b, v19.16b \n"
|
||||
static uint32_t SumSquareError_NEON(const uint8_t* src_a,
|
||||
const uint8_t* src_b,
|
||||
int count) {
|
||||
volatile uint32_t sse;
|
||||
asm volatile(
|
||||
"eor v16.16b, v16.16b, v16.16b \n"
|
||||
"eor v18.16b, v18.16b, v18.16b \n"
|
||||
"eor v17.16b, v17.16b, v17.16b \n"
|
||||
"eor v19.16b, v19.16b, v19.16b \n"
|
||||
|
||||
"1: \n"
|
||||
"ld1 {v0.16b}, [%0], #16 \n"
|
||||
"ld1 {v1.16b}, [%1], #16 \n"
|
||||
"subs %w2, %w2, #16 \n"
|
||||
"usubl v2.8h, v0.8b, v1.8b \n"
|
||||
"usubl2 v3.8h, v0.16b, v1.16b \n"
|
||||
"smlal v16.4s, v2.4h, v2.4h \n"
|
||||
"smlal v17.4s, v3.4h, v3.4h \n"
|
||||
"smlal2 v18.4s, v2.8h, v2.8h \n"
|
||||
"smlal2 v19.4s, v3.8h, v3.8h \n"
|
||||
"b.gt 1b \n"
|
||||
"1: \n"
|
||||
"ld1 {v0.16b}, [%0], #16 \n"
|
||||
"ld1 {v1.16b}, [%1], #16 \n"
|
||||
"subs %w2, %w2, #16 \n"
|
||||
"usubl v2.8h, v0.8b, v1.8b \n"
|
||||
"usubl2 v3.8h, v0.16b, v1.16b \n"
|
||||
"smlal v16.4s, v2.4h, v2.4h \n"
|
||||
"smlal v17.4s, v3.4h, v3.4h \n"
|
||||
"smlal2 v18.4s, v2.8h, v2.8h \n"
|
||||
"smlal2 v19.4s, v3.8h, v3.8h \n"
|
||||
"b.gt 1b \n"
|
||||
|
||||
"add v16.4s, v16.4s, v17.4s \n"
|
||||
"add v18.4s, v18.4s, v19.4s \n"
|
||||
"add v19.4s, v16.4s, v18.4s \n"
|
||||
"addv s0, v19.4s \n"
|
||||
"fmov %w3, s0 \n"
|
||||
: "+r"(src_a),
|
||||
"+r"(src_b),
|
||||
"+r"(count),
|
||||
"=r"(sse)
|
||||
:
|
||||
: "cc", "v0", "v1", "v2", "v3", "v16", "v17", "v18", "v19");
|
||||
"add v16.4s, v16.4s, v17.4s \n"
|
||||
"add v18.4s, v18.4s, v19.4s \n"
|
||||
"add v19.4s, v16.4s, v18.4s \n"
|
||||
"addv s0, v19.4s \n"
|
||||
"fmov %w3, s0 \n"
|
||||
: "+r"(src_a), "+r"(src_b), "+r"(count), "=r"(sse)
|
||||
:
|
||||
: "cc", "v0", "v1", "v2", "v3", "v16", "v17", "v18", "v19");
|
||||
return sse;
|
||||
}
|
||||
#elif !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && defined(_MSC_VER)
|
||||
#define HAS_SUMSQUAREERROR_SSE2
|
||||
__declspec(naked)
|
||||
static uint32 SumSquareError_SSE2(const uint8* /*src_a*/,
|
||||
const uint8* /*src_b*/, int /*count*/) {
|
||||
__declspec(naked) static uint32_t SumSquareError_SSE2(const uint8_t* /*src_a*/,
|
||||
const uint8_t* /*src_b*/,
|
||||
int /*count*/) {
|
||||
__asm {
|
||||
mov eax, [esp + 4] // src_a
|
||||
mov edx, [esp + 8] // src_b
|
||||
mov ecx, [esp + 12] // count
|
||||
mov eax, [esp + 4] // src_a
|
||||
mov edx, [esp + 8] // src_b
|
||||
mov ecx, [esp + 12] // count
|
||||
pxor xmm0, xmm0
|
||||
pxor xmm5, xmm5
|
||||
sub edx, eax
|
||||
|
|
@ -150,46 +146,48 @@ static uint32 SumSquareError_SSE2(const uint8* /*src_a*/,
|
|||
}
|
||||
#elif !defined(LIBYUV_DISABLE_X86) && (defined(__x86_64__) || defined(__i386__))
|
||||
#define HAS_SUMSQUAREERROR_SSE2
|
||||
static uint32 SumSquareError_SSE2(const uint8* src_a,
|
||||
const uint8* src_b, int count) {
|
||||
uint32 sse;
|
||||
asm volatile ( // NOLINT
|
||||
"pxor %%xmm0,%%xmm0 \n"
|
||||
"pxor %%xmm5,%%xmm5 \n"
|
||||
"sub %0,%1 \n"
|
||||
static uint32_t SumSquareError_SSE2(const uint8_t* src_a,
|
||||
const uint8_t* src_b,
|
||||
int count) {
|
||||
uint32_t sse;
|
||||
asm volatile( // NOLINT
|
||||
"pxor %%xmm0,%%xmm0 \n"
|
||||
"pxor %%xmm5,%%xmm5 \n"
|
||||
"sub %0,%1 \n"
|
||||
|
||||
"1: \n"
|
||||
"movdqu (%0),%%xmm1 \n"
|
||||
"movdqu (%0,%1,1),%%xmm2 \n"
|
||||
"lea 0x10(%0),%0 \n"
|
||||
"movdqu %%xmm1,%%xmm3 \n"
|
||||
"psubusb %%xmm2,%%xmm1 \n"
|
||||
"psubusb %%xmm3,%%xmm2 \n"
|
||||
"por %%xmm2,%%xmm1 \n"
|
||||
"movdqu %%xmm1,%%xmm2 \n"
|
||||
"punpcklbw %%xmm5,%%xmm1 \n"
|
||||
"punpckhbw %%xmm5,%%xmm2 \n"
|
||||
"pmaddwd %%xmm1,%%xmm1 \n"
|
||||
"pmaddwd %%xmm2,%%xmm2 \n"
|
||||
"paddd %%xmm1,%%xmm0 \n"
|
||||
"paddd %%xmm2,%%xmm0 \n"
|
||||
"sub $0x10,%2 \n"
|
||||
"ja 1b \n"
|
||||
"1: \n"
|
||||
"movdqu (%0),%%xmm1 \n"
|
||||
"movdqu (%0,%1,1),%%xmm2 \n"
|
||||
"lea 0x10(%0),%0 \n"
|
||||
"movdqu %%xmm1,%%xmm3 \n"
|
||||
"psubusb %%xmm2,%%xmm1 \n"
|
||||
"psubusb %%xmm3,%%xmm2 \n"
|
||||
"por %%xmm2,%%xmm1 \n"
|
||||
"movdqu %%xmm1,%%xmm2 \n"
|
||||
"punpcklbw %%xmm5,%%xmm1 \n"
|
||||
"punpckhbw %%xmm5,%%xmm2 \n"
|
||||
"pmaddwd %%xmm1,%%xmm1 \n"
|
||||
"pmaddwd %%xmm2,%%xmm2 \n"
|
||||
"paddd %%xmm1,%%xmm0 \n"
|
||||
"paddd %%xmm2,%%xmm0 \n"
|
||||
"sub $0x10,%2 \n"
|
||||
"ja 1b \n"
|
||||
|
||||
"pshufd $0xee,%%xmm0,%%xmm1 \n"
|
||||
"paddd %%xmm1,%%xmm0 \n"
|
||||
"pshufd $0x1,%%xmm0,%%xmm1 \n"
|
||||
"paddd %%xmm1,%%xmm0 \n"
|
||||
"movd %%xmm0,%3 \n"
|
||||
"pshufd $0xee,%%xmm0,%%xmm1 \n"
|
||||
"paddd %%xmm1,%%xmm0 \n"
|
||||
"pshufd $0x1,%%xmm0,%%xmm1 \n"
|
||||
"paddd %%xmm1,%%xmm0 \n"
|
||||
"movd %%xmm0,%3 \n"
|
||||
|
||||
: "+r"(src_a), // %0
|
||||
"+r"(src_b), // %1
|
||||
"+r"(count), // %2
|
||||
"=g"(sse) // %3
|
||||
:
|
||||
: "memory", "cc"
|
||||
: "+r"(src_a), // %0
|
||||
"+r"(src_b), // %1
|
||||
"+r"(count), // %2
|
||||
"=g"(sse) // %3
|
||||
:
|
||||
: "memory", "cc"
|
||||
#if defined(__SSE2__)
|
||||
, "xmm0", "xmm1", "xmm2", "xmm3", "xmm5"
|
||||
,
|
||||
"xmm0", "xmm1", "xmm2", "xmm3", "xmm5"
|
||||
#endif
|
||||
); // NOLINT
|
||||
return sse;
|
||||
|
|
@ -199,20 +197,22 @@ static uint32 SumSquareError_SSE2(const uint8* src_a,
|
|||
#if defined(HAS_SUMSQUAREERROR_SSE2)
|
||||
#if (defined(__pic__) || defined(__APPLE__)) && defined(__i386__)
|
||||
static __inline void __cpuid(int cpu_info[4], int info_type) {
|
||||
asm volatile ( // NOLINT
|
||||
"mov %%ebx, %%edi \n"
|
||||
"cpuid \n"
|
||||
"xchg %%edi, %%ebx \n"
|
||||
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
||||
: "a"(info_type));
|
||||
asm volatile( // NOLINT
|
||||
"mov %%ebx, %%edi \n"
|
||||
"cpuid \n"
|
||||
"xchg %%edi, %%ebx \n"
|
||||
: "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]),
|
||||
"=d"(cpu_info[3])
|
||||
: "a"(info_type));
|
||||
}
|
||||
// For gcc/clang but not clangcl.
|
||||
#elif (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER)
|
||||
#elif !defined(_MSC_VER) && (defined(__i386__) || defined(__x86_64__))
|
||||
static __inline void __cpuid(int cpu_info[4], int info_type) {
|
||||
asm volatile ( // NOLINT
|
||||
"cpuid \n"
|
||||
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
|
||||
: "a"(info_type));
|
||||
asm volatile( // NOLINT
|
||||
"cpuid \n"
|
||||
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
|
||||
"=d"(cpu_info[3])
|
||||
: "a"(info_type));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -228,20 +228,22 @@ static int CpuHasSSE2() {
|
|||
}
|
||||
#endif // HAS_SUMSQUAREERROR_SSE2
|
||||
|
||||
static uint32 SumSquareError_C(const uint8* src_a,
|
||||
const uint8* src_b, int count) {
|
||||
uint32 sse = 0u;
|
||||
static uint32_t SumSquareError_C(const uint8_t* src_a,
|
||||
const uint8_t* src_b,
|
||||
int count) {
|
||||
uint32_t sse = 0u;
|
||||
for (int x = 0; x < count; ++x) {
|
||||
int diff = src_a[x] - src_b[x];
|
||||
sse += static_cast<uint32>(diff * diff);
|
||||
sse += static_cast<uint32_t>(diff * diff);
|
||||
}
|
||||
return sse;
|
||||
}
|
||||
|
||||
double ComputeSumSquareError(const uint8* src_a,
|
||||
const uint8* src_b, int count) {
|
||||
uint32 (*SumSquareError)(const uint8* src_a,
|
||||
const uint8* src_b, int count) = SumSquareError_C;
|
||||
double ComputeSumSquareError(const uint8_t* src_a,
|
||||
const uint8_t* src_b,
|
||||
int count) {
|
||||
uint32_t (*SumSquareError)(const uint8_t* src_a, const uint8_t* src_b,
|
||||
int count) = SumSquareError_C;
|
||||
#if defined(HAS_SUMSQUAREERROR_NEON)
|
||||
SumSquareError = SumSquareError_NEON;
|
||||
#endif
|
||||
|
|
@ -251,9 +253,9 @@ double ComputeSumSquareError(const uint8* src_a,
|
|||
}
|
||||
#endif
|
||||
const int kBlockSize = 1 << 15;
|
||||
uint64 sse = 0;
|
||||
uint64_t sse = 0;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for reduction(+: sse)
|
||||
#pragma omp parallel for reduction(+ : sse)
|
||||
#endif
|
||||
for (int i = 0; i < (count - (kBlockSize - 1)); i += kBlockSize) {
|
||||
sse += SumSquareError(src_a + i, src_b + i, kBlockSize);
|
||||
|
|
@ -278,8 +280,9 @@ double ComputeSumSquareError(const uint8* src_a,
|
|||
// Returns 128.0 (kMaxPSNR) if sse is 0 (perfect match).
|
||||
double ComputePSNR(double sse, double size) {
|
||||
const double kMINSSE = 255.0 * 255.0 * size / pow(10.0, kMaxPSNR / 10.0);
|
||||
if (sse <= kMINSSE)
|
||||
if (sse <= kMINSSE) {
|
||||
sse = kMINSSE; // Produces max PSNR of 128
|
||||
}
|
||||
return 10.0 * log10(255.0 * 255.0 * size / sse);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#if !defined(INT_TYPES_DEFINED) && !defined(UINT8_TYPE_DEFINED)
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned char uint8_t;
|
||||
#define UINT8_TYPE_DEFINED
|
||||
#endif
|
||||
|
||||
|
|
@ -31,7 +31,9 @@ static const double kMaxPSNR = 128.0;
|
|||
#if !defined(HAVE_JPEG)
|
||||
// Computer Sum of Squared Error (SSE).
|
||||
// Pass this to ComputePSNR for final result.
|
||||
double ComputeSumSquareError(const uint8* org, const uint8* rec, int size);
|
||||
double ComputeSumSquareError(const uint8_t* src_a,
|
||||
const uint8_t* src_b,
|
||||
int count);
|
||||
#endif
|
||||
|
||||
// PSNR formula: psnr = 10 * log10 (Peak Signal^2 * size / sse)
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ bool ExtractResolutionFromFilename(const char* name,
|
|||
// Isolate the .width_height. section of the filename by searching for a
|
||||
// dot or underscore followed by a digit.
|
||||
for (int i = 0; name[i]; ++i) {
|
||||
if ((name[i] == '.' || name[i] == '_') &&
|
||||
name[i + 1] >= '0' && name[i + 1] <= '9') {
|
||||
if ((name[i] == '.' || name[i] == '_') && name[i + 1] >= '0' &&
|
||||
name[i + 1] <= '9') {
|
||||
int n = sscanf(name + i + 1, "%dx%d", width_ptr, height_ptr); // NOLINT
|
||||
if (2 == n) {
|
||||
return true;
|
||||
|
|
@ -88,11 +88,11 @@ bool ExtractResolutionFromFilename(const char* name,
|
|||
return false;
|
||||
}
|
||||
fseek(file_org, 0, SEEK_END);
|
||||
size_t total_size = ftell(file_org);
|
||||
size_t total_size = ftell(file_org);
|
||||
fseek(file_org, 0, SEEK_SET);
|
||||
uint8* const ch_org = new uint8[total_size];
|
||||
uint8_t* const ch_org = new uint8_t[total_size];
|
||||
memset(ch_org, 0, total_size);
|
||||
size_t bytes_org = fread(ch_org, sizeof(uint8), total_size, file_org);
|
||||
size_t bytes_org = fread(ch_org, sizeof(uint8_t), total_size, file_org);
|
||||
fclose(file_org);
|
||||
if (bytes_org == total_size) {
|
||||
if (0 == libyuv::MJPGSize(ch_org, total_size, width_ptr, height_ptr)) {
|
||||
|
|
@ -107,11 +107,15 @@ bool ExtractResolutionFromFilename(const char* name,
|
|||
|
||||
// Scale Y channel from 16..240 to 0..255.
|
||||
// This can be useful when comparing codecs that are inconsistant about Y
|
||||
uint8 ScaleY(uint8 y) {
|
||||
uint8_t ScaleY(uint8_t y) {
|
||||
int ny = (y - 16) * 256 / 224;
|
||||
if (ny < 0) ny = 0;
|
||||
if (ny > 255) ny = 255;
|
||||
return static_cast<uint8>(ny);
|
||||
if (ny < 0) {
|
||||
ny = 0;
|
||||
}
|
||||
if (ny > 255) {
|
||||
ny = 255;
|
||||
}
|
||||
return static_cast<uint8_t>(ny);
|
||||
}
|
||||
|
||||
// MSE = Mean Square Error
|
||||
|
|
@ -119,16 +123,18 @@ double GetMSE(double sse, double size) {
|
|||
return sse / size;
|
||||
}
|
||||
|
||||
void PrintHelp(const char * program) {
|
||||
void PrintHelp(const char* program) {
|
||||
printf("%s [-options] org_seq rec_seq [rec_seq2.. etc]\n", program);
|
||||
#ifdef HAVE_JPEG
|
||||
printf("jpeg or raw YUV 420 supported.\n");
|
||||
#endif
|
||||
printf("options:\n");
|
||||
printf(" -s <width> <height> .... specify YUV size, mandatory if none of the "
|
||||
"sequences have the\n");
|
||||
printf(" resolution embedded in their filename (ie. "
|
||||
"name.1920x800_24Hz_P420.yuv)\n");
|
||||
printf(
|
||||
" -s <width> <height> .... specify YUV size, mandatory if none of the "
|
||||
"sequences have the\n");
|
||||
printf(
|
||||
" resolution embedded in their filename (ie. "
|
||||
"name.1920x800_24Hz_P420.yuv)\n");
|
||||
printf(" -psnr .................. compute PSNR (default)\n");
|
||||
printf(" -ssim .................. compute SSIM\n");
|
||||
printf(" -mse ................... compute MSE\n");
|
||||
|
|
@ -146,7 +152,9 @@ void PrintHelp(const char * program) {
|
|||
}
|
||||
|
||||
void ParseOptions(int argc, const char* argv[]) {
|
||||
if (argc <= 1) PrintHelp(argv[0]);
|
||||
if (argc <= 1) {
|
||||
PrintHelp(argv[0]);
|
||||
}
|
||||
for (int c = 1; c < argc; ++c) {
|
||||
if (!strcmp(argv[c], "-v")) {
|
||||
verbose = true;
|
||||
|
|
@ -168,16 +176,16 @@ void ParseOptions(int argc, const char* argv[]) {
|
|||
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||
PrintHelp(argv[0]);
|
||||
} else if (!strcmp(argv[c], "-s") && c + 2 < argc) {
|
||||
image_width = atoi(argv[++c]); // NOLINT
|
||||
image_height = atoi(argv[++c]); // NOLINT
|
||||
image_width = atoi(argv[++c]); // NOLINT
|
||||
image_height = atoi(argv[++c]); // NOLINT
|
||||
} else if (!strcmp(argv[c], "-skip") && c + 2 < argc) {
|
||||
num_skip_org = atoi(argv[++c]); // NOLINT
|
||||
num_skip_rec = atoi(argv[++c]); // NOLINT
|
||||
num_skip_org = atoi(argv[++c]); // NOLINT
|
||||
num_skip_rec = atoi(argv[++c]); // NOLINT
|
||||
} else if (!strcmp(argv[c], "-frames") && c + 1 < argc) {
|
||||
num_frames = atoi(argv[++c]); // NOLINT
|
||||
num_frames = atoi(argv[++c]); // NOLINT
|
||||
#ifdef _OPENMP
|
||||
} else if (!strcmp(argv[c], "-t") && c + 1 < argc) {
|
||||
num_threads = atoi(argv[++c]); // NOLINT
|
||||
num_threads = atoi(argv[++c]); // NOLINT
|
||||
#endif
|
||||
} else if (argv[c][0] == '-') {
|
||||
fprintf(stderr, "Unknown option. %s\n", argv[c]);
|
||||
|
|
@ -206,11 +214,9 @@ void ParseOptions(int argc, const char* argv[]) {
|
|||
int org_width, org_height;
|
||||
int rec_width, rec_height;
|
||||
bool org_res_avail = ExtractResolutionFromFilename(argv[fileindex_org],
|
||||
&org_width,
|
||||
&org_height);
|
||||
&org_width, &org_height);
|
||||
bool rec_res_avail = ExtractResolutionFromFilename(argv[fileindex_rec],
|
||||
&rec_width,
|
||||
&rec_height);
|
||||
&rec_width, &rec_height);
|
||||
if (org_res_avail) {
|
||||
if (rec_res_avail) {
|
||||
if ((org_width == rec_width) && (org_height == rec_height)) {
|
||||
|
|
@ -234,24 +240,28 @@ void ParseOptions(int argc, const char* argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
bool UpdateMetrics(uint8* ch_org, uint8* ch_rec,
|
||||
const int y_size, const int uv_size, const size_t total_size,
|
||||
bool UpdateMetrics(uint8_t* ch_org,
|
||||
uint8_t* ch_rec,
|
||||
const int y_size,
|
||||
const int uv_size,
|
||||
const size_t total_size,
|
||||
int number_of_frames,
|
||||
metric* cur_distortion_psnr,
|
||||
metric* distorted_frame, bool do_psnr) {
|
||||
metric* distorted_frame,
|
||||
bool compute_psnr) {
|
||||
const int uv_offset = (do_swap_uv ? uv_size : 0);
|
||||
const uint8* const u_org = ch_org + y_size + uv_offset;
|
||||
const uint8* const u_rec = ch_rec + y_size;
|
||||
const uint8* const v_org = ch_org + y_size + (uv_size - uv_offset);
|
||||
const uint8* const v_rec = ch_rec + y_size + uv_size;
|
||||
if (do_psnr) {
|
||||
const uint8_t* const u_org = ch_org + y_size + uv_offset;
|
||||
const uint8_t* const u_rec = ch_rec + y_size;
|
||||
const uint8_t* const v_org = ch_org + y_size + (uv_size - uv_offset);
|
||||
const uint8_t* const v_rec = ch_rec + y_size + uv_size;
|
||||
if (compute_psnr) {
|
||||
#ifdef HAVE_JPEG
|
||||
double y_err = static_cast<double>(
|
||||
libyuv::ComputeSumSquareError(ch_org, ch_rec, y_size));
|
||||
libyuv::ComputeSumSquareError(ch_org, ch_rec, y_size));
|
||||
double u_err = static_cast<double>(
|
||||
libyuv::ComputeSumSquareError(u_org, u_rec, uv_size));
|
||||
libyuv::ComputeSumSquareError(u_org, u_rec, uv_size));
|
||||
double v_err = static_cast<double>(
|
||||
libyuv::ComputeSumSquareError(v_org, v_rec, uv_size));
|
||||
libyuv::ComputeSumSquareError(v_org, v_rec, uv_size));
|
||||
#else
|
||||
double y_err = ComputeSumSquareError(ch_org, ch_rec, y_size);
|
||||
double u_err = ComputeSumSquareError(u_org, u_rec, uv_size);
|
||||
|
|
@ -265,17 +275,17 @@ bool UpdateMetrics(uint8* ch_org, uint8* ch_rec,
|
|||
distorted_frame->y = ComputePSNR(y_err, static_cast<double>(y_size));
|
||||
distorted_frame->u = ComputePSNR(u_err, static_cast<double>(uv_size));
|
||||
distorted_frame->v = ComputePSNR(v_err, static_cast<double>(uv_size));
|
||||
distorted_frame->all = ComputePSNR(total_err,
|
||||
static_cast<double>(total_size));
|
||||
distorted_frame->all =
|
||||
ComputePSNR(total_err, static_cast<double>(total_size));
|
||||
} else {
|
||||
distorted_frame->y = CalcSSIM(ch_org, ch_rec, image_width, image_height);
|
||||
distorted_frame->u = CalcSSIM(u_org, u_rec, (image_width + 1) / 2,
|
||||
(image_height + 1) / 2);
|
||||
distorted_frame->v = CalcSSIM(v_org, v_rec, (image_width + 1) / 2,
|
||||
(image_height + 1) / 2);
|
||||
distorted_frame->u =
|
||||
CalcSSIM(u_org, u_rec, (image_width + 1) / 2, (image_height + 1) / 2);
|
||||
distorted_frame->v =
|
||||
CalcSSIM(v_org, v_rec, (image_width + 1) / 2, (image_height + 1) / 2);
|
||||
distorted_frame->all =
|
||||
(distorted_frame->y + distorted_frame->u + distorted_frame->v)
|
||||
/ total_size;
|
||||
(distorted_frame->y + distorted_frame->u + distorted_frame->v) /
|
||||
total_size;
|
||||
distorted_frame->y /= y_size;
|
||||
distorted_frame->u /= uv_size;
|
||||
distorted_frame->v /= uv_size;
|
||||
|
|
@ -294,12 +304,15 @@ bool UpdateMetrics(uint8* ch_org, uint8* ch_rec,
|
|||
cur_distortion_psnr->all += distorted_frame->all;
|
||||
|
||||
bool ismin = false;
|
||||
if (distorted_frame->y < cur_distortion_psnr->min_y)
|
||||
if (distorted_frame->y < cur_distortion_psnr->min_y) {
|
||||
cur_distortion_psnr->min_y = distorted_frame->y;
|
||||
if (distorted_frame->u < cur_distortion_psnr->min_u)
|
||||
}
|
||||
if (distorted_frame->u < cur_distortion_psnr->min_u) {
|
||||
cur_distortion_psnr->min_u = distorted_frame->u;
|
||||
if (distorted_frame->v < cur_distortion_psnr->min_v)
|
||||
}
|
||||
if (distorted_frame->v < cur_distortion_psnr->min_v) {
|
||||
cur_distortion_psnr->min_v = distorted_frame->v;
|
||||
}
|
||||
if (distorted_frame->all < cur_distortion_psnr->min_all) {
|
||||
cur_distortion_psnr->min_all = distorted_frame->all;
|
||||
cur_distortion_psnr->min_frame = number_of_frames;
|
||||
|
|
@ -330,8 +343,8 @@ int main(int argc, const char* argv[]) {
|
|||
}
|
||||
|
||||
// Open all files to compare to
|
||||
FILE** file_rec = new FILE* [num_rec];
|
||||
memset(file_rec, 0, num_rec * sizeof(FILE*)); // NOLINT
|
||||
FILE** file_rec = new FILE*[num_rec];
|
||||
memset(file_rec, 0, num_rec * sizeof(FILE*)); // NOLINT
|
||||
for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) {
|
||||
file_rec[cur_rec] = fopen(argv[fileindex_rec + cur_rec], "rb");
|
||||
if (file_rec[cur_rec] == NULL) {
|
||||
|
|
@ -347,27 +360,28 @@ int main(int argc, const char* argv[]) {
|
|||
|
||||
const int y_size = image_width * image_height;
|
||||
const int uv_size = ((image_width + 1) / 2) * ((image_height + 1) / 2);
|
||||
const size_t total_size = y_size + 2 * uv_size; // NOLINT
|
||||
const size_t total_size = y_size + 2 * uv_size; // NOLINT
|
||||
#if defined(_MSC_VER)
|
||||
_fseeki64(file_org,
|
||||
static_cast<__int64>(num_skip_org) *
|
||||
static_cast<__int64>(total_size), SEEK_SET);
|
||||
_fseeki64(
|
||||
file_org,
|
||||
static_cast<__int64>(num_skip_org) * static_cast<__int64>(total_size),
|
||||
SEEK_SET);
|
||||
#else
|
||||
fseek(file_org, num_skip_org * total_size, SEEK_SET);
|
||||
#endif
|
||||
for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) {
|
||||
#if defined(_MSC_VER)
|
||||
_fseeki64(file_rec[cur_rec],
|
||||
static_cast<__int64>(num_skip_rec) *
|
||||
static_cast<__int64>(total_size),
|
||||
SEEK_SET);
|
||||
_fseeki64(
|
||||
file_rec[cur_rec],
|
||||
static_cast<__int64>(num_skip_rec) * static_cast<__int64>(total_size),
|
||||
SEEK_SET);
|
||||
#else
|
||||
fseek(file_rec[cur_rec], num_skip_rec * total_size, SEEK_SET);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8* const ch_org = new uint8[total_size];
|
||||
uint8* const ch_rec = new uint8[total_size];
|
||||
uint8_t* const ch_org = new uint8_t[total_size];
|
||||
uint8_t* const ch_rec = new uint8_t[total_size];
|
||||
if (ch_org == NULL || ch_rec == NULL) {
|
||||
fprintf(stderr, "No memory available\n");
|
||||
fclose(file_org);
|
||||
|
|
@ -420,29 +434,24 @@ int main(int argc, const char* argv[]) {
|
|||
}
|
||||
|
||||
int number_of_frames;
|
||||
for (number_of_frames = 0; ; ++number_of_frames) {
|
||||
if (num_frames && number_of_frames >= num_frames)
|
||||
for (number_of_frames = 0;; ++number_of_frames) {
|
||||
if (num_frames && number_of_frames >= num_frames) {
|
||||
break;
|
||||
}
|
||||
|
||||
size_t bytes_org = fread(ch_org, sizeof(uint8), total_size, file_org);
|
||||
size_t bytes_org = fread(ch_org, sizeof(uint8_t), total_size, file_org);
|
||||
if (bytes_org < total_size) {
|
||||
#ifdef HAVE_JPEG
|
||||
// Try parsing file as a jpeg.
|
||||
uint8* const ch_jpeg = new uint8[bytes_org];
|
||||
uint8_t* const ch_jpeg = new uint8_t[bytes_org];
|
||||
memcpy(ch_jpeg, ch_org, bytes_org);
|
||||
memset(ch_org, 0, total_size);
|
||||
|
||||
if (0 != libyuv::MJPGToI420(ch_jpeg, bytes_org,
|
||||
ch_org,
|
||||
image_width,
|
||||
ch_org + y_size,
|
||||
(image_width + 1) / 2,
|
||||
if (0 != libyuv::MJPGToI420(ch_jpeg, bytes_org, ch_org, image_width,
|
||||
ch_org + y_size, (image_width + 1) / 2,
|
||||
ch_org + y_size + uv_size,
|
||||
(image_width + 1) / 2,
|
||||
image_width,
|
||||
image_height,
|
||||
image_width,
|
||||
image_height)) {
|
||||
(image_width + 1) / 2, image_width,
|
||||
image_height, image_width, image_height)) {
|
||||
delete[] ch_jpeg;
|
||||
break;
|
||||
}
|
||||
|
|
@ -453,26 +462,20 @@ int main(int argc, const char* argv[]) {
|
|||
}
|
||||
|
||||
for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) {
|
||||
size_t bytes_rec = fread(ch_rec, sizeof(uint8),
|
||||
total_size, file_rec[cur_rec]);
|
||||
size_t bytes_rec =
|
||||
fread(ch_rec, sizeof(uint8_t), total_size, file_rec[cur_rec]);
|
||||
if (bytes_rec < total_size) {
|
||||
#ifdef HAVE_JPEG
|
||||
// Try parsing file as a jpeg.
|
||||
uint8* const ch_jpeg = new uint8[bytes_rec];
|
||||
uint8_t* const ch_jpeg = new uint8_t[bytes_rec];
|
||||
memcpy(ch_jpeg, ch_rec, bytes_rec);
|
||||
memset(ch_rec, 0, total_size);
|
||||
|
||||
if (0 != libyuv::MJPGToI420(ch_jpeg, bytes_rec,
|
||||
ch_rec,
|
||||
image_width,
|
||||
ch_rec + y_size,
|
||||
(image_width + 1) / 2,
|
||||
if (0 != libyuv::MJPGToI420(ch_jpeg, bytes_rec, ch_rec, image_width,
|
||||
ch_rec + y_size, (image_width + 1) / 2,
|
||||
ch_rec + y_size + uv_size,
|
||||
(image_width + 1) / 2,
|
||||
image_width,
|
||||
image_height,
|
||||
image_width,
|
||||
image_height)) {
|
||||
(image_width + 1) / 2, image_width,
|
||||
image_height, image_width, image_height)) {
|
||||
delete[] ch_jpeg;
|
||||
break;
|
||||
}
|
||||
|
|
@ -486,12 +489,10 @@ int main(int argc, const char* argv[]) {
|
|||
printf("%5d", number_of_frames);
|
||||
}
|
||||
if (do_psnr) {
|
||||
metric distorted_frame;
|
||||
metric distorted_frame = {};
|
||||
metric* cur_distortion_psnr = &distortion_psnr[cur_rec];
|
||||
bool ismin = UpdateMetrics(ch_org, ch_rec,
|
||||
y_size, uv_size, total_size,
|
||||
number_of_frames,
|
||||
cur_distortion_psnr,
|
||||
bool ismin = UpdateMetrics(ch_org, ch_rec, y_size, uv_size, total_size,
|
||||
number_of_frames, cur_distortion_psnr,
|
||||
&distorted_frame, true);
|
||||
if (verbose) {
|
||||
printf("\t%10.6f", distorted_frame.y);
|
||||
|
|
@ -502,12 +503,10 @@ int main(int argc, const char* argv[]) {
|
|||
}
|
||||
}
|
||||
if (do_ssim) {
|
||||
metric distorted_frame;
|
||||
metric distorted_frame = {};
|
||||
metric* cur_distortion_ssim = &distortion_ssim[cur_rec];
|
||||
bool ismin = UpdateMetrics(ch_org, ch_rec,
|
||||
y_size, uv_size, total_size,
|
||||
number_of_frames,
|
||||
cur_distortion_ssim,
|
||||
bool ismin = UpdateMetrics(ch_org, ch_rec, y_size, uv_size, total_size,
|
||||
number_of_frames, cur_distortion_ssim,
|
||||
&distorted_frame, false);
|
||||
if (verbose) {
|
||||
printf("\t%10.6f", distorted_frame.y);
|
||||
|
|
@ -543,24 +542,20 @@ int main(int argc, const char* argv[]) {
|
|||
}
|
||||
|
||||
if (do_psnr) {
|
||||
const double global_psnr_y = ComputePSNR(
|
||||
cur_distortion_psnr->global_y,
|
||||
static_cast<double>(y_size) * number_of_frames);
|
||||
const double global_psnr_u = ComputePSNR(
|
||||
cur_distortion_psnr->global_u,
|
||||
static_cast<double>(uv_size) * number_of_frames);
|
||||
const double global_psnr_v = ComputePSNR(
|
||||
cur_distortion_psnr->global_v,
|
||||
static_cast<double>(uv_size) * number_of_frames);
|
||||
const double global_psnr_all = ComputePSNR(
|
||||
cur_distortion_psnr->global_all,
|
||||
static_cast<double>(total_size) * number_of_frames);
|
||||
printf("Global:\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d",
|
||||
global_psnr_y,
|
||||
global_psnr_u,
|
||||
global_psnr_v,
|
||||
global_psnr_all,
|
||||
number_of_frames);
|
||||
const double global_psnr_y =
|
||||
ComputePSNR(cur_distortion_psnr->global_y,
|
||||
static_cast<double>(y_size) * number_of_frames);
|
||||
const double global_psnr_u =
|
||||
ComputePSNR(cur_distortion_psnr->global_u,
|
||||
static_cast<double>(uv_size) * number_of_frames);
|
||||
const double global_psnr_v =
|
||||
ComputePSNR(cur_distortion_psnr->global_v,
|
||||
static_cast<double>(uv_size) * number_of_frames);
|
||||
const double global_psnr_all =
|
||||
ComputePSNR(cur_distortion_psnr->global_all,
|
||||
static_cast<double>(total_size) * number_of_frames);
|
||||
printf("Global:\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", global_psnr_y,
|
||||
global_psnr_u, global_psnr_v, global_psnr_all, number_of_frames);
|
||||
if (show_name) {
|
||||
printf("\t%s", argv[fileindex_rec + cur_rec]);
|
||||
}
|
||||
|
|
@ -570,20 +565,14 @@ int main(int argc, const char* argv[]) {
|
|||
if (!quiet) {
|
||||
printf("Avg:");
|
||||
if (do_psnr) {
|
||||
printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d",
|
||||
cur_distortion_psnr->y,
|
||||
cur_distortion_psnr->u,
|
||||
cur_distortion_psnr->v,
|
||||
cur_distortion_psnr->all,
|
||||
number_of_frames);
|
||||
printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", cur_distortion_psnr->y,
|
||||
cur_distortion_psnr->u, cur_distortion_psnr->v,
|
||||
cur_distortion_psnr->all, number_of_frames);
|
||||
}
|
||||
if (do_ssim) {
|
||||
printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d",
|
||||
cur_distortion_ssim->y,
|
||||
cur_distortion_ssim->u,
|
||||
cur_distortion_ssim->v,
|
||||
cur_distortion_ssim->all,
|
||||
number_of_frames);
|
||||
printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", cur_distortion_ssim->y,
|
||||
cur_distortion_ssim->u, cur_distortion_ssim->v,
|
||||
cur_distortion_ssim->all, number_of_frames);
|
||||
}
|
||||
if (show_name) {
|
||||
printf("\t%s", argv[fileindex_rec + cur_rec]);
|
||||
|
|
@ -594,19 +583,15 @@ int main(int argc, const char* argv[]) {
|
|||
printf("Min:");
|
||||
if (do_psnr) {
|
||||
printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d",
|
||||
cur_distortion_psnr->min_y,
|
||||
cur_distortion_psnr->min_u,
|
||||
cur_distortion_psnr->min_v,
|
||||
cur_distortion_psnr->min_all,
|
||||
cur_distortion_psnr->min_frame);
|
||||
cur_distortion_psnr->min_y, cur_distortion_psnr->min_u,
|
||||
cur_distortion_psnr->min_v, cur_distortion_psnr->min_all,
|
||||
cur_distortion_psnr->min_frame);
|
||||
}
|
||||
if (do_ssim) {
|
||||
printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d",
|
||||
cur_distortion_ssim->min_y,
|
||||
cur_distortion_ssim->min_u,
|
||||
cur_distortion_ssim->min_v,
|
||||
cur_distortion_ssim->min_all,
|
||||
cur_distortion_ssim->min_frame);
|
||||
cur_distortion_ssim->min_y, cur_distortion_ssim->min_u,
|
||||
cur_distortion_ssim->min_v, cur_distortion_ssim->min_all,
|
||||
cur_distortion_ssim->min_frame);
|
||||
}
|
||||
if (show_name) {
|
||||
printf("\t%s", argv[fileindex_rec + cur_rec]);
|
||||
|
|
@ -615,20 +600,20 @@ int main(int argc, const char* argv[]) {
|
|||
}
|
||||
|
||||
if (do_mse) {
|
||||
double global_mse_y = GetMSE(cur_distortion_psnr->global_y,
|
||||
static_cast<double>(y_size) * number_of_frames);
|
||||
double global_mse_u = GetMSE(cur_distortion_psnr->global_u,
|
||||
static_cast<double>(uv_size) * number_of_frames);
|
||||
double global_mse_v = GetMSE(cur_distortion_psnr->global_v,
|
||||
static_cast<double>(uv_size) * number_of_frames);
|
||||
double global_mse_all = GetMSE(cur_distortion_psnr->global_all,
|
||||
static_cast<double>(total_size) * number_of_frames);
|
||||
printf("MSE:\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d",
|
||||
global_mse_y,
|
||||
global_mse_u,
|
||||
global_mse_v,
|
||||
global_mse_all,
|
||||
number_of_frames);
|
||||
double global_mse_y =
|
||||
GetMSE(cur_distortion_psnr->global_y,
|
||||
static_cast<double>(y_size) * number_of_frames);
|
||||
double global_mse_u =
|
||||
GetMSE(cur_distortion_psnr->global_u,
|
||||
static_cast<double>(uv_size) * number_of_frames);
|
||||
double global_mse_v =
|
||||
GetMSE(cur_distortion_psnr->global_v,
|
||||
static_cast<double>(uv_size) * number_of_frames);
|
||||
double global_mse_all =
|
||||
GetMSE(cur_distortion_psnr->global_all,
|
||||
static_cast<double>(total_size) * number_of_frames);
|
||||
printf("MSE:\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", global_mse_y,
|
||||
global_mse_u, global_mse_v, global_mse_all, number_of_frames);
|
||||
if (show_name) {
|
||||
printf("\t%s", argv[fileindex_rec + cur_rec]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned int uint32; // NOLINT
|
||||
typedef unsigned short uint16; // NOLINT
|
||||
typedef unsigned int uint32_t; // NOLINT
|
||||
typedef unsigned short uint16_t; // NOLINT
|
||||
|
||||
#if !defined(LIBYUV_DISABLE_X86) && !defined(__SSE2__) && \
|
||||
(defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)))
|
||||
(defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP >= 2)))
|
||||
#define __SSE2__
|
||||
#endif
|
||||
#if !defined(LIBYUV_DISABLE_X86) && defined(__SSE2__)
|
||||
|
|
@ -38,56 +38,69 @@ enum { KERNEL = 3, KERNEL_SIZE = 2 * KERNEL + 1 };
|
|||
// The maximum value (11 x 11) must be less than 128 to avoid sign
|
||||
// problems during the calls to _mm_mullo_epi16().
|
||||
static const int K[KERNEL_SIZE] = {
|
||||
1, 3, 7, 11, 7, 3, 1 // ~11 * exp(-0.3 * i * i)
|
||||
1, 3, 7, 11, 7, 3, 1 // ~11 * exp(-0.3 * i * i)
|
||||
};
|
||||
static const double kiW[KERNEL + 1 + 1] = {
|
||||
1. / 1089., // 1 / sum(i:0..6, j..6) K[i]*K[j]
|
||||
1. / 1089., // 1 / sum(i:0..6, j..6) K[i]*K[j]
|
||||
1. / 1056., // 1 / sum(i:0..5, j..6) K[i]*K[j]
|
||||
1. / 957., // 1 / sum(i:0..4, j..6) K[i]*K[j]
|
||||
1. / 726., // 1 / sum(i:0..3, j..6) K[i]*K[j]
|
||||
1. / 1089., // 1 / sum(i:0..6, j..6) K[i]*K[j]
|
||||
1. / 1089., // 1 / sum(i:0..6, j..6) K[i]*K[j]
|
||||
1. / 1056., // 1 / sum(i:0..5, j..6) K[i]*K[j]
|
||||
1. / 957., // 1 / sum(i:0..4, j..6) K[i]*K[j]
|
||||
1. / 726., // 1 / sum(i:0..3, j..6) K[i]*K[j]
|
||||
};
|
||||
|
||||
#if !defined(LIBYUV_DISABLE_X86) && defined(__SSE2__)
|
||||
|
||||
#define PWEIGHT(A, B) static_cast<uint16>(K[(A)] * K[(B)]) // weight product
|
||||
#define MAKE_WEIGHT(L) \
|
||||
{ { { PWEIGHT(L, 0), PWEIGHT(L, 1), PWEIGHT(L, 2), PWEIGHT(L, 3), \
|
||||
PWEIGHT(L, 4), PWEIGHT(L, 5), PWEIGHT(L, 6), 0 } } }
|
||||
#define PWEIGHT(A, B) static_cast<uint16_t>(K[(A)] * K[(B)]) // weight product
|
||||
#define MAKE_WEIGHT(L) \
|
||||
{ \
|
||||
{ \
|
||||
{ \
|
||||
PWEIGHT(L, 0) \
|
||||
, PWEIGHT(L, 1), PWEIGHT(L, 2), PWEIGHT(L, 3), PWEIGHT(L, 4), \
|
||||
PWEIGHT(L, 5), PWEIGHT(L, 6), 0 \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
// We need this union trick to be able to initialize constant static __m128i
|
||||
// values. We can't call _mm_set_epi16() for static compile-time initialization.
|
||||
static const struct {
|
||||
union {
|
||||
uint16 i16_[8];
|
||||
uint16_t i16_[8];
|
||||
__m128i m_;
|
||||
} values_;
|
||||
} W0 = MAKE_WEIGHT(0),
|
||||
W1 = MAKE_WEIGHT(1),
|
||||
W2 = MAKE_WEIGHT(2),
|
||||
} W0 = MAKE_WEIGHT(0), W1 = MAKE_WEIGHT(1), W2 = MAKE_WEIGHT(2),
|
||||
W3 = MAKE_WEIGHT(3);
|
||||
// ... the rest is symmetric.
|
||||
// ... the rest is symmetric.
|
||||
#undef MAKE_WEIGHT
|
||||
#undef PWEIGHT
|
||||
#endif
|
||||
|
||||
// Common final expression for SSIM, once the weighted sums are known.
|
||||
static double FinalizeSSIM(double iw, double xm, double ym,
|
||||
double xxm, double xym, double yym) {
|
||||
static double FinalizeSSIM(double iw,
|
||||
double xm,
|
||||
double ym,
|
||||
double xxm,
|
||||
double xym,
|
||||
double yym) {
|
||||
const double iwx = xm * iw;
|
||||
const double iwy = ym * iw;
|
||||
double sxx = xxm * iw - iwx * iwx;
|
||||
double syy = yym * iw - iwy * iwy;
|
||||
// small errors are possible, due to rounding. Clamp to zero.
|
||||
if (sxx < 0.) sxx = 0.;
|
||||
if (syy < 0.) syy = 0.;
|
||||
if (sxx < 0.) {
|
||||
sxx = 0.;
|
||||
}
|
||||
if (syy < 0.) {
|
||||
syy = 0.;
|
||||
}
|
||||
const double sxsy = sqrt(sxx * syy);
|
||||
const double sxy = xym * iw - iwx * iwy;
|
||||
static const double C11 = (0.01 * 0.01) * (255 * 255);
|
||||
static const double C22 = (0.03 * 0.03) * (255 * 255);
|
||||
static const double C33 = (0.015 * 0.015) * (255 * 255);
|
||||
const double l = (2. * iwx * iwy + C11) / (iwx * iwx + iwy * iwy + C11);
|
||||
const double c = (2. * sxsy + C22) / (sxx + syy + C22);
|
||||
const double c = (2. * sxsy + C22) / (sxx + syy + C22);
|
||||
const double s = (sxy + C33) / (sxsy + C33);
|
||||
return l * c * s;
|
||||
}
|
||||
|
|
@ -98,15 +111,22 @@ static double FinalizeSSIM(double iw, double xm, double ym,
|
|||
// Note: worst case of accumulation is a weight of 33 = 11 + 2 * (7 + 3 + 1)
|
||||
// with a diff of 255, squared. The maximum error is thus 0x4388241,
|
||||
// which fits into 32 bits integers.
|
||||
double GetSSIM(const uint8 *org, const uint8 *rec,
|
||||
int xo, int yo, int W, int H, int stride) {
|
||||
uint32 ws = 0, xm = 0, ym = 0, xxm = 0, xym = 0, yym = 0;
|
||||
double GetSSIM(const uint8_t* org,
|
||||
const uint8_t* rec,
|
||||
int xo,
|
||||
int yo,
|
||||
int W,
|
||||
int H,
|
||||
int stride) {
|
||||
uint32_t ws = 0, xm = 0, ym = 0, xxm = 0, xym = 0, yym = 0;
|
||||
org += (yo - KERNEL) * stride;
|
||||
org += (xo - KERNEL);
|
||||
rec += (yo - KERNEL) * stride;
|
||||
rec += (xo - KERNEL);
|
||||
for (int y_ = 0; y_ < KERNEL_SIZE; ++y_, org += stride, rec += stride) {
|
||||
if (((yo - KERNEL + y_) < 0) || ((yo - KERNEL + y_) >= H)) continue;
|
||||
if (((yo - KERNEL + y_) < 0) || ((yo - KERNEL + y_) >= H)) {
|
||||
continue;
|
||||
}
|
||||
const int Wy = K[y_];
|
||||
for (int x_ = 0; x_ < KERNEL_SIZE; ++x_) {
|
||||
const int Wxy = Wy * K[x_];
|
||||
|
|
@ -114,8 +134,8 @@ double GetSSIM(const uint8 *org, const uint8 *rec,
|
|||
const int org_x = org[x_];
|
||||
const int rec_x = rec[x_];
|
||||
ws += Wxy;
|
||||
xm += Wxy * org_x;
|
||||
ym += Wxy * rec_x;
|
||||
xm += Wxy * org_x;
|
||||
ym += Wxy * rec_x;
|
||||
xxm += Wxy * org_x * org_x;
|
||||
xym += Wxy * org_x * rec_x;
|
||||
yym += Wxy * rec_x * rec_x;
|
||||
|
|
@ -125,10 +145,13 @@ double GetSSIM(const uint8 *org, const uint8 *rec,
|
|||
return FinalizeSSIM(1. / ws, xm, ym, xxm, xym, yym);
|
||||
}
|
||||
|
||||
double GetSSIMFullKernel(const uint8 *org, const uint8 *rec,
|
||||
int xo, int yo, int stride,
|
||||
double GetSSIMFullKernel(const uint8_t* org,
|
||||
const uint8_t* rec,
|
||||
int xo,
|
||||
int yo,
|
||||
int stride,
|
||||
double area_weight) {
|
||||
uint32 xm = 0, ym = 0, xxm = 0, xym = 0, yym = 0;
|
||||
uint32_t xm = 0, ym = 0, xxm = 0, xym = 0, yym = 0;
|
||||
|
||||
#if defined(LIBYUV_DISABLE_X86) || !defined(__SSE2__)
|
||||
|
||||
|
|
@ -161,8 +184,8 @@ double GetSSIMFullKernel(const uint8 *org, const uint8 *rec,
|
|||
const int ll2 = rec[dy2 - x];
|
||||
const int lr2 = rec[dy2 + x];
|
||||
|
||||
xm += Wxy * (ul1 + ur1 + ll1 + lr1);
|
||||
ym += Wxy * (ul2 + ur2 + ll2 + lr2);
|
||||
xm += Wxy * (ul1 + ur1 + ll1 + lr1);
|
||||
ym += Wxy * (ul2 + ur2 + ll2 + lr2);
|
||||
xxm += Wxy * (ul1 * ul1 + ur1 * ur1 + ll1 * ll1 + lr1 * lr1);
|
||||
xym += Wxy * (ul1 * ul2 + ur1 * ur2 + ll1 * ll2 + lr1 * lr2);
|
||||
yym += Wxy * (ul2 * ul2 + ur2 * ur2 + ll2 * ll2 + lr2 * lr2);
|
||||
|
|
@ -189,8 +212,8 @@ double GetSSIMFullKernel(const uint8 *org, const uint8 *rec,
|
|||
const int l2 = rec[-y];
|
||||
const int r2 = rec[y];
|
||||
|
||||
xm += Wxy * (u1 + d1 + l1 + r1);
|
||||
ym += Wxy * (u2 + d2 + l2 + r2);
|
||||
xm += Wxy * (u1 + d1 + l1 + r1);
|
||||
ym += Wxy * (u2 + d2 + l2 + r2);
|
||||
xxm += Wxy * (u1 * u1 + d1 * d1 + l1 * l1 + r1 * r1);
|
||||
xym += Wxy * (u1 * u2 + d1 * d2 + l1 * l2 + r1 * r2);
|
||||
yym += Wxy * (u2 * u2 + d2 * d2 + l2 * l2 + r2 * r2);
|
||||
|
|
@ -201,13 +224,13 @@ double GetSSIMFullKernel(const uint8 *org, const uint8 *rec,
|
|||
const int s1 = org[0];
|
||||
const int s2 = rec[0];
|
||||
|
||||
xm += Wxy * s1;
|
||||
ym += Wxy * s2;
|
||||
xm += Wxy * s1;
|
||||
ym += Wxy * s2;
|
||||
xxm += Wxy * s1 * s1;
|
||||
xym += Wxy * s1 * s2;
|
||||
yym += Wxy * s2 * s2;
|
||||
|
||||
#else // __SSE2__
|
||||
#else // __SSE2__
|
||||
|
||||
org += (yo - KERNEL) * stride + (xo - KERNEL);
|
||||
rec += (yo - KERNEL) * stride + (xo - KERNEL);
|
||||
|
|
@ -221,29 +244,31 @@ double GetSSIMFullKernel(const uint8 *org, const uint8 *rec,
|
|||
|
||||
// Read 8 pixels at line #L, and convert to 16bit, perform weighting
|
||||
// and acccumulate.
|
||||
#define LOAD_LINE_PAIR(L, WEIGHT) do { \
|
||||
const __m128i v0 = \
|
||||
_mm_loadl_epi64(reinterpret_cast<const __m128i*>(org + (L) * stride)); \
|
||||
const __m128i v1 = \
|
||||
_mm_loadl_epi64(reinterpret_cast<const __m128i*>(rec + (L) * stride)); \
|
||||
const __m128i w0 = _mm_unpacklo_epi8(v0, zero); \
|
||||
const __m128i w1 = _mm_unpacklo_epi8(v1, zero); \
|
||||
const __m128i ww0 = _mm_mullo_epi16(w0, (WEIGHT).values_.m_); \
|
||||
const __m128i ww1 = _mm_mullo_epi16(w1, (WEIGHT).values_.m_); \
|
||||
x = _mm_add_epi32(x, _mm_unpacklo_epi16(ww0, zero)); \
|
||||
y = _mm_add_epi32(y, _mm_unpacklo_epi16(ww1, zero)); \
|
||||
x = _mm_add_epi32(x, _mm_unpackhi_epi16(ww0, zero)); \
|
||||
y = _mm_add_epi32(y, _mm_unpackhi_epi16(ww1, zero)); \
|
||||
xx = _mm_add_epi32(xx, _mm_madd_epi16(ww0, w0)); \
|
||||
xy = _mm_add_epi32(xy, _mm_madd_epi16(ww0, w1)); \
|
||||
yy = _mm_add_epi32(yy, _mm_madd_epi16(ww1, w1)); \
|
||||
} while (0)
|
||||
#define LOAD_LINE_PAIR(L, WEIGHT) \
|
||||
do { \
|
||||
const __m128i v0 = \
|
||||
_mm_loadl_epi64(reinterpret_cast<const __m128i*>(org + (L)*stride)); \
|
||||
const __m128i v1 = \
|
||||
_mm_loadl_epi64(reinterpret_cast<const __m128i*>(rec + (L)*stride)); \
|
||||
const __m128i w0 = _mm_unpacklo_epi8(v0, zero); \
|
||||
const __m128i w1 = _mm_unpacklo_epi8(v1, zero); \
|
||||
const __m128i ww0 = _mm_mullo_epi16(w0, (WEIGHT).values_.m_); \
|
||||
const __m128i ww1 = _mm_mullo_epi16(w1, (WEIGHT).values_.m_); \
|
||||
x = _mm_add_epi32(x, _mm_unpacklo_epi16(ww0, zero)); \
|
||||
y = _mm_add_epi32(y, _mm_unpacklo_epi16(ww1, zero)); \
|
||||
x = _mm_add_epi32(x, _mm_unpackhi_epi16(ww0, zero)); \
|
||||
y = _mm_add_epi32(y, _mm_unpackhi_epi16(ww1, zero)); \
|
||||
xx = _mm_add_epi32(xx, _mm_madd_epi16(ww0, w0)); \
|
||||
xy = _mm_add_epi32(xy, _mm_madd_epi16(ww0, w1)); \
|
||||
yy = _mm_add_epi32(yy, _mm_madd_epi16(ww1, w1)); \
|
||||
} while (0)
|
||||
|
||||
#define ADD_AND_STORE_FOUR_EPI32(M, OUT) do { \
|
||||
uint32 tmp[4]; \
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(tmp), (M)); \
|
||||
(OUT) = tmp[3] + tmp[2] + tmp[1] + tmp[0]; \
|
||||
} while (0)
|
||||
#define ADD_AND_STORE_FOUR_EPI32(M, OUT) \
|
||||
do { \
|
||||
uint32_t tmp[4]; \
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i*>(tmp), (M)); \
|
||||
(OUT) = tmp[3] + tmp[2] + tmp[1] + tmp[0]; \
|
||||
} while (0)
|
||||
|
||||
LOAD_LINE_PAIR(0, W0);
|
||||
LOAD_LINE_PAIR(1, W1);
|
||||
|
|
@ -266,10 +291,14 @@ double GetSSIMFullKernel(const uint8 *org, const uint8 *rec,
|
|||
return FinalizeSSIM(area_weight, xm, ym, xxm, xym, yym);
|
||||
}
|
||||
|
||||
static int start_max(int x, int y) { return (x > y) ? x : y; }
|
||||
static int start_max(int x, int y) {
|
||||
return (x > y) ? x : y;
|
||||
}
|
||||
|
||||
double CalcSSIM(const uint8 *org, const uint8 *rec,
|
||||
const int image_width, const int image_height) {
|
||||
double CalcSSIM(const uint8_t* org,
|
||||
const uint8_t* rec,
|
||||
const int image_width,
|
||||
const int image_height) {
|
||||
double SSIM = 0.;
|
||||
const int KERNEL_Y = (image_height < KERNEL) ? image_height : KERNEL;
|
||||
const int KERNEL_X = (image_width < KERNEL) ? image_width : KERNEL;
|
||||
|
|
@ -284,7 +313,7 @@ double CalcSSIM(const uint8 *org, const uint8 *rec,
|
|||
}
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for reduction(+: SSIM)
|
||||
#pragma omp parallel for reduction(+ : SSIM)
|
||||
#endif
|
||||
for (int j = KERNEL_Y; j < image_height - KERNEL_Y; ++j) {
|
||||
for (int i = 0; i < KERNEL_X; ++i) {
|
||||
|
|
@ -302,8 +331,8 @@ double CalcSSIM(const uint8 *org, const uint8 *rec,
|
|||
// NOTE: we could use similar method for the left-most pixels too.
|
||||
const int kScratchWidth = 8;
|
||||
const int kScratchStride = kScratchWidth + KERNEL + 1;
|
||||
uint8 scratch_org[KERNEL_SIZE * kScratchStride] = { 0 };
|
||||
uint8 scratch_rec[KERNEL_SIZE * kScratchStride] = { 0 };
|
||||
uint8_t scratch_org[KERNEL_SIZE * kScratchStride] = {0};
|
||||
uint8_t scratch_rec[KERNEL_SIZE * kScratchStride] = {0};
|
||||
|
||||
for (int k = 0; k < KERNEL_SIZE; ++k) {
|
||||
const int offset =
|
||||
|
|
@ -311,9 +340,9 @@ double CalcSSIM(const uint8 *org, const uint8 *rec,
|
|||
memcpy(scratch_org + k * kScratchStride, org + offset, kScratchWidth);
|
||||
memcpy(scratch_rec + k * kScratchStride, rec + offset, kScratchWidth);
|
||||
}
|
||||
for (int k = 0; k <= KERNEL_X + 1; ++k) {
|
||||
SSIM += GetSSIMFullKernel(scratch_org, scratch_rec,
|
||||
KERNEL + k, KERNEL, kScratchStride, kiW[k]);
|
||||
for (int k = 0; k <= KERNEL_X + 1; ++k) {
|
||||
SSIM += GetSSIMFullKernel(scratch_org, scratch_rec, KERNEL + k, KERNEL,
|
||||
kScratchStride, kiW[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -333,4 +362,3 @@ double CalcLSSIM(double ssim) {
|
|||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
// Get SSIM for video sequence. Assuming RAW 4:2:0 Y:Cb:Cr format
|
||||
|
||||
#ifndef UTIL_SSIM_H_ // NOLINT
|
||||
#ifndef UTIL_SSIM_H_
|
||||
#define UTIL_SSIM_H_
|
||||
|
||||
#include <math.h> // For log10()
|
||||
|
|
@ -20,12 +20,14 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#if !defined(INT_TYPES_DEFINED) && !defined(UINT8_TYPE_DEFINED)
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned char uint8_t;
|
||||
#define UINT8_TYPE_DEFINED
|
||||
#endif
|
||||
|
||||
double CalcSSIM(const uint8* org, const uint8* rec,
|
||||
const int image_width, const int image_height);
|
||||
double CalcSSIM(const uint8_t* org,
|
||||
const uint8_t* rec,
|
||||
const int image_width,
|
||||
const int image_height);
|
||||
|
||||
double CalcLSSIM(double ssim);
|
||||
|
||||
|
|
@ -33,4 +35,4 @@ double CalcLSSIM(double ssim);
|
|||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // UTIL_SSIM_H_ // NOLINT
|
||||
#endif // UTIL_SSIM_H_
|
||||
|
|
|
|||
106
media/libyuv/util/yuvconstants.c
Normal file
106
media/libyuv/util/yuvconstants.c
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright 2021 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// This utility computes values needed to generate yuvconstants based on
|
||||
// white point values.
|
||||
// The yuv formulas are tuned for 8 bit YUV channels.
|
||||
|
||||
// See Also
|
||||
// https://mymusing.co/bt601-yuv-to-rgb-conversion-color/
|
||||
|
||||
// BT.709 full range YUV to RGB reference
|
||||
// R = Y + V * 1.5748
|
||||
// G = Y - U * 0.18732 - V * 0.46812
|
||||
// B = Y + U * 1.8556
|
||||
// KR = 0.2126
|
||||
// KB = 0.0722
|
||||
|
||||
// // Y contribution to R,G,B. Scale and bias.
|
||||
// #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */
|
||||
// #define YB 32 /* 64 / 2 */
|
||||
//
|
||||
// // U and V contributions to R,G,B.
|
||||
// #define UB 113 /* round(1.77200 * 64) */
|
||||
// #define UG 22 /* round(0.34414 * 64) */
|
||||
// #define VG 46 /* round(0.71414 * 64) */
|
||||
// #define VR 90 /* round(1.40200 * 64) */
|
||||
//
|
||||
// // Bias values to round, and subtract 128 from U and V.
|
||||
// #define BB (-UB * 128 + YB)
|
||||
// #define BG (UG * 128 + VG * 128 + YB)
|
||||
// #define BR (-VR * 128 + YB)
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
if (argc < 3) {
|
||||
printf("yuvconstants [KR] [KB]\n");
|
||||
printf(" e.g. yuvconstants 0.2126 0.0722\n");
|
||||
printf(" MC BT KR KB\n");
|
||||
printf(" 1 BT.709 KR = 0.2126; KB = 0.0722\n");
|
||||
printf(" 4 FCC KR = 0.30; KB = 0.11\n");
|
||||
printf(" 6 BT.601 KR = 0.299; KB = 0.114\n");
|
||||
printf(" 7 SMPTE 240M KR = 0.212; KB = 0.087\n");
|
||||
printf(" 9 BT.2020 KR = 0.2627; KB = 0.0593\n");
|
||||
return -1;
|
||||
}
|
||||
float kr = atof(argv[1]);
|
||||
float kb = atof(argv[2]);
|
||||
float kg = 1 - kr - kb;
|
||||
|
||||
float vr = 2 * (1 - kr);
|
||||
float ug = 2 * ((1 - kb) * kb / kg);
|
||||
float vg = 2 * ((1 - kr) * kr / kg);
|
||||
float ub = 2 * (1 - kb);
|
||||
|
||||
printf("Full range\n");
|
||||
printf("R = Y + V * %5f\n", vr);
|
||||
printf("G = Y - U * %6f - V * %6f\n", ug, vg);
|
||||
printf("B = Y + U * %5f\n", ub);
|
||||
|
||||
printf("KR = %4f; ", kr);
|
||||
printf("KB = %4f\n", kb);
|
||||
// printf("KG = %4f\n", kg);
|
||||
// #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */
|
||||
// #define YB 32 /* 64 / 2 */
|
||||
//
|
||||
// // U and V contributions to R,G,B.
|
||||
|
||||
printf("UB %-3.0f /* round(%f * 64 = %8.4f) */\n", round(ub * 64), ub, ub * 64);
|
||||
printf("UG %-3.0f /* round(%f * 64 = %8.4f) */\n", round(ug * 64), ug, ug * 64);
|
||||
printf("VG %-3.0f /* round(%f * 64 = %8.4f) */\n", round(vg * 64), vg, vg * 64);
|
||||
printf("VR %-3.0f /* round(%f * 64 = %8.4f) */\n", round(vr * 64), vr, vr * 64);
|
||||
|
||||
vr = 255.f / 224.f * 2 * (1 - kr);
|
||||
ug = 255.f / 224.f * 2 * ((1 - kb) * kb / kg);
|
||||
vg = 255.f / 224.f * 2 * ((1 - kr) * kr / kg);
|
||||
ub = 255.f / 224.f * 2 * (1 - kb);
|
||||
|
||||
printf("\nLimited range\n");
|
||||
printf("R = (Y - 16) * 1.164 + V * %5f\n", vr);
|
||||
printf("G = (Y - 16) * 1.164 - U * %6f - V * %6f\n", ug, vg);
|
||||
printf("B = (Y - 16) * 1.164 + U * %5f\n", ub);
|
||||
|
||||
// printf("KG = %4f\n", kg);
|
||||
// #define YG 16320 /* round(1.000 * 64 * 256 * 256 / 257) */
|
||||
// #define YB 32 /* 64 / 2 */
|
||||
//
|
||||
// // U and V contributions to R,G,B.
|
||||
|
||||
printf("UB %-3.0f /* round(%f * 64 = %8.4f) */\n", round(ub * 64), ub, ub * 64);
|
||||
printf("UG %-3.0f /* round(%f * 64 = %8.4f) */\n", round(ug * 64), ug, ug * 64);
|
||||
printf("VG %-3.0f /* round(%f * 64 = %8.4f) */\n", round(vg * 64), vg, vg * 64);
|
||||
printf("VR %-3.0f /* round(%f * 64 = %8.4f) */\n", round(vr * 64), vr, vr * 64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
|
||||
// Convert an ARGB image to YUV.
|
||||
// Usage: convert src_argb.raw dst_yuv.raw
|
||||
// Usage: yuvconvert src_argb.raw dst_yuv.raw
|
||||
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
|
@ -29,27 +29,27 @@ bool verbose = false;
|
|||
bool attenuate = false;
|
||||
bool unattenuate = false;
|
||||
int image_width = 0, image_height = 0; // original width and height
|
||||
int dst_width = 0, dst_height = 0; // new width and height
|
||||
int dst_width = 0, dst_height = 0; // new width and height
|
||||
int fileindex_org = 0; // argv argument contains the original file name.
|
||||
int fileindex_rec = 0; // argv argument contains the reconstructed file name.
|
||||
int num_rec = 0; // Number of reconstructed images.
|
||||
int num_skip_org = 0; // Number of frames to skip in original.
|
||||
int num_frames = 0; // Number of frames to convert.
|
||||
int filter = 1; // Bilinear filter for scaling.
|
||||
int num_rec = 0; // Number of reconstructed images.
|
||||
int num_skip_org = 0; // Number of frames to skip in original.
|
||||
int num_frames = 0; // Number of frames to convert.
|
||||
int filter = 1; // Bilinear filter for scaling.
|
||||
|
||||
static __inline uint32 Abs(int32 v) {
|
||||
static __inline uint32_t Abs(int32_t v) {
|
||||
return v >= 0 ? v : -v;
|
||||
}
|
||||
|
||||
// Parse PYUV format. ie name.1920x800_24Hz_P420.yuv
|
||||
bool ExtractResolutionFromFilename(const char* name,
|
||||
int* width_ptr,
|
||||
int* height_ptr) {
|
||||
static bool ExtractResolutionFromFilename(const char* name,
|
||||
int* width_ptr,
|
||||
int* height_ptr) {
|
||||
// Isolate the .width_height. section of the filename by searching for a
|
||||
// dot or underscore followed by a digit.
|
||||
for (int i = 0; name[i]; ++i) {
|
||||
if ((name[i] == '.' || name[i] == '_') &&
|
||||
name[i + 1] >= '0' && name[i + 1] <= '9') {
|
||||
if ((name[i] == '.' || name[i] == '_') && name[i + 1] >= '0' &&
|
||||
name[i + 1] <= '9') {
|
||||
int n = sscanf(name + i + 1, "%dx%d", width_ptr, height_ptr); // NOLINT
|
||||
if (2 == n) {
|
||||
return true;
|
||||
|
|
@ -59,13 +59,14 @@ bool ExtractResolutionFromFilename(const char* name,
|
|||
return false;
|
||||
}
|
||||
|
||||
void PrintHelp(const char * program) {
|
||||
static void PrintHelp(const char* program) {
|
||||
printf("%s [-options] src_argb.raw dst_yuv.raw\n", program);
|
||||
printf(" -s <width> <height> .... specify source resolution. "
|
||||
"Optional if name contains\n"
|
||||
" resolution (ie. "
|
||||
"name.1920x800_24Hz_P420.yuv)\n"
|
||||
" Negative value mirrors.\n");
|
||||
printf(
|
||||
" -s <width> <height> .... specify source resolution. "
|
||||
"Optional if name contains\n"
|
||||
" resolution (ie. "
|
||||
"name.1920x800_24Hz_P420.yuv)\n"
|
||||
" Negative value mirrors.\n");
|
||||
printf(" -d <width> <height> .... specify destination resolution.\n");
|
||||
printf(" -f <filter> ............ 0 = point, 1 = bilinear (default).\n");
|
||||
printf(" -skip <src_argb> ....... Number of frame to skip of src_argb\n");
|
||||
|
|
@ -77,8 +78,10 @@ void PrintHelp(const char * program) {
|
|||
exit(0);
|
||||
}
|
||||
|
||||
void ParseOptions(int argc, const char* argv[]) {
|
||||
if (argc <= 1) PrintHelp(argv[0]);
|
||||
static void ParseOptions(int argc, const char* argv[]) {
|
||||
if (argc <= 1) {
|
||||
PrintHelp(argv[0]);
|
||||
}
|
||||
for (int c = 1; c < argc; ++c) {
|
||||
if (!strcmp(argv[c], "-v")) {
|
||||
verbose = true;
|
||||
|
|
@ -89,17 +92,17 @@ void ParseOptions(int argc, const char* argv[]) {
|
|||
} else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
|
||||
PrintHelp(argv[0]);
|
||||
} else if (!strcmp(argv[c], "-s") && c + 2 < argc) {
|
||||
image_width = atoi(argv[++c]); // NOLINT
|
||||
image_height = atoi(argv[++c]); // NOLINT
|
||||
image_width = atoi(argv[++c]); // NOLINT
|
||||
image_height = atoi(argv[++c]); // NOLINT
|
||||
} else if (!strcmp(argv[c], "-d") && c + 2 < argc) {
|
||||
dst_width = atoi(argv[++c]); // NOLINT
|
||||
dst_height = atoi(argv[++c]); // NOLINT
|
||||
dst_width = atoi(argv[++c]); // NOLINT
|
||||
dst_height = atoi(argv[++c]); // NOLINT
|
||||
} else if (!strcmp(argv[c], "-skip") && c + 1 < argc) {
|
||||
num_skip_org = atoi(argv[++c]); // NOLINT
|
||||
num_skip_org = atoi(argv[++c]); // NOLINT
|
||||
} else if (!strcmp(argv[c], "-frames") && c + 1 < argc) {
|
||||
num_frames = atoi(argv[++c]); // NOLINT
|
||||
num_frames = atoi(argv[++c]); // NOLINT
|
||||
} else if (!strcmp(argv[c], "-f") && c + 1 < argc) {
|
||||
filter = atoi(argv[++c]); // NOLINT
|
||||
filter = atoi(argv[++c]); // NOLINT
|
||||
} else if (argv[c][0] == '-') {
|
||||
fprintf(stderr, "Unknown option. %s\n", argv[c]);
|
||||
} else if (fileindex_org == 0) {
|
||||
|
|
@ -127,11 +130,9 @@ void ParseOptions(int argc, const char* argv[]) {
|
|||
int org_width, org_height;
|
||||
int rec_width, rec_height;
|
||||
bool org_res_avail = ExtractResolutionFromFilename(argv[fileindex_org],
|
||||
&org_width,
|
||||
&org_height);
|
||||
&org_width, &org_height);
|
||||
bool rec_res_avail = ExtractResolutionFromFilename(argv[fileindex_rec],
|
||||
&rec_width,
|
||||
&rec_height);
|
||||
&rec_width, &rec_height);
|
||||
if (image_width == 0 || image_height == 0) {
|
||||
if (org_res_avail) {
|
||||
image_width = org_width;
|
||||
|
|
@ -158,26 +159,29 @@ void ParseOptions(int argc, const char* argv[]) {
|
|||
static const int kTileX = 32;
|
||||
static const int kTileY = 32;
|
||||
|
||||
static int TileARGBScale(const uint8* src_argb, int src_stride_argb,
|
||||
int src_width, int src_height,
|
||||
uint8* dst_argb, int dst_stride_argb,
|
||||
int dst_width, int dst_height,
|
||||
static int TileARGBScale(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
int src_width,
|
||||
int src_height,
|
||||
uint8_t* dst_argb,
|
||||
int dst_stride_argb,
|
||||
int destination_width,
|
||||
int destination_height,
|
||||
libyuv::FilterMode filtering) {
|
||||
for (int y = 0; y < dst_height; y += kTileY) {
|
||||
for (int x = 0; x < dst_width; x += kTileX) {
|
||||
for (int y = 0; y < destination_height; y += kTileY) {
|
||||
for (int x = 0; x < destination_width; x += kTileX) {
|
||||
int clip_width = kTileX;
|
||||
if (x + clip_width > dst_width) {
|
||||
clip_width = dst_width - x;
|
||||
if (x + clip_width > destination_width) {
|
||||
clip_width = destination_width - x;
|
||||
}
|
||||
int clip_height = kTileY;
|
||||
if (y + clip_height > dst_height) {
|
||||
clip_height = dst_height - y;
|
||||
if (y + clip_height > destination_height) {
|
||||
clip_height = destination_height - y;
|
||||
}
|
||||
int r = libyuv::ARGBScaleClip(src_argb, src_stride_argb,
|
||||
src_width, src_height,
|
||||
dst_argb, dst_stride_argb,
|
||||
dst_width, dst_height,
|
||||
x, y, clip_width, clip_height, filtering);
|
||||
int r = libyuv::ARGBScaleClip(src_argb, src_stride_argb, src_width,
|
||||
src_height, dst_argb, dst_stride_argb,
|
||||
destination_width, destination_height, x, y,
|
||||
clip_width, clip_height, filtering);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
|
@ -197,8 +201,8 @@ int main(int argc, const char* argv[]) {
|
|||
}
|
||||
|
||||
// Open all files to convert to
|
||||
FILE** file_rec = new FILE* [num_rec];
|
||||
memset(file_rec, 0, num_rec * sizeof(FILE*)); // NOLINT
|
||||
FILE** file_rec = new FILE*[num_rec];
|
||||
memset(file_rec, 0, num_rec * sizeof(FILE*)); // NOLINT
|
||||
for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) {
|
||||
file_rec[cur_rec] = fopen(argv[fileindex_rec + cur_rec], "wb");
|
||||
if (file_rec[cur_rec] == NULL) {
|
||||
|
|
@ -222,8 +226,8 @@ int main(int argc, const char* argv[]) {
|
|||
// Input is YUV
|
||||
if (org_is_yuv) {
|
||||
const int y_size = Abs(image_width) * Abs(image_height);
|
||||
const int uv_size = ((Abs(image_width) + 1) / 2) *
|
||||
((Abs(image_height) + 1) / 2);
|
||||
const int uv_size =
|
||||
((Abs(image_width) + 1) / 2) * ((Abs(image_height) + 1) / 2);
|
||||
org_size = y_size + 2 * uv_size; // YUV original.
|
||||
}
|
||||
|
||||
|
|
@ -233,15 +237,15 @@ int main(int argc, const char* argv[]) {
|
|||
const size_t total_size = y_size + 2 * uv_size;
|
||||
#if defined(_MSC_VER)
|
||||
_fseeki64(file_org,
|
||||
static_cast<__int64>(num_skip_org) *
|
||||
static_cast<__int64>(org_size), SEEK_SET);
|
||||
static_cast<__int64>(num_skip_org) * static_cast<__int64>(org_size),
|
||||
SEEK_SET);
|
||||
#else
|
||||
fseek(file_org, num_skip_org * total_size, SEEK_SET);
|
||||
#endif
|
||||
|
||||
uint8* const ch_org = new uint8[org_size];
|
||||
uint8* const ch_dst = new uint8[dst_size];
|
||||
uint8* const ch_rec = new uint8[total_size];
|
||||
uint8_t* const ch_org = new uint8_t[org_size];
|
||||
uint8_t* const ch_dst = new uint8_t[dst_size];
|
||||
uint8_t* const ch_rec = new uint8_t[total_size];
|
||||
if (ch_org == NULL || ch_rec == NULL) {
|
||||
fprintf(stderr, "No memory available\n");
|
||||
fclose(file_org);
|
||||
|
|
@ -256,20 +260,22 @@ int main(int argc, const char* argv[]) {
|
|||
}
|
||||
|
||||
if (verbose) {
|
||||
printf("Size: %dx%d to %dx%d\n", image_width, image_height,
|
||||
dst_width, dst_height);
|
||||
printf("Size: %dx%d to %dx%d\n", image_width, image_height, dst_width,
|
||||
dst_height);
|
||||
}
|
||||
|
||||
int number_of_frames;
|
||||
for (number_of_frames = 0; ; ++number_of_frames) {
|
||||
if (num_frames && number_of_frames >= num_frames)
|
||||
for (number_of_frames = 0;; ++number_of_frames) {
|
||||
if (num_frames && number_of_frames >= num_frames) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Load original YUV or ARGB frame.
|
||||
size_t bytes_org = fread(ch_org, sizeof(uint8),
|
||||
static_cast<size_t>(org_size), file_org);
|
||||
if (bytes_org < static_cast<size_t>(org_size))
|
||||
size_t bytes_org =
|
||||
fread(ch_org, sizeof(uint8_t), static_cast<size_t>(org_size), file_org);
|
||||
if (bytes_org < static_cast<size_t>(org_size)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO(fbarchard): Attenuate doesnt need to know dimensions.
|
||||
// ARGB attenuate frame
|
||||
|
|
@ -290,22 +296,17 @@ int main(int argc, const char* argv[]) {
|
|||
int half_src_height = (src_height + 1) / 2;
|
||||
int half_dst_width = (dst_width + 1) / 2;
|
||||
int half_dst_height = (dst_height + 1) / 2;
|
||||
I420Scale(ch_org, src_width,
|
||||
ch_org + src_width * src_height, half_src_width,
|
||||
ch_org + src_width * src_height +
|
||||
half_src_width * half_src_height, half_src_width,
|
||||
image_width, image_height,
|
||||
ch_rec, dst_width,
|
||||
ch_rec + dst_width * dst_height, half_dst_width,
|
||||
ch_rec + dst_width * dst_height +
|
||||
half_dst_width * half_dst_height, half_dst_width,
|
||||
dst_width, dst_height,
|
||||
static_cast<libyuv::FilterMode>(filter));
|
||||
I420Scale(
|
||||
ch_org, src_width, ch_org + src_width * src_height, half_src_width,
|
||||
ch_org + src_width * src_height + half_src_width * half_src_height,
|
||||
half_src_width, image_width, image_height, ch_rec, dst_width,
|
||||
ch_rec + dst_width * dst_height, half_dst_width,
|
||||
ch_rec + dst_width * dst_height + half_dst_width * half_dst_height,
|
||||
half_dst_width, dst_width, dst_height,
|
||||
static_cast<libyuv::FilterMode>(filter));
|
||||
} else {
|
||||
TileARGBScale(ch_org, Abs(image_width) * 4,
|
||||
image_width, image_height,
|
||||
ch_dst, dst_width * 4,
|
||||
dst_width, dst_height,
|
||||
TileARGBScale(ch_org, Abs(image_width) * 4, image_width, image_height,
|
||||
ch_dst, dst_width * 4, dst_width, dst_height,
|
||||
static_cast<libyuv::FilterMode>(filter));
|
||||
}
|
||||
bool rec_is_yuv = strstr(argv[fileindex_rec + cur_rec], "_P420.") != NULL;
|
||||
|
|
@ -321,27 +322,28 @@ int main(int argc, const char* argv[]) {
|
|||
if (!org_is_yuv && rec_is_yuv) {
|
||||
int half_width = (dst_width + 1) / 2;
|
||||
int half_height = (dst_height + 1) / 2;
|
||||
libyuv::ARGBToI420(ch_dst, dst_width * 4,
|
||||
ch_rec, dst_width,
|
||||
ch_rec + dst_width * dst_height, half_width,
|
||||
ch_rec + dst_width * dst_height +
|
||||
half_width * half_height, half_width,
|
||||
dst_width, dst_height);
|
||||
libyuv::ARGBToI420(
|
||||
ch_dst, dst_width * 4, ch_rec, dst_width,
|
||||
ch_rec + dst_width * dst_height, half_width,
|
||||
ch_rec + dst_width * dst_height + half_width * half_height,
|
||||
half_width, dst_width, dst_height);
|
||||
}
|
||||
|
||||
// Output YUV or ARGB frame.
|
||||
if (rec_is_yuv) {
|
||||
size_t bytes_rec = fwrite(ch_rec, sizeof(uint8),
|
||||
static_cast<size_t>(total_size),
|
||||
file_rec[cur_rec]);
|
||||
if (bytes_rec < static_cast<size_t>(total_size))
|
||||
size_t bytes_rec =
|
||||
fwrite(ch_rec, sizeof(uint8_t), static_cast<size_t>(total_size),
|
||||
file_rec[cur_rec]);
|
||||
if (bytes_rec < static_cast<size_t>(total_size)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
size_t bytes_rec = fwrite(ch_dst, sizeof(uint8),
|
||||
static_cast<size_t>(dst_size),
|
||||
file_rec[cur_rec]);
|
||||
if (bytes_rec < static_cast<size_t>(dst_size))
|
||||
size_t bytes_rec =
|
||||
fwrite(ch_dst, sizeof(uint8_t), static_cast<size_t>(dst_size),
|
||||
file_rec[cur_rec]);
|
||||
if (bytes_rec < static_cast<size_t>(dst_size)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (verbose) {
|
||||
printf("%5d", number_of_frames);
|
||||
Loading…
Add table
Add a link
Reference in a new issue