Commit aed1cc94 authored by mikhal@webrtc.org's avatar mikhal@webrtc.org

first draft


git-svn-id: http://libyuv.googlecode.com/svn/trunk@2 16f28f9a-4ce2-e073-06de-1de4eb20be90
parent 81a7628e
/*
* Copyright (c) 2011 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.
*/
#ifndef LIBYUV_COMMON_BASIC_TYPES_H_
#define LIBYUV_COMMON_BASIC_TYPES_H_
#include <stddef.h> // for NULL, size_t
#ifndef WIN32
#include <stdint.h> // for uintptr_t
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "constructor_magic.h"
#ifndef INT_TYPES_DEFINED
#define INT_TYPES_DEFINED
#ifdef COMPILER_MSVC
typedef __int64 int64;
#else
typedef long long int64;
#endif /* COMPILER_MSVC */
typedef int int32;
typedef short int16;
typedef char int8;
#ifdef COMPILER_MSVC
typedef unsigned __int64 uint64;
typedef __int64 int64;
#ifndef INT64_C
#define INT64_C(x) x ## I64
#endif
#ifndef UINT64_C
#define UINT64_C(x) x ## UI64
#endif
#define INT64_F "I64"
#else
typedef unsigned long long uint64;
typedef long long int64;
#ifndef INT64_C
#define INT64_C(x) x ## LL
#endif
#ifndef UINT64_C
#define UINT64_C(x) x ## ULL
#endif
#define INT64_F "ll"
#endif /* COMPILER_MSVC */
typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
#endif // INT_TYPES_DEFINED
#ifdef WIN32
typedef int socklen_t;
#endif
namespace libyuv {
template<class T> inline T _min(T a, T b) { return (a > b) ? b : a; }
template<class T> inline T _max(T a, T b) { return (a < b) ? b : a; }
// For wait functions that take a number of milliseconds, kForever indicates
// unlimited time.
const int kForever = -1;
}
// Detect compiler is for x86 or x64.
#if defined(__x86_64__) || defined(_M_X64) || \
defined(__i386__) || defined(_M_IX86)
#define CPU_X86 1
#endif
#ifdef WIN32
#define alignof(t) __alignof(t)
#else // !WIN32
#define alignof(t) __alignof__(t)
#endif // !WIN32
#define IS_ALIGNED(p, a) (0==(reinterpret_cast<uintptr_t>(p) & ((a)-1)))
#define ALIGNP(p, t) \
(reinterpret_cast<uint8*>(((reinterpret_cast<uintptr_t>(p) + \
((t)-1)) & ~((t)-1))))
#ifndef UNUSED
#define UNUSED(x) Unused(static_cast<const void *>(&x))
#define UNUSED2(x,y) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y))
#define UNUSED3(x,y,z) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y)); Unused(static_cast<const void *>(&z))
#define UNUSED4(x,y,z,a) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y)); Unused(static_cast<const void *>(&z)); Unused(static_cast<const void *>(&a))
#define UNUSED5(x,y,z,a,b) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y)); Unused(static_cast<const void *>(&z)); Unused(static_cast<const void *>(&a)); Unused(static_cast<const void *>(&b))
inline void Unused(const void *) { }
#endif // UNUSED
#if defined(__GNUC__)
#define GCC_ATTR(x) __attribute__ ((x))
#else // !__GNUC__
#define GCC_ATTR(x)
#endif // !__GNUC__
#endif // LIBYUV_COMMON_BASIC_TYPES_H_
/*
* Copyright (c) 2011 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.
*/
#ifndef LIBYUV_SOURCE_COMMON_H_
#define LIBYUV_SOURCE_COMMON_H_
#include "constructor_magic.h"
#if defined(_MSC_VER)
// warning C4355: 'this' : used in base member initializer list
#pragma warning(disable:4355)
#endif
//////////////////////////////////////////////////////////////////////
// General Utilities
//////////////////////////////////////////////////////////////////////
#ifndef UNUSED
#define UNUSED(x) Unused(static_cast<const void *>(&x))
#define UNUSED2(x,y) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y))
#define UNUSED3(x,y,z) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y)); Unused(static_cast<const void *>(&z))
#define UNUSED4(x,y,z,a) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y)); Unused(static_cast<const void *>(&z)); Unused(static_cast<const void *>(&a))
#define UNUSED5(x,y,z,a,b) Unused(static_cast<const void *>(&x)); Unused(static_cast<const void *>(&y)); Unused(static_cast<const void *>(&z)); Unused(static_cast<const void *>(&a)); Unused(static_cast<const void *>(&b))
inline void Unused(const void *) { }
#endif // UNUSED
#ifndef WIN32
#define strnicmp(x,y,n) strncasecmp(x,y,n)
#define stricmp(x,y) strcasecmp(x,y)
// TODO(sergeyu): Remove this. std::max should be used everywhere in the code.
// NOMINMAX must be defined where we include <windows.h>.
#define stdmax(x,y) std::max(x,y)
#else
#define stdmax(x,y) libyuv::_max(x,y)
#endif
#define ARRAY_SIZE(x) (static_cast<int>((sizeof(x)/sizeof(x[0]))))
/////////////////////////////////////////////////////////////////////////////
// Assertions
/////////////////////////////////////////////////////////////////////////////
#ifndef ENABLE_DEBUG
#define ENABLE_DEBUG _DEBUG
#endif // !defined(ENABLE_DEBUG)
#if ENABLE_DEBUG
namespace libyuv {
// Break causes the debugger to stop executing, or the program to abort
void Break();
// LogAssert writes information about an assertion to the log
void LogAssert(const char * function, const char * file, int line,
const char * expression);
inline bool Assert(bool result, const char * function, const char * file,
int line, const char * expression) {
if (!result) {
LogAssert(function, file, line, expression);
Break();
return false;
}
return true;
}
} // namespace libyuv
#if defined(_MSC_VER) && _MSC_VER < 1300
#define __FUNCTION__ ""
#endif
#ifndef ASSERT
#define ASSERT(x) (void)libyuv::Assert((x),__FUNCTION__,__FILE__,__LINE__,#x)
#endif
#ifndef VERIFY
#define VERIFY(x) libyuv::Assert((x),__FUNCTION__,__FILE__,__LINE__,#x)
#endif
#else // !ENABLE_DEBUG
namespace libyuv {
inline bool libyuv(bool result) { return result; }
} // namespace libyuv
#ifndef ASSERT
#define ASSERT(x) (void)0
#endif
#ifndef VERIFY
#define VERIFY(x) libyuv::ImplicitCastToBool(x)
#endif
#endif // !ENABLE_DEBUG
#define COMPILE_TIME_ASSERT(expr) char CTA_UNIQUE_NAME[expr]
#define CTA_UNIQUE_NAME CTA_MAKE_NAME(__LINE__)
#define CTA_MAKE_NAME(line) CTA_MAKE_NAME2(line)
#define CTA_MAKE_NAME2(line) constraint_ ## line
#ifdef __GNUC__
// Forces compiler to inline, even against its better judgement. Use wisely.
#define FORCE_INLINE __attribute__((always_inline))
#else
#define FORCE_INLINE
#endif
#endif // LIBYUV_SOURCE_COMMON_H_
/*
* Copyright (c) 2011 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.
*/
#ifndef LIBYUV_COMMON_CONSTRUCTOR_MAGIC_H_
#define LIBYUV_COMMON_CONSTRUCTOR_MAGIC_H_
#define DISALLOW_ASSIGN(TypeName) \
void operator=(const TypeName&)
// A macro to disallow the evil copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
DISALLOW_ASSIGN(TypeName)
// Alternative, less-accurate legacy name.
#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
DISALLOW_COPY_AND_ASSIGN(TypeName)
// A macro to disallow all the implicit constructors, namely the
// default constructor, copy constructor and operator= functions.
//
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName(); \
DISALLOW_EVIL_CONSTRUCTORS(TypeName)
#endif // LIBYUV_COMMON_CONSTRUCTOR_MAGIC_H_
/*
* Copyright (c) 2011 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.
*/
#ifndef LIBYUV_INCLUDE_CONVERT_H_
#define LIBYUV_INCLUDE_CONVERT_H_
#include "basic_types.h"
namespace libyuv
{
int
ConvertI420ToRGB24(const uint8* src_yplane, int src_ystride,
const uint8* src_uplane, int src_ustride,
const uint8* src_vplane, int src_vstride,
uint8* dst_frame, int dst_stride,
int src_width,
int src_height
);
int
ConvertI420ToARGB(const uint8* src_yplane, int src_ystride,
const uint8* src_uplane, int src_ustride,
const uint8* src_vplane, int src_vstride,
uint8* dst_frame, int dst_stride,
int src_width,
int src_height
);
int
ConvertI420ToARGB4444(const uint8* src_yplane, int src_ystride,
const uint8* src_uplane, int src_ustride,
const uint8* src_vplane, int src_vstride,
uint8* dst_frame, int dst_stride,
int src_width,
int src_height
);
int
ConvertI420ToRGB565(const uint8* src_yplane, int src_ystride,
const uint8* src_uplane, int src_ustride,
const uint8* src_vplane, int src_vstride,
uint8* dst_frame, int dst_stride,
int src_width,
int src_height
);
int
ConvertI420ToRGB565Android(const uint8* src_yplane, int src_ystride,
const uint8* src_uplane, int src_ustride,
const uint8* src_vplane, int src_vstride,
uint8* dst_frame, int dst_stride,
int src_width,
int src_height
);
int
ConvertI420ToARGB1555(const uint8* src_yplane, int src_ystride,
const uint8* src_uplane, int src_ustride,
const uint8* src_vplane, int src_vstride,
uint8* dst_frame, int dst_stride,
int src_width,
int src_height
);
int
ConvertYV12ToARGB(const uint8* src_yplane, int src_ystride,
const uint8* src_uplane, int src_ustride,
const uint8* src_vplane, int src_vstride,
uint8* dst_frame, int dst_stride,
int src_width,
int src_height
);
int
ConvertYV12ToRGBA(const uint8* src_yplane, int src_ystride,
const uint8* src_uplane, int src_ustride,
const uint8* src_vplane, int src_vstride,
uint8* dst_frame, int dst_stride,
int src_width,
int src_height
);
int
ConvertI420ToYUY2(const uint8* src_yplane, int src_ystride,
const uint8* src_uplane, int src_ustride,
const uint8* src_vplane, int src_vstride,
uint8* dst_frame, int dst_stride,
int src_width,
int src_height
);
int
ConvertUYVYToI420(const uint8* src_frame, int src_stride,
uint8* dst_yplane, int dst_ystride,
uint8* dst_uplane, int dst_ustride,
uint8* dst_vplane, int dst_vstride,
int src_width,
int src_height);
int
ConvertI420ToYUY2(const uint8* src_yplane, int src_ystride,
const uint8* src_uplane, int src_ustride,
const uint8* src_vplane, int src_vstride,
uint8* dst_frame, int dst_stride,
int src_width,
int src_height
);
int
ConvertI420ToYV12(const uint8* src_yplane, int src_ystride,
const uint8* src_uplane, int src_ustride,
const uint8* src_vplane, int src_vstride,
uint8* dst_frame, int dst_stride,
int src_width,
int src_height
);
int
ConvertRGB24ToARGB(const uint8* src_frame, int src_stride,
uint8* dst_frame, int dst_stride,
int src_width, int src_height
);
int
ConvertRGB24ToI420(const uint8* src_frame, int src_stride,
uint8* dst_yplane, int dst_ystride,
uint8* dst_uplane, int dst_ustride,
uint8* dst_vplane, int dst_vstride,
int src_width,
int src_height
);
int
ConvertABGRToI420(const uint8* src_frame, int src_stride,
uint8* dst_yplane, int dst_ystride,
uint8* dst_uplane, int dst_ustride,
uint8* dst_vplane, int dst_vstride,
int src_width,
int src_height
);
int
ConvertNv12ToRGB565(const uint8* src_yplane, int src_ystride,
const uint8* src_uvplane, int src_uvstride,
uint8* dst_frame, int dst_stride,
int src_width,
int src_height
);
int
ConvertI420ToABGR(const uint8* src_yplane, int src_ystride,
const uint8* src_uplane, int src_ustride,
const uint8* src_vplane, int src_vstride,
uint8* dst_frame, int dst_stride,
int src_width,
int src_height
);
} // namespace libyuv
#endif // LIBYUV_INCLUDE_CONVERT_H_
/*
* Copyright (c) 2011 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.
*/
#ifndef LIBYUV_INCLUDE_FORMAT_CONVERSION_H_
#define LIBYUV_INCLUDE_FORMAT_CONVERSION_H_
#include "basic_types.h"
namespace libyuv {
// Converts any Bayer RGB format to I420.
void BayerRGBToI420(const uint8* src_bayer, int src_pitch_bayer,
uint32 src_fourcc_bayer,
uint8* dst_y, int dst_pitch_y,
uint8* dst_u, int dst_pitch_u,
uint8* dst_v, int dst_pitch_v,
int width, int height);
// Converts any 32 bit ARGB to any Bayer RGB format.
void RGB32ToBayerRGB(const uint8* src_rgb, int src_pitch_rgb,
uint32 src_fourcc_rgb,
uint8* dst_bayer, int dst_pitch_bayer,
uint32 dst_fourcc_bayer,
int width, int height);
} // namespace libyuv
#endif // LIBYUV_INCLUDE_FORMAT_CONVERSION_H_
/*
* Copyright (c) 2011 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.
*/
/*
* General operations on YUV images.
*/
#ifndef LIBYUV_INCLUDE_GENERAL_H_
#define LIBYUV_INCLUDE_GENERAL_H_
#include "basic_types.h"
namespace libyuv {
// Supported rotation
enum VideoRotationMode
{
kRotateNone = 0,
kRotateClockwise = 90,
kRotateAntiClockwise = -90,
kRotate180 = 180,
};
// Mirror functions
// The following 2 functions perform mirroring on an image (LeftRight/UpDown)
// Input:
// - width : Image width in pixels.
// - height : Image height in pixels.
// - inFrame : Reference to input image.
// - outFrame : Reference to converted image.
// Return value: 0 if OK, < 0 otherwise.
int
MirrorI420LeftRight(const uint8* src_frame, int src_stride,
uint8* dst_frame, int dst_stride,
int src_width, int src_height);
// Cut/Pad I420 frame to match desird dimensions.
int
CutPadI420Frame(const uint8* inFrame, int inWidth,
int inHeight, uint8* outFrame,
int outWidth, int outHeight);
// I420 Cut - make a center cut
int
CutI420Frame(uint8* frame, int fromWidth,
int fromHeight, int toWidth,
int toHeight);
} // namespace libyuv
#endif // LIBYUV_INCLUDE_GENERAL_H_
/*
* Copyright (c) 2011 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.
*/
#ifndef LIBYUV_INCLUDE_PLANAR_FUNCTIONS_H_
#define LIBYUV_INCLUDE_PLANAR_FUNCTIONS_H_
#include "basic_types.h"
namespace libyuv {
class PlanarFunctions {
public:
// Copy I420 to I420.
static void I420Copy(const uint8* src_y, int src_pitch_y,
const uint8* src_u, int src_pitch_u,
const uint8* src_v, int src_pitch_v,
uint8* dst_y, int dst_pitch_y,
uint8* dst_u, int dst_pitch_u,
uint8* dst_v, int dst_pitch_v,
int width, int height);
// Convert I422 to I420. Used by MJPG.
static void I422ToI420(const uint8* src_y, int src_pitch_y,
const uint8* src_u, int src_pitch_u,
const uint8* src_v, int src_pitch_v,
uint8* dst_y, int dst_pitch_y,
uint8* dst_u, int dst_pitch_u,
uint8* dst_v, int dst_pitch_v,
int width, int height);
// Convert M420 to I420.
static void M420ToI420(uint8* dst_y, int dst_pitch_y,
uint8* dst_u, int dst_pitch_u,
uint8* dst_v, int dst_pitch_v,
const uint8* m420, int pitch_m420,
int width, int height);
// Convert NV12 to I420. Also used for NV21.
static void NV12ToI420(uint8* dst_y, int dst_pitch_y,
uint8* dst_u, int dst_pitch_u,
uint8* dst_v, int dst_pitch_v,
const uint8* src_y,
const uint8* src_uv,
int src_pitch,
int width, int height);
DISALLOW_IMPLICIT_CONSTRUCTORS(PlanarFunctions);
};
} // namespace libyuv
#endif // LIBYUV_INCLUDE_PLANAR_FUNCTIONS_H_
#ifndef LIBYUV_INCLUDE_SCALE_H_
#define LIBYUV_INCLUDE_SCALE_H_
#include "basic_types.h"
#if defined(_MSC_VER)
#define ALIGN16(var) __declspec(align(16)) var
#else
#define ALIGN16(var) var __attribute__((aligned(16)))
#endif
namespace libyuv
{
class YuvScaler {
public:
// Scales a YUV 4:2:0 image from the input width and height to the
// output width and height. If outh_offset is nonzero, the image is
// offset by that many pixels and stretched to (outh - outh_offset * 2)
// pixels high, instead of outh.
// If interpolate is not set, a simple nearest-neighbor algorithm is
// used. This produces basic (blocky) quality at the fastest speed.
// If interpolate is set, interpolation is used to produce a better
// quality image, at the expense of speed.
// Returns true if successful.
static bool Scale(const uint8 *in, int32 inw, int32 inh,
uint8 *out, int32 outw, int32 outh, int32 outh_offset,
bool interpolate);
// Same, but specified in terms of each plane location and stride.
static bool Scale(const uint8 *inY, const uint8 *inU, const uint8 *inV,
int32 istrideY, int32 istrideU, int32 istrideV,
int32 iwidth, int32 iheight,
uint8 *outY, uint8 *outU, uint8 *outV,
int32 ostrideY, int32 ostrideU, int32 ostrideV,
int32 owidth, int32 oheight,
bool interpolate);
// For testing, allow disabling of optimizations.
static void SetUseReferenceImpl(bool use) { use_reference_impl_ = use; }
private:
static bool use_reference_impl_;
DISALLOW_IMPLICIT_CONSTRUCTORS(YuvScaler);
};
} // namespace libyuv
#endif // LIBYUV_INCLUDE_SCALE_H_
# Copyright (c) 2011 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.
{
'targets': [
{
'target_name': 'libyuv',
'type': 'static_library',
'dependencies': [
],
'include_dirs': [
'include',
'common',
],
'sources': [
# includes
'include/convert.h',
'include/general.h',
'include/scale.h',
'include/planar_functions.h',
# headers
'common/basic_types.h',
'common/common.h',
'common/constructor_magic.h',
'source/cpu_id.h',
'source/row.h',
'source/video_common.h',
# sources
'source/convert.cc',
'source/general.cc',
'source/scale.cc',
'source/cpu_id.cc',
'source/format_conversion.cc',
'source/planar_functions.cc',
'source/row_posix.cc',
'source/row_table.cc',
'source/video_common.cc',
],
},
], # targets
}
# Local Variables:
# tab-width:2
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=2 shiftwidth=2:
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2011 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 "cpu_id.h"
#ifdef _MSC_VER
#include <intrin.h>
#elif LINUX
#include "linux.h"
#endif
// TODO(fbarchard): Use cpuid.h when gcc 4.4 is used on OSX and Linux.
#if (defined(__pic__) || defined(__APPLE__)) && defined(__i386__)
static inline void __cpuid(int cpu_info[4], int info_type) {
__asm__ volatile (
"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)
);
}
#elif defined(__i386__) || defined(__x86_64__)
static inline void __cpuid(int cpu_info[4], int info_type) {
__asm__ volatile (
"cpuid\n"
: "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
: "a"(info_type)
);
}
#endif
namespace libyuv {
// CPU detect function for SIMD instruction sets.
bool CpuInfo::cpu_info_initialized_ = false;
int CpuInfo::cpu_info_ = 0;
// Global lock for cpu initialization.
#ifdef CPU_X86
void cpuid(int cpu_info[4], int info_type) {
__cpuid(cpu_info, info_type);
}
#endif
void CpuInfo::InitCpuFlags() {
#ifdef CPU_X86
int cpu_info[4];
__cpuid(cpu_info, 1);
cpu_info_ = (cpu_info[2] & 0x00000200 ? kCpuHasSSSE3 : 0) |
(cpu_info[3] & 0x04000000 ? kCpuHasSSE2 : 0);
#elif defined(__ARM_NEON__)
// gcc -mfpu=neon defines __ARM_NEON__
// if code is specifically built for Neon-only, enable the flag.
cpu_info_ |= kCpuHasNEON;
#elif LINUX && defined(__arm__)
cpu_info_ = 0;
// Look for NEON support in /proc/cpuinfo
ProcCpuInfo proc_info;
size_t section_count;
if (proc_info.LoadFromSystem() &&
proc_info.GetSectionCount(&section_count)) {
for (size_t i = 0; i < section_count; ++i) {
std::string out_features;
if (proc_info.GetSectionStringValue(i, "Features", &out_features)) {
if (out_features.find("neon") != std::string::npos) {
cpu_info_ |= kCpuHasNEON;
}
break;
}
}
}
#else
cpu_info_ = 0;
#endif
cpu_info_initialized_ = true;
}
void CpuInfo::MaskCpuFlagsForTest(int enable_flags) {
InitCpuFlags();
cpu_info_ &= enable_flags;
}
bool CpuInfo::TestCpuFlag(int flag) {
if (!cpu_info_initialized_) {
InitCpuFlags();
}
return cpu_info_ & flag ? true : false;
}
// Returns the vendor string from the cpu, e.g. "GenuineIntel", "AuthenticAMD".
// See "Intel Processor Identification and the CPUID Instruction"
// (Intel document number: 241618)
std::string CpuInfo::GetCpuVendor() {
#ifdef CPU_X86
int cpu_info[4];
cpuid(cpu_info, 0);
cpu_info[0] = cpu_info[1]; // Reorder output
cpu_info[1] = cpu_info[3];
cpu_info[2] = cpu_info[2];
cpu_info[3] = 0;
return std::string(reinterpret_cast<char *>(&cpu_info[0]));
#else
return std::string("Undefined");
#endif
}
} // namespace libyuv
/*
* Copyright (c) 2011 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.
*/
#ifndef LIBYUV_SOURCE_CPU_ID_H_
#define LIBYUV_SOURCE_CPU_ID_H_
#include <string>
#include "basic_types.h"
namespace libyuv {
#ifdef CPU_X86
void cpuid(int cpu_info[4], int info_type);
#endif
class CpuInfo {
public:
// These flags are only valid on x86 processors
static const int kCpuHasSSE2 = 1;
static const int kCpuHasSSSE3 = 2;
// SIMD support on ARM processors
static const int kCpuHasNEON = 4;
// Detect CPU has SSE2 etc.
static bool TestCpuFlag(int flag);
// Detect CPU vendor: "GenuineIntel" or "AuthenticAMD"
static std::string GetCpuVendor();
// For testing, allow CPU flags to be disabled.
static void MaskCpuFlagsForTest(int enable_flags);
private:
// Global lock for the cpu initialization
static bool cpu_info_initialized_;
static int cpu_info_;
static void InitCpuFlags();
DISALLOW_IMPLICIT_CONSTRUCTORS(CpuInfo);
};
} // namespace libyuv
#endif // LIBYUV_SOURCE_CPU_ID_H_
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2011 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.
*/
#if defined(LINUX) || defined(ANDROID)
#include "linux.h"
#include <ctype.h>
#include <errno.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <cstdio>
#include <set>
namespace libyuv {
static const char kCpuInfoFile[] = "/proc/cpuinfo";
static const char kCpuMaxFreqFile[] =
"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
ProcCpuInfo::ProcCpuInfo() {
}
ProcCpuInfo::~ProcCpuInfo() {
}
bool ProcCpuInfo::LoadFromSystem() {
ConfigParser procfs;
if (!procfs.Open(kCpuInfoFile)) {
return false;
}
return procfs.Parse(&sections_);
};
bool ProcCpuInfo::GetSectionCount(size_t* count) {
if (sections_.empty()) {
return false;
}
if (count) {
*count = sections_.size();
}
return true;
}
bool ProcCpuInfo::GetNumCpus(int* num) {
if (sections_.empty()) {
return false;
}
int total_cpus = 0;
#if defined(__arm__)
// Count the number of blocks that have a "processor" key defined. On ARM,
// there may be extra blocks of information that aren't per-processor.
size_t section_count = sections_.size();
for (size_t i = 0; i < section_count; ++i) {
int processor_id;
if (GetSectionIntValue(i, "processor", &processor_id)) {
++total_cpus;
}
}
// Single core ARM systems don't include "processor" keys at all, so return
// that we have a single core if we didn't find any explicitly above.
if (total_cpus == 0) {
total_cpus = 1;
}
#else
// On X86, there is exactly one info section per processor.
total_cpus = static_cast<int>(sections_.size());
#endif
if (num) {
*num = total_cpus;
}
return true;
}
bool ProcCpuInfo::GetNumPhysicalCpus(int* num) {
if (sections_.empty()) {
return false;
}
// TODO(noahric): /proc/cpuinfo only reports cores that are currently
// _online_, so this may underreport the number of physical cores.
#if defined(__arm__)
// ARM (currently) has no hyperthreading, so just return the same value
// as GetNumCpus.
return GetNumCpus(num);
#else
int total_cores = 0;
std::set<int> physical_ids;
size_t section_count = sections_.size();
for (size_t i = 0; i < section_count; ++i) {
int physical_id;
int cores;
// Count the cores for the physical id only if we have not counted the id.
if (GetSectionIntValue(i, "physical id", &physical_id) &&
GetSectionIntValue(i, "cpu cores", &cores) &&
physical_ids.find(physical_id) == physical_ids.end()) {
physical_ids.insert(physical_id);
total_cores += cores;
}
}
if (num) {
*num = total_cores;
}
return true;
#endif
}
bool ProcCpuInfo::GetCpuFamily(int* id) {
int cpu_family = 0;
// shh {
#if defined(__arm__)
// On ChromeOS seaboard, there is no 'cpu family' in '/proc/cpuinfo'. But
// there is 'CPU Architecture' which can be used as 'cpu family'.
// See http://en.wikipedia.org/wiki/ARM_architecture for a good list of
// ARM cpu families, architectures, and their mappings.
// There may be multiple sessions that aren't per-processor. We need to scan
// through each session until we find the first 'CPU architecture'.
size_t section_count = sections_.size();
for (size_t i = 0; i < section_count; ++i) {
if (GetSectionIntValue(i, "CPU architecture", &cpu_family)) {
// We returns the first one (if there are multiple entries).
break;
};
}
#else
// shh }
GetSectionIntValue(0, "cpu family", &cpu_family);
// shh {
#endif
// shh }
if (id) {
*id = cpu_family;
}
return true;
}
bool ProcCpuInfo::GetSectionStringValue(size_t section_num,
const std::string& key,
std::string* result) {
if (section_num >= sections_.size()) {
return false;
}
ConfigParser::SimpleMap::iterator iter = sections_[section_num].find(key);
if (iter == sections_[section_num].end()) {
return false;
}
*result = iter->second;
return true;
}
bool ProcCpuInfo::GetSectionIntValue(size_t section_num,
const std::string& key,
int* result) {
if (section_num >= sections_.size()) {
return false;
}
ConfigParser::SimpleMap::iterator iter = sections_[section_num].find(key);
if (iter == sections_[section_num].end()) {
return false;
}
return FromString(iter->second, result);
}
ConfigParser::ConfigParser() {}
ConfigParser::~ConfigParser() {}
bool ConfigParser::Open(const std::string& filename) {
FileStream* fs = new FileStream();
if (!fs->Open(filename, "r", NULL)) {
return false;
}
instream_.reset(fs);
return true;
}
void ConfigParser::Attach(StreamInterface* stream) {
instream_.reset(stream);
}
bool ConfigParser::Parse(MapVector* key_val_pairs) {
// Parses the file and places the found key-value pairs into key_val_pairs.
SimpleMap section;
while (ParseSection(&section)) {
key_val_pairs->push_back(section);
section.clear();
}
return (!key_val_pairs->empty());
}
bool ConfigParser::ParseSection(SimpleMap* key_val_pair) {
// Parses the next section in the filestream and places the found key-value
// pairs into key_val_pair.
std::string key, value;
while (ParseLine(&key, &value)) {
(*key_val_pair)[key] = value;
}
return (!key_val_pair->empty());
}
bool ConfigParser::ParseLine(std::string* key, std::string* value) {
// Parses the next line in the filestream and places the found key-value
// pair into key and val.
std::string line;
if ((instream_->ReadLine(&line)) == EOF) {
return false;
}
std::vector<std::string> tokens;
if (2 != split(line, ':', &tokens)) {
return false;
}
// Removes whitespace at the end of Key name
size_t pos = tokens[0].length() - 1;
while ((pos > 0) && isspace(tokens[0][pos])) {
pos--;
}
tokens[0].erase(pos + 1);
// Removes whitespace at the start of value
pos = 0;
while (pos < tokens[1].length() && isspace(tokens[1][pos])) {
pos++;
}
tokens[1].erase(0, pos);
*key = tokens[0];
*value = tokens[1];
return true;
}
static bool ExpectLineFromStream(FileStream* stream,
std::string* out) {
StreamResult res = stream->ReadLine(out);
if (res != SR_SUCCESS) {
if (res != SR_EOS) {
LOG(LS_ERROR) << "Error when reading from stream";
} else {
LOG(LS_ERROR) << "Incorrect number of lines in stream";
}
return false;
}
return true;
}
static void ExpectEofFromStream(FileStream* stream) {
std::string unused;
StreamResult res = stream->ReadLine(&unused);
if (res == SR_SUCCESS) {
LOG(LS_WARNING) << "Ignoring unexpected extra lines from stream";
} else if (res != SR_EOS) {
LOG(LS_WARNING) << "Error when checking for extra lines from stream";
}
}
// For caching the lsb_release output (reading it invokes a sub-process and
// hence is somewhat expensive).
static std::string lsb_release_string;
static CriticalSection lsb_release_string_critsec;
std::string ReadLinuxLsbRelease() {
CritScope cs(&lsb_release_string_critsec);
if (!lsb_release_string.empty()) {
// Have cached result from previous call.
return lsb_release_string;
}
// No cached result. Run lsb_release and parse output.
POpenStream lsb_release_output;
if (!lsb_release_output.Open("lsb_release -idrcs", "r", NULL)) {
LOG_ERR(LS_ERROR) << "Can't run lsb_release";
return lsb_release_string; // empty
}
// Read in the command's output and build the string.
std::ostringstream sstr;
std::string line;
int wait_status;
if (!ExpectLineFromStream(&lsb_release_output, &line)) {
return lsb_release_string; // empty
}
sstr << "DISTRIB_ID=" << line;
if (!ExpectLineFromStream(&lsb_release_output, &line)) {
return lsb_release_string; // empty
}
sstr << " DISTRIB_DESCRIPTION=\"" << line << '"';
if (!ExpectLineFromStream(&lsb_release_output, &line)) {
return lsb_release_string; // empty
}
sstr << " DISTRIB_RELEASE=" << line;
if (!ExpectLineFromStream(&lsb_release_output, &line)) {
return lsb_release_string; // empty
}
sstr << " DISTRIB_CODENAME=" << line;
// Should not be anything left.
ExpectEofFromStream(&lsb_release_output);
lsb_release_output.Close();
wait_status = lsb_release_output.GetWaitStatus();
if (wait_status == -1 ||
!WIFEXITED(wait_status) ||
WEXITSTATUS(wait_status) != 0) {
LOG(LS_WARNING) << "Unexpected exit status from lsb_release";
}
lsb_release_string = sstr.str();
return lsb_release_string;
}
std::string ReadLinuxUname() {
struct utsname buf;
if (uname(&buf) < 0) {
LOG_ERR(LS_ERROR) << "Can't call uname()";
return std::string();
}
std::ostringstream sstr;
sstr << buf.sysname << " "
<< buf.release << " "
<< buf.version << " "
<< buf.machine;
return sstr.str();
}
int ReadCpuMaxFreq() {
FileStream fs;
std::string str;
int freq = -1;
if (!fs.Open(kCpuMaxFreqFile, "r", NULL) ||
SR_SUCCESS != fs.ReadLine(&str) ||
!FromString(str, &freq)) {
return -1;
}
return freq;
}
} // namespace libyuv
#endif // defined(LINUX) || defined(ANDROID)
/*
* Copyright (c) 2011 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.
*/
#ifndef LIBYUV_SOURCE_LINUX_H_
#define LIBYUV_SOURCE_LINUX_H_
#if defined(LINUX) || defined(ANDROID)
#include <string>
#include <map>
#include <vector>
namespace libyuv {
//////////////////////////////////////////////////////////////////////////////
// ConfigParser parses a FileStream of an ".ini."-type format into a map.
//////////////////////////////////////////////////////////////////////////////
// Sample Usage:
// ConfigParser parser;
// ConfigParser::MapVector key_val_pairs;
// if (parser.Open(inifile) && parser.Parse(&key_val_pairs)) {
// for (int section_num=0; i < key_val_pairs.size(); ++section_num) {
// std::string val1 = key_val_pairs[section_num][key1];
// std::string val2 = key_val_pairs[section_num][key2];
// // Do something with valn;
// }
// }
class ConfigParser {
public:
typedef std::map<std::string, std::string> SimpleMap;
typedef std::vector<SimpleMap> MapVector;
ConfigParser();
virtual ~ConfigParser();
virtual bool Open(const std::string& filename);
virtual void Attach(StreamInterface* stream);
virtual bool Parse(MapVector* key_val_pairs);
virtual bool ParseSection(SimpleMap* key_val_pair);
virtual bool ParseLine(std::string* key, std::string* value);
private:
scoped_ptr<StreamInterface> instream_;
};
//////////////////////////////////////////////////////////////////////////////
// ProcCpuInfo reads CPU info from the /proc subsystem on any *NIX platform.
//////////////////////////////////////////////////////////////////////////////
// Sample Usage:
// ProcCpuInfo proc_info;
// int no_of_cpu;
// if (proc_info.LoadFromSystem()) {
// std::string out_str;
// proc_info.GetNumCpus(&no_of_cpu);
// proc_info.GetCpuStringValue(0, "vendor_id", &out_str);
// }
// }
class ProcCpuInfo {
public:
ProcCpuInfo();
virtual ~ProcCpuInfo();
// Reads the proc subsystem's cpu info into memory. If this fails, this
// returns false; if it succeeds, it returns true.
virtual bool LoadFromSystem();
// Obtains the number of logical CPU threads and places the value num.
virtual bool GetNumCpus(int* num);
// Obtains the number of physical CPU cores and places the value num.
virtual bool GetNumPhysicalCpus(int* num);
// Obtains the CPU family id.
virtual bool GetCpuFamily(int* id);
// Obtains the number of sections in /proc/cpuinfo, which may be greater
// than the number of CPUs (e.g. on ARM)
virtual bool GetSectionCount(size_t* count);
// Looks for the CPU proc item with the given name for the given section
// number and places the string value in result.
virtual bool GetSectionStringValue(size_t section_num, const std::string& key,
std::string* result);
// Looks for the CPU proc item with the given name for the given section
// number and places the int value in result.
virtual bool GetSectionIntValue(size_t section_num, const std::string& key,
int* result);
private:
ConfigParser::MapVector sections_;
};
// Builds a string containing the info from lsb_release on a single line.
std::string ReadLinuxLsbRelease();
// Returns the output of "uname".
std::string ReadLinuxUname();
// Returns the content (int) of
// /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
// Returns -1 on error.
int ReadCpuMaxFreq();
} // namespace libyuv
#endif // defined(LINUX) || defined(ANDROID)
#endif // LIBYUV_SOURCE_LINUX_H_
This diff is collapsed.
/*
* Copyright (c) 2011 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.
*/
#ifndef LIBYUV_SOURCE_ROW_H_
#define LIBYUV_SOURCE_ROW_H_
#include "basic_types.h"
extern "C" {
// Can only do 1x.
// This is the second fastest of the scalers.
void FastConvertYUVToRGB32Row(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int width);
#if defined(_MSC_VER)
#define SIMD_ALIGNED(var) __declspec(align(16)) var
#else
#define SIMD_ALIGNED(var) var __attribute__((aligned(16)))
#endif
#ifdef OSX
extern SIMD_ALIGNED(const int16 kCoefficientsRgbY[768][4]);
#else
extern SIMD_ALIGNED(const int16 _kCoefficientsRgbY[768][4]);
#endif
// Method to force C version.
//#define USE_MMX 0
//#define USE_SSE2 0
#if !defined(USE_MMX)
// Windows, Mac and Linux use MMX
#if defined(__i386__) || defined(_MSC_VER)
#define USE_MMX 1
#else
#define USE_MMX 0
#endif
#endif
#if !defined(USE_SSE2)
#if defined(__SSE2__) || defined(ARCH_CPU_X86_64) || _M_IX86_FP==2
#define USE_SSE2 1
#else
#define USE_SSE2 0
#endif
#endif
// x64 uses MMX2 (SSE) so emms is not required.
// Warning C4799: function has no EMMS instruction.
// EMMS() is slow and should be called by the calling function once per image.
#if USE_MMX && !defined(ARCH_CPU_X86_64)
#if defined(_MSC_VER)
#define EMMS() __asm emms
#pragma warning(disable: 4799)
#else
#define EMMS() asm("emms")
#endif
#else
#define EMMS()
#endif
} // extern "C"
#endif // LIBYUV_SOURCE_ROW_H_
/*
* Copyright (c) 2011 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 "row.h"
extern "C" {
#if defined(__x86_64__)
// 64 bit linux gcc version
void FastConvertYUVToRGB32Row(const uint8* y_buf, // rdi
const uint8* u_buf, // rsi
const uint8* v_buf, // rdx
uint8* rgb_buf, // rcx
int width) { // r8
asm(
"1:"
"movzb (%1),%%r10\n"
"lea 1(%1),%1\n"
"movzb (%2),%%r11\n"
"lea 1(%2),%2\n"
"movq 2048(%5,%%r10,8),%%xmm0\n"
"movzb (%0),%%r10\n"
"movq 4096(%5,%%r11,8),%%xmm1\n"
"movzb 0x1(%0),%%r11\n"
"paddsw %%xmm1,%%xmm0\n"
"movq (%5,%%r10,8),%%xmm2\n"
"lea 2(%0),%0\n"
"movq (%5,%%r11,8),%%xmm3\n"
"paddsw %%xmm0,%%xmm2\n"
"paddsw %%xmm0,%%xmm3\n"
"shufps $0x44,%%xmm3,%%xmm2\n"
"psraw $0x6,%%xmm2\n"
"packuswb %%xmm2,%%xmm2\n"
"movq %%xmm2,0x0(%3)\n"
"lea 8(%3),%3\n"
"sub $0x2,%4\n"
"ja 1b\n"
:
: "r"(y_buf), // %0
"r"(u_buf), // %1
"r"(v_buf), // %2
"r"(rgb_buf), // %3
"r"(width), // %4
"r" (_kCoefficientsRgbY) // %5
: "memory", "r10", "r11", "xmm0", "xmm1", "xmm2", "xmm3"
);
}
#elif defined(__i386__)
// 32 bit gcc version
void FastConvertYUVToRGB32Row(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int width);
asm(
".text\n"
#if defined(OSX) || defined(IOS)
".globl _FastConvertYUVToRGB32Row\n"
"_FastConvertYUVToRGB32Row:\n"
#else
".global FastConvertYUVToRGB32Row\n"
"FastConvertYUVToRGB32Row:\n"
#endif
"pusha\n"
"mov 0x24(%esp),%edx\n"
"mov 0x28(%esp),%edi\n"
"mov 0x2c(%esp),%esi\n"
"mov 0x30(%esp),%ebp\n"
"mov 0x34(%esp),%ecx\n"
"1:"
"movzbl (%edi),%eax\n"
"lea 1(%edi),%edi\n"
"movzbl (%esi),%ebx\n"
"lea 1(%esi),%esi\n"
"movq _kCoefficientsRgbY+2048(,%eax,8),%mm0\n"
"movzbl (%edx),%eax\n"
"paddsw _kCoefficientsRgbY+4096(,%ebx,8),%mm0\n"
"movzbl 0x1(%edx),%ebx\n"
"movq _kCoefficientsRgbY(,%eax,8),%mm1\n"
"lea 2(%edx),%edx\n"
"movq _kCoefficientsRgbY(,%ebx,8),%mm2\n"
"paddsw %mm0,%mm1\n"
"paddsw %mm0,%mm2\n"
"psraw $0x6,%mm1\n"
"psraw $0x6,%mm2\n"
"packuswb %mm2,%mm1\n"
"movntq %mm1,0x0(%ebp)\n"
"lea 8(%ebp),%ebp\n"
"sub $0x2,%ecx\n"
"ja 1b\n"
"popa\n"
"ret\n"
);
#else
// C reference code that mimic the YUV assembly.
#define packuswb(x) ((x) < 0 ? 0 : ((x) > 255 ? 255 : (x)))
#define paddsw(x, y) (((x) + (y)) < -32768 ? -32768 : \
(((x) + (y)) > 32767 ? 32767 : ((x) + (y))))
static inline void YuvPixel(uint8 y,
uint8 u,
uint8 v,
uint8* rgb_buf) {
int b = _kCoefficientsRgbY[256+u][0];
int g = _kCoefficientsRgbY[256+u][1];
int r = _kCoefficientsRgbY[256+u][2];
int a = _kCoefficientsRgbY[256+u][3];
b = paddsw(b, _kCoefficientsRgbY[512+v][0]);
g = paddsw(g, _kCoefficientsRgbY[512+v][1]);
r = paddsw(r, _kCoefficientsRgbY[512+v][2]);
a = paddsw(a, _kCoefficientsRgbY[512+v][3]);
b = paddsw(b, _kCoefficientsRgbY[y][0]);
g = paddsw(g, _kCoefficientsRgbY[y][1]);
r = paddsw(r, _kCoefficientsRgbY[y][2]);
a = paddsw(a, _kCoefficientsRgbY[y][3]);
b >>= 6;
g >>= 6;
r >>= 6;
a >>= 6;
*reinterpret_cast<uint32*>(rgb_buf) = (packuswb(b)) |
(packuswb(g) << 8) |
(packuswb(r) << 16) |
(packuswb(a) << 24);
}
void FastConvertYUVToRGB32Row(const uint8* y_buf,
const uint8* u_buf,
const uint8* v_buf,
uint8* rgb_buf,
int width) {
for (int x = 0; x < width; x += 2) {
uint8 u = u_buf[x >> 1];
uint8 v = v_buf[x >> 1];
uint8 y0 = y_buf[x];
YuvPixel(y0, u, v, rgb_buf);
if ((x + 1) < width) {
uint8 y1 = y_buf[x + 1];
YuvPixel(y1, u, v, rgb_buf + 4);
}
rgb_buf += 8; // Advance 2 pixels.
}
}
#endif
} // extern "C"
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2011 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 "video_common.h"
#include <sstream>
#include "common.h"
namespace libyuv {
struct FourCCAliasEntry {
uint32 alias;
uint32 canonical;
};
static const FourCCAliasEntry kFourCCAliases[] = {
{FOURCC_IYUV, FOURCC_I420},
{FOURCC_YU12, FOURCC_I420},
{FOURCC_YUYV, FOURCC_YUY2},
{FOURCC_YUVS, FOURCC_YUY2},
{FOURCC_HDYC, FOURCC_UYVY},
{FOURCC_2VUY, FOURCC_UYVY},
{FOURCC_BA81, FOURCC_BGGR},
{FOURCC_JPEG, FOURCC_MJPG}, // Note: JPEG has DHT while MJPG does not.
{FOURCC_RGB3, FOURCC_RAW},
{FOURCC_BGR3, FOURCC_24BG},
};
uint32 CanonicalFourCC(uint32 fourcc) {
for (int i = 0; i < ARRAY_SIZE(kFourCCAliases); ++i) {
if (kFourCCAliases[i].alias == fourcc) {
return kFourCCAliases[i].canonical;
}
}
// Not an alias, so return it as-is.
return fourcc;
}
std::string VideoFormat::ToString() const {
std::string fourcc_name = GetFourccName(fourcc) + " ";
for (std::string::const_iterator i = fourcc_name.begin();
i < fourcc_name.end(); ++i) {
// Test character is printable; Avoid isprint() which asserts on negatives
if (*i < 32 || *i >= 127) {
fourcc_name = "";
break;
}
}
std::ostringstream ss;
ss << fourcc_name << width << "x" << height << "x" << IntervalToFps(interval);
return ss.str();
}
} // namespace libyuv
/*
* Copyright (c) 2011 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.
*/
/*
* Common definitions for video, including fourcc and VideoFormat
*/
#ifndef LIBYUV_SOURCE_VIDEO_COMMON_H_
#define LIBYUV_SOURCE_VIDEO_COMMON_H_
#include <string>
#include "basic_types.h"
namespace libyuv {
//////////////////////////////////////////////////////////////////////////////
// Definition of fourcc.
//////////////////////////////////////////////////////////////////////////////
// Convert four characters to a fourcc code.
// Needs to be a macro otherwise the OS X compiler complains when the kFormat*
// constants are used in a switch.
#define FOURCC(a, b, c, d) (\
(static_cast<uint32>(a)) | (static_cast<uint32>(b) << 8) | \
(static_cast<uint32>(c) << 16) | (static_cast<uint32>(d) << 24))
// Get the name, that is, string with four characters, of a fourcc code.
inline std::string GetFourccName(uint32 fourcc) {
std::string name;
name.push_back(static_cast<char>(fourcc & 0xFF));
name.push_back(static_cast<char>((fourcc >> 8) & 0xFF));
name.push_back(static_cast<char>((fourcc >> 16) & 0xFF));
name.push_back(static_cast<char>((fourcc >> 24) & 0xFF));
return name;
}
// Some good pages discussing FourCC codes:
// http://developer.apple.com/quicktime/icefloe/dispatch020.html
// http://www.fourcc.org/yuv.php
enum FourCC {
// Canonical fourcc codes used in our code.
FOURCC_I420 = FOURCC('I', '4', '2', '0'),
FOURCC_YV12 = FOURCC('Y', 'V', '1', '2'),
FOURCC_YUY2 = FOURCC('Y', 'U', 'Y', '2'),
FOURCC_UYVY = FOURCC('U', 'Y', 'V', 'Y'),
FOURCC_M420 = FOURCC('M', '4', '2', '0'),
FOURCC_24BG = FOURCC('2', '4', 'B', 'G'),
FOURCC_ABGR = FOURCC('A', 'B', 'G', 'R'),
FOURCC_BGRA = FOURCC('B', 'G', 'R', 'A'),
FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'),
FOURCC_MJPG = FOURCC('M', 'J', 'P', 'G'),
FOURCC_RAW = FOURCC('r', 'a', 'w', ' '),
FOURCC_NV21 = FOURCC('N', 'V', '2', '1'),
FOURCC_NV12 = FOURCC('N', 'V', '1', '2'),
// Next four are Bayer RGB formats. The four characters define the order of
// the colours in each 2x2 pixel grid, going left-to-right and top-to-bottom.
FOURCC_RGGB = FOURCC('R', 'G', 'G', 'B'),
FOURCC_BGGR = FOURCC('B', 'G', 'G', 'R'),
FOURCC_GRBG = FOURCC('G', 'R', 'B', 'G'),
FOURCC_GBRG = FOURCC('G', 'B', 'R', 'G'),
// Aliases for canonical fourcc codes, replaced with their canonical
// equivalents by CanonicalFourCC().
FOURCC_IYUV = FOURCC('I', 'Y', 'U', 'V'), // Alias for I420
FOURCC_YU12 = FOURCC('Y', 'U', '1', '2'), // Alias for I420
FOURCC_YUYV = FOURCC('Y', 'U', 'Y', 'V'), // Alias for YUY2
FOURCC_YUVS = FOURCC('y', 'u', 'v', 's'), // Alias for YUY2 on Mac
FOURCC_HDYC = FOURCC('H', 'D', 'Y', 'C'), // Alias for UYVY
FOURCC_2VUY = FOURCC('2', 'v', 'u', 'y'), // Alias for UYVY
FOURCC_JPEG = FOURCC('J', 'P', 'E', 'G'), // Alias for MJPG
FOURCC_BA81 = FOURCC('B', 'A', '8', '1'), // Alias for BGGR
FOURCC_RGB3 = FOURCC('R', 'G', 'B', '3'), // Alias for RAW
FOURCC_BGR3 = FOURCC('B', 'G', 'R', '3'), // Alias for 24BG
// Match any fourcc.
FOURCC_ANY = 0xFFFFFFFF,
};
// Converts fourcc aliases into canonical ones.
uint32 CanonicalFourCC(uint32 fourcc);
//////////////////////////////////////////////////////////////////////////////
// Definition of VideoFormat.
//////////////////////////////////////////////////////////////////////////////
static const int64 kNumNanosecsPerSec = 1000000000;
struct VideoFormat {
static const int64 kMinimumInterval = kNumNanosecsPerSec / 10000; // 10k fps
VideoFormat() : width(0), height(0), interval(0), fourcc(0) {}
VideoFormat(int w, int h, int64 interval_ns, uint32 cc)
: width(w),
height(h),
interval(interval_ns),
fourcc(cc) {
}
VideoFormat(const VideoFormat& format)
: width(format.width),
height(format.height),
interval(format.interval),
fourcc(format.fourcc) {
}
static int64 FpsToInterval(int fps) {
return fps ? kNumNanosecsPerSec / fps : kMinimumInterval;
}
static int IntervalToFps(int64 interval) {
// Normalize the interval first.
interval = libyuv::_max(interval, kMinimumInterval);
return static_cast<int>(kNumNanosecsPerSec / interval);
}
bool operator==(const VideoFormat& format) const {
return width == format.width && height == format.height &&
interval == format.interval && fourcc == format.fourcc;
}
bool operator!=(const VideoFormat& format) const {
return !(*this == format);
}
bool operator<(const VideoFormat& format) const {
return (fourcc < format.fourcc) ||
(fourcc == format.fourcc && width < format.width) ||
(fourcc == format.fourcc && width == format.width &&
height < format.height) ||
(fourcc == format.fourcc && width == format.width &&
height == format.height && interval > format.interval);
}
int framerate() const { return IntervalToFps(interval); }
// Check if both width and height are 0.
bool IsSize0x0() const { return 0 == width && 0 == height; }
// Check if this format is less than another one by comparing the resolution
// and frame rate.
bool IsPixelRateLess(const VideoFormat& format) const {
return width * height * framerate() <
format.width * format.height * format.framerate();
}
// Get a string presentation in the form of "fourcc width x height x fps"
std::string ToString() const;
int width; // in number of pixels
int height; // in number of pixels
int64 interval; // in nanoseconds
uint32 fourcc; // color space. FOURCC_ANY means that any color space is OK.
};
// Result of video capturer start.
enum CaptureResult {
CR_SUCCESS, // The capturer starts successfully.
CR_PENDING, // The capturer is pending to start the capture device.
CR_FAILURE, // The capturer fails to start.
CR_NO_DEVICE, // The capturer has no device and fails to start.
};
} // namespace libyuv
#endif // LIBYUV_SOURCE_VIDEO_COMMON_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment