1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Rename ffmpeg-4.2-fit to ffmpeg-4-fit

This commit is contained in:
winlin 2021-03-02 17:48:40 +08:00
parent b19074721c
commit 27712fdda7
720 changed files with 14 additions and 14 deletions

View file

@ -0,0 +1,250 @@
NAME = avutil
DESC = FFmpeg utility library
HEADERS = adler32.h \
aes.h \
aes_ctr.h \
attributes.h \
audio_fifo.h \
avassert.h \
avstring.h \
avutil.h \
base64.h \
blowfish.h \
bprint.h \
bswap.h \
buffer.h \
cast5.h \
camellia.h \
channel_layout.h \
common.h \
cpu.h \
crc.h \
des.h \
dict.h \
display.h \
downmix_info.h \
encryption_info.h \
error.h \
eval.h \
fifo.h \
file.h \
frame.h \
hash.h \
hdr_dynamic_metadata.h \
hmac.h \
hwcontext.h \
hwcontext_cuda.h \
hwcontext_d3d11va.h \
hwcontext_drm.h \
hwcontext_dxva2.h \
hwcontext_qsv.h \
hwcontext_mediacodec.h \
hwcontext_vaapi.h \
hwcontext_videotoolbox.h \
hwcontext_vdpau.h \
imgutils.h \
intfloat.h \
intreadwrite.h \
lfg.h \
log.h \
macros.h \
mathematics.h \
mastering_display_metadata.h \
md5.h \
mem.h \
motion_vector.h \
murmur3.h \
opt.h \
parseutils.h \
pixdesc.h \
pixelutils.h \
pixfmt.h \
random_seed.h \
rc4.h \
rational.h \
replaygain.h \
ripemd.h \
samplefmt.h \
sha.h \
sha512.h \
spherical.h \
stereo3d.h \
threadmessage.h \
time.h \
timecode.h \
timestamp.h \
tree.h \
twofish.h \
version.h \
xtea.h \
tea.h \
tx.h \
HEADERS-$(CONFIG_LZO) += lzo.h
ARCH_HEADERS = bswap.h \
intmath.h \
intreadwrite.h \
timer.h \
BUILT_HEADERS = avconfig.h \
ffversion.h
OBJS = adler32.o \
aes.o \
aes_ctr.o \
audio_fifo.o \
avstring.o \
avsscanf.o \
base64.o \
blowfish.o \
bprint.o \
buffer.o \
cast5.o \
camellia.o \
channel_layout.o \
color_utils.o \
cpu.o \
crc.o \
des.o \
dict.o \
display.o \
downmix_info.o \
encryption_info.o \
error.o \
eval.o \
fifo.o \
file.o \
file_open.o \
float_dsp.o \
fixed_dsp.o \
frame.o \
hash.o \
hdr_dynamic_metadata.o \
hmac.o \
hwcontext.o \
imgutils.o \
integer.o \
intmath.o \
lfg.o \
lls.o \
log.o \
log2_tab.o \
mathematics.o \
mastering_display_metadata.o \
md5.o \
mem.o \
murmur3.o \
opt.o \
parseutils.o \
pixdesc.o \
pixelutils.o \
random_seed.o \
rational.o \
reverse.o \
rc4.o \
ripemd.o \
samplefmt.o \
sha.o \
sha512.o \
slicethread.o \
spherical.o \
stereo3d.o \
threadmessage.o \
time.o \
timecode.o \
tree.o \
twofish.o \
utils.o \
xga_font_data.o \
xtea.o \
tea.o \
tx.o \
OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o
OBJS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.o
OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o
OBJS-$(CONFIG_LIBDRM) += hwcontext_drm.o
OBJS-$(CONFIG_LZO) += lzo.o
OBJS-$(CONFIG_MEDIACODEC) += hwcontext_mediacodec.o
OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o
OBJS-$(CONFIG_QSV) += hwcontext_qsv.o
OBJS-$(CONFIG_VAAPI) += hwcontext_vaapi.o
OBJS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.o
OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o
OBJS += $(COMPAT_OBJS:%=../compat/%)
# Windows resource file
SLIBOBJS-$(HAVE_GNU_WINDRES) += avutilres.o
SKIPHEADERS-$(HAVE_CUDA_H) += hwcontext_cuda.h
SKIPHEADERS-$(CONFIG_CUDA) += hwcontext_cuda_internal.h \
cuda_check.h
SKIPHEADERS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.h
SKIPHEADERS-$(CONFIG_DXVA2) += hwcontext_dxva2.h
SKIPHEADERS-$(CONFIG_QSV) += hwcontext_qsv.h
SKIPHEADERS-$(CONFIG_OPENCL) += hwcontext_opencl.h
SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h
SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.h
SKIPHEADERS-$(CONFIG_VDPAU) += hwcontext_vdpau.h
TESTPROGS = adler32 \
aes \
aes_ctr \
audio_fifo \
avstring \
base64 \
blowfish \
bprint \
cast5 \
camellia \
color_utils \
cpu \
crc \
des \
dict \
display \
encryption_info \
error \
eval \
file \
fifo \
hash \
hmac \
hwdevice \
integer \
imgutils \
lfg \
lls \
log \
md5 \
murmur3 \
opt \
pca \
parseutils \
pixdesc \
pixelutils \
pixfmt_best \
random_seed \
rational \
ripemd \
sha \
sha512 \
softfloat \
tree \
twofish \
utf8 \
xtea \
tea \
TESTPROGS-$(HAVE_THREADS) += cpu_init
TESTPROGS-$(HAVE_LZO1X_999_COMPRESS) += lzo
TOOLS = crypto_bench ffhash ffeval ffescape
tools/crypto_bench$(EXESUF): ELIBS += $(if $(VERSUS),$(subst +, -l,+$(VERSUS)),)
tools/crypto_bench$(EXESUF): CFLAGS += -DUSE_EXT_LIBS=0$(if $(VERSUS),$(subst +,+USE_,+$(VERSUS)),)
$(SUBDIR)tests/lzo$(EXESUF): ELIBS = -llzo2

View file

@ -0,0 +1,4 @@
OBJS += aarch64/cpu.o \
aarch64/float_dsp_init.o \
NEON-OBJS += aarch64/float_dsp_neon.o

View file

@ -0,0 +1,50 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_AARCH64_BSWAP_H
#define AVUTIL_AARCH64_BSWAP_H
#include <stdint.h>
#include "config.h"
#include "libavutil/attributes.h"
#if HAVE_INLINE_ASM
#define av_bswap16 av_bswap16
static av_always_inline av_const unsigned av_bswap16(unsigned x)
{
__asm__("rev16 %w0, %w0" : "+r"(x));
return x;
}
#define av_bswap32 av_bswap32
static av_always_inline av_const uint32_t av_bswap32(uint32_t x)
{
__asm__("rev %w0, %w0" : "+r"(x));
return x;
}
#define av_bswap64 av_bswap64
static av_always_inline av_const uint64_t av_bswap64(uint64_t x)
{
__asm__("rev %0, %0" : "+r"(x));
return x;
}
#endif /* HAVE_INLINE_ASM */
#endif /* AVUTIL_AARCH64_BSWAP_H */

View file

@ -0,0 +1,38 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/cpu.h"
#include "libavutil/cpu_internal.h"
#include "config.h"
int ff_get_cpu_flags_aarch64(void)
{
return AV_CPU_FLAG_ARMV8 * HAVE_ARMV8 |
AV_CPU_FLAG_NEON * HAVE_NEON |
AV_CPU_FLAG_VFP * HAVE_VFP;
}
size_t ff_get_cpu_max_align_aarch64(void)
{
int flags = av_get_cpu_flags();
if (flags & AV_CPU_FLAG_NEON)
return 16;
return 8;
}

View file

@ -0,0 +1,29 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_AARCH64_CPU_H
#define AVUTIL_AARCH64_CPU_H
#include "libavutil/cpu.h"
#include "libavutil/cpu_internal.h"
#define have_armv8(flags) CPUEXT(flags, ARMV8)
#define have_neon(flags) CPUEXT(flags, NEON)
#define have_vfp(flags) CPUEXT(flags, VFP)
#endif /* AVUTIL_AARCH64_CPU_H */

View file

@ -0,0 +1,69 @@
/*
* ARM NEON optimised Float DSP functions
* Copyright (c) 2008 Mans Rullgard <mans@mansr.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include "libavutil/attributes.h"
#include "libavutil/cpu.h"
#include "libavutil/float_dsp.h"
#include "cpu.h"
void ff_vector_fmul_neon(float *dst, const float *src0, const float *src1,
int len);
void ff_vector_fmac_scalar_neon(float *dst, const float *src, float mul,
int len);
void ff_vector_fmul_scalar_neon(float *dst, const float *src, float mul,
int len);
void ff_vector_dmul_scalar_neon(double *dst, const double *src, double mul,
int len);
void ff_vector_fmul_window_neon(float *dst, const float *src0,
const float *src1, const float *win, int len);
void ff_vector_fmul_add_neon(float *dst, const float *src0, const float *src1,
const float *src2, int len);
void ff_vector_fmul_reverse_neon(float *dst, const float *src0,
const float *src1, int len);
void ff_butterflies_float_neon(float *v1, float *v2, int len);
float ff_scalarproduct_float_neon(const float *v1, const float *v2, int len);
av_cold void ff_float_dsp_init_aarch64(AVFloatDSPContext *fdsp)
{
int cpu_flags = av_get_cpu_flags();
if (have_neon(cpu_flags)) {
fdsp->butterflies_float = ff_butterflies_float_neon;
fdsp->scalarproduct_float = ff_scalarproduct_float_neon;
fdsp->vector_dmul_scalar = ff_vector_dmul_scalar_neon;
fdsp->vector_fmul = ff_vector_fmul_neon;
fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_neon;
fdsp->vector_fmul_add = ff_vector_fmul_add_neon;
fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_neon;
fdsp->vector_fmul_scalar = ff_vector_fmul_scalar_neon;
fdsp->vector_fmul_window = ff_vector_fmul_window_neon;
}
}

View file

@ -0,0 +1,70 @@
/*
* check NEON registers for clobbering
* Copyright (c) 2008 Ramiro Polla <ramiro.polla@gmail.com>
* Copyright (c) 2013 Martin Storsjo
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_AARCH64_NEONTEST_H
#define AVUTIL_AARCH64_NEONTEST_H
#include <inttypes.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "libavutil/bswap.h"
#define storeneonregs(mem) \
__asm__ volatile( \
"stp d8, d9, [%0]\n\t" \
"stp d10, d11, [%0, #16]\n\t" \
"stp d12, d13, [%0, #32]\n\t" \
"stp d14, d15, [%0, #48]\n\t" \
:: "r"(mem) : "memory")
#define testneonclobbers(func, ctx, ...) \
uint64_t neon[2][8]; \
int ret; \
storeneonregs(neon[0]); \
ret = __real_ ## func(ctx, __VA_ARGS__); \
storeneonregs(neon[1]); \
if (memcmp(neon[0], neon[1], sizeof(neon[0]))) { \
int i; \
av_log(ctx, AV_LOG_ERROR, \
"NEON REGS CLOBBERED IN %s!\n", #func); \
for (i = 0; i < 8; i ++) \
if (neon[0][i] != neon[1][i]) { \
av_log(ctx, AV_LOG_ERROR, \
"d%-2d = %016"PRIx64"\n", \
8 + i, av_bswap64(neon[0][i])); \
av_log(ctx, AV_LOG_ERROR, \
" -> %016"PRIx64"\n", \
av_bswap64(neon[1][i])); \
} \
abort(); \
} \
return ret
#define wrap(func) \
int __real_ ## func; \
int __wrap_ ## func; \
int __wrap_ ## func
#endif /* AVUTIL_AARCH64_NEONTEST_H */

View file

@ -0,0 +1,44 @@
/*
* Copyright (c) 2015 Janne Grunau <janne-libav@jannau.net>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_AARCH64_TIMER_H
#define AVUTIL_AARCH64_TIMER_H
#include <stdint.h>
#include "config.h"
#if HAVE_INLINE_ASM
#define AV_READ_TIME read_time
static inline uint64_t read_time(void)
{
uint64_t cycle_counter;
__asm__ volatile(
"isb \t\n"
"mrs %0, pmccntr_el0 "
: "=r"(cycle_counter) :: "memory" );
return cycle_counter;
}
#endif /* HAVE_INLINE_ASM */
#endif /* AVUTIL_AARCH64_TIMER_H */

View file

@ -0,0 +1,97 @@
/*
* Compute the Adler-32 checksum of a data stream.
* This is a modified version based on adler32.c from the zlib library.
*
* Copyright (C) 1995 Mark Adler
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
/**
* @file
* Computes the Adler-32 checksum of a data stream
*
* This is a modified version based on adler32.c from the zlib library.
* @author Mark Adler
* @ingroup lavu_adler32
*/
#include "config.h"
#include "adler32.h"
#include "common.h"
#include "intreadwrite.h"
#define BASE 65521L /* largest prime smaller than 65536 */
#define DO1(buf) { s1 += *buf++; s2 += s1; }
#define DO4(buf) DO1(buf); DO1(buf); DO1(buf); DO1(buf);
#define DO16(buf) DO4(buf); DO4(buf); DO4(buf); DO4(buf);
unsigned long av_adler32_update(unsigned long adler, const uint8_t * buf,
unsigned int len)
{
unsigned long s1 = adler & 0xffff;
unsigned long s2 = adler >> 16;
while (len > 0) {
#if HAVE_FAST_64BIT && HAVE_FAST_UNALIGNED && !CONFIG_SMALL
unsigned len2 = FFMIN((len-1) & ~7, 23*8);
if (len2) {
uint64_t a1= 0;
uint64_t a2= 0;
uint64_t b1= 0;
uint64_t b2= 0;
len -= len2;
s2 += s1*len2;
while (len2 >= 8) {
uint64_t v = AV_RN64(buf);
a2 += a1;
b2 += b1;
a1 += v &0x00FF00FF00FF00FF;
b1 += (v>>8)&0x00FF00FF00FF00FF;
len2 -= 8;
buf+=8;
}
//We combine the 8 interleaved adler32 checksums without overflows
//Decreasing the number of iterations would allow below code to be
//simplified but would likely be slower due to the fewer iterations
//of the inner loop
s1 += ((a1+b1)*0x1000100010001)>>48;
s2 += ((((a2&0xFFFF0000FFFF)+(b2&0xFFFF0000FFFF)+((a2>>16)&0xFFFF0000FFFF)+((b2>>16)&0xFFFF0000FFFF))*0x800000008)>>32)
#if HAVE_BIGENDIAN
+ 2*((b1*0x1000200030004)>>48)
+ ((a1*0x1000100010001)>>48)
+ 2*((a1*0x0000100020003)>>48);
#else
+ 2*((a1*0x4000300020001)>>48)
+ ((b1*0x1000100010001)>>48)
+ 2*((b1*0x3000200010000)>>48);
#endif
}
#else
while (len > 4 && s2 < (1U << 31)) {
DO4(buf);
len -= 4;
}
#endif
DO1(buf); len--;
s1 %= BASE;
s2 %= BASE;
}
return (s2 << 16) | s1;
}

View file

@ -0,0 +1,60 @@
/*
* copyright (c) 2006 Mans Rullgard
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* @ingroup lavu_adler32
* Public header for Adler-32 hash function implementation.
*/
#ifndef AVUTIL_ADLER32_H
#define AVUTIL_ADLER32_H
#include <stdint.h>
#include "attributes.h"
/**
* @defgroup lavu_adler32 Adler-32
* @ingroup lavu_hash
* Adler-32 hash function implementation.
*
* @{
*/
/**
* Calculate the Adler32 checksum of a buffer.
*
* Passing the return value to a subsequent av_adler32_update() call
* allows the checksum of multiple buffers to be calculated as though
* they were concatenated.
*
* @param adler initial checksum value
* @param buf pointer to input buffer
* @param len size of input buffer
* @return updated checksum
*/
unsigned long av_adler32_update(unsigned long adler, const uint8_t *buf,
unsigned int len) av_pure;
/**
* @}
*/
#endif /* AVUTIL_ADLER32_H */

View file

@ -0,0 +1,268 @@
/*
* copyright (c) 2007 Michael Niedermayer <michaelni@gmx.at>
*
* some optimization ideas from aes128.c by Reimar Doeffinger
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "common.h"
#include "aes.h"
#include "aes_internal.h"
#include "intreadwrite.h"
#include "timer.h"
const int av_aes_size= sizeof(AVAES);
struct AVAES *av_aes_alloc(void)
{
return av_mallocz(sizeof(struct AVAES));
}
static const uint8_t rcon[10] = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
};
static uint8_t sbox[256];
static uint8_t inv_sbox[256];
#if CONFIG_SMALL
static uint32_t enc_multbl[1][256];
static uint32_t dec_multbl[1][256];
#else
static uint32_t enc_multbl[4][256];
static uint32_t dec_multbl[4][256];
#endif
#if HAVE_BIGENDIAN
# define ROT(x, s) (((x) >> (s)) | ((x) << (32-(s))))
#else
# define ROT(x, s) (((x) << (s)) | ((x) >> (32-(s))))
#endif
static inline void addkey(av_aes_block *dst, const av_aes_block *src,
const av_aes_block *round_key)
{
dst->u64[0] = src->u64[0] ^ round_key->u64[0];
dst->u64[1] = src->u64[1] ^ round_key->u64[1];
}
static inline void addkey_s(av_aes_block *dst, const uint8_t *src,
const av_aes_block *round_key)
{
dst->u64[0] = AV_RN64(src) ^ round_key->u64[0];
dst->u64[1] = AV_RN64(src + 8) ^ round_key->u64[1];
}
static inline void addkey_d(uint8_t *dst, const av_aes_block *src,
const av_aes_block *round_key)
{
AV_WN64(dst, src->u64[0] ^ round_key->u64[0]);
AV_WN64(dst + 8, src->u64[1] ^ round_key->u64[1]);
}
static void subshift(av_aes_block s0[2], int s, const uint8_t *box)
{
av_aes_block *s1 = (av_aes_block *) (s0[0].u8 - s);
av_aes_block *s3 = (av_aes_block *) (s0[0].u8 + s);
s0[0].u8[ 0] = box[s0[1].u8[ 0]];
s0[0].u8[ 4] = box[s0[1].u8[ 4]];
s0[0].u8[ 8] = box[s0[1].u8[ 8]];
s0[0].u8[12] = box[s0[1].u8[12]];
s1[0].u8[ 3] = box[s1[1].u8[ 7]];
s1[0].u8[ 7] = box[s1[1].u8[11]];
s1[0].u8[11] = box[s1[1].u8[15]];
s1[0].u8[15] = box[s1[1].u8[ 3]];
s0[0].u8[ 2] = box[s0[1].u8[10]];
s0[0].u8[10] = box[s0[1].u8[ 2]];
s0[0].u8[ 6] = box[s0[1].u8[14]];
s0[0].u8[14] = box[s0[1].u8[ 6]];
s3[0].u8[ 1] = box[s3[1].u8[13]];
s3[0].u8[13] = box[s3[1].u8[ 9]];
s3[0].u8[ 9] = box[s3[1].u8[ 5]];
s3[0].u8[ 5] = box[s3[1].u8[ 1]];
}
static inline int mix_core(uint32_t multbl[][256], int a, int b, int c, int d)
{
#if CONFIG_SMALL
return multbl[0][a] ^ ROT(multbl[0][b], 8) ^ ROT(multbl[0][c], 16) ^ ROT(multbl[0][d], 24);
#else
return multbl[0][a] ^ multbl[1][b] ^ multbl[2][c] ^ multbl[3][d];
#endif
}
static inline void mix(av_aes_block state[2], uint32_t multbl[][256], int s1, int s3)
{
uint8_t (*src)[4] = state[1].u8x4;
state[0].u32[0] = mix_core(multbl, src[0][0], src[s1 ][1], src[2][2], src[s3 ][3]);
state[0].u32[1] = mix_core(multbl, src[1][0], src[s3 - 1][1], src[3][2], src[s1 - 1][3]);
state[0].u32[2] = mix_core(multbl, src[2][0], src[s3 ][1], src[0][2], src[s1 ][3]);
state[0].u32[3] = mix_core(multbl, src[3][0], src[s1 - 1][1], src[1][2], src[s3 - 1][3]);
}
static inline void aes_crypt(AVAES *a, int s, const uint8_t *sbox,
uint32_t multbl[][256])
{
int r;
for (r = a->rounds - 1; r > 0; r--) {
mix(a->state, multbl, 3 - s, 1 + s);
addkey(&a->state[1], &a->state[0], &a->round_key[r]);
}
subshift(&a->state[0], s, sbox);
}
static void aes_encrypt(AVAES *a, uint8_t *dst, const uint8_t *src,
int count, uint8_t *iv, int rounds)
{
while (count--) {
addkey_s(&a->state[1], src, &a->round_key[rounds]);
if (iv)
addkey_s(&a->state[1], iv, &a->state[1]);
aes_crypt(a, 2, sbox, enc_multbl);
addkey_d(dst, &a->state[0], &a->round_key[0]);
if (iv)
memcpy(iv, dst, 16);
src += 16;
dst += 16;
}
}
static void aes_decrypt(AVAES *a, uint8_t *dst, const uint8_t *src,
int count, uint8_t *iv, int rounds)
{
while (count--) {
addkey_s(&a->state[1], src, &a->round_key[rounds]);
aes_crypt(a, 0, inv_sbox, dec_multbl);
if (iv) {
addkey_s(&a->state[0], iv, &a->state[0]);
memcpy(iv, src, 16);
}
addkey_d(dst, &a->state[0], &a->round_key[0]);
src += 16;
dst += 16;
}
}
void av_aes_crypt(AVAES *a, uint8_t *dst, const uint8_t *src,
int count, uint8_t *iv, int decrypt)
{
a->crypt(a, dst, src, count, iv, a->rounds);
}
static void init_multbl2(uint32_t tbl[][256], const int c[4],
const uint8_t *log8, const uint8_t *alog8,
const uint8_t *sbox)
{
int i;
for (i = 0; i < 256; i++) {
int x = sbox[i];
if (x) {
int k, l, m, n;
x = log8[x];
k = alog8[x + log8[c[0]]];
l = alog8[x + log8[c[1]]];
m = alog8[x + log8[c[2]]];
n = alog8[x + log8[c[3]]];
tbl[0][i] = AV_NE(MKBETAG(k, l, m, n), MKTAG(k, l, m, n));
#if !CONFIG_SMALL
tbl[1][i] = ROT(tbl[0][i], 8);
tbl[2][i] = ROT(tbl[0][i], 16);
tbl[3][i] = ROT(tbl[0][i], 24);
#endif
}
}
}
// this is based on the reference AES code by Paulo Barreto and Vincent Rijmen
int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt)
{
int i, j, t, rconpointer = 0;
uint8_t tk[8][4];
int KC = key_bits >> 5;
int rounds = KC + 6;
uint8_t log8[256];
uint8_t alog8[512];
a->crypt = decrypt ? aes_decrypt : aes_encrypt;
if (!enc_multbl[FF_ARRAY_ELEMS(enc_multbl) - 1][FF_ARRAY_ELEMS(enc_multbl[0]) - 1]) {
j = 1;
for (i = 0; i < 255; i++) {
alog8[i] = alog8[i + 255] = j;
log8[j] = i;
j ^= j + j;
if (j > 255)
j ^= 0x11B;
}
for (i = 0; i < 256; i++) {
j = i ? alog8[255 - log8[i]] : 0;
j ^= (j << 1) ^ (j << 2) ^ (j << 3) ^ (j << 4);
j = (j ^ (j >> 8) ^ 99) & 255;
inv_sbox[j] = i;
sbox[i] = j;
}
init_multbl2(dec_multbl, (const int[4]) { 0xe, 0x9, 0xd, 0xb },
log8, alog8, inv_sbox);
init_multbl2(enc_multbl, (const int[4]) { 0x2, 0x1, 0x1, 0x3 },
log8, alog8, sbox);
}
if (key_bits != 128 && key_bits != 192 && key_bits != 256)
return AVERROR(EINVAL);
a->rounds = rounds;
memcpy(tk, key, KC * 4);
memcpy(a->round_key[0].u8, key, KC * 4);
for (t = KC * 4; t < (rounds + 1) * 16; t += KC * 4) {
for (i = 0; i < 4; i++)
tk[0][i] ^= sbox[tk[KC - 1][(i + 1) & 3]];
tk[0][0] ^= rcon[rconpointer++];
for (j = 1; j < KC; j++) {
if (KC != 8 || j != KC >> 1)
for (i = 0; i < 4; i++)
tk[j][i] ^= tk[j - 1][i];
else
for (i = 0; i < 4; i++)
tk[j][i] ^= sbox[tk[j - 1][i]];
}
memcpy(a->round_key[0].u8 + t, tk, KC * 4);
}
if (decrypt) {
for (i = 1; i < rounds; i++) {
av_aes_block tmp[3];
tmp[2] = a->round_key[i];
subshift(&tmp[1], 0, sbox);
mix(tmp, dec_multbl, 1, 3);
a->round_key[i] = tmp[0];
}
} else {
for (i = 0; i < (rounds + 1) >> 1; i++)
FFSWAP(av_aes_block, a->round_key[i], a->round_key[rounds - i]);
}
return 0;
}

View file

@ -0,0 +1,65 @@
/*
* copyright (c) 2007 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_AES_H
#define AVUTIL_AES_H
#include <stdint.h>
#include "attributes.h"
#include "version.h"
/**
* @defgroup lavu_aes AES
* @ingroup lavu_crypto
* @{
*/
extern const int av_aes_size;
struct AVAES;
/**
* Allocate an AVAES context.
*/
struct AVAES *av_aes_alloc(void);
/**
* Initialize an AVAES context.
* @param key_bits 128, 192 or 256
* @param decrypt 0 for encryption, 1 for decryption
*/
int av_aes_init(struct AVAES *a, const uint8_t *key, int key_bits, int decrypt);
/**
* Encrypt or decrypt a buffer using a previously initialized context.
* @param count number of 16 byte blocks
* @param dst destination array, can be equal to src
* @param src source array, can be equal to dst
* @param iv initialization vector for CBC mode, if NULL then ECB will be used
* @param decrypt 0 for encryption, 1 for decryption
*/
void av_aes_crypt(struct AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt);
/**
* @}
*/
#endif /* AVUTIL_AES_H */

View file

@ -0,0 +1,135 @@
/*
* AES-CTR cipher
* Copyright (c) 2015 Eran Kornblau <erankor at gmail dot com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "common.h"
#include "aes_ctr.h"
#include "aes.h"
#include "random_seed.h"
#define AES_BLOCK_SIZE (16)
typedef struct AVAESCTR {
struct AVAES* aes;
uint8_t counter[AES_BLOCK_SIZE];
uint8_t encrypted_counter[AES_BLOCK_SIZE];
int block_offset;
} AVAESCTR;
struct AVAESCTR *av_aes_ctr_alloc(void)
{
return av_mallocz(sizeof(struct AVAESCTR));
}
void av_aes_ctr_set_iv(struct AVAESCTR *a, const uint8_t* iv)
{
memcpy(a->counter, iv, AES_CTR_IV_SIZE);
memset(a->counter + AES_CTR_IV_SIZE, 0, sizeof(a->counter) - AES_CTR_IV_SIZE);
a->block_offset = 0;
}
void av_aes_ctr_set_full_iv(struct AVAESCTR *a, const uint8_t* iv)
{
memcpy(a->counter, iv, sizeof(a->counter));
a->block_offset = 0;
}
const uint8_t* av_aes_ctr_get_iv(struct AVAESCTR *a)
{
return a->counter;
}
void av_aes_ctr_set_random_iv(struct AVAESCTR *a)
{
uint32_t iv[2];
iv[0] = av_get_random_seed();
iv[1] = av_get_random_seed();
av_aes_ctr_set_iv(a, (uint8_t*)iv);
}
int av_aes_ctr_init(struct AVAESCTR *a, const uint8_t *key)
{
a->aes = av_aes_alloc();
if (!a->aes) {
return AVERROR(ENOMEM);
}
av_aes_init(a->aes, key, 128, 0);
memset(a->counter, 0, sizeof(a->counter));
a->block_offset = 0;
return 0;
}
void av_aes_ctr_free(struct AVAESCTR *a)
{
if (a) {
av_freep(&a->aes);
av_free(a);
}
}
static void av_aes_ctr_increment_be64(uint8_t* counter)
{
uint8_t* cur_pos;
for (cur_pos = counter + 7; cur_pos >= counter; cur_pos--) {
(*cur_pos)++;
if (*cur_pos != 0) {
break;
}
}
}
void av_aes_ctr_increment_iv(struct AVAESCTR *a)
{
av_aes_ctr_increment_be64(a->counter);
memset(a->counter + AES_CTR_IV_SIZE, 0, sizeof(a->counter) - AES_CTR_IV_SIZE);
a->block_offset = 0;
}
void av_aes_ctr_crypt(struct AVAESCTR *a, uint8_t *dst, const uint8_t *src, int count)
{
const uint8_t* src_end = src + count;
const uint8_t* cur_end_pos;
uint8_t* encrypted_counter_pos;
while (src < src_end) {
if (a->block_offset == 0) {
av_aes_crypt(a->aes, a->encrypted_counter, a->counter, 1, NULL, 0);
av_aes_ctr_increment_be64(a->counter + 8);
}
encrypted_counter_pos = a->encrypted_counter + a->block_offset;
cur_end_pos = src + AES_BLOCK_SIZE - a->block_offset;
cur_end_pos = FFMIN(cur_end_pos, src_end);
a->block_offset += cur_end_pos - src;
a->block_offset &= (AES_BLOCK_SIZE - 1);
while (src < cur_end_pos) {
*dst++ = *src++ ^ *encrypted_counter_pos++;
}
}
}

View file

@ -0,0 +1,88 @@
/*
* AES-CTR cipher
* Copyright (c) 2015 Eran Kornblau <erankor at gmail dot com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_AES_CTR_H
#define AVUTIL_AES_CTR_H
#include <stdint.h>
#include "attributes.h"
#include "version.h"
#define AES_CTR_KEY_SIZE (16)
#define AES_CTR_IV_SIZE (8)
struct AVAESCTR;
/**
* Allocate an AVAESCTR context.
*/
struct AVAESCTR *av_aes_ctr_alloc(void);
/**
* Initialize an AVAESCTR context.
* @param key encryption key, must have a length of AES_CTR_KEY_SIZE
*/
int av_aes_ctr_init(struct AVAESCTR *a, const uint8_t *key);
/**
* Release an AVAESCTR context.
*/
void av_aes_ctr_free(struct AVAESCTR *a);
/**
* Process a buffer using a previously initialized context.
* @param dst destination array, can be equal to src
* @param src source array, can be equal to dst
* @param size the size of src and dst
*/
void av_aes_ctr_crypt(struct AVAESCTR *a, uint8_t *dst, const uint8_t *src, int size);
/**
* Get the current iv
*/
const uint8_t* av_aes_ctr_get_iv(struct AVAESCTR *a);
/**
* Generate a random iv
*/
void av_aes_ctr_set_random_iv(struct AVAESCTR *a);
/**
* Forcefully change the 8-byte iv
*/
void av_aes_ctr_set_iv(struct AVAESCTR *a, const uint8_t* iv);
/**
* Forcefully change the "full" 16-byte iv, including the counter
*/
void av_aes_ctr_set_full_iv(struct AVAESCTR *a, const uint8_t* iv);
/**
* Increment the top 64 bit of the iv (performed after each frame)
*/
void av_aes_ctr_increment_iv(struct AVAESCTR *a);
/**
* @}
*/
#endif /* AVUTIL_AES_CTR_H */

View file

@ -0,0 +1,43 @@
/*
* copyright (c) 2015 Rodger Combs <rodger.combs@gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_AES_INTERNAL_H
#define AVUTIL_AES_INTERNAL_H
#include "mem.h"
#include <stdint.h>
typedef union {
uint64_t u64[2];
uint32_t u32[4];
uint8_t u8x4[4][4];
uint8_t u8[16];
} av_aes_block;
typedef struct AVAES {
// Note: round_key[16] is accessed in the init code, but this only
// overwrites state, which does not matter (see also commit ba554c0).
DECLARE_ALIGNED(16, av_aes_block, round_key)[15];
DECLARE_ALIGNED(16, av_aes_block, state)[2];
int rounds;
void (*crypt)(struct AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int rounds);
} AVAES;
#endif /* AVUTIL_AES_INTERNAL_H */

View file

@ -0,0 +1,8 @@
OBJS += arm/cpu.o \
arm/float_dsp_init_arm.o \
VFP-OBJS += arm/float_dsp_init_vfp.o \
arm/float_dsp_vfp.o \
NEON-OBJS += arm/float_dsp_init_neon.o \
arm/float_dsp_neon.o \

View file

@ -0,0 +1,67 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_ARM_BSWAP_H
#define AVUTIL_ARM_BSWAP_H
#include <stdint.h>
#include "config.h"
#include "libavutil/attributes.h"
#ifdef __ARMCC_VERSION
#if HAVE_ARMV6
#define av_bswap32 av_bswap32
static av_always_inline av_const uint32_t av_bswap32(uint32_t x)
{
return __rev(x);
}
#endif /* HAVE_ARMV6 */
#elif HAVE_INLINE_ASM
#if HAVE_ARMV6_INLINE
#define av_bswap16 av_bswap16
static av_always_inline av_const unsigned av_bswap16(unsigned x)
{
__asm__("rev16 %0, %0" : "+r"(x));
return x;
}
#endif
#if AV_GCC_VERSION_AT_MOST(4,4)
#define av_bswap32 av_bswap32
static av_always_inline av_const uint32_t av_bswap32(uint32_t x)
{
#if HAVE_ARMV6_INLINE
__asm__("rev %0, %0" : "+r"(x));
#else
uint32_t t;
__asm__ ("eor %1, %0, %0, ror #16 \n\t"
"bic %1, %1, #0xFF0000 \n\t"
"mov %0, %0, ror #8 \n\t"
"eor %0, %0, %1, lsr #8 \n\t"
: "+r"(x), "=&r"(t));
#endif /* HAVE_ARMV6_INLINE */
return x;
}
#endif /* AV_GCC_VERSION_AT_MOST(4,4) */
#endif /* __ARMCC_VERSION */
#endif /* AVUTIL_ARM_BSWAP_H */

View file

@ -0,0 +1,170 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/cpu.h"
#include "libavutil/cpu_internal.h"
#include "config.h"
#define CORE_FLAG(f) \
(AV_CPU_FLAG_ ## f * (HAVE_ ## f ## _EXTERNAL || HAVE_ ## f ## _INLINE))
#define CORE_CPU_FLAGS \
(CORE_FLAG(ARMV5TE) | \
CORE_FLAG(ARMV6) | \
CORE_FLAG(ARMV6T2) | \
CORE_FLAG(VFP) | \
CORE_FLAG(VFPV3) | \
CORE_FLAG(NEON))
#if defined __linux__ || defined __ANDROID__
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "libavutil/avstring.h"
#define AT_HWCAP 16
/* Relevant HWCAP values from kernel headers */
#define HWCAP_VFP (1 << 6)
#define HWCAP_EDSP (1 << 7)
#define HWCAP_THUMBEE (1 << 11)
#define HWCAP_NEON (1 << 12)
#define HWCAP_VFPv3 (1 << 13)
#define HWCAP_TLS (1 << 15)
static int get_hwcap(uint32_t *hwcap)
{
struct { uint32_t a_type; uint32_t a_val; } auxv;
FILE *f = fopen("/proc/self/auxv", "r");
int err = -1;
if (!f)
return -1;
while (fread(&auxv, sizeof(auxv), 1, f) > 0) {
if (auxv.a_type == AT_HWCAP) {
*hwcap = auxv.a_val;
err = 0;
break;
}
}
fclose(f);
return err;
}
static int get_cpuinfo(uint32_t *hwcap)
{
FILE *f = fopen("/proc/cpuinfo", "r");
char buf[200];
if (!f)
return -1;
*hwcap = 0;
while (fgets(buf, sizeof(buf), f)) {
if (av_strstart(buf, "Features", NULL)) {
if (strstr(buf, " edsp "))
*hwcap |= HWCAP_EDSP;
if (strstr(buf, " tls "))
*hwcap |= HWCAP_TLS;
if (strstr(buf, " thumbee "))
*hwcap |= HWCAP_THUMBEE;
if (strstr(buf, " vfp "))
*hwcap |= HWCAP_VFP;
if (strstr(buf, " vfpv3 "))
*hwcap |= HWCAP_VFPv3;
if (strstr(buf, " neon ") || strstr(buf, " asimd "))
*hwcap |= HWCAP_NEON;
if (strstr(buf, " fp ")) // Listed on 64 bit ARMv8 kernels
*hwcap |= HWCAP_VFP | HWCAP_VFPv3;
break;
}
}
fclose(f);
return 0;
}
int ff_get_cpu_flags_arm(void)
{
int flags = CORE_CPU_FLAGS;
uint32_t hwcap;
if (get_hwcap(&hwcap) < 0)
if (get_cpuinfo(&hwcap) < 0)
return flags;
#define check_cap(cap, flag) do { \
if (hwcap & HWCAP_ ## cap) \
flags |= AV_CPU_FLAG_ ## flag; \
} while (0)
/* No flags explicitly indicate v6 or v6T2 so check others which
imply support. */
check_cap(EDSP, ARMV5TE);
check_cap(TLS, ARMV6);
check_cap(THUMBEE, ARMV6T2);
check_cap(VFP, VFP);
check_cap(VFPv3, VFPV3);
check_cap(NEON, NEON);
/* The v6 checks above are not reliable so let higher flags
trickle down. */
if (flags & (AV_CPU_FLAG_VFPV3 | AV_CPU_FLAG_NEON))
flags |= AV_CPU_FLAG_ARMV6T2;
else if (flags & (AV_CPU_FLAG_ARMV6T2 | AV_CPU_FLAG_ARMV6))
/* Some functions use the 'setend' instruction which is deprecated on ARMv8
* and serializing on some ARMv7 cores. This ensures such functions
* are only enabled on ARMv6. */
flags |= AV_CPU_FLAG_SETEND;
if (flags & AV_CPU_FLAG_ARMV6T2)
flags |= AV_CPU_FLAG_ARMV6;
/* set the virtual VFPv2 vector mode flag */
if ((flags & AV_CPU_FLAG_VFP) && !(flags & (AV_CPU_FLAG_VFPV3 | AV_CPU_FLAG_NEON)))
flags |= AV_CPU_FLAG_VFP_VM;
return flags;
}
#else
int ff_get_cpu_flags_arm(void)
{
return AV_CPU_FLAG_ARMV5TE * HAVE_ARMV5TE |
AV_CPU_FLAG_ARMV6 * HAVE_ARMV6 |
AV_CPU_FLAG_ARMV6T2 * HAVE_ARMV6T2 |
AV_CPU_FLAG_VFP * HAVE_VFP |
AV_CPU_FLAG_VFPV3 * HAVE_VFPV3 |
AV_CPU_FLAG_NEON * HAVE_NEON |
AV_CPU_FLAG_SETEND * !(HAVE_NEON | HAVE_VFPV3);
}
#endif
size_t ff_get_cpu_max_align_arm(void)
{
int flags = av_get_cpu_flags();
if (flags & AV_CPU_FLAG_NEON)
return 16;
return 8;
}

View file

@ -0,0 +1,38 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_ARM_CPU_H
#define AVUTIL_ARM_CPU_H
#include "libavutil/cpu.h"
#include "libavutil/cpu_internal.h"
#define have_armv5te(flags) CPUEXT(flags, ARMV5TE)
#define have_armv6(flags) CPUEXT(flags, ARMV6)
#define have_armv6t2(flags) CPUEXT(flags, ARMV6T2)
#define have_vfp(flags) CPUEXT(flags, VFP)
#define have_vfpv3(flags) CPUEXT(flags, VFPV3)
#define have_neon(flags) CPUEXT(flags, NEON)
#define have_setend(flags) CPUEXT(flags, SETEND)
/* some functions use the VFPv2 vector mode which is deprecated in ARMv7-A
* and might trap on such CPU depending on the OS configuration */
#define have_vfp_vm(flags) \
(HAVE_VFP && ((flags) & AV_CPU_FLAG_VFP_VM))
#endif /* AVUTIL_ARM_CPU_H */

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2009 Mans Rullgard <mans@mansr.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_ARM_FLOAT_DSP_ARM_H
#define AVUTIL_ARM_FLOAT_DSP_ARM_H
#include "libavutil/float_dsp.h"
void ff_float_dsp_init_vfp(AVFloatDSPContext *fdsp, int cpu_flags);
void ff_float_dsp_init_neon(AVFloatDSPContext *fdsp);
#endif /* AVUTIL_ARM_FLOAT_DSP_ARM_H */

View file

@ -0,0 +1,32 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/attributes.h"
#include "libavutil/float_dsp.h"
#include "cpu.h"
#include "float_dsp_arm.h"
av_cold void ff_float_dsp_init_arm(AVFloatDSPContext *fdsp)
{
int cpu_flags = av_get_cpu_flags();
if (have_vfp(cpu_flags))
ff_float_dsp_init_vfp(fdsp, cpu_flags);
if (have_neon(cpu_flags))
ff_float_dsp_init_neon(fdsp);
}

View file

@ -0,0 +1,59 @@
/*
* ARM NEON optimised Float DSP functions
* Copyright (c) 2008 Mans Rullgard <mans@mansr.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include "libavutil/attributes.h"
#include "libavutil/float_dsp.h"
#include "float_dsp_arm.h"
void ff_vector_fmul_neon(float *dst, const float *src0, const float *src1, int len);
void ff_vector_fmac_scalar_neon(float *dst, const float *src, float mul,
int len);
void ff_vector_fmul_scalar_neon(float *dst, const float *src, float mul,
int len);
void ff_vector_fmul_window_neon(float *dst, const float *src0,
const float *src1, const float *win, int len);
void ff_vector_fmul_add_neon(float *dst, const float *src0, const float *src1,
const float *src2, int len);
void ff_vector_fmul_reverse_neon(float *dst, const float *src0,
const float *src1, int len);
void ff_butterflies_float_neon(float *v1, float *v2, int len);
float ff_scalarproduct_float_neon(const float *v1, const float *v2, int len);
av_cold void ff_float_dsp_init_neon(AVFloatDSPContext *fdsp)
{
fdsp->vector_fmul = ff_vector_fmul_neon;
fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_neon;
fdsp->vector_fmul_scalar = ff_vector_fmul_scalar_neon;
fdsp->vector_fmul_window = ff_vector_fmul_window_neon;
fdsp->vector_fmul_add = ff_vector_fmul_add_neon;
fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_neon;
fdsp->butterflies_float = ff_butterflies_float_neon;
fdsp->scalarproduct_float = ff_scalarproduct_float_neon;
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2008 Siarhei Siamashka <ssvb@users.sourceforge.net>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/attributes.h"
#include "libavutil/float_dsp.h"
#include "cpu.h"
#include "float_dsp_arm.h"
void ff_vector_fmul_vfp(float *dst, const float *src0, const float *src1,
int len);
void ff_vector_fmul_window_vfp(float *dst, const float *src0,
const float *src1, const float *win, int len);
void ff_vector_fmul_reverse_vfp(float *dst, const float *src0,
const float *src1, int len);
void ff_butterflies_float_vfp(float *av_restrict v1, float *av_restrict v2, int len);
av_cold void ff_float_dsp_init_vfp(AVFloatDSPContext *fdsp, int cpu_flags)
{
if (have_vfp_vm(cpu_flags)) {
fdsp->vector_fmul = ff_vector_fmul_vfp;
fdsp->vector_fmul_window = ff_vector_fmul_window_vfp;
}
fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_vfp;
if (have_vfp_vm(cpu_flags))
fdsp->butterflies_float = ff_butterflies_float_vfp;
}

View file

@ -0,0 +1,134 @@
/*
* Copyright (c) 2010 Mans Rullgard <mans@mansr.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_ARM_INTMATH_H
#define AVUTIL_ARM_INTMATH_H
#include <stdint.h>
#include "config.h"
#include "libavutil/attributes.h"
#if HAVE_INLINE_ASM
#if HAVE_ARMV6_INLINE
#define av_clip_uint8 av_clip_uint8_arm
static av_always_inline av_const int av_clip_uint8_arm(int a)
{
int x;
__asm__ ("usat %0, #8, %1" : "=r"(x) : "r"(a));
return x;
}
#define av_clip_int8 av_clip_int8_arm
static av_always_inline av_const int av_clip_int8_arm(int a)
{
int x;
__asm__ ("ssat %0, #8, %1" : "=r"(x) : "r"(a));
return x;
}
#define av_clip_uint16 av_clip_uint16_arm
static av_always_inline av_const int av_clip_uint16_arm(int a)
{
int x;
__asm__ ("usat %0, #16, %1" : "=r"(x) : "r"(a));
return x;
}
#define av_clip_int16 av_clip_int16_arm
static av_always_inline av_const int av_clip_int16_arm(int a)
{
int x;
__asm__ ("ssat %0, #16, %1" : "=r"(x) : "r"(a));
return x;
}
#define av_clip_intp2 av_clip_intp2_arm
static av_always_inline av_const int av_clip_intp2_arm(int a, int p)
{
unsigned x;
__asm__ ("ssat %0, %2, %1" : "=r"(x) : "r"(a), "i"(p+1));
return x;
}
#define av_clip_uintp2 av_clip_uintp2_arm
static av_always_inline av_const unsigned av_clip_uintp2_arm(int a, int p)
{
unsigned x;
__asm__ ("usat %0, %2, %1" : "=r"(x) : "r"(a), "i"(p));
return x;
}
#define av_sat_add32 av_sat_add32_arm
static av_always_inline int av_sat_add32_arm(int a, int b)
{
int r;
__asm__ ("qadd %0, %1, %2" : "=r"(r) : "r"(a), "r"(b));
return r;
}
#define av_sat_dadd32 av_sat_dadd32_arm
static av_always_inline int av_sat_dadd32_arm(int a, int b)
{
int r;
__asm__ ("qdadd %0, %1, %2" : "=r"(r) : "r"(a), "r"(b));
return r;
}
#define av_sat_sub32 av_sat_sub32_arm
static av_always_inline int av_sat_sub32_arm(int a, int b)
{
int r;
__asm__ ("qsub %0, %1, %2" : "=r"(r) : "r"(a), "r"(b));
return r;
}
#define av_sat_dsub32 av_sat_dsub32_arm
static av_always_inline int av_sat_dsub32_arm(int a, int b)
{
int r;
__asm__ ("qdsub %0, %1, %2" : "=r"(r) : "r"(a), "r"(b));
return r;
}
#endif /* HAVE_ARMV6_INLINE */
#if HAVE_ASM_MOD_Q
#define av_clipl_int32 av_clipl_int32_arm
static av_always_inline av_const int32_t av_clipl_int32_arm(int64_t a)
{
int x, y;
__asm__ ("adds %1, %R2, %Q2, lsr #31 \n\t"
"itet ne \n\t"
"mvnne %1, #1<<31 \n\t"
"moveq %0, %Q2 \n\t"
"eorne %0, %1, %R2, asr #31 \n\t"
: "=r"(x), "=&r"(y) : "r"(a) : "cc");
return x;
}
#endif /* HAVE_ASM_MOD_Q */
#endif /* HAVE_INLINE_ASM */
#endif /* AVUTIL_ARM_INTMATH_H */

View file

@ -0,0 +1,91 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_ARM_INTREADWRITE_H
#define AVUTIL_ARM_INTREADWRITE_H
#include <stdint.h>
#include "config.h"
#include "libavutil/attributes.h"
#if HAVE_FAST_UNALIGNED && HAVE_INLINE_ASM && AV_GCC_VERSION_AT_MOST(4,6)
#define AV_RN16 AV_RN16
static av_always_inline unsigned AV_RN16(const void *p)
{
const uint8_t *q = p;
unsigned v;
#if AV_GCC_VERSION_AT_MOST(4,5)
__asm__ ("ldrh %0, %1" : "=r"(v) : "m"(*(const uint16_t *)q));
#elif defined __thumb__
__asm__ ("ldrh %0, %1" : "=r"(v) : "m"(q[0]), "m"(q[1]));
#else
__asm__ ("ldrh %0, %1" : "=r"(v) : "Uq"(q[0]), "m"(q[1]));
#endif
return v;
}
#define AV_WN16 AV_WN16
static av_always_inline void AV_WN16(void *p, uint16_t v)
{
__asm__ ("strh %1, %0" : "=m"(*(uint16_t *)p) : "r"(v));
}
#define AV_RN32 AV_RN32
static av_always_inline uint32_t AV_RN32(const void *p)
{
const struct __attribute__((packed)) { uint32_t v; } *q = p;
uint32_t v;
__asm__ ("ldr %0, %1" : "=r"(v) : "m"(*q));
return v;
}
#define AV_WN32 AV_WN32
static av_always_inline void AV_WN32(void *p, uint32_t v)
{
__asm__ ("str %1, %0" : "=m"(*(uint32_t *)p) : "r"(v));
}
#if HAVE_ASM_MOD_Q
#define AV_RN64 AV_RN64
static av_always_inline uint64_t AV_RN64(const void *p)
{
const struct __attribute__((packed)) { uint32_t v; } *q = p;
uint64_t v;
__asm__ ("ldr %Q0, %1 \n\t"
"ldr %R0, %2 \n\t"
: "=&r"(v)
: "m"(q[0]), "m"(q[1]));
return v;
}
#define AV_WN64 AV_WN64
static av_always_inline void AV_WN64(void *p, uint64_t v)
{
__asm__ ("str %Q2, %0 \n\t"
"str %R2, %1 \n\t"
: "=m"(*(uint32_t*)p), "=m"(*((uint32_t*)p+1))
: "r"(v));
}
#endif /* HAVE_ASM_MOD_Q */
#endif /* HAVE_INLINE_ASM */
#endif /* AVUTIL_ARM_INTREADWRITE_H */

View file

@ -0,0 +1,67 @@
/*
* check NEON registers for clobbering
* Copyright (c) 2008 Ramiro Polla <ramiro.polla@gmail.com>
* Copyright (c) 2013 Martin Storsjo
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_ARM_NEONTEST_H
#define AVUTIL_ARM_NEONTEST_H
#include <inttypes.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "libavutil/bswap.h"
#define storeneonregs(mem) \
__asm__ volatile( \
"vstm %0, {d8-d15}\n\t" \
:: "r"(mem) : "memory")
#define testneonclobbers(func, ctx, ...) \
uint64_t neon[2][8]; \
int ret; \
storeneonregs(neon[0]); \
ret = __real_ ## func(ctx, __VA_ARGS__); \
storeneonregs(neon[1]); \
if (memcmp(neon[0], neon[1], sizeof(neon[0]))) { \
int i; \
av_log(ctx, AV_LOG_ERROR, \
"NEON REGS CLOBBERED IN %s!\n", #func); \
for (i = 0; i < 8; i ++) \
if (neon[0][i] != neon[1][i]) { \
av_log(ctx, AV_LOG_ERROR, \
"d%-2d = %016"PRIx64"\n", \
8 + i, av_bswap64(neon[0][i])); \
av_log(ctx, AV_LOG_ERROR, \
" -> %016"PRIx64"\n", \
av_bswap64(neon[1][i])); \
} \
abort(); \
} \
return ret
#define wrap(func) \
int __real_ ## func; \
int __wrap_ ## func; \
int __wrap_ ## func
#endif /* AVUTIL_ARM_NEONTEST_H */

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2009 Mans Rullgard <mans@mansr.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_ARM_TIMER_H
#define AVUTIL_ARM_TIMER_H
#include <stdint.h>
#include "config.h"
#if HAVE_INLINE_ASM && defined(__ARM_ARCH_7A__)
#define AV_READ_TIME read_time
static inline uint64_t read_time(void)
{
unsigned cc;
__asm__ volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r"(cc));
return cc;
}
#endif /* HAVE_INLINE_ASM && __ARM_ARCH_7A__ */
#endif /* AVUTIL_ARM_TIMER_H */

View file

@ -0,0 +1,167 @@
/*
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Macro definitions for various function/variable attributes
*/
#ifndef AVUTIL_ATTRIBUTES_H
#define AVUTIL_ATTRIBUTES_H
#ifdef __GNUC__
# define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
# define AV_GCC_VERSION_AT_MOST(x,y) (__GNUC__ < (x) || __GNUC__ == (x) && __GNUC_MINOR__ <= (y))
#else
# define AV_GCC_VERSION_AT_LEAST(x,y) 0
# define AV_GCC_VERSION_AT_MOST(x,y) 0
#endif
#ifndef av_always_inline
#if AV_GCC_VERSION_AT_LEAST(3,1)
# define av_always_inline __attribute__((always_inline)) inline
#elif defined(_MSC_VER)
# define av_always_inline __forceinline
#else
# define av_always_inline inline
#endif
#endif
#ifndef av_extern_inline
#if defined(__ICL) && __ICL >= 1210 || defined(__GNUC_STDC_INLINE__)
# define av_extern_inline extern inline
#else
# define av_extern_inline inline
#endif
#endif
#if AV_GCC_VERSION_AT_LEAST(3,4)
# define av_warn_unused_result __attribute__((warn_unused_result))
#else
# define av_warn_unused_result
#endif
#if AV_GCC_VERSION_AT_LEAST(3,1)
# define av_noinline __attribute__((noinline))
#elif defined(_MSC_VER)
# define av_noinline __declspec(noinline)
#else
# define av_noinline
#endif
#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__)
# define av_pure __attribute__((pure))
#else
# define av_pure
#endif
#if AV_GCC_VERSION_AT_LEAST(2,6) || defined(__clang__)
# define av_const __attribute__((const))
#else
# define av_const
#endif
#if AV_GCC_VERSION_AT_LEAST(4,3) || defined(__clang__)
# define av_cold __attribute__((cold))
#else
# define av_cold
#endif
#if AV_GCC_VERSION_AT_LEAST(4,1) && !defined(__llvm__)
# define av_flatten __attribute__((flatten))
#else
# define av_flatten
#endif
#if AV_GCC_VERSION_AT_LEAST(3,1)
# define attribute_deprecated __attribute__((deprecated))
#elif defined(_MSC_VER)
# define attribute_deprecated __declspec(deprecated)
#else
# define attribute_deprecated
#endif
/**
* Disable warnings about deprecated features
* This is useful for sections of code kept for backward compatibility and
* scheduled for removal.
*/
#ifndef AV_NOWARN_DEPRECATED
#if AV_GCC_VERSION_AT_LEAST(4,6)
# define AV_NOWARN_DEPRECATED(code) \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \
code \
_Pragma("GCC diagnostic pop")
#elif defined(_MSC_VER)
# define AV_NOWARN_DEPRECATED(code) \
__pragma(warning(push)) \
__pragma(warning(disable : 4996)) \
code; \
__pragma(warning(pop))
#else
# define AV_NOWARN_DEPRECATED(code) code
#endif
#endif
#if defined(__GNUC__) || defined(__clang__)
# define av_unused __attribute__((unused))
#else
# define av_unused
#endif
/**
* Mark a variable as used and prevent the compiler from optimizing it
* away. This is useful for variables accessed only from inline
* assembler without the compiler being aware.
*/
#if AV_GCC_VERSION_AT_LEAST(3,1) || defined(__clang__)
# define av_used __attribute__((used))
#else
# define av_used
#endif
#if AV_GCC_VERSION_AT_LEAST(3,3) || defined(__clang__)
# define av_alias __attribute__((may_alias))
#else
# define av_alias
#endif
#if (defined(__GNUC__) || defined(__clang__)) && !defined(__INTEL_COMPILER)
# define av_uninit(x) x=x
#else
# define av_uninit(x) x
#endif
#if defined(__GNUC__) || defined(__clang__)
# define av_builtin_constant_p __builtin_constant_p
# define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos)))
#else
# define av_builtin_constant_p(x) 0
# define av_printf_format(fmtpos, attrpos)
#endif
#if AV_GCC_VERSION_AT_LEAST(2,5) || defined(__clang__)
# define av_noreturn __attribute__((noreturn))
#else
# define av_noreturn
#endif
#endif /* AVUTIL_ATTRIBUTES_H */

View file

@ -0,0 +1,236 @@
/*
* Audio FIFO
* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Audio FIFO
*/
#include "avutil.h"
#include "audio_fifo.h"
#include "common.h"
#include "fifo.h"
#include "mem.h"
#include "samplefmt.h"
struct AVAudioFifo {
AVFifoBuffer **buf; /**< single buffer for interleaved, per-channel buffers for planar */
int nb_buffers; /**< number of buffers */
int nb_samples; /**< number of samples currently in the FIFO */
int allocated_samples; /**< current allocated size, in samples */
int channels; /**< number of channels */
enum AVSampleFormat sample_fmt; /**< sample format */
int sample_size; /**< size, in bytes, of one sample in a buffer */
};
void av_audio_fifo_free(AVAudioFifo *af)
{
if (af) {
if (af->buf) {
int i;
for (i = 0; i < af->nb_buffers; i++) {
av_fifo_freep(&af->buf[i]);
}
av_freep(&af->buf);
}
av_free(af);
}
}
AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels,
int nb_samples)
{
AVAudioFifo *af;
int buf_size, i;
/* get channel buffer size (also validates parameters) */
if (av_samples_get_buffer_size(&buf_size, channels, nb_samples, sample_fmt, 1) < 0)
return NULL;
af = av_mallocz(sizeof(*af));
if (!af)
return NULL;
af->channels = channels;
af->sample_fmt = sample_fmt;
af->sample_size = buf_size / nb_samples;
af->nb_buffers = av_sample_fmt_is_planar(sample_fmt) ? channels : 1;
af->buf = av_mallocz_array(af->nb_buffers, sizeof(*af->buf));
if (!af->buf)
goto error;
for (i = 0; i < af->nb_buffers; i++) {
af->buf[i] = av_fifo_alloc(buf_size);
if (!af->buf[i])
goto error;
}
af->allocated_samples = nb_samples;
return af;
error:
av_audio_fifo_free(af);
return NULL;
}
int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples)
{
int i, ret, buf_size;
if ((ret = av_samples_get_buffer_size(&buf_size, af->channels, nb_samples,
af->sample_fmt, 1)) < 0)
return ret;
for (i = 0; i < af->nb_buffers; i++) {
if ((ret = av_fifo_realloc2(af->buf[i], buf_size)) < 0)
return ret;
}
af->allocated_samples = nb_samples;
return 0;
}
int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples)
{
int i, ret, size;
/* automatically reallocate buffers if needed */
if (av_audio_fifo_space(af) < nb_samples) {
int current_size = av_audio_fifo_size(af);
/* check for integer overflow in new size calculation */
if (INT_MAX / 2 - current_size < nb_samples)
return AVERROR(EINVAL);
/* reallocate buffers */
if ((ret = av_audio_fifo_realloc(af, 2 * (current_size + nb_samples))) < 0)
return ret;
}
size = nb_samples * af->sample_size;
for (i = 0; i < af->nb_buffers; i++) {
ret = av_fifo_generic_write(af->buf[i], data[i], size, NULL);
if (ret != size)
return AVERROR_BUG;
}
af->nb_samples += nb_samples;
return nb_samples;
}
int av_audio_fifo_peek(AVAudioFifo *af, void **data, int nb_samples)
{
int i, ret, size;
if (nb_samples < 0)
return AVERROR(EINVAL);
nb_samples = FFMIN(nb_samples, af->nb_samples);
if (!nb_samples)
return 0;
size = nb_samples * af->sample_size;
for (i = 0; i < af->nb_buffers; i++) {
if ((ret = av_fifo_generic_peek(af->buf[i], data[i], size, NULL)) < 0)
return AVERROR_BUG;
}
return nb_samples;
}
int av_audio_fifo_peek_at(AVAudioFifo *af, void **data, int nb_samples, int offset)
{
int i, ret, size;
if (offset < 0 || offset >= af->nb_samples)
return AVERROR(EINVAL);
if (nb_samples < 0)
return AVERROR(EINVAL);
nb_samples = FFMIN(nb_samples, af->nb_samples);
if (!nb_samples)
return 0;
if (offset > af->nb_samples - nb_samples)
return AVERROR(EINVAL);
offset *= af->sample_size;
size = nb_samples * af->sample_size;
for (i = 0; i < af->nb_buffers; i++) {
if ((ret = av_fifo_generic_peek_at(af->buf[i], data[i], offset, size, NULL)) < 0)
return AVERROR_BUG;
}
return nb_samples;
}
int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples)
{
int i, size;
if (nb_samples < 0)
return AVERROR(EINVAL);
nb_samples = FFMIN(nb_samples, af->nb_samples);
if (!nb_samples)
return 0;
size = nb_samples * af->sample_size;
for (i = 0; i < af->nb_buffers; i++) {
if (av_fifo_generic_read(af->buf[i], data[i], size, NULL) < 0)
return AVERROR_BUG;
}
af->nb_samples -= nb_samples;
return nb_samples;
}
int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples)
{
int i, size;
if (nb_samples < 0)
return AVERROR(EINVAL);
nb_samples = FFMIN(nb_samples, af->nb_samples);
if (nb_samples) {
size = nb_samples * af->sample_size;
for (i = 0; i < af->nb_buffers; i++)
av_fifo_drain(af->buf[i], size);
af->nb_samples -= nb_samples;
}
return 0;
}
void av_audio_fifo_reset(AVAudioFifo *af)
{
int i;
for (i = 0; i < af->nb_buffers; i++)
av_fifo_reset(af->buf[i]);
af->nb_samples = 0;
}
int av_audio_fifo_size(AVAudioFifo *af)
{
return af->nb_samples;
}
int av_audio_fifo_space(AVAudioFifo *af)
{
return af->allocated_samples - af->nb_samples;
}

View file

@ -0,0 +1,187 @@
/*
* Audio FIFO
* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Audio FIFO Buffer
*/
#ifndef AVUTIL_AUDIO_FIFO_H
#define AVUTIL_AUDIO_FIFO_H
#include "avutil.h"
#include "fifo.h"
#include "samplefmt.h"
/**
* @addtogroup lavu_audio
* @{
*
* @defgroup lavu_audiofifo Audio FIFO Buffer
* @{
*/
/**
* Context for an Audio FIFO Buffer.
*
* - Operates at the sample level rather than the byte level.
* - Supports multiple channels with either planar or packed sample format.
* - Automatic reallocation when writing to a full buffer.
*/
typedef struct AVAudioFifo AVAudioFifo;
/**
* Free an AVAudioFifo.
*
* @param af AVAudioFifo to free
*/
void av_audio_fifo_free(AVAudioFifo *af);
/**
* Allocate an AVAudioFifo.
*
* @param sample_fmt sample format
* @param channels number of channels
* @param nb_samples initial allocation size, in samples
* @return newly allocated AVAudioFifo, or NULL on error
*/
AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels,
int nb_samples);
/**
* Reallocate an AVAudioFifo.
*
* @param af AVAudioFifo to reallocate
* @param nb_samples new allocation size, in samples
* @return 0 if OK, or negative AVERROR code on failure
*/
av_warn_unused_result
int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples);
/**
* Write data to an AVAudioFifo.
*
* The AVAudioFifo will be reallocated automatically if the available space
* is less than nb_samples.
*
* @see enum AVSampleFormat
* The documentation for AVSampleFormat describes the data layout.
*
* @param af AVAudioFifo to write to
* @param data audio data plane pointers
* @param nb_samples number of samples to write
* @return number of samples actually written, or negative AVERROR
* code on failure. If successful, the number of samples
* actually written will always be nb_samples.
*/
int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples);
/**
* Peek data from an AVAudioFifo.
*
* @see enum AVSampleFormat
* The documentation for AVSampleFormat describes the data layout.
*
* @param af AVAudioFifo to read from
* @param data audio data plane pointers
* @param nb_samples number of samples to peek
* @return number of samples actually peek, or negative AVERROR code
* on failure. The number of samples actually peek will not
* be greater than nb_samples, and will only be less than
* nb_samples if av_audio_fifo_size is less than nb_samples.
*/
int av_audio_fifo_peek(AVAudioFifo *af, void **data, int nb_samples);
/**
* Peek data from an AVAudioFifo.
*
* @see enum AVSampleFormat
* The documentation for AVSampleFormat describes the data layout.
*
* @param af AVAudioFifo to read from
* @param data audio data plane pointers
* @param nb_samples number of samples to peek
* @param offset offset from current read position
* @return number of samples actually peek, or negative AVERROR code
* on failure. The number of samples actually peek will not
* be greater than nb_samples, and will only be less than
* nb_samples if av_audio_fifo_size is less than nb_samples.
*/
int av_audio_fifo_peek_at(AVAudioFifo *af, void **data, int nb_samples, int offset);
/**
* Read data from an AVAudioFifo.
*
* @see enum AVSampleFormat
* The documentation for AVSampleFormat describes the data layout.
*
* @param af AVAudioFifo to read from
* @param data audio data plane pointers
* @param nb_samples number of samples to read
* @return number of samples actually read, or negative AVERROR code
* on failure. The number of samples actually read will not
* be greater than nb_samples, and will only be less than
* nb_samples if av_audio_fifo_size is less than nb_samples.
*/
int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples);
/**
* Drain data from an AVAudioFifo.
*
* Removes the data without reading it.
*
* @param af AVAudioFifo to drain
* @param nb_samples number of samples to drain
* @return 0 if OK, or negative AVERROR code on failure
*/
int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples);
/**
* Reset the AVAudioFifo buffer.
*
* This empties all data in the buffer.
*
* @param af AVAudioFifo to reset
*/
void av_audio_fifo_reset(AVAudioFifo *af);
/**
* Get the current number of samples in the AVAudioFifo available for reading.
*
* @param af the AVAudioFifo to query
* @return number of samples available for reading
*/
int av_audio_fifo_size(AVAudioFifo *af);
/**
* Get the current number of samples in the AVAudioFifo available for writing.
*
* @param af the AVAudioFifo to query
* @return number of samples available for writing
*/
int av_audio_fifo_space(AVAudioFifo *af);
/**
* @}
* @}
*/
#endif /* AVUTIL_AUDIO_FIFO_H */

View file

@ -0,0 +1,75 @@
/*
* copyright (c) 2010 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* simple assert() macros that are a bit more flexible than ISO C assert().
* @author Michael Niedermayer <michaelni@gmx.at>
*/
#ifndef AVUTIL_AVASSERT_H
#define AVUTIL_AVASSERT_H
#include <stdlib.h>
#include "avutil.h"
#include "log.h"
/**
* assert() equivalent, that is always enabled.
*/
#define av_assert0(cond) do { \
if (!(cond)) { \
av_log(NULL, AV_LOG_PANIC, "Assertion %s failed at %s:%d\n", \
AV_STRINGIFY(cond), __FILE__, __LINE__); \
abort(); \
} \
} while (0)
/**
* assert() equivalent, that does not lie in speed critical code.
* These asserts() thus can be enabled without fearing speed loss.
*/
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 0
#define av_assert1(cond) av_assert0(cond)
#else
#define av_assert1(cond) ((void)0)
#endif
/**
* assert() equivalent, that does lie in speed critical code.
*/
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1
#define av_assert2(cond) av_assert0(cond)
#define av_assert2_fpu() av_assert0_fpu()
#else
#define av_assert2(cond) ((void)0)
#define av_assert2_fpu() ((void)0)
#endif
/**
* Assert that floating point operations can be executed.
*
* This will av_assert0() that the cpu is not in MMX state on X86
*/
void av_assert0_fpu(void);
#endif /* AVUTIL_AVASSERT_H */

View file

@ -0,0 +1,970 @@
/*
* Copyright (c) 2005-2014 Rich Felker, et al.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <float.h>
#include "config.h"
#include "common.h"
#include "mem.h"
#include "avassert.h"
#include "avstring.h"
#include "bprint.h"
typedef struct FFFILE {
size_t buf_size;
unsigned char *buf;
unsigned char *rpos, *rend;
unsigned char *shend;
ptrdiff_t shlim, shcnt;
void *cookie;
size_t (*read)(struct FFFILE *, unsigned char *, size_t);
} FFFILE;
#define SIZE_hh -2
#define SIZE_h -1
#define SIZE_def 0
#define SIZE_l 1
#define SIZE_L 2
#define SIZE_ll 3
#define shcnt(f) ((f)->shcnt + ((f)->rpos - (f)->buf))
static int fftoread(FFFILE *f)
{
f->rpos = f->rend = f->buf + f->buf_size;
return 0;
}
static size_t ffstring_read(FFFILE *f, unsigned char *buf, size_t len)
{
char *src = f->cookie;
size_t k = len+256;
char *end = memchr(src, 0, k);
if (end) k = end-src;
if (k < len) len = k;
memcpy(buf, src, len);
f->rpos = (void *)(src+len);
f->rend = (void *)(src+k);
f->cookie = src+k;
return len;
}
static int ffuflow(FFFILE *f)
{
unsigned char c;
if (!fftoread(f) && f->read(f, &c, 1)==1) return c;
return EOF;
}
static void ffshlim(FFFILE *f, ptrdiff_t lim)
{
f->shlim = lim;
f->shcnt = f->buf - f->rpos;
/* If lim is nonzero, rend must be a valid pointer. */
if (lim && f->rend - f->rpos > lim)
f->shend = f->rpos + lim;
else
f->shend = f->rend;
}
static int ffshgetc(FFFILE *f)
{
int c;
ptrdiff_t cnt = shcnt(f);
if (f->shlim && cnt >= f->shlim || (c=ffuflow(f)) < 0) {
f->shcnt = f->buf - f->rpos + cnt;
f->shend = 0;
return EOF;
}
cnt++;
if (f->shlim && f->rend - f->rpos > f->shlim - cnt)
f->shend = f->rpos + (f->shlim - cnt);
else
f->shend = f->rend;
f->shcnt = f->buf - f->rpos + cnt;
if (f->rpos[-1] != c) f->rpos[-1] = c;
return c;
}
#define shlim(f, lim) ffshlim((f), (lim))
#define shgetc(f) (((f)->rpos != (f)->shend) ? *(f)->rpos++ : ffshgetc(f))
#define shunget(f) ((f)->shend ? (void)(f)->rpos-- : (void)0)
static const unsigned char table[] = { -1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
-1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
-1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
};
static unsigned long long ffintscan(FFFILE *f, unsigned base, int pok, unsigned long long lim)
{
const unsigned char *val = table+1;
int c, neg=0;
unsigned x;
unsigned long long y;
if (base > 36 || base == 1) {
errno = EINVAL;
return 0;
}
while (av_isspace((c=shgetc(f))));
if (c=='+' || c=='-') {
neg = -(c=='-');
c = shgetc(f);
}
if ((base == 0 || base == 16) && c=='0') {
c = shgetc(f);
if ((c|32)=='x') {
c = shgetc(f);
if (val[c]>=16) {
shunget(f);
if (pok) shunget(f);
else shlim(f, 0);
return 0;
}
base = 16;
} else if (base == 0) {
base = 8;
}
} else {
if (base == 0) base = 10;
if (val[c] >= base) {
shunget(f);
shlim(f, 0);
errno = EINVAL;
return 0;
}
}
if (base == 10) {
for (x=0; c-'0'<10U && x<=UINT_MAX/10-1; c=shgetc(f))
x = x*10 + (c-'0');
for (y=x; c-'0'<10U && y<=ULLONG_MAX/10 && 10*y<=ULLONG_MAX-(c-'0'); c=shgetc(f))
y = y*10 + (c-'0');
if (c-'0'>=10U) goto done;
} else if (!(base & base-1)) {
int bs = "\0\1\2\4\7\3\6\5"[(0x17*base)>>5&7];
for (x=0; val[c]<base && x<=UINT_MAX/32; c=shgetc(f))
x = x<<bs | val[c];
for (y=x; val[c]<base && y<=ULLONG_MAX>>bs; c=shgetc(f))
y = y<<bs | val[c];
} else {
for (x=0; val[c]<base && x<=UINT_MAX/36-1; c=shgetc(f))
x = x*base + val[c];
for (y=x; val[c]<base && y<=ULLONG_MAX/base && base*y<=ULLONG_MAX-val[c]; c=shgetc(f))
y = y*base + val[c];
}
if (val[c]<base) {
for (; val[c]<base; c=shgetc(f));
errno = ERANGE;
y = lim;
if (lim&1) neg = 0;
}
done:
shunget(f);
if (y>=lim) {
if (!(lim&1) && !neg) {
errno = ERANGE;
return lim-1;
} else if (y>lim) {
errno = ERANGE;
return lim;
}
}
return (y^neg)-neg;
}
static long long scanexp(FFFILE *f, int pok)
{
int c;
int x;
long long y;
int neg = 0;
c = shgetc(f);
if (c=='+' || c=='-') {
neg = (c=='-');
c = shgetc(f);
if (c-'0'>=10U && pok) shunget(f);
}
if (c-'0'>=10U) {
shunget(f);
return LLONG_MIN;
}
for (x=0; c-'0'<10U && x<INT_MAX/10; c = shgetc(f))
x = 10*x + c-'0';
for (y=x; c-'0'<10U && y<LLONG_MAX/100; c = shgetc(f))
y = 10*y + c-'0';
for (; c-'0'<10U; c = shgetc(f));
shunget(f);
return neg ? -y : y;
}
#define LD_B1B_DIG 2
#define LD_B1B_MAX 9007199, 254740991
#define KMAX 128
#define MASK (KMAX-1)
static double decfloat(FFFILE *f, int c, int bits, int emin, int sign, int pok)
{
uint32_t x[KMAX];
static const uint32_t th[] = { LD_B1B_MAX };
int i, j, k, a, z;
long long lrp=0, dc=0;
long long e10=0;
int lnz = 0;
int gotdig = 0, gotrad = 0;
int rp;
int e2;
int emax = -emin-bits+3;
int denormal = 0;
double y;
double frac=0;
double bias=0;
static const int p10s[] = { 10, 100, 1000, 10000,
100000, 1000000, 10000000, 100000000 };
j=0;
k=0;
/* Don't let leading zeros consume buffer space */
for (; c=='0'; c = shgetc(f)) gotdig=1;
if (c=='.') {
gotrad = 1;
for (c = shgetc(f); c=='0'; c = shgetc(f)) gotdig=1, lrp--;
}
x[0] = 0;
for (; c-'0'<10U || c=='.'; c = shgetc(f)) {
if (c == '.') {
if (gotrad) break;
gotrad = 1;
lrp = dc;
} else if (k < KMAX-3) {
dc++;
if (c!='0') lnz = dc;
if (j) x[k] = x[k]*10 + c-'0';
else x[k] = c-'0';
if (++j==9) {
k++;
j=0;
}
gotdig=1;
} else {
dc++;
if (c!='0') {
lnz = (KMAX-4)*9;
x[KMAX-4] |= 1;
}
}
}
if (!gotrad) lrp=dc;
if (gotdig && (c|32)=='e') {
e10 = scanexp(f, pok);
if (e10 == LLONG_MIN) {
if (pok) {
shunget(f);
} else {
shlim(f, 0);
return 0;
}
e10 = 0;
}
lrp += e10;
} else if (c>=0) {
shunget(f);
}
if (!gotdig) {
errno = EINVAL;
shlim(f, 0);
return 0;
}
/* Handle zero specially to avoid nasty special cases later */
if (!x[0]) return sign * 0.0;
/* Optimize small integers (w/no exponent) and over/under-flow */
if (lrp==dc && dc<10 && (bits>30 || x[0]>>bits==0))
return sign * (double)x[0];
if (lrp > -emin/2) {
errno = ERANGE;
return sign * DBL_MAX * DBL_MAX;
}
if (lrp < emin-2*DBL_MANT_DIG) {
errno = ERANGE;
return sign * DBL_MIN * DBL_MIN;
}
/* Align incomplete final B1B digit */
if (j) {
for (; j<9; j++) x[k]*=10;
k++;
j=0;
}
a = 0;
z = k;
e2 = 0;
rp = lrp;
/* Optimize small to mid-size integers (even in exp. notation) */
if (lnz<9 && lnz<=rp && rp < 18) {
int bitlim;
if (rp == 9) return sign * (double)x[0];
if (rp < 9) return sign * (double)x[0] / p10s[8-rp];
bitlim = bits-3*(int)(rp-9);
if (bitlim>30 || x[0]>>bitlim==0)
return sign * (double)x[0] * p10s[rp-10];
}
/* Drop trailing zeros */
for (; !x[z-1]; z--);
/* Align radix point to B1B digit boundary */
if (rp % 9) {
int rpm9 = rp>=0 ? rp%9 : rp%9+9;
int p10 = p10s[8-rpm9];
uint32_t carry = 0;
for (k=a; k!=z; k++) {
uint32_t tmp = x[k] % p10;
x[k] = x[k]/p10 + carry;
carry = 1000000000/p10 * tmp;
if (k==a && !x[k]) {
a = (a+1 & MASK);
rp -= 9;
}
}
if (carry) x[z++] = carry;
rp += 9-rpm9;
}
/* Upscale until desired number of bits are left of radix point */
while (rp < 9*LD_B1B_DIG || (rp == 9*LD_B1B_DIG && x[a]<th[0])) {
uint32_t carry = 0;
e2 -= 29;
for (k=(z-1 & MASK); ; k=(k-1 & MASK)) {
uint64_t tmp = ((uint64_t)x[k] << 29) + carry;
if (tmp > 1000000000) {
carry = tmp / 1000000000;
x[k] = tmp % 1000000000;
} else {
carry = 0;
x[k] = tmp;
}
if (k==(z-1 & MASK) && k!=a && !x[k]) z = k;
if (k==a) break;
}
if (carry) {
rp += 9;
a = (a-1 & MASK);
if (a == z) {
z = (z-1 & MASK);
x[z-1 & MASK] |= x[z];
}
x[a] = carry;
}
}
/* Downscale until exactly number of bits are left of radix point */
for (;;) {
uint32_t carry = 0;
int sh = 1;
for (i=0; i<LD_B1B_DIG; i++) {
k = (a+i & MASK);
if (k == z || x[k] < th[i]) {
i=LD_B1B_DIG;
break;
}
if (x[a+i & MASK] > th[i]) break;
}
if (i==LD_B1B_DIG && rp==9*LD_B1B_DIG) break;
/* FIXME: find a way to compute optimal sh */
if (rp > 9+9*LD_B1B_DIG) sh = 9;
e2 += sh;
for (k=a; k!=z; k=(k+1 & MASK)) {
uint32_t tmp = x[k] & (1<<sh)-1;
x[k] = (x[k]>>sh) + carry;
carry = (1000000000>>sh) * tmp;
if (k==a && !x[k]) {
a = (a+1 & MASK);
i--;
rp -= 9;
}
}
if (carry) {
if ((z+1 & MASK) != a) {
x[z] = carry;
z = (z+1 & MASK);
} else x[z-1 & MASK] |= 1;
}
}
/* Assemble desired bits into floating point variable */
for (y=i=0; i<LD_B1B_DIG; i++) {
if ((a+i & MASK)==z) x[(z=(z+1 & MASK))-1] = 0;
y = 1000000000.0L * y + x[a+i & MASK];
}
y *= sign;
/* Limit precision for denormal results */
if (bits > DBL_MANT_DIG+e2-emin) {
bits = DBL_MANT_DIG+e2-emin;
if (bits<0) bits=0;
denormal = 1;
}
/* Calculate bias term to force rounding, move out lower bits */
if (bits < DBL_MANT_DIG) {
bias = copysign(scalbn(1, 2*DBL_MANT_DIG-bits-1), y);
frac = fmod(y, scalbn(1, DBL_MANT_DIG-bits));
y -= frac;
y += bias;
}
/* Process tail of decimal input so it can affect rounding */
if ((a+i & MASK) != z) {
uint32_t t = x[a+i & MASK];
if (t < 500000000 && (t || (a+i+1 & MASK) != z))
frac += 0.25*sign;
else if (t > 500000000)
frac += 0.75*sign;
else if (t == 500000000) {
if ((a+i+1 & MASK) == z)
frac += 0.5*sign;
else
frac += 0.75*sign;
}
if (DBL_MANT_DIG-bits >= 2 && !fmod(frac, 1))
frac++;
}
y += frac;
y -= bias;
if ((e2+DBL_MANT_DIG & INT_MAX) > emax-5) {
if (fabs(y) >= pow(2, DBL_MANT_DIG)) {
if (denormal && bits==DBL_MANT_DIG+e2-emin)
denormal = 0;
y *= 0.5;
e2++;
}
if (e2+DBL_MANT_DIG>emax || (denormal && frac))
errno = ERANGE;
}
return scalbn(y, e2);
}
static double hexfloat(FFFILE *f, int bits, int emin, int sign, int pok)
{
uint32_t x = 0;
double y = 0;
double scale = 1;
double bias = 0;
int gottail = 0, gotrad = 0, gotdig = 0;
long long rp = 0;
long long dc = 0;
long long e2 = 0;
int d;
int c;
c = shgetc(f);
/* Skip leading zeros */
for (; c=='0'; c = shgetc(f))
gotdig = 1;
if (c=='.') {
gotrad = 1;
c = shgetc(f);
/* Count zeros after the radix point before significand */
for (rp=0; c=='0'; c = shgetc(f), rp--) gotdig = 1;
}
for (; c-'0'<10U || (c|32)-'a'<6U || c=='.'; c = shgetc(f)) {
if (c=='.') {
if (gotrad) break;
rp = dc;
gotrad = 1;
} else {
gotdig = 1;
if (c > '9') d = (c|32)+10-'a';
else d = c-'0';
if (dc<8) {
x = x*16 + d;
} else if (dc < DBL_MANT_DIG/4+1) {
y += d*(scale/=16);
} else if (d && !gottail) {
y += 0.5*scale;
gottail = 1;
}
dc++;
}
}
if (!gotdig) {
shunget(f);
if (pok) {
shunget(f);
if (gotrad) shunget(f);
} else {
shlim(f, 0);
}
return sign * 0.0;
}
if (!gotrad) rp = dc;
while (dc<8) x *= 16, dc++;
if ((c|32)=='p') {
e2 = scanexp(f, pok);
if (e2 == LLONG_MIN) {
if (pok) {
shunget(f);
} else {
shlim(f, 0);
return 0;
}
e2 = 0;
}
} else {
shunget(f);
}
e2 += 4*rp - 32;
if (!x) return sign * 0.0;
if (e2 > -emin) {
errno = ERANGE;
return sign * DBL_MAX * DBL_MAX;
}
if (e2 < emin-2*DBL_MANT_DIG) {
errno = ERANGE;
return sign * DBL_MIN * DBL_MIN;
}
while (x < 0x80000000) {
if (y>=0.5) {
x += x + 1;
y += y - 1;
} else {
x += x;
y += y;
}
e2--;
}
if (bits > 32+e2-emin) {
bits = 32+e2-emin;
if (bits<0) bits=0;
}
if (bits < DBL_MANT_DIG)
bias = copysign(scalbn(1, 32+DBL_MANT_DIG-bits-1), sign);
if (bits<32 && y && !(x&1)) x++, y=0;
y = bias + sign*(double)x + sign*y;
y -= bias;
if (!y) errno = ERANGE;
return scalbn(y, e2);
}
static double fffloatscan(FFFILE *f, int prec, int pok)
{
int sign = 1;
size_t i;
int bits;
int emin;
int c;
switch (prec) {
case 0:
bits = FLT_MANT_DIG;
emin = FLT_MIN_EXP-bits;
break;
case 1:
bits = DBL_MANT_DIG;
emin = DBL_MIN_EXP-bits;
break;
case 2:
bits = DBL_MANT_DIG;
emin = DBL_MIN_EXP-bits;
break;
default:
return 0;
}
while (av_isspace((c = shgetc(f))));
if (c=='+' || c=='-') {
sign -= 2*(c=='-');
c = shgetc(f);
}
for (i=0; i<8 && (c|32)=="infinity"[i]; i++)
if (i<7) c = shgetc(f);
if (i==3 || i==8 || (i>3 && pok)) {
if (i!=8) {
shunget(f);
if (pok) for (; i>3; i--) shunget(f);
}
return sign * INFINITY;
}
if (!i) for (i=0; i<3 && (c|32)=="nan"[i]; i++)
if (i<2) c = shgetc(f);
if (i==3) {
if (shgetc(f) != '(') {
shunget(f);
return NAN;
}
for (i=1; ; i++) {
c = shgetc(f);
if (c-'0'<10U || c-'A'<26U || c-'a'<26U || c=='_')
continue;
if (c==')') return NAN;
shunget(f);
if (!pok) {
errno = EINVAL;
shlim(f, 0);
return 0;
}
while (i--) shunget(f);
return NAN;
}
return NAN;
}
if (i) {
shunget(f);
errno = EINVAL;
shlim(f, 0);
return 0;
}
if (c=='0') {
c = shgetc(f);
if ((c|32) == 'x')
return hexfloat(f, bits, emin, sign, pok);
shunget(f);
c = '0';
}
return decfloat(f, c, bits, emin, sign, pok);
}
static void *arg_n(va_list ap, unsigned int n)
{
void *p;
unsigned int i;
va_list ap2;
va_copy(ap2, ap);
for (i=n; i>1; i--) va_arg(ap2, void *);
p = va_arg(ap2, void *);
va_end(ap2);
return p;
}
static void store_int(void *dest, int size, unsigned long long i)
{
if (!dest) return;
switch (size) {
case SIZE_hh:
*(char *)dest = i;
break;
case SIZE_h:
*(short *)dest = i;
break;
case SIZE_def:
*(int *)dest = i;
break;
case SIZE_l:
*(long *)dest = i;
break;
case SIZE_ll:
*(long long *)dest = i;
break;
}
}
static int ff_vfscanf(FFFILE *f, const char *fmt, va_list ap)
{
int width;
int size;
int base;
const unsigned char *p;
int c, t;
char *s;
void *dest=NULL;
int invert;
int matches=0;
unsigned long long x;
double y;
ptrdiff_t pos = 0;
unsigned char scanset[257];
size_t i;
for (p=(const unsigned char *)fmt; *p; p++) {
if (av_isspace(*p)) {
while (av_isspace(p[1])) p++;
shlim(f, 0);
while (av_isspace(shgetc(f)));
shunget(f);
pos += shcnt(f);
continue;
}
if (*p != '%' || p[1] == '%') {
shlim(f, 0);
if (*p == '%') {
p++;
while (av_isspace((c=shgetc(f))));
} else {
c = shgetc(f);
}
if (c!=*p) {
shunget(f);
if (c<0) goto input_fail;
goto match_fail;
}
pos += shcnt(f);
continue;
}
p++;
if (*p=='*') {
dest = 0; p++;
} else if (av_isdigit(*p) && p[1]=='$') {
dest = arg_n(ap, *p-'0'); p+=2;
} else {
dest = va_arg(ap, void *);
}
for (width=0; av_isdigit(*p); p++) {
width = 10*width + *p - '0';
}
if (*p=='m') {
s = 0;
p++;
}
size = SIZE_def;
switch (*p++) {
case 'h':
if (*p == 'h') p++, size = SIZE_hh;
else size = SIZE_h;
break;
case 'l':
if (*p == 'l') p++, size = SIZE_ll;
else size = SIZE_l;
break;
case 'j':
size = SIZE_ll;
break;
case 'z':
case 't':
size = SIZE_l;
break;
case 'L':
size = SIZE_L;
break;
case 'd': case 'i': case 'o': case 'u': case 'x':
case 'a': case 'e': case 'f': case 'g':
case 'A': case 'E': case 'F': case 'G': case 'X':
case 's': case 'c': case '[':
case 'S': case 'C':
case 'p': case 'n':
p--;
break;
default:
goto fmt_fail;
}
t = *p;
/* C or S */
if ((t&0x2f) == 3) {
t |= 32;
size = SIZE_l;
}
switch (t) {
case 'c':
if (width < 1) width = 1;
case '[':
break;
case 'n':
store_int(dest, size, pos);
/* do not increment match count, etc! */
continue;
default:
shlim(f, 0);
while (av_isspace(shgetc(f)));
shunget(f);
pos += shcnt(f);
}
shlim(f, width);
if (shgetc(f) < 0) goto input_fail;
shunget(f);
switch (t) {
case 's':
case 'c':
case '[':
if (t == 'c' || t == 's') {
memset(scanset, -1, sizeof scanset);
scanset[0] = 0;
if (t == 's') {
scanset[1 + '\t'] = 0;
scanset[1 + '\n'] = 0;
scanset[1 + '\v'] = 0;
scanset[1 + '\f'] = 0;
scanset[1 + '\r'] = 0;
scanset[1 + ' ' ] = 0;
}
} else {
if (*++p == '^') p++, invert = 1;
else invert = 0;
memset(scanset, invert, sizeof scanset);
scanset[0] = 0;
if (*p == '-') p++, scanset[1+'-'] = 1-invert;
else if (*p == ']') p++, scanset[1+']'] = 1-invert;
for (; *p != ']'; p++) {
if (!*p) goto fmt_fail;
if (*p=='-' && p[1] && p[1] != ']')
for (c=p++[-1]; c<*p; c++)
scanset[1+c] = 1-invert;
scanset[1+*p] = 1-invert;
}
}
s = 0;
i = 0;
if ((s = dest)) {
while (scanset[(c=shgetc(f))+1])
s[i++] = c;
} else {
while (scanset[(c=shgetc(f))+1]);
}
shunget(f);
if (!shcnt(f)) goto match_fail;
if (t == 'c' && shcnt(f) != width) goto match_fail;
if (t != 'c') {
if (s) s[i] = 0;
}
break;
case 'p':
case 'X':
case 'x':
base = 16;
goto int_common;
case 'o':
base = 8;
goto int_common;
case 'd':
case 'u':
base = 10;
goto int_common;
case 'i':
base = 0;
int_common:
x = ffintscan(f, base, 0, ULLONG_MAX);
if (!shcnt(f))
goto match_fail;
if (t=='p' && dest)
*(void **)dest = (void *)(uintptr_t)x;
else
store_int(dest, size, x);
break;
case 'a': case 'A':
case 'e': case 'E':
case 'f': case 'F':
case 'g': case 'G':
y = fffloatscan(f, size, 0);
if (!shcnt(f))
goto match_fail;
if (dest) {
switch (size) {
case SIZE_def:
*(float *)dest = y;
break;
case SIZE_l:
*(double *)dest = y;
break;
case SIZE_L:
*(double *)dest = y;
break;
}
}
break;
}
pos += shcnt(f);
if (dest) matches++;
}
if (0) {
fmt_fail:
input_fail:
if (!matches) matches--;
}
match_fail:
return matches;
}
static int ff_vsscanf(const char *s, const char *fmt, va_list ap)
{
FFFILE f = {
.buf = (void *)s, .cookie = (void *)s,
.read = ffstring_read,
};
return ff_vfscanf(&f, fmt, ap);
}
int av_sscanf(const char *string, const char *format, ...)
{
int ret;
va_list ap;
va_start(ap, format);
ret = ff_vsscanf(string, format, ap);
va_end(ap);
return ret;
}

View file

@ -0,0 +1,461 @@
/*
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
* Copyright (c) 2007 Mans Rullgard
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "config.h"
#include "common.h"
#include "mem.h"
#include "avassert.h"
#include "avstring.h"
#include "bprint.h"
int av_strstart(const char *str, const char *pfx, const char **ptr)
{
while (*pfx && *pfx == *str) {
pfx++;
str++;
}
if (!*pfx && ptr)
*ptr = str;
return !*pfx;
}
int av_stristart(const char *str, const char *pfx, const char **ptr)
{
while (*pfx && av_toupper((unsigned)*pfx) == av_toupper((unsigned)*str)) {
pfx++;
str++;
}
if (!*pfx && ptr)
*ptr = str;
return !*pfx;
}
char *av_stristr(const char *s1, const char *s2)
{
if (!*s2)
return (char*)(intptr_t)s1;
do
if (av_stristart(s1, s2, NULL))
return (char*)(intptr_t)s1;
while (*s1++);
return NULL;
}
char *av_strnstr(const char *haystack, const char *needle, size_t hay_length)
{
size_t needle_len = strlen(needle);
if (!needle_len)
return (char*)haystack;
while (hay_length >= needle_len) {
hay_length--;
if (!memcmp(haystack, needle, needle_len))
return (char*)haystack;
haystack++;
}
return NULL;
}
size_t av_strlcpy(char *dst, const char *src, size_t size)
{
size_t len = 0;
while (++len < size && *src)
*dst++ = *src++;
if (len <= size)
*dst = 0;
return len + strlen(src) - 1;
}
size_t av_strlcat(char *dst, const char *src, size_t size)
{
size_t len = strlen(dst);
if (size <= len + 1)
return len + strlen(src);
return len + av_strlcpy(dst + len, src, size - len);
}
size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...)
{
size_t len = strlen(dst);
va_list vl;
va_start(vl, fmt);
len += vsnprintf(dst + len, size > len ? size - len : 0, fmt, vl);
va_end(vl);
return len;
}
char *av_asprintf(const char *fmt, ...)
{
char *p = NULL;
va_list va;
int len;
va_start(va, fmt);
len = vsnprintf(NULL, 0, fmt, va);
va_end(va);
if (len < 0)
goto end;
p = av_malloc(len + 1);
if (!p)
goto end;
va_start(va, fmt);
len = vsnprintf(p, len + 1, fmt, va);
va_end(va);
if (len < 0)
av_freep(&p);
end:
return p;
}
char *av_d2str(double d)
{
char *str = av_malloc(16);
if (str)
snprintf(str, 16, "%f", d);
return str;
}
#define WHITESPACES " \n\t\r"
char *av_get_token(const char **buf, const char *term)
{
char *out = av_malloc(strlen(*buf) + 1);
char *ret = out, *end = out;
const char *p = *buf;
if (!out)
return NULL;
p += strspn(p, WHITESPACES);
while (*p && !strspn(p, term)) {
char c = *p++;
if (c == '\\' && *p) {
*out++ = *p++;
end = out;
} else if (c == '\'') {
while (*p && *p != '\'')
*out++ = *p++;
if (*p) {
p++;
end = out;
}
} else {
*out++ = c;
}
}
do
*out-- = 0;
while (out >= end && strspn(out, WHITESPACES));
*buf = p;
return ret;
}
char *av_strtok(char *s, const char *delim, char **saveptr)
{
char *tok;
if (!s && !(s = *saveptr))
return NULL;
/* skip leading delimiters */
s += strspn(s, delim);
/* s now points to the first non delimiter char, or to the end of the string */
if (!*s) {
*saveptr = NULL;
return NULL;
}
tok = s++;
/* skip non delimiters */
s += strcspn(s, delim);
if (*s) {
*s = 0;
*saveptr = s+1;
} else {
*saveptr = NULL;
}
return tok;
}
int av_strcasecmp(const char *a, const char *b)
{
uint8_t c1, c2;
do {
c1 = av_tolower(*a++);
c2 = av_tolower(*b++);
} while (c1 && c1 == c2);
return c1 - c2;
}
int av_strncasecmp(const char *a, const char *b, size_t n)
{
uint8_t c1, c2;
if (n <= 0)
return 0;
do {
c1 = av_tolower(*a++);
c2 = av_tolower(*b++);
} while (--n && c1 && c1 == c2);
return c1 - c2;
}
char *av_strireplace(const char *str, const char *from, const char *to)
{
char *ret = NULL;
const char *pstr2, *pstr = str;
size_t tolen = strlen(to), fromlen = strlen(from);
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
while ((pstr2 = av_stristr(pstr, from))) {
av_bprint_append_data(&pbuf, pstr, pstr2 - pstr);
pstr = pstr2 + fromlen;
av_bprint_append_data(&pbuf, to, tolen);
}
av_bprint_append_data(&pbuf, pstr, strlen(pstr));
if (!av_bprint_is_complete(&pbuf)) {
av_bprint_finalize(&pbuf, NULL);
} else {
av_bprint_finalize(&pbuf, &ret);
}
return ret;
}
const char *av_basename(const char *path)
{
char *p = strrchr(path, '/');
#if HAVE_DOS_PATHS
char *q = strrchr(path, '\\');
char *d = strchr(path, ':');
p = FFMAX3(p, q, d);
#endif
if (!p)
return path;
return p + 1;
}
const char *av_dirname(char *path)
{
char *p = strrchr(path, '/');
#if HAVE_DOS_PATHS
char *q = strrchr(path, '\\');
char *d = strchr(path, ':');
d = d ? d + 1 : d;
p = FFMAX3(p, q, d);
#endif
if (!p)
return ".";
*p = '\0';
return path;
}
char *av_append_path_component(const char *path, const char *component)
{
size_t p_len, c_len;
char *fullpath;
if (!path)
return av_strdup(component);
if (!component)
return av_strdup(path);
p_len = strlen(path);
c_len = strlen(component);
if (p_len > SIZE_MAX - c_len || p_len + c_len > SIZE_MAX - 2)
return NULL;
fullpath = av_malloc(p_len + c_len + 2);
if (fullpath) {
if (p_len) {
av_strlcpy(fullpath, path, p_len + 1);
if (c_len) {
if (fullpath[p_len - 1] != '/' && component[0] != '/')
fullpath[p_len++] = '/';
else if (fullpath[p_len - 1] == '/' && component[0] == '/')
p_len--;
}
}
av_strlcpy(&fullpath[p_len], component, c_len + 1);
fullpath[p_len + c_len] = 0;
}
return fullpath;
}
int av_escape(char **dst, const char *src, const char *special_chars,
enum AVEscapeMode mode, int flags)
{
AVBPrint dstbuf;
av_bprint_init(&dstbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
av_bprint_escape(&dstbuf, src, special_chars, mode, flags);
if (!av_bprint_is_complete(&dstbuf)) {
av_bprint_finalize(&dstbuf, NULL);
return AVERROR(ENOMEM);
} else {
av_bprint_finalize(&dstbuf, dst);
return dstbuf.len;
}
}
int av_match_name(const char *name, const char *names)
{
const char *p;
int len, namelen;
if (!name || !names)
return 0;
namelen = strlen(name);
while (*names) {
int negate = '-' == *names;
p = strchr(names, ',');
if (!p)
p = names + strlen(names);
names += negate;
len = FFMAX(p - names, namelen);
if (!av_strncasecmp(name, names, len) || !strncmp("ALL", names, FFMAX(3, p - names)))
return !negate;
names = p + (*p == ',');
}
return 0;
}
int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end,
unsigned int flags)
{
const uint8_t *p = *bufp;
uint32_t top;
uint64_t code;
int ret = 0, tail_len;
uint32_t overlong_encoding_mins[6] = {
0x00000000, 0x00000080, 0x00000800, 0x00010000, 0x00200000, 0x04000000,
};
if (p >= buf_end)
return 0;
code = *p++;
/* first sequence byte starts with 10, or is 1111-1110 or 1111-1111,
which is not admitted */
if ((code & 0xc0) == 0x80 || code >= 0xFE) {
ret = AVERROR(EILSEQ);
goto end;
}
top = (code & 128) >> 1;
tail_len = 0;
while (code & top) {
int tmp;
tail_len++;
if (p >= buf_end) {
(*bufp) ++;
return AVERROR(EILSEQ); /* incomplete sequence */
}
/* we assume the byte to be in the form 10xx-xxxx */
tmp = *p++ - 128; /* strip leading 1 */
if (tmp>>6) {
(*bufp) ++;
return AVERROR(EILSEQ);
}
code = (code<<6) + tmp;
top <<= 5;
}
code &= (top << 1) - 1;
/* check for overlong encodings */
av_assert0(tail_len <= 5);
if (code < overlong_encoding_mins[tail_len]) {
ret = AVERROR(EILSEQ);
goto end;
}
if (code >= 1U<<31) {
ret = AVERROR(EILSEQ); /* out-of-range value */
goto end;
}
*codep = code;
if (code > 0x10FFFF &&
!(flags & AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES))
ret = AVERROR(EILSEQ);
if (code < 0x20 && code != 0x9 && code != 0xA && code != 0xD &&
flags & AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES)
ret = AVERROR(EILSEQ);
if (code >= 0xD800 && code <= 0xDFFF &&
!(flags & AV_UTF8_FLAG_ACCEPT_SURROGATES))
ret = AVERROR(EILSEQ);
if ((code == 0xFFFE || code == 0xFFFF) &&
!(flags & AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS))
ret = AVERROR(EILSEQ);
end:
*bufp = p;
return ret;
}
int av_match_list(const char *name, const char *list, char separator)
{
const char *p, *q;
for (p = name; p && *p; ) {
for (q = list; q && *q; ) {
int k;
for (k = 0; p[k] == q[k] || (p[k]*q[k] == 0 && p[k]+q[k] == separator); k++)
if (k && (!p[k] || p[k] == separator))
return 1;
q = strchr(q, separator);
q += !!q;
}
p = strchr(p, separator);
p += !!p;
}
return 0;
}

View file

@ -0,0 +1,413 @@
/*
* Copyright (c) 2007 Mans Rullgard
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_AVSTRING_H
#define AVUTIL_AVSTRING_H
#include <stddef.h>
#include <stdint.h>
#include "attributes.h"
/**
* @addtogroup lavu_string
* @{
*/
/**
* Return non-zero if pfx is a prefix of str. If it is, *ptr is set to
* the address of the first character in str after the prefix.
*
* @param str input string
* @param pfx prefix to test
* @param ptr updated if the prefix is matched inside str
* @return non-zero if the prefix matches, zero otherwise
*/
int av_strstart(const char *str, const char *pfx, const char **ptr);
/**
* Return non-zero if pfx is a prefix of str independent of case. If
* it is, *ptr is set to the address of the first character in str
* after the prefix.
*
* @param str input string
* @param pfx prefix to test
* @param ptr updated if the prefix is matched inside str
* @return non-zero if the prefix matches, zero otherwise
*/
int av_stristart(const char *str, const char *pfx, const char **ptr);
/**
* Locate the first case-independent occurrence in the string haystack
* of the string needle. A zero-length string needle is considered to
* match at the start of haystack.
*
* This function is a case-insensitive version of the standard strstr().
*
* @param haystack string to search in
* @param needle string to search for
* @return pointer to the located match within haystack
* or a null pointer if no match
*/
char *av_stristr(const char *haystack, const char *needle);
/**
* Locate the first occurrence of the string needle in the string haystack
* where not more than hay_length characters are searched. A zero-length
* string needle is considered to match at the start of haystack.
*
* This function is a length-limited version of the standard strstr().
*
* @param haystack string to search in
* @param needle string to search for
* @param hay_length length of string to search in
* @return pointer to the located match within haystack
* or a null pointer if no match
*/
char *av_strnstr(const char *haystack, const char *needle, size_t hay_length);
/**
* Copy the string src to dst, but no more than size - 1 bytes, and
* null-terminate dst.
*
* This function is the same as BSD strlcpy().
*
* @param dst destination buffer
* @param src source string
* @param size size of destination buffer
* @return the length of src
*
* @warning since the return value is the length of src, src absolutely
* _must_ be a properly 0-terminated string, otherwise this will read beyond
* the end of the buffer and possibly crash.
*/
size_t av_strlcpy(char *dst, const char *src, size_t size);
/**
* Append the string src to the string dst, but to a total length of
* no more than size - 1 bytes, and null-terminate dst.
*
* This function is similar to BSD strlcat(), but differs when
* size <= strlen(dst).
*
* @param dst destination buffer
* @param src source string
* @param size size of destination buffer
* @return the total length of src and dst
*
* @warning since the return value use the length of src and dst, these
* absolutely _must_ be a properly 0-terminated strings, otherwise this
* will read beyond the end of the buffer and possibly crash.
*/
size_t av_strlcat(char *dst, const char *src, size_t size);
/**
* Append output to a string, according to a format. Never write out of
* the destination buffer, and always put a terminating 0 within
* the buffer.
* @param dst destination buffer (string to which the output is
* appended)
* @param size total size of the destination buffer
* @param fmt printf-compatible format string, specifying how the
* following parameters are used
* @return the length of the string that would have been generated
* if enough space had been available
*/
size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...) av_printf_format(3, 4);
/**
* Get the count of continuous non zero chars starting from the beginning.
*
* @param len maximum number of characters to check in the string, that
* is the maximum value which is returned by the function
*/
static inline size_t av_strnlen(const char *s, size_t len)
{
size_t i;
for (i = 0; i < len && s[i]; i++)
;
return i;
}
/**
* Print arguments following specified format into a large enough auto
* allocated buffer. It is similar to GNU asprintf().
* @param fmt printf-compatible format string, specifying how the
* following parameters are used.
* @return the allocated string
* @note You have to free the string yourself with av_free().
*/
char *av_asprintf(const char *fmt, ...) av_printf_format(1, 2);
/**
* Convert a number to an av_malloced string.
*/
char *av_d2str(double d);
/**
* Unescape the given string until a non escaped terminating char,
* and return the token corresponding to the unescaped string.
*
* The normal \ and ' escaping is supported. Leading and trailing
* whitespaces are removed, unless they are escaped with '\' or are
* enclosed between ''.
*
* @param buf the buffer to parse, buf will be updated to point to the
* terminating char
* @param term a 0-terminated list of terminating chars
* @return the malloced unescaped string, which must be av_freed by
* the user, NULL in case of allocation failure
*/
char *av_get_token(const char **buf, const char *term);
/**
* Split the string into several tokens which can be accessed by
* successive calls to av_strtok().
*
* A token is defined as a sequence of characters not belonging to the
* set specified in delim.
*
* On the first call to av_strtok(), s should point to the string to
* parse, and the value of saveptr is ignored. In subsequent calls, s
* should be NULL, and saveptr should be unchanged since the previous
* call.
*
* This function is similar to strtok_r() defined in POSIX.1.
*
* @param s the string to parse, may be NULL
* @param delim 0-terminated list of token delimiters, must be non-NULL
* @param saveptr user-provided pointer which points to stored
* information necessary for av_strtok() to continue scanning the same
* string. saveptr is updated to point to the next character after the
* first delimiter found, or to NULL if the string was terminated
* @return the found token, or NULL when no token is found
*/
char *av_strtok(char *s, const char *delim, char **saveptr);
/**
* Locale-independent conversion of ASCII isdigit.
*/
static inline av_const int av_isdigit(int c)
{
return c >= '0' && c <= '9';
}
/**
* Locale-independent conversion of ASCII isgraph.
*/
static inline av_const int av_isgraph(int c)
{
return c > 32 && c < 127;
}
/**
* Locale-independent conversion of ASCII isspace.
*/
static inline av_const int av_isspace(int c)
{
return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' ||
c == '\v';
}
/**
* Locale-independent conversion of ASCII characters to uppercase.
*/
static inline av_const int av_toupper(int c)
{
if (c >= 'a' && c <= 'z')
c ^= 0x20;
return c;
}
/**
* Locale-independent conversion of ASCII characters to lowercase.
*/
static inline av_const int av_tolower(int c)
{
if (c >= 'A' && c <= 'Z')
c ^= 0x20;
return c;
}
/**
* Locale-independent conversion of ASCII isxdigit.
*/
static inline av_const int av_isxdigit(int c)
{
c = av_tolower(c);
return av_isdigit(c) || (c >= 'a' && c <= 'f');
}
/**
* Locale-independent case-insensitive compare.
* @note This means only ASCII-range characters are case-insensitive
*/
int av_strcasecmp(const char *a, const char *b);
/**
* Locale-independent case-insensitive compare.
* @note This means only ASCII-range characters are case-insensitive
*/
int av_strncasecmp(const char *a, const char *b, size_t n);
/**
* Locale-independent strings replace.
* @note This means only ASCII-range characters are replace
*/
char *av_strireplace(const char *str, const char *from, const char *to);
/**
* Thread safe basename.
* @param path the path, on DOS both \ and / are considered separators.
* @return pointer to the basename substring.
*/
const char *av_basename(const char *path);
/**
* Thread safe dirname.
* @param path the path, on DOS both \ and / are considered separators.
* @return the path with the separator replaced by the string terminator or ".".
* @note the function may change the input string.
*/
const char *av_dirname(char *path);
/**
* Match instances of a name in a comma-separated list of names.
* List entries are checked from the start to the end of the names list,
* the first match ends further processing. If an entry prefixed with '-'
* matches, then 0 is returned. The "ALL" list entry is considered to
* match all names.
*
* @param name Name to look for.
* @param names List of names.
* @return 1 on match, 0 otherwise.
*/
int av_match_name(const char *name, const char *names);
/**
* Append path component to the existing path.
* Path separator '/' is placed between when needed.
* Resulting string have to be freed with av_free().
* @param path base path
* @param component component to be appended
* @return new path or NULL on error.
*/
char *av_append_path_component(const char *path, const char *component);
enum AVEscapeMode {
AV_ESCAPE_MODE_AUTO, ///< Use auto-selected escaping mode.
AV_ESCAPE_MODE_BACKSLASH, ///< Use backslash escaping.
AV_ESCAPE_MODE_QUOTE, ///< Use single-quote escaping.
};
/**
* Consider spaces special and escape them even in the middle of the
* string.
*
* This is equivalent to adding the whitespace characters to the special
* characters lists, except it is guaranteed to use the exact same list
* of whitespace characters as the rest of libavutil.
*/
#define AV_ESCAPE_FLAG_WHITESPACE (1 << 0)
/**
* Escape only specified special characters.
* Without this flag, escape also any characters that may be considered
* special by av_get_token(), such as the single quote.
*/
#define AV_ESCAPE_FLAG_STRICT (1 << 1)
/**
* Escape string in src, and put the escaped string in an allocated
* string in *dst, which must be freed with av_free().
*
* @param dst pointer where an allocated string is put
* @param src string to escape, must be non-NULL
* @param special_chars string containing the special characters which
* need to be escaped, can be NULL
* @param mode escape mode to employ, see AV_ESCAPE_MODE_* macros.
* Any unknown value for mode will be considered equivalent to
* AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without
* notice.
* @param flags flags which control how to escape, see AV_ESCAPE_FLAG_ macros
* @return the length of the allocated string, or a negative error code in case of error
* @see av_bprint_escape()
*/
av_warn_unused_result
int av_escape(char **dst, const char *src, const char *special_chars,
enum AVEscapeMode mode, int flags);
#define AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES 1 ///< accept codepoints over 0x10FFFF
#define AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS 2 ///< accept non-characters - 0xFFFE and 0xFFFF
#define AV_UTF8_FLAG_ACCEPT_SURROGATES 4 ///< accept UTF-16 surrogates codes
#define AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES 8 ///< exclude control codes not accepted by XML
#define AV_UTF8_FLAG_ACCEPT_ALL \
AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES|AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS|AV_UTF8_FLAG_ACCEPT_SURROGATES
/**
* Read and decode a single UTF-8 code point (character) from the
* buffer in *buf, and update *buf to point to the next byte to
* decode.
*
* In case of an invalid byte sequence, the pointer will be updated to
* the next byte after the invalid sequence and the function will
* return an error code.
*
* Depending on the specified flags, the function will also fail in
* case the decoded code point does not belong to a valid range.
*
* @note For speed-relevant code a carefully implemented use of
* GET_UTF8() may be preferred.
*
* @param codep pointer used to return the parsed code in case of success.
* The value in *codep is set even in case the range check fails.
* @param bufp pointer to the address the first byte of the sequence
* to decode, updated by the function to point to the
* byte next after the decoded sequence
* @param buf_end pointer to the end of the buffer, points to the next
* byte past the last in the buffer. This is used to
* avoid buffer overreads (in case of an unfinished
* UTF-8 sequence towards the end of the buffer).
* @param flags a collection of AV_UTF8_FLAG_* flags
* @return >= 0 in case a sequence was successfully read, a negative
* value in case of invalid sequence
*/
av_warn_unused_result
int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end,
unsigned int flags);
/**
* Check if a name is in a list.
* @returns 0 if not found, or the 1 based index where it has been found in the
* list.
*/
int av_match_list(const char *name, const char *list, char separator);
/**
* See libc sscanf manual for more information.
* Locale-independent sscanf implementation.
*/
int av_sscanf(const char *string, const char *format, ...);
/**
* @}
*/
#endif /* AVUTIL_AVSTRING_H */

View file

@ -0,0 +1,365 @@
/*
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_AVUTIL_H
#define AVUTIL_AVUTIL_H
/**
* @file
* @ingroup lavu
* Convenience header that includes @ref lavu "libavutil"'s core.
*/
/**
* @mainpage
*
* @section ffmpeg_intro Introduction
*
* This document describes the usage of the different libraries
* provided by FFmpeg.
*
* @li @ref libavc "libavcodec" encoding/decoding library
* @li @ref lavfi "libavfilter" graph-based frame editing library
* @li @ref libavf "libavformat" I/O and muxing/demuxing library
* @li @ref lavd "libavdevice" special devices muxing/demuxing library
* @li @ref lavu "libavutil" common utility library
* @li @ref lswr "libswresample" audio resampling, format conversion and mixing
* @li @ref lpp "libpostproc" post processing library
* @li @ref libsws "libswscale" color conversion and scaling library
*
* @section ffmpeg_versioning Versioning and compatibility
*
* Each of the FFmpeg libraries contains a version.h header, which defines a
* major, minor and micro version number with the
* <em>LIBRARYNAME_VERSION_{MAJOR,MINOR,MICRO}</em> macros. The major version
* number is incremented with backward incompatible changes - e.g. removing
* parts of the public API, reordering public struct members, etc. The minor
* version number is incremented for backward compatible API changes or major
* new features - e.g. adding a new public function or a new decoder. The micro
* version number is incremented for smaller changes that a calling program
* might still want to check for - e.g. changing behavior in a previously
* unspecified situation.
*
* FFmpeg guarantees backward API and ABI compatibility for each library as long
* as its major version number is unchanged. This means that no public symbols
* will be removed or renamed. Types and names of the public struct members and
* values of public macros and enums will remain the same (unless they were
* explicitly declared as not part of the public API). Documented behavior will
* not change.
*
* In other words, any correct program that works with a given FFmpeg snapshot
* should work just as well without any changes with any later snapshot with the
* same major versions. This applies to both rebuilding the program against new
* FFmpeg versions or to replacing the dynamic FFmpeg libraries that a program
* links against.
*
* However, new public symbols may be added and new members may be appended to
* public structs whose size is not part of public ABI (most public structs in
* FFmpeg). New macros and enum values may be added. Behavior in undocumented
* situations may change slightly (and be documented). All those are accompanied
* by an entry in doc/APIchanges and incrementing either the minor or micro
* version number.
*/
/**
* @defgroup lavu libavutil
* Common code shared across all FFmpeg libraries.
*
* @note
* libavutil is designed to be modular. In most cases, in order to use the
* functions provided by one component of libavutil you must explicitly include
* the specific header containing that feature. If you are only using
* media-related components, you could simply include libavutil/avutil.h, which
* brings in most of the "core" components.
*
* @{
*
* @defgroup lavu_crypto Crypto and Hashing
*
* @{
* @}
*
* @defgroup lavu_math Mathematics
* @{
*
* @}
*
* @defgroup lavu_string String Manipulation
*
* @{
*
* @}
*
* @defgroup lavu_mem Memory Management
*
* @{
*
* @}
*
* @defgroup lavu_data Data Structures
* @{
*
* @}
*
* @defgroup lavu_video Video related
*
* @{
*
* @}
*
* @defgroup lavu_audio Audio related
*
* @{
*
* @}
*
* @defgroup lavu_error Error Codes
*
* @{
*
* @}
*
* @defgroup lavu_log Logging Facility
*
* @{
*
* @}
*
* @defgroup lavu_misc Other
*
* @{
*
* @defgroup preproc_misc Preprocessor String Macros
*
* @{
*
* @}
*
* @defgroup version_utils Library Version Macros
*
* @{
*
* @}
*/
/**
* @addtogroup lavu_ver
* @{
*/
/**
* Return the LIBAVUTIL_VERSION_INT constant.
*/
unsigned avutil_version(void);
/**
* Return an informative version string. This usually is the actual release
* version number or a git commit description. This string has no fixed format
* and can change any time. It should never be parsed by code.
*/
const char *av_version_info(void);
/**
* Return the libavutil build-time configuration.
*/
const char *avutil_configuration(void);
/**
* Return the libavutil license.
*/
const char *avutil_license(void);
/**
* @}
*/
/**
* @addtogroup lavu_media Media Type
* @brief Media Type
*/
enum AVMediaType {
AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATA
AVMEDIA_TYPE_VIDEO,
AVMEDIA_TYPE_AUDIO,
AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuous
AVMEDIA_TYPE_SUBTITLE,
AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparse
AVMEDIA_TYPE_NB
};
/**
* Return a string describing the media_type enum, NULL if media_type
* is unknown.
*/
const char *av_get_media_type_string(enum AVMediaType media_type);
/**
* @defgroup lavu_const Constants
* @{
*
* @defgroup lavu_enc Encoding specific
*
* @note those definition should move to avcodec
* @{
*/
#define FF_LAMBDA_SHIFT 7
#define FF_LAMBDA_SCALE (1<<FF_LAMBDA_SHIFT)
#define FF_QP2LAMBDA 118 ///< factor to convert from H.263 QP to lambda
#define FF_LAMBDA_MAX (256*128-1)
#define FF_QUALITY_SCALE FF_LAMBDA_SCALE //FIXME maybe remove
/**
* @}
* @defgroup lavu_time Timestamp specific
*
* FFmpeg internal timebase and timestamp definitions
*
* @{
*/
/**
* @brief Undefined timestamp value
*
* Usually reported by demuxer that work on containers that do not provide
* either pts or dts.
*/
#define AV_NOPTS_VALUE ((int64_t)UINT64_C(0x8000000000000000))
/**
* Internal time base represented as integer
*/
#define AV_TIME_BASE 1000000
/**
* Internal time base represented as fractional value
*/
#define AV_TIME_BASE_Q (AVRational){1, AV_TIME_BASE}
/**
* @}
* @}
* @defgroup lavu_picture Image related
*
* AVPicture types, pixel formats and basic image planes manipulation.
*
* @{
*/
enum AVPictureType {
AV_PICTURE_TYPE_NONE = 0, ///< Undefined
AV_PICTURE_TYPE_I, ///< Intra
AV_PICTURE_TYPE_P, ///< Predicted
AV_PICTURE_TYPE_B, ///< Bi-dir predicted
AV_PICTURE_TYPE_S, ///< S(GMC)-VOP MPEG-4
AV_PICTURE_TYPE_SI, ///< Switching Intra
AV_PICTURE_TYPE_SP, ///< Switching Predicted
AV_PICTURE_TYPE_BI, ///< BI type
};
/**
* Return a single letter to describe the given picture type
* pict_type.
*
* @param[in] pict_type the picture type @return a single character
* representing the picture type, '?' if pict_type is unknown
*/
char av_get_picture_type_char(enum AVPictureType pict_type);
/**
* @}
*/
#include "common.h"
#include "error.h"
#include "rational.h"
#include "version.h"
#include "macros.h"
#include "mathematics.h"
#include "log.h"
#include "pixfmt.h"
/**
* Return x default pointer in case p is NULL.
*/
static inline void *av_x_if_null(const void *p, const void *x)
{
return (void *)(intptr_t)(p ? p : x);
}
/**
* Compute the length of an integer list.
*
* @param elsize size in bytes of each list element (only 1, 2, 4 or 8)
* @param term list terminator (usually 0 or -1)
* @param list pointer to the list
* @return length of the list, in elements, not counting the terminator
*/
unsigned av_int_list_length_for_size(unsigned elsize,
const void *list, uint64_t term) av_pure;
/**
* Compute the length of an integer list.
*
* @param term list terminator (usually 0 or -1)
* @param list pointer to the list
* @return length of the list, in elements, not counting the terminator
*/
#define av_int_list_length(list, term) \
av_int_list_length_for_size(sizeof(*(list)), list, term)
/**
* Open a file using a UTF-8 filename.
* The API of this function matches POSIX fopen(), errors are returned through
* errno.
*/
FILE *av_fopen_utf8(const char *path, const char *mode);
/**
* Return the fractional representation of the internal time base.
*/
AVRational av_get_time_base_q(void);
#define AV_FOURCC_MAX_STRING_SIZE 32
#define av_fourcc2str(fourcc) av_fourcc_make_string((char[AV_FOURCC_MAX_STRING_SIZE]){0}, fourcc)
/**
* Fill the provided buffer with a string containing a FourCC (four-character
* code) representation.
*
* @param buf a buffer with size in bytes of at least AV_FOURCC_MAX_STRING_SIZE
* @param fourcc the fourcc to represent
* @return the buffer in input
*/
char *av_fourcc_make_string(char *buf, uint32_t fourcc);
/**
* @}
* @}
*/
#endif /* AVUTIL_AVUTIL_H */

View file

@ -0,0 +1,55 @@
/*
* Windows resource file for libavutil
*
* Copyright (C) 2012 James Almer
* Copyright (C) 2013 Tiancheng "Timothy" Gu
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <windows.h>
#include "libavutil/version.h"
#include "libavutil/ffversion.h"
#include "config.h"
1 VERSIONINFO
FILEVERSION LIBAVUTIL_VERSION_MAJOR, LIBAVUTIL_VERSION_MINOR, LIBAVUTIL_VERSION_MICRO, 0
PRODUCTVERSION LIBAVUTIL_VERSION_MAJOR, LIBAVUTIL_VERSION_MINOR, LIBAVUTIL_VERSION_MICRO, 0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
{
BLOCK "StringFileInfo"
{
BLOCK "040904B0"
{
VALUE "CompanyName", "FFmpeg Project"
VALUE "FileDescription", "FFmpeg utility library"
VALUE "FileVersion", AV_STRINGIFY(LIBAVUTIL_VERSION)
VALUE "InternalName", "libavutil"
VALUE "LegalCopyright", "Copyright (C) 2000-" AV_STRINGIFY(CONFIG_THIS_YEAR) " FFmpeg Project"
VALUE "OriginalFilename", "avutil" BUILDSUF "-" AV_STRINGIFY(LIBAVUTIL_VERSION_MAJOR) SLIBSUF
VALUE "ProductName", "FFmpeg"
VALUE "ProductVersion", FFMPEG_VERSION
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409, 0x04B0
}
}

View file

@ -0,0 +1,174 @@
/*
* Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* @brief Base64 encode/decode
* @author Ryan Martell <rdm4@martellventures.com> (with lots of Michael)
*/
#include "common.h"
#include "base64.h"
#include "intreadwrite.h"
#include "timer.h"
/* ---------------- private code */
static const uint8_t map2[256] =
{
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff,
0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x01,
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b,
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
#define BASE64_DEC_STEP(i) do { \
bits = map2[in[i]]; \
if (bits & 0x80) \
goto out ## i; \
v = i ? (v << 6) + bits : bits; \
} while(0)
int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
{
uint8_t *dst = out;
uint8_t *end = out + out_size;
// no sign extension
const uint8_t *in = in_str;
unsigned bits = 0xff;
unsigned v;
while (end - dst > 3) {
BASE64_DEC_STEP(0);
BASE64_DEC_STEP(1);
BASE64_DEC_STEP(2);
BASE64_DEC_STEP(3);
// Using AV_WB32 directly confuses compiler
v = av_be2ne32(v << 8);
AV_WN32(dst, v);
dst += 3;
in += 4;
}
if (end - dst) {
BASE64_DEC_STEP(0);
BASE64_DEC_STEP(1);
BASE64_DEC_STEP(2);
BASE64_DEC_STEP(3);
*dst++ = v >> 16;
if (end - dst)
*dst++ = v >> 8;
if (end - dst)
*dst++ = v;
in += 4;
}
while (1) {
BASE64_DEC_STEP(0);
in++;
BASE64_DEC_STEP(0);
in++;
BASE64_DEC_STEP(0);
in++;
BASE64_DEC_STEP(0);
in++;
}
out3:
*dst++ = v >> 10;
v <<= 2;
out2:
*dst++ = v >> 4;
out1:
out0:
return bits & 1 ? AVERROR_INVALIDDATA : dst - out;
}
/*****************************************************************************
* b64_encode: Stolen from VLC's http.c.
* Simplified by Michael.
* Fixed edge cases and made it work from data (vs. strings) by Ryan.
*****************************************************************************/
char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
{
static const char b64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char *ret, *dst;
unsigned i_bits = 0;
int i_shift = 0;
int bytes_remaining = in_size;
if (in_size >= UINT_MAX / 4 ||
out_size < AV_BASE64_SIZE(in_size))
return NULL;
ret = dst = out;
while (bytes_remaining > 3) {
i_bits = AV_RB32(in);
in += 3; bytes_remaining -= 3;
*dst++ = b64[ i_bits>>26 ];
*dst++ = b64[(i_bits>>20) & 0x3F];
*dst++ = b64[(i_bits>>14) & 0x3F];
*dst++ = b64[(i_bits>>8 ) & 0x3F];
}
i_bits = 0;
while (bytes_remaining) {
i_bits = (i_bits << 8) + *in++;
bytes_remaining--;
i_shift += 8;
}
while (i_shift > 0) {
*dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
i_shift -= 6;
}
while ((dst - ret) & 3)
*dst++ = '=';
*dst = '\0';
return ret;
}

View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_BASE64_H
#define AVUTIL_BASE64_H
#include <stdint.h>
/**
* @defgroup lavu_base64 Base64
* @ingroup lavu_crypto
* @{
*/
/**
* Decode a base64-encoded string.
*
* @param out buffer for decoded data
* @param in null-terminated input string
* @param out_size size in bytes of the out buffer, must be at
* least 3/4 of the length of in, that is AV_BASE64_DECODE_SIZE(strlen(in))
* @return number of bytes written, or a negative value in case of
* invalid input
*/
int av_base64_decode(uint8_t *out, const char *in, int out_size);
/**
* Calculate the output size in bytes needed to decode a base64 string
* with length x to a data buffer.
*/
#define AV_BASE64_DECODE_SIZE(x) ((x) * 3LL / 4)
/**
* Encode data to base64 and null-terminate.
*
* @param out buffer for encoded data
* @param out_size size in bytes of the out buffer (including the
* null terminator), must be at least AV_BASE64_SIZE(in_size)
* @param in input buffer containing the data to encode
* @param in_size size in bytes of the in buffer
* @return out or NULL in case of error
*/
char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size);
/**
* Calculate the output size needed to base64-encode x bytes to a
* null-terminated string.
*/
#define AV_BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1)
/**
* @}
*/
#endif /* AVUTIL_BASE64_H */

View file

@ -0,0 +1,424 @@
/*
* Blowfish algorithm
* Copyright (c) 2012 Samuel Pitoiset
*
* loosely based on Paul Kocher's implementation
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avutil.h"
#include "common.h"
#include "intreadwrite.h"
#include "mem.h"
#include "blowfish.h"
static const uint32_t orig_p[AV_BF_ROUNDS + 2] = {
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
0x9216D5D9, 0x8979FB1B
};
static const uint32_t orig_s[4][256] = {
{ 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A },
{ 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7 },
{ 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0 },
{ 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 }
};
#define F(Xl, Xr, P) \
Xr ^=((( ctx->s[0][ Xl >> 24 ] \
+ ctx->s[1][(Xl >> 16) & 0xFF])\
^ ctx->s[2][(Xl >> 8) & 0xFF])\
+ ctx->s[3][ Xl & 0xFF])\
^ P;
AVBlowfish *av_blowfish_alloc(void)
{
return av_mallocz(sizeof(struct AVBlowfish));
}
av_cold void av_blowfish_init(AVBlowfish *ctx, const uint8_t *key, int key_len)
{
uint32_t data, data_l, data_r;
int i, j, k;
memcpy(ctx->s, orig_s, sizeof(orig_s));
j = 0;
for (i = 0; i < AV_BF_ROUNDS + 2; ++i) {
data = 0;
for (k = 0; k < 4; k++) {
data = (data << 8) | key[j];
if (++j >= key_len)
j = 0;
}
ctx->p[i] = orig_p[i] ^ data;
}
data_l = data_r = 0;
for (i = 0; i < AV_BF_ROUNDS + 2; i += 2) {
av_blowfish_crypt_ecb(ctx, &data_l, &data_r, 0);
ctx->p[i] = data_l;
ctx->p[i + 1] = data_r;
}
for (i = 0; i < 4; ++i) {
for (j = 0; j < 256; j += 2) {
av_blowfish_crypt_ecb(ctx, &data_l, &data_r, 0);
ctx->s[i][j] = data_l;
ctx->s[i][j + 1] = data_r;
}
}
}
void av_blowfish_crypt_ecb(AVBlowfish *ctx, uint32_t *xl, uint32_t *xr,
int decrypt)
{
uint32_t Xl, Xr;
int i;
Xl = *xl;
Xr = *xr;
if (decrypt) {
Xl ^= ctx->p[AV_BF_ROUNDS + 1];
for (i = AV_BF_ROUNDS; i > 0; i-=2) {
F(Xl, Xr, ctx->p[i ]);
F(Xr, Xl, ctx->p[i-1]);
}
Xr ^= ctx->p[0];
} else {
Xl ^= ctx->p[0];
for (i = 1; i < AV_BF_ROUNDS+1; i+=2){
F(Xl, Xr, ctx->p[i ]);
F(Xr, Xl, ctx->p[i+1]);
}
Xr ^= ctx->p[AV_BF_ROUNDS + 1];
}
*xl = Xr;
*xr = Xl;
}
void av_blowfish_crypt(AVBlowfish *ctx, uint8_t *dst, const uint8_t *src,
int count, uint8_t *iv, int decrypt)
{
uint32_t v0, v1;
int i;
if (decrypt) {
while (count--) {
v0 = AV_RB32(src);
v1 = AV_RB32(src + 4);
av_blowfish_crypt_ecb(ctx, &v0, &v1, decrypt);
if (iv) {
v0 ^= AV_RB32(iv);
v1 ^= AV_RB32(iv + 4);
memcpy(iv, src, 8);
}
AV_WB32(dst, v0);
AV_WB32(dst + 4, v1);
src += 8;
dst += 8;
}
} else {
while (count--) {
if (iv) {
for (i = 0; i < 8; i++)
dst[i] = src[i] ^ iv[i];
v0 = AV_RB32(dst);
v1 = AV_RB32(dst + 4);
} else {
v0 = AV_RB32(src);
v1 = AV_RB32(src + 4);
}
av_blowfish_crypt_ecb(ctx, &v0, &v1, decrypt);
AV_WB32(dst, v0);
AV_WB32(dst + 4, v1);
if (iv)
memcpy(iv, dst, 8);
src += 8;
dst += 8;
}
}
}

View file

@ -0,0 +1,82 @@
/*
* Blowfish algorithm
* Copyright (c) 2012 Samuel Pitoiset
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_BLOWFISH_H
#define AVUTIL_BLOWFISH_H
#include <stdint.h>
/**
* @defgroup lavu_blowfish Blowfish
* @ingroup lavu_crypto
* @{
*/
#define AV_BF_ROUNDS 16
typedef struct AVBlowfish {
uint32_t p[AV_BF_ROUNDS + 2];
uint32_t s[4][256];
} AVBlowfish;
/**
* Allocate an AVBlowfish context.
*/
AVBlowfish *av_blowfish_alloc(void);
/**
* Initialize an AVBlowfish context.
*
* @param ctx an AVBlowfish context
* @param key a key
* @param key_len length of the key
*/
void av_blowfish_init(struct AVBlowfish *ctx, const uint8_t *key, int key_len);
/**
* Encrypt or decrypt a buffer using a previously initialized context.
*
* @param ctx an AVBlowfish context
* @param xl left four bytes halves of input to be encrypted
* @param xr right four bytes halves of input to be encrypted
* @param decrypt 0 for encryption, 1 for decryption
*/
void av_blowfish_crypt_ecb(struct AVBlowfish *ctx, uint32_t *xl, uint32_t *xr,
int decrypt);
/**
* Encrypt or decrypt a buffer using a previously initialized context.
*
* @param ctx an AVBlowfish context
* @param dst destination array, can be equal to src
* @param src source array, can be equal to dst
* @param count number of 8 byte blocks
* @param iv initialization vector for CBC mode, if NULL ECB will be used
* @param decrypt 0 for encryption, 1 for decryption
*/
void av_blowfish_crypt(struct AVBlowfish *ctx, uint8_t *dst, const uint8_t *src,
int count, uint8_t *iv, int decrypt);
/**
* @}
*/
#endif /* AVUTIL_BLOWFISH_H */

View file

@ -0,0 +1,305 @@
/*
* Copyright (c) 2012 Nicolas George
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "avassert.h"
#include "avstring.h"
#include "bprint.h"
#include "common.h"
#include "compat/va_copy.h"
#include "error.h"
#include "mem.h"
#define av_bprint_room(buf) ((buf)->size - FFMIN((buf)->len, (buf)->size))
#define av_bprint_is_allocated(buf) ((buf)->str != (buf)->reserved_internal_buffer)
static int av_bprint_alloc(AVBPrint *buf, unsigned room)
{
char *old_str, *new_str;
unsigned min_size, new_size;
if (buf->size == buf->size_max)
return AVERROR(EIO);
if (!av_bprint_is_complete(buf))
return AVERROR_INVALIDDATA; /* it is already truncated anyway */
min_size = buf->len + 1 + FFMIN(UINT_MAX - buf->len - 1, room);
new_size = buf->size > buf->size_max / 2 ? buf->size_max : buf->size * 2;
if (new_size < min_size)
new_size = FFMIN(buf->size_max, min_size);
old_str = av_bprint_is_allocated(buf) ? buf->str : NULL;
new_str = av_realloc(old_str, new_size);
if (!new_str)
return AVERROR(ENOMEM);
if (!old_str)
memcpy(new_str, buf->str, buf->len + 1);
buf->str = new_str;
buf->size = new_size;
return 0;
}
static void av_bprint_grow(AVBPrint *buf, unsigned extra_len)
{
/* arbitrary margin to avoid small overflows */
extra_len = FFMIN(extra_len, UINT_MAX - 5 - buf->len);
buf->len += extra_len;
if (buf->size)
buf->str[FFMIN(buf->len, buf->size - 1)] = 0;
}
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
{
unsigned size_auto = (char *)buf + sizeof(*buf) -
buf->reserved_internal_buffer;
if (size_max == 1)
size_max = size_auto;
buf->str = buf->reserved_internal_buffer;
buf->len = 0;
buf->size = FFMIN(size_auto, size_max);
buf->size_max = size_max;
*buf->str = 0;
if (size_init > buf->size)
av_bprint_alloc(buf, size_init - 1);
}
void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size)
{
buf->str = buffer;
buf->len = 0;
buf->size = size;
buf->size_max = size;
*buf->str = 0;
}
void av_bprintf(AVBPrint *buf, const char *fmt, ...)
{
unsigned room;
char *dst;
va_list vl;
int extra_len;
while (1) {
room = av_bprint_room(buf);
dst = room ? buf->str + buf->len : NULL;
va_start(vl, fmt);
extra_len = vsnprintf(dst, room, fmt, vl);
va_end(vl);
if (extra_len <= 0)
return;
if (extra_len < room)
break;
if (av_bprint_alloc(buf, extra_len))
break;
}
av_bprint_grow(buf, extra_len);
}
void av_vbprintf(AVBPrint *buf, const char *fmt, va_list vl_arg)
{
unsigned room;
char *dst;
int extra_len;
va_list vl;
while (1) {
room = av_bprint_room(buf);
dst = room ? buf->str + buf->len : NULL;
va_copy(vl, vl_arg);
extra_len = vsnprintf(dst, room, fmt, vl);
va_end(vl);
if (extra_len <= 0)
return;
if (extra_len < room)
break;
if (av_bprint_alloc(buf, extra_len))
break;
}
av_bprint_grow(buf, extra_len);
}
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
{
unsigned room, real_n;
while (1) {
room = av_bprint_room(buf);
if (n < room)
break;
if (av_bprint_alloc(buf, n))
break;
}
if (room) {
real_n = FFMIN(n, room - 1);
memset(buf->str + buf->len, c, real_n);
}
av_bprint_grow(buf, n);
}
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size)
{
unsigned room, real_n;
while (1) {
room = av_bprint_room(buf);
if (size < room)
break;
if (av_bprint_alloc(buf, size))
break;
}
if (room) {
real_n = FFMIN(size, room - 1);
memcpy(buf->str + buf->len, data, real_n);
}
av_bprint_grow(buf, size);
}
void av_bprint_strftime(AVBPrint *buf, const char *fmt, const struct tm *tm)
{
unsigned room;
size_t l;
if (!*fmt)
return;
while (1) {
room = av_bprint_room(buf);
if (room && (l = strftime(buf->str + buf->len, room, fmt, tm)))
break;
/* strftime does not tell us how much room it would need: let us
retry with twice as much until the buffer is large enough */
room = !room ? strlen(fmt) + 1 :
room <= INT_MAX / 2 ? room * 2 : INT_MAX;
if (av_bprint_alloc(buf, room)) {
/* impossible to grow, try to manage something useful anyway */
room = av_bprint_room(buf);
if (room < 1024) {
/* if strftime fails because the buffer has (almost) reached
its maximum size, let us try in a local buffer; 1k should
be enough to format any real date+time string */
char buf2[1024];
if ((l = strftime(buf2, sizeof(buf2), fmt, tm))) {
av_bprintf(buf, "%s", buf2);
return;
}
}
if (room) {
/* if anything else failed and the buffer is not already
truncated, let us add a stock string and force truncation */
static const char txt[] = "[truncated strftime output]";
memset(buf->str + buf->len, '!', room);
memcpy(buf->str + buf->len, txt, FFMIN(sizeof(txt) - 1, room));
av_bprint_grow(buf, room); /* force truncation */
}
return;
}
}
av_bprint_grow(buf, l);
}
void av_bprint_get_buffer(AVBPrint *buf, unsigned size,
unsigned char **mem, unsigned *actual_size)
{
if (size > av_bprint_room(buf))
av_bprint_alloc(buf, size);
*actual_size = av_bprint_room(buf);
*mem = *actual_size ? buf->str + buf->len : NULL;
}
void av_bprint_clear(AVBPrint *buf)
{
if (buf->len) {
*buf->str = 0;
buf->len = 0;
}
}
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
{
unsigned real_size = FFMIN(buf->len + 1, buf->size);
char *str;
int ret = 0;
if (ret_str) {
if (av_bprint_is_allocated(buf)) {
str = av_realloc(buf->str, real_size);
if (!str)
str = buf->str;
buf->str = NULL;
} else {
str = av_malloc(real_size);
if (str)
memcpy(str, buf->str, real_size);
else
ret = AVERROR(ENOMEM);
}
*ret_str = str;
} else {
if (av_bprint_is_allocated(buf))
av_freep(&buf->str);
}
buf->size = real_size;
return ret;
}
#define WHITESPACES " \n\t\r"
void av_bprint_escape(AVBPrint *dstbuf, const char *src, const char *special_chars,
enum AVEscapeMode mode, int flags)
{
const char *src0 = src;
if (mode == AV_ESCAPE_MODE_AUTO)
mode = AV_ESCAPE_MODE_BACKSLASH; /* TODO: implement a heuristic */
switch (mode) {
case AV_ESCAPE_MODE_QUOTE:
/* enclose the string between '' */
av_bprint_chars(dstbuf, '\'', 1);
for (; *src; src++) {
if (*src == '\'')
av_bprintf(dstbuf, "'\\''");
else
av_bprint_chars(dstbuf, *src, 1);
}
av_bprint_chars(dstbuf, '\'', 1);
break;
/* case AV_ESCAPE_MODE_BACKSLASH or unknown mode */
default:
/* \-escape characters */
for (; *src; src++) {
int is_first_last = src == src0 || !*(src+1);
int is_ws = !!strchr(WHITESPACES, *src);
int is_strictly_special = special_chars && strchr(special_chars, *src);
int is_special =
is_strictly_special || strchr("'\\", *src) ||
(is_ws && (flags & AV_ESCAPE_FLAG_WHITESPACE));
if (is_strictly_special ||
(!(flags & AV_ESCAPE_FLAG_STRICT) &&
(is_special || (is_ws && is_first_last))))
av_bprint_chars(dstbuf, '\\', 1);
av_bprint_chars(dstbuf, *src, 1);
}
break;
}
}

View file

@ -0,0 +1,219 @@
/*
* Copyright (c) 2012 Nicolas George
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_BPRINT_H
#define AVUTIL_BPRINT_H
#include <stdarg.h>
#include "attributes.h"
#include "avstring.h"
/**
* Define a structure with extra padding to a fixed size
* This helps ensuring binary compatibility with future versions.
*/
#define FF_PAD_STRUCTURE(name, size, ...) \
struct ff_pad_helper_##name { __VA_ARGS__ }; \
typedef struct name { \
__VA_ARGS__ \
char reserved_padding[size - sizeof(struct ff_pad_helper_##name)]; \
} name;
/**
* Buffer to print data progressively
*
* The string buffer grows as necessary and is always 0-terminated.
* The content of the string is never accessed, and thus is
* encoding-agnostic and can even hold binary data.
*
* Small buffers are kept in the structure itself, and thus require no
* memory allocation at all (unless the contents of the buffer is needed
* after the structure goes out of scope). This is almost as lightweight as
* declaring a local "char buf[512]".
*
* The length of the string can go beyond the allocated size: the buffer is
* then truncated, but the functions still keep account of the actual total
* length.
*
* In other words, buf->len can be greater than buf->size and records the
* total length of what would have been to the buffer if there had been
* enough memory.
*
* Append operations do not need to be tested for failure: if a memory
* allocation fails, data stop being appended to the buffer, but the length
* is still updated. This situation can be tested with
* av_bprint_is_complete().
*
* The size_max field determines several possible behaviours:
*
* size_max = -1 (= UINT_MAX) or any large value will let the buffer be
* reallocated as necessary, with an amortized linear cost.
*
* size_max = 0 prevents writing anything to the buffer: only the total
* length is computed. The write operations can then possibly be repeated in
* a buffer with exactly the necessary size
* (using size_init = size_max = len + 1).
*
* size_max = 1 is automatically replaced by the exact size available in the
* structure itself, thus ensuring no dynamic memory allocation. The
* internal buffer is large enough to hold a reasonable paragraph of text,
* such as the current paragraph.
*/
FF_PAD_STRUCTURE(AVBPrint, 1024,
char *str; /**< string so far */
unsigned len; /**< length so far */
unsigned size; /**< allocated memory */
unsigned size_max; /**< maximum allocated memory */
char reserved_internal_buffer[1];
)
/**
* Convenience macros for special values for av_bprint_init() size_max
* parameter.
*/
#define AV_BPRINT_SIZE_UNLIMITED ((unsigned)-1)
#define AV_BPRINT_SIZE_AUTOMATIC 1
#define AV_BPRINT_SIZE_COUNT_ONLY 0
/**
* Init a print buffer.
*
* @param buf buffer to init
* @param size_init initial size (including the final 0)
* @param size_max maximum size;
* 0 means do not write anything, just count the length;
* 1 is replaced by the maximum value for automatic storage;
* any large value means that the internal buffer will be
* reallocated as needed up to that limit; -1 is converted to
* UINT_MAX, the largest limit possible.
* Check also AV_BPRINT_SIZE_* macros.
*/
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max);
/**
* Init a print buffer using a pre-existing buffer.
*
* The buffer will not be reallocated.
*
* @param buf buffer structure to init
* @param buffer byte buffer to use for the string data
* @param size size of buffer
*/
void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size);
/**
* Append a formatted string to a print buffer.
*/
void av_bprintf(AVBPrint *buf, const char *fmt, ...) av_printf_format(2, 3);
/**
* Append a formatted string to a print buffer.
*/
void av_vbprintf(AVBPrint *buf, const char *fmt, va_list vl_arg);
/**
* Append char c n times to a print buffer.
*/
void av_bprint_chars(AVBPrint *buf, char c, unsigned n);
/**
* Append data to a print buffer.
*
* param buf bprint buffer to use
* param data pointer to data
* param size size of data
*/
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size);
struct tm;
/**
* Append a formatted date and time to a print buffer.
*
* param buf bprint buffer to use
* param fmt date and time format string, see strftime()
* param tm broken-down time structure to translate
*
* @note due to poor design of the standard strftime function, it may
* produce poor results if the format string expands to a very long text and
* the bprint buffer is near the limit stated by the size_max option.
*/
void av_bprint_strftime(AVBPrint *buf, const char *fmt, const struct tm *tm);
/**
* Allocate bytes in the buffer for external use.
*
* @param[in] buf buffer structure
* @param[in] size required size
* @param[out] mem pointer to the memory area
* @param[out] actual_size size of the memory area after allocation;
* can be larger or smaller than size
*/
void av_bprint_get_buffer(AVBPrint *buf, unsigned size,
unsigned char **mem, unsigned *actual_size);
/**
* Reset the string to "" but keep internal allocated data.
*/
void av_bprint_clear(AVBPrint *buf);
/**
* Test if the print buffer is complete (not truncated).
*
* It may have been truncated due to a memory allocation failure
* or the size_max limit (compare size and size_max if necessary).
*/
static inline int av_bprint_is_complete(const AVBPrint *buf)
{
return buf->len < buf->size;
}
/**
* Finalize a print buffer.
*
* The print buffer can no longer be used afterwards,
* but the len and size fields are still valid.
*
* @arg[out] ret_str if not NULL, used to return a permanent copy of the
* buffer contents, or NULL if memory allocation fails;
* if NULL, the buffer is discarded and freed
* @return 0 for success or error code (probably AVERROR(ENOMEM))
*/
int av_bprint_finalize(AVBPrint *buf, char **ret_str);
/**
* Escape the content in src and append it to dstbuf.
*
* @param dstbuf already inited destination bprint buffer
* @param src string containing the text to escape
* @param special_chars string containing the special characters which
* need to be escaped, can be NULL
* @param mode escape mode to employ, see AV_ESCAPE_MODE_* macros.
* Any unknown value for mode will be considered equivalent to
* AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without
* notice.
* @param flags flags which control how to escape, see AV_ESCAPE_FLAG_* macros
*/
void av_bprint_escape(AVBPrint *dstbuf, const char *src, const char *special_chars,
enum AVEscapeMode mode, int flags);
#endif /* AVUTIL_BPRINT_H */

View file

@ -0,0 +1,109 @@
/*
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* byte swapping routines
*/
#ifndef AVUTIL_BSWAP_H
#define AVUTIL_BSWAP_H
#include <stdint.h>
#include "libavutil/avconfig.h"
#include "attributes.h"
#ifdef HAVE_AV_CONFIG_H
#include "config.h"
#if ARCH_AARCH64
# include "aarch64/bswap.h"
#elif ARCH_ARM
# include "arm/bswap.h"
#elif ARCH_AVR32
# include "avr32/bswap.h"
#elif ARCH_SH4
# include "sh4/bswap.h"
#elif ARCH_X86
# include "x86/bswap.h"
#endif
#endif /* HAVE_AV_CONFIG_H */
#define AV_BSWAP16C(x) (((x) << 8 & 0xff00) | ((x) >> 8 & 0x00ff))
#define AV_BSWAP32C(x) (AV_BSWAP16C(x) << 16 | AV_BSWAP16C((x) >> 16))
#define AV_BSWAP64C(x) (AV_BSWAP32C(x) << 32 | AV_BSWAP32C((x) >> 32))
#define AV_BSWAPC(s, x) AV_BSWAP##s##C(x)
#ifndef av_bswap16
static av_always_inline av_const uint16_t av_bswap16(uint16_t x)
{
x= (x>>8) | (x<<8);
return x;
}
#endif
#ifndef av_bswap32
static av_always_inline av_const uint32_t av_bswap32(uint32_t x)
{
return AV_BSWAP32C(x);
}
#endif
#ifndef av_bswap64
static inline uint64_t av_const av_bswap64(uint64_t x)
{
return (uint64_t)av_bswap32(x) << 32 | av_bswap32(x >> 32);
}
#endif
// be2ne ... big-endian to native-endian
// le2ne ... little-endian to native-endian
#if AV_HAVE_BIGENDIAN
#define av_be2ne16(x) (x)
#define av_be2ne32(x) (x)
#define av_be2ne64(x) (x)
#define av_le2ne16(x) av_bswap16(x)
#define av_le2ne32(x) av_bswap32(x)
#define av_le2ne64(x) av_bswap64(x)
#define AV_BE2NEC(s, x) (x)
#define AV_LE2NEC(s, x) AV_BSWAPC(s, x)
#else
#define av_be2ne16(x) av_bswap16(x)
#define av_be2ne32(x) av_bswap32(x)
#define av_be2ne64(x) av_bswap64(x)
#define av_le2ne16(x) (x)
#define av_le2ne32(x) (x)
#define av_le2ne64(x) (x)
#define AV_BE2NEC(s, x) AV_BSWAPC(s, x)
#define AV_LE2NEC(s, x) (x)
#endif
#define AV_BE2NE16C(x) AV_BE2NEC(16, x)
#define AV_BE2NE32C(x) AV_BE2NEC(32, x)
#define AV_BE2NE64C(x) AV_BE2NEC(64, x)
#define AV_LE2NE16C(x) AV_LE2NEC(16, x)
#define AV_LE2NE32C(x) AV_LE2NEC(32, x)
#define AV_LE2NE64C(x) AV_LE2NEC(64, x)
#endif /* AVUTIL_BSWAP_H */

View file

@ -0,0 +1,357 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdatomic.h>
#include <stdint.h>
#include <string.h>
#include "buffer_internal.h"
#include "common.h"
#include "mem.h"
#include "thread.h"
AVBufferRef *av_buffer_create(uint8_t *data, int size,
void (*free)(void *opaque, uint8_t *data),
void *opaque, int flags)
{
AVBufferRef *ref = NULL;
AVBuffer *buf = NULL;
buf = av_mallocz(sizeof(*buf));
if (!buf)
return NULL;
buf->data = data;
buf->size = size;
buf->free = free ? free : av_buffer_default_free;
buf->opaque = opaque;
atomic_init(&buf->refcount, 1);
if (flags & AV_BUFFER_FLAG_READONLY)
buf->flags |= BUFFER_FLAG_READONLY;
ref = av_mallocz(sizeof(*ref));
if (!ref) {
av_freep(&buf);
return NULL;
}
ref->buffer = buf;
ref->data = data;
ref->size = size;
return ref;
}
void av_buffer_default_free(void *opaque, uint8_t *data)
{
av_free(data);
}
AVBufferRef *av_buffer_alloc(int size)
{
AVBufferRef *ret = NULL;
uint8_t *data = NULL;
data = av_malloc(size);
if (!data)
return NULL;
ret = av_buffer_create(data, size, av_buffer_default_free, NULL, 0);
if (!ret)
av_freep(&data);
return ret;
}
AVBufferRef *av_buffer_allocz(int size)
{
AVBufferRef *ret = av_buffer_alloc(size);
if (!ret)
return NULL;
memset(ret->data, 0, size);
return ret;
}
AVBufferRef *av_buffer_ref(AVBufferRef *buf)
{
AVBufferRef *ret = av_mallocz(sizeof(*ret));
if (!ret)
return NULL;
*ret = *buf;
atomic_fetch_add_explicit(&buf->buffer->refcount, 1, memory_order_relaxed);
return ret;
}
static void buffer_replace(AVBufferRef **dst, AVBufferRef **src)
{
AVBuffer *b;
b = (*dst)->buffer;
if (src) {
**dst = **src;
av_freep(src);
} else
av_freep(dst);
if (atomic_fetch_add_explicit(&b->refcount, -1, memory_order_acq_rel) == 1) {
b->free(b->opaque, b->data);
av_freep(&b);
}
}
void av_buffer_unref(AVBufferRef **buf)
{
if (!buf || !*buf)
return;
buffer_replace(buf, NULL);
}
int av_buffer_is_writable(const AVBufferRef *buf)
{
if (buf->buffer->flags & AV_BUFFER_FLAG_READONLY)
return 0;
return atomic_load(&buf->buffer->refcount) == 1;
}
void *av_buffer_get_opaque(const AVBufferRef *buf)
{
return buf->buffer->opaque;
}
int av_buffer_get_ref_count(const AVBufferRef *buf)
{
return atomic_load(&buf->buffer->refcount);
}
int av_buffer_make_writable(AVBufferRef **pbuf)
{
AVBufferRef *newbuf, *buf = *pbuf;
if (av_buffer_is_writable(buf))
return 0;
newbuf = av_buffer_alloc(buf->size);
if (!newbuf)
return AVERROR(ENOMEM);
memcpy(newbuf->data, buf->data, buf->size);
buffer_replace(pbuf, &newbuf);
return 0;
}
int av_buffer_realloc(AVBufferRef **pbuf, int size)
{
AVBufferRef *buf = *pbuf;
uint8_t *tmp;
if (!buf) {
/* allocate a new buffer with av_realloc(), so it will be reallocatable
* later */
uint8_t *data = av_realloc(NULL, size);
if (!data)
return AVERROR(ENOMEM);
buf = av_buffer_create(data, size, av_buffer_default_free, NULL, 0);
if (!buf) {
av_freep(&data);
return AVERROR(ENOMEM);
}
buf->buffer->flags |= BUFFER_FLAG_REALLOCATABLE;
*pbuf = buf;
return 0;
} else if (buf->size == size)
return 0;
if (!(buf->buffer->flags & BUFFER_FLAG_REALLOCATABLE) ||
!av_buffer_is_writable(buf) || buf->data != buf->buffer->data) {
/* cannot realloc, allocate a new reallocable buffer and copy data */
AVBufferRef *new = NULL;
av_buffer_realloc(&new, size);
if (!new)
return AVERROR(ENOMEM);
memcpy(new->data, buf->data, FFMIN(size, buf->size));
buffer_replace(pbuf, &new);
return 0;
}
tmp = av_realloc(buf->buffer->data, size);
if (!tmp)
return AVERROR(ENOMEM);
buf->buffer->data = buf->data = tmp;
buf->buffer->size = buf->size = size;
return 0;
}
AVBufferPool *av_buffer_pool_init2(int size, void *opaque,
AVBufferRef* (*alloc)(void *opaque, int size),
void (*pool_free)(void *opaque))
{
AVBufferPool *pool = av_mallocz(sizeof(*pool));
if (!pool)
return NULL;
ff_mutex_init(&pool->mutex, NULL);
pool->size = size;
pool->opaque = opaque;
pool->alloc2 = alloc;
pool->pool_free = pool_free;
atomic_init(&pool->refcount, 1);
return pool;
}
AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size))
{
AVBufferPool *pool = av_mallocz(sizeof(*pool));
if (!pool)
return NULL;
ff_mutex_init(&pool->mutex, NULL);
pool->size = size;
pool->alloc = alloc ? alloc : av_buffer_alloc;
atomic_init(&pool->refcount, 1);
return pool;
}
/*
* This function gets called when the pool has been uninited and
* all the buffers returned to it.
*/
static void buffer_pool_free(AVBufferPool *pool)
{
while (pool->pool) {
BufferPoolEntry *buf = pool->pool;
pool->pool = buf->next;
buf->free(buf->opaque, buf->data);
av_freep(&buf);
}
ff_mutex_destroy(&pool->mutex);
if (pool->pool_free)
pool->pool_free(pool->opaque);
av_freep(&pool);
}
void av_buffer_pool_uninit(AVBufferPool **ppool)
{
AVBufferPool *pool;
if (!ppool || !*ppool)
return;
pool = *ppool;
*ppool = NULL;
if (atomic_fetch_add_explicit(&pool->refcount, -1, memory_order_acq_rel) == 1)
buffer_pool_free(pool);
}
static void pool_release_buffer(void *opaque, uint8_t *data)
{
BufferPoolEntry *buf = opaque;
AVBufferPool *pool = buf->pool;
if(CONFIG_MEMORY_POISONING)
memset(buf->data, FF_MEMORY_POISON, pool->size);
ff_mutex_lock(&pool->mutex);
buf->next = pool->pool;
pool->pool = buf;
ff_mutex_unlock(&pool->mutex);
if (atomic_fetch_add_explicit(&pool->refcount, -1, memory_order_acq_rel) == 1)
buffer_pool_free(pool);
}
/* allocate a new buffer and override its free() callback so that
* it is returned to the pool on free */
static AVBufferRef *pool_alloc_buffer(AVBufferPool *pool)
{
BufferPoolEntry *buf;
AVBufferRef *ret;
ret = pool->alloc2 ? pool->alloc2(pool->opaque, pool->size) :
pool->alloc(pool->size);
if (!ret)
return NULL;
buf = av_mallocz(sizeof(*buf));
if (!buf) {
av_buffer_unref(&ret);
return NULL;
}
buf->data = ret->buffer->data;
buf->opaque = ret->buffer->opaque;
buf->free = ret->buffer->free;
buf->pool = pool;
ret->buffer->opaque = buf;
ret->buffer->free = pool_release_buffer;
return ret;
}
AVBufferRef *av_buffer_pool_get(AVBufferPool *pool)
{
AVBufferRef *ret;
BufferPoolEntry *buf;
ff_mutex_lock(&pool->mutex);
buf = pool->pool;
if (buf) {
ret = av_buffer_create(buf->data, pool->size, pool_release_buffer,
buf, 0);
if (ret) {
pool->pool = buf->next;
buf->next = NULL;
}
} else {
ret = pool_alloc_buffer(pool);
}
ff_mutex_unlock(&pool->mutex);
if (ret)
atomic_fetch_add_explicit(&pool->refcount, 1, memory_order_relaxed);
return ret;
}

View file

@ -0,0 +1,291 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* @ingroup lavu_buffer
* refcounted data buffer API
*/
#ifndef AVUTIL_BUFFER_H
#define AVUTIL_BUFFER_H
#include <stdint.h>
/**
* @defgroup lavu_buffer AVBuffer
* @ingroup lavu_data
*
* @{
* AVBuffer is an API for reference-counted data buffers.
*
* There are two core objects in this API -- AVBuffer and AVBufferRef. AVBuffer
* represents the data buffer itself; it is opaque and not meant to be accessed
* by the caller directly, but only through AVBufferRef. However, the caller may
* e.g. compare two AVBuffer pointers to check whether two different references
* are describing the same data buffer. AVBufferRef represents a single
* reference to an AVBuffer and it is the object that may be manipulated by the
* caller directly.
*
* There are two functions provided for creating a new AVBuffer with a single
* reference -- av_buffer_alloc() to just allocate a new buffer, and
* av_buffer_create() to wrap an existing array in an AVBuffer. From an existing
* reference, additional references may be created with av_buffer_ref().
* Use av_buffer_unref() to free a reference (this will automatically free the
* data once all the references are freed).
*
* The convention throughout this API and the rest of FFmpeg is such that the
* buffer is considered writable if there exists only one reference to it (and
* it has not been marked as read-only). The av_buffer_is_writable() function is
* provided to check whether this is true and av_buffer_make_writable() will
* automatically create a new writable buffer when necessary.
* Of course nothing prevents the calling code from violating this convention,
* however that is safe only when all the existing references are under its
* control.
*
* @note Referencing and unreferencing the buffers is thread-safe and thus
* may be done from multiple threads simultaneously without any need for
* additional locking.
*
* @note Two different references to the same buffer can point to different
* parts of the buffer (i.e. their AVBufferRef.data will not be equal).
*/
/**
* A reference counted buffer type. It is opaque and is meant to be used through
* references (AVBufferRef).
*/
typedef struct AVBuffer AVBuffer;
/**
* A reference to a data buffer.
*
* The size of this struct is not a part of the public ABI and it is not meant
* to be allocated directly.
*/
typedef struct AVBufferRef {
AVBuffer *buffer;
/**
* The data buffer. It is considered writable if and only if
* this is the only reference to the buffer, in which case
* av_buffer_is_writable() returns 1.
*/
uint8_t *data;
/**
* Size of data in bytes.
*/
int size;
} AVBufferRef;
/**
* Allocate an AVBuffer of the given size using av_malloc().
*
* @return an AVBufferRef of given size or NULL when out of memory
*/
AVBufferRef *av_buffer_alloc(int size);
/**
* Same as av_buffer_alloc(), except the returned buffer will be initialized
* to zero.
*/
AVBufferRef *av_buffer_allocz(int size);
/**
* Always treat the buffer as read-only, even when it has only one
* reference.
*/
#define AV_BUFFER_FLAG_READONLY (1 << 0)
/**
* Create an AVBuffer from an existing array.
*
* If this function is successful, data is owned by the AVBuffer. The caller may
* only access data through the returned AVBufferRef and references derived from
* it.
* If this function fails, data is left untouched.
* @param data data array
* @param size size of data in bytes
* @param free a callback for freeing this buffer's data
* @param opaque parameter to be got for processing or passed to free
* @param flags a combination of AV_BUFFER_FLAG_*
*
* @return an AVBufferRef referring to data on success, NULL on failure.
*/
AVBufferRef *av_buffer_create(uint8_t *data, int size,
void (*free)(void *opaque, uint8_t *data),
void *opaque, int flags);
/**
* Default free callback, which calls av_free() on the buffer data.
* This function is meant to be passed to av_buffer_create(), not called
* directly.
*/
void av_buffer_default_free(void *opaque, uint8_t *data);
/**
* Create a new reference to an AVBuffer.
*
* @return a new AVBufferRef referring to the same AVBuffer as buf or NULL on
* failure.
*/
AVBufferRef *av_buffer_ref(AVBufferRef *buf);
/**
* Free a given reference and automatically free the buffer if there are no more
* references to it.
*
* @param buf the reference to be freed. The pointer is set to NULL on return.
*/
void av_buffer_unref(AVBufferRef **buf);
/**
* @return 1 if the caller may write to the data referred to by buf (which is
* true if and only if buf is the only reference to the underlying AVBuffer).
* Return 0 otherwise.
* A positive answer is valid until av_buffer_ref() is called on buf.
*/
int av_buffer_is_writable(const AVBufferRef *buf);
/**
* @return the opaque parameter set by av_buffer_create.
*/
void *av_buffer_get_opaque(const AVBufferRef *buf);
int av_buffer_get_ref_count(const AVBufferRef *buf);
/**
* Create a writable reference from a given buffer reference, avoiding data copy
* if possible.
*
* @param buf buffer reference to make writable. On success, buf is either left
* untouched, or it is unreferenced and a new writable AVBufferRef is
* written in its place. On failure, buf is left untouched.
* @return 0 on success, a negative AVERROR on failure.
*/
int av_buffer_make_writable(AVBufferRef **buf);
/**
* Reallocate a given buffer.
*
* @param buf a buffer reference to reallocate. On success, buf will be
* unreferenced and a new reference with the required size will be
* written in its place. On failure buf will be left untouched. *buf
* may be NULL, then a new buffer is allocated.
* @param size required new buffer size.
* @return 0 on success, a negative AVERROR on failure.
*
* @note the buffer is actually reallocated with av_realloc() only if it was
* initially allocated through av_buffer_realloc(NULL) and there is only one
* reference to it (i.e. the one passed to this function). In all other cases
* a new buffer is allocated and the data is copied.
*/
int av_buffer_realloc(AVBufferRef **buf, int size);
/**
* @}
*/
/**
* @defgroup lavu_bufferpool AVBufferPool
* @ingroup lavu_data
*
* @{
* AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers.
*
* Frequently allocating and freeing large buffers may be slow. AVBufferPool is
* meant to solve this in cases when the caller needs a set of buffers of the
* same size (the most obvious use case being buffers for raw video or audio
* frames).
*
* At the beginning, the user must call av_buffer_pool_init() to create the
* buffer pool. Then whenever a buffer is needed, call av_buffer_pool_get() to
* get a reference to a new buffer, similar to av_buffer_alloc(). This new
* reference works in all aspects the same way as the one created by
* av_buffer_alloc(). However, when the last reference to this buffer is
* unreferenced, it is returned to the pool instead of being freed and will be
* reused for subsequent av_buffer_pool_get() calls.
*
* When the caller is done with the pool and no longer needs to allocate any new
* buffers, av_buffer_pool_uninit() must be called to mark the pool as freeable.
* Once all the buffers are released, it will automatically be freed.
*
* Allocating and releasing buffers with this API is thread-safe as long as
* either the default alloc callback is used, or the user-supplied one is
* thread-safe.
*/
/**
* The buffer pool. This structure is opaque and not meant to be accessed
* directly. It is allocated with av_buffer_pool_init() and freed with
* av_buffer_pool_uninit().
*/
typedef struct AVBufferPool AVBufferPool;
/**
* Allocate and initialize a buffer pool.
*
* @param size size of each buffer in this pool
* @param alloc a function that will be used to allocate new buffers when the
* pool is empty. May be NULL, then the default allocator will be used
* (av_buffer_alloc()).
* @return newly created buffer pool on success, NULL on error.
*/
AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size));
/**
* Allocate and initialize a buffer pool with a more complex allocator.
*
* @param size size of each buffer in this pool
* @param opaque arbitrary user data used by the allocator
* @param alloc a function that will be used to allocate new buffers when the
* pool is empty.
* @param pool_free a function that will be called immediately before the pool
* is freed. I.e. after av_buffer_pool_uninit() is called
* by the caller and all the frames are returned to the pool
* and freed. It is intended to uninitialize the user opaque
* data.
* @return newly created buffer pool on success, NULL on error.
*/
AVBufferPool *av_buffer_pool_init2(int size, void *opaque,
AVBufferRef* (*alloc)(void *opaque, int size),
void (*pool_free)(void *opaque));
/**
* Mark the pool as being available for freeing. It will actually be freed only
* once all the allocated buffers associated with the pool are released. Thus it
* is safe to call this function while some of the allocated buffers are still
* in use.
*
* @param pool pointer to the pool to be freed. It will be set to NULL.
*/
void av_buffer_pool_uninit(AVBufferPool **pool);
/**
* Allocate a new AVBuffer, reusing an old buffer from the pool when available.
* This function may be called simultaneously from multiple threads.
*
* @return a reference to the new buffer on success, NULL on error.
*/
AVBufferRef *av_buffer_pool_get(AVBufferPool *pool);
/**
* @}
*/
#endif /* AVUTIL_BUFFER_H */

View file

@ -0,0 +1,98 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_BUFFER_INTERNAL_H
#define AVUTIL_BUFFER_INTERNAL_H
#include <stdatomic.h>
#include <stdint.h>
#include "buffer.h"
#include "thread.h"
/**
* The buffer is always treated as read-only.
*/
#define BUFFER_FLAG_READONLY (1 << 0)
/**
* The buffer was av_realloc()ed, so it is reallocatable.
*/
#define BUFFER_FLAG_REALLOCATABLE (1 << 1)
struct AVBuffer {
uint8_t *data; /**< data described by this buffer */
int size; /**< size of data in bytes */
/**
* number of existing AVBufferRef instances referring to this buffer
*/
atomic_uint refcount;
/**
* a callback for freeing the data
*/
void (*free)(void *opaque, uint8_t *data);
/**
* an opaque pointer, to be used by the freeing callback
*/
void *opaque;
/**
* A combination of BUFFER_FLAG_*
*/
int flags;
};
typedef struct BufferPoolEntry {
uint8_t *data;
/*
* Backups of the original opaque/free of the AVBuffer corresponding to
* data. They will be used to free the buffer when the pool is freed.
*/
void *opaque;
void (*free)(void *opaque, uint8_t *data);
AVBufferPool *pool;
struct BufferPoolEntry *next;
} BufferPoolEntry;
struct AVBufferPool {
AVMutex mutex;
BufferPoolEntry *pool;
/*
* This is used to track when the pool is to be freed.
* The pointer to the pool itself held by the caller is considered to
* be one reference. Each buffer requested by the caller increases refcount
* by one, returning the buffer to the pool decreases it by one.
* refcount reaches zero when the buffer has been uninited AND all the
* buffers have been released, then it's safe to free the pool and all
* the buffers in it.
*/
atomic_uint refcount;
int size;
void *opaque;
AVBufferRef* (*alloc)(int size);
AVBufferRef* (*alloc2)(void *opaque, int size);
void (*pool_free)(void *opaque);
};
#endif /* AVUTIL_BUFFER_INTERNAL_H */

View file

@ -0,0 +1,412 @@
/*
* An implementation of the CAMELLIA algorithm as mentioned in RFC3713
* Copyright (c) 2014 Supraja Meedinti
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "camellia.h"
#include "common.h"
#include "intreadwrite.h"
#include "attributes.h"
#define LR32(x,c) ((x) << (c) | (x) >> (32 - (c)))
#define RR32(x,c) ((x) >> (c) | (x) << (32 - (c)))
#define MASK8 0xff
#define MASK32 0xffffffff
#define MASK64 0xffffffffffffffff
#define Sigma1 0xA09E667F3BCC908B
#define Sigma2 0xB67AE8584CAA73B2
#define Sigma3 0xC6EF372FE94F82BE
#define Sigma4 0x54FF53A5F1D36F1C
#define Sigma5 0x10E527FADE682D1D
#define Sigma6 0xB05688C2B3E6C1FD
static uint64_t SP[8][256];
typedef struct AVCAMELLIA {
uint64_t Kw[4];
uint64_t Ke[6];
uint64_t K[24];
int key_bits;
} AVCAMELLIA;
static const uint8_t SBOX1[256] = {
112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65,
35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189,
134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26,
166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77,
139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153,
223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215,
20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34,
254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80,
170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210,
16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148,
135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226,
82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46,
233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89,
120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250,
114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164,
64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158
};
static const uint8_t SBOX2[256] = {
224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130,
70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123,
13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52,
77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154,
23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51,
191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175,
40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68,
253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160,
85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165,
32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41,
15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197,
164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92,
211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178,
240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245,
228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73,
128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61
};
static const uint8_t SBOX3[256] = {
56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160,
145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222,
67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13,
83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166,
197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204,
239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235,
10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17,
127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40,
85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105,
8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74,
195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113,
41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23,
244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172,
60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125,
57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82,
32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79
};
static const uint8_t SBOX4[256] = {
112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146,
134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108,
139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4,
20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105,
170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221,
135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99,
233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141,
114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128,
130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189,
184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77,
13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215,
88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80,
208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148,
92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46,
121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250,
7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158
};
const int av_camellia_size = sizeof(AVCAMELLIA);
static void LR128(uint64_t d[2], const uint64_t K[2], int x)
{
int i = 0;
if (64 <= x && x < 128) {
i = 1;
x -= 64;
}
if (x <= 0 || x >= 128) {
d[0] = K[i];
d[1] = K[!i];
return;
}
d[0] = (K[i] << x | K[!i] >> (64 - x));
d[1] = (K[!i] << x | K[i] >> (64 - x));
}
static uint64_t F(uint64_t F_IN, uint64_t KE)
{
KE ^= F_IN;
F_IN=SP[0][KE >> 56]^SP[1][(KE >> 48) & MASK8]^SP[2][(KE >> 40) & MASK8]^SP[3][(KE >> 32) & MASK8]^SP[4][(KE >> 24) & MASK8]^SP[5][(KE >> 16) & MASK8]^SP[6][(KE >> 8) & MASK8]^SP[7][KE & MASK8];
return F_IN;
}
static uint64_t FL(uint64_t FL_IN, uint64_t KE)
{
uint32_t x1, x2, k1, k2;
x1 = FL_IN >> 32;
x2 = FL_IN & MASK32;
k1 = KE >> 32;
k2 = KE & MASK32;
x2 = x2 ^ LR32((x1 & k1), 1);
x1 = x1 ^ (x2 | k2);
return ((uint64_t)x1 << 32) | (uint64_t)x2;
}
static uint64_t FLINV(uint64_t FLINV_IN, uint64_t KE)
{
uint32_t x1, x2, k1, k2;
x1 = FLINV_IN >> 32;
x2 = FLINV_IN & MASK32;
k1 = KE >> 32;
k2 = KE & MASK32;
x1 = x1 ^ (x2 | k2);
x2 = x2 ^ LR32((x1 & k1), 1);
return ((uint64_t)x1 << 32) | (uint64_t)x2;
}
static const uint8_t shifts[2][12] = {
{0, 15, 15, 45, 45, 60, 94, 94, 111},
{0, 15, 15, 30, 45, 45, 60, 60, 77, 94, 94, 111}
};
static const uint8_t vars[2][12] = {
{2, 0, 2, 0, 2, 2, 0, 2, 0},
{3, 1, 2, 3, 0, 2, 1, 3, 0, 1, 2, 0}
};
static void generate_round_keys(AVCAMELLIA *cs, uint64_t Kl[2], uint64_t Kr[2], uint64_t Ka[2], uint64_t Kb[2])
{
int i;
uint64_t *Kd[4], d[2];
Kd[0] = Kl;
Kd[1] = Kr;
Kd[2] = Ka;
Kd[3] = Kb;
cs->Kw[0] = Kl[0];
cs->Kw[1] = Kl[1];
if (cs->key_bits == 128) {
for (i = 0; i < 9; i++) {
LR128(d, Kd[vars[0][i]], shifts[0][i]);
cs->K[2*i] = d[0];
cs->K[2*i+1] = d[1];
}
LR128(d, Kd[0], 60);
cs->K[9] = d[1];
LR128(d, Kd[2], 30);
cs->Ke[0] = d[0];
cs->Ke[1] = d[1];
LR128(d, Kd[0], 77);
cs->Ke[2] = d[0];
cs->Ke[3] = d[1];
LR128(d, Kd[2], 111);
cs->Kw[2] = d[0];
cs->Kw[3] = d[1];
} else {
for (i = 0; i < 12; i++) {
LR128(d, Kd[vars[1][i]], shifts[1][i]);
cs->K[2*i] = d[0];
cs->K[2*i+1] = d[1];
}
LR128(d, Kd[1], 30);
cs->Ke[0] = d[0];
cs->Ke[1] = d[1];
LR128(d, Kd[0], 60);
cs->Ke[2] = d[0];
cs->Ke[3] = d[1];
LR128(d, Kd[2], 77);
cs->Ke[4] = d[0];
cs->Ke[5] = d[1];
LR128(d, Kd[3], 111);
cs->Kw[2] = d[0];
cs->Kw[3] = d[1];
}
}
static void camellia_encrypt(AVCAMELLIA *cs, uint8_t *dst, const uint8_t *src)
{
uint64_t D1, D2;
D1 = AV_RB64(src);
D2 = AV_RB64(src + 8);
D1 ^= cs->Kw[0];
D2 ^= cs->Kw[1];
D2 ^= F(D1, cs->K[0]);
D1 ^= F(D2, cs->K[1]);
D2 ^= F(D1, cs->K[2]);
D1 ^= F(D2, cs->K[3]);
D2 ^= F(D1, cs->K[4]);
D1 ^= F(D2, cs->K[5]);
D1 = FL(D1, cs->Ke[0]);
D2 = FLINV(D2, cs->Ke[1]);
D2 ^= F(D1, cs->K[6]);
D1 ^= F(D2, cs->K[7]);
D2 ^= F(D1, cs->K[8]);
D1 ^= F(D2, cs->K[9]);
D2 ^= F(D1, cs->K[10]);
D1 ^= F(D2, cs->K[11]);
D1 = FL(D1, cs->Ke[2]);
D2 = FLINV(D2, cs->Ke[3]);
D2 ^= F(D1, cs->K[12]);
D1 ^= F(D2, cs->K[13]);
D2 ^= F(D1, cs->K[14]);
D1 ^= F(D2, cs->K[15]);
D2 ^= F(D1, cs->K[16]);
D1 ^= F(D2, cs->K[17]);
if (cs->key_bits != 128) {
D1 = FL(D1, cs->Ke[4]);
D2 = FLINV(D2, cs->Ke[5]);
D2 ^= F(D1, cs->K[18]);
D1 ^= F(D2, cs->K[19]);
D2 ^= F(D1, cs->K[20]);
D1 ^= F(D2, cs->K[21]);
D2 ^= F(D1, cs->K[22]);
D1 ^= F(D2, cs->K[23]);
}
D2 ^= cs->Kw[2];
D1 ^= cs->Kw[3];
AV_WB64(dst, D2);
AV_WB64(dst + 8, D1);
}
static void camellia_decrypt(AVCAMELLIA *cs, uint8_t *dst, const uint8_t *src, uint8_t *iv)
{
uint64_t D1, D2;
D1 = AV_RB64(src);
D2 = AV_RB64(src + 8);
D1 ^= cs->Kw[2];
D2 ^= cs->Kw[3];
if (cs->key_bits != 128) {
D2 ^= F(D1, cs->K[23]);
D1 ^= F(D2, cs->K[22]);
D2 ^= F(D1, cs->K[21]);
D1 ^= F(D2, cs->K[20]);
D2 ^= F(D1, cs->K[19]);
D1 ^= F(D2, cs->K[18]);
D1 = FL(D1, cs->Ke[5]);
D2 = FLINV(D2, cs->Ke[4]);
}
D2 ^= F(D1, cs->K[17]);
D1 ^= F(D2, cs->K[16]);
D2 ^= F(D1, cs->K[15]);
D1 ^= F(D2, cs->K[14]);
D2 ^= F(D1, cs->K[13]);
D1 ^= F(D2, cs->K[12]);
D1 = FL(D1, cs->Ke[3]);
D2 = FLINV(D2, cs->Ke[2]);
D2 ^= F(D1, cs->K[11]);
D1 ^= F(D2, cs->K[10]);
D2 ^= F(D1, cs->K[9]);
D1 ^= F(D2, cs->K[8]);
D2 ^= F(D1, cs->K[7]);
D1 ^= F(D2, cs->K[6]);
D1 = FL(D1, cs->Ke[1]);
D2 = FLINV(D2, cs->Ke[0]);
D2 ^= F(D1, cs->K[5]);
D1 ^= F(D2, cs->K[4]);
D2 ^= F(D1, cs->K[3]);
D1 ^= F(D2, cs->K[2]);
D2 ^= F(D1, cs->K[1]);
D1 ^= F(D2, cs->K[0]);
D2 ^= cs->Kw[0];
D1 ^= cs->Kw[1];
if (iv) {
D2 ^= AV_RB64(iv);
D1 ^= AV_RB64(iv + 8);
memcpy(iv, src, 16);
}
AV_WB64(dst, D2);
AV_WB64(dst + 8, D1);
}
static void computeSP(void)
{
uint64_t z;
int i;
for (i = 0; i < 256; i++) {
z = SBOX1[i];
SP[0][i] = (z << 56) ^ (z << 48) ^ (z << 40) ^ (z << 24) ^ z;
SP[7][i] = (z << 56) ^ (z << 48) ^ (z << 40) ^ (z << 24) ^ (z << 16) ^ (z << 8);
z = SBOX2[i];
SP[1][i] = (z << 48) ^ (z << 40) ^ (z << 32) ^ (z << 24) ^ (z << 16);
SP[4][i] = (z << 48) ^ (z << 40) ^ (z << 32) ^ (z << 16) ^ (z << 8) ^ z;
z = SBOX3[i];
SP[2][i] = (z << 56) ^ (z << 40) ^ (z << 32) ^ (z << 16) ^ (z << 8);
SP[5][i] = (z << 56) ^ (z << 40) ^ (z << 32) ^ (z << 24) ^ (z << 8) ^ z;
z = SBOX4[i];
SP[3][i] = (z << 56) ^ (z << 48) ^ (z << 32) ^ (z << 8) ^ z;
SP[6][i] = (z << 56) ^ (z << 48) ^ (z << 32) ^ (z << 24) ^ (z << 16) ^ z;
}
}
struct AVCAMELLIA *av_camellia_alloc(void)
{
return av_mallocz(sizeof(struct AVCAMELLIA));
}
av_cold int av_camellia_init(AVCAMELLIA *cs, const uint8_t *key, int key_bits)
{
uint64_t Kl[2], Kr[2], Ka[2], Kb[2];
uint64_t D1, D2;
if (key_bits != 128 && key_bits != 192 && key_bits != 256)
return AVERROR(EINVAL);
memset(Kb, 0, sizeof(Kb));
memset(Kr, 0, sizeof(Kr));
cs->key_bits = key_bits;
Kl[0] = AV_RB64(key);
Kl[1] = AV_RB64(key + 8);
if (key_bits == 192) {
Kr[0] = AV_RB64(key + 16);
Kr[1] = ~Kr[0];
} else if (key_bits == 256) {
Kr[0] = AV_RB64(key + 16);
Kr[1] = AV_RB64(key + 24);
}
computeSP();
D1 = Kl[0] ^ Kr[0];
D2 = Kl[1] ^ Kr[1];
D2 ^= F(D1, Sigma1);
D1 ^= F(D2, Sigma2);
D1 ^= Kl[0];
D2 ^= Kl[1];
D2 ^= F(D1, Sigma3);
D1 ^= F(D2, Sigma4);
Ka[0] = D1;
Ka[1] = D2;
if (key_bits != 128) {
D1 = Ka[0] ^ Kr[0];
D2 = Ka[1] ^ Kr[1];
D2 ^= F(D1, Sigma5);
D1 ^= F(D2, Sigma6);
Kb[0] = D1;
Kb[1] = D2;
}
generate_round_keys(cs, Kl, Kr, Ka, Kb);
return 0;
}
void av_camellia_crypt(AVCAMELLIA *cs, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt)
{
int i;
while (count--) {
if (decrypt) {
camellia_decrypt(cs, dst, src, iv);
} else {
if (iv) {
for (i = 0; i < 16; i++)
dst[i] = src[i] ^ iv[i];
camellia_encrypt(cs, dst, dst);
memcpy(iv, dst, 16);
} else {
camellia_encrypt(cs, dst, src);
}
}
src = src + 16;
dst = dst + 16;
}
}

View file

@ -0,0 +1,70 @@
/*
* An implementation of the CAMELLIA algorithm as mentioned in RFC3713
* Copyright (c) 2014 Supraja Meedinti
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_CAMELLIA_H
#define AVUTIL_CAMELLIA_H
#include <stdint.h>
/**
* @file
* @brief Public header for libavutil CAMELLIA algorithm
* @defgroup lavu_camellia CAMELLIA
* @ingroup lavu_crypto
* @{
*/
extern const int av_camellia_size;
struct AVCAMELLIA;
/**
* Allocate an AVCAMELLIA context
* To free the struct: av_free(ptr)
*/
struct AVCAMELLIA *av_camellia_alloc(void);
/**
* Initialize an AVCAMELLIA context.
*
* @param ctx an AVCAMELLIA context
* @param key a key of 16, 24, 32 bytes used for encryption/decryption
* @param key_bits number of keybits: possible are 128, 192, 256
*/
int av_camellia_init(struct AVCAMELLIA *ctx, const uint8_t *key, int key_bits);
/**
* Encrypt or decrypt a buffer using a previously initialized context
*
* @param ctx an AVCAMELLIA context
* @param dst destination array, can be equal to src
* @param src source array, can be equal to dst
* @param count number of 16 byte blocks
* @paran iv initialization vector for CBC mode, NULL for ECB mode
* @param decrypt 0 for encryption, 1 for decryption
*/
void av_camellia_crypt(struct AVCAMELLIA *ctx, uint8_t *dst, const uint8_t *src, int count, uint8_t* iv, int decrypt);
/**
* @}
*/
#endif /* AVUTIL_CAMELLIA_H */

View file

@ -0,0 +1,507 @@
/*
* An implementation of the CAST128 algorithm as mentioned in RFC2144
* Copyright (c) 2014 Supraja Meedinti
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "cast5.h"
#include "common.h"
#include "intreadwrite.h"
#include "attributes.h"
#define IA(x) ((x) >> 24)
#define IB(x) (((x) >> 16) & 0xff)
#define IC(x) (((x) >> 8) & 0xff)
#define ID(x) ((x) & 0xff)
#define LR(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
#define F3(l, r, i) \
do { \
I = LR(cs->Km[i] - r, cs->Kr[i]); \
f = ((S1[IA(I)] + S2[IB(I)]) ^ S3[IC(I)]) - S4[ID(I)]; \
l = f ^ l; \
} while (0)
#define F2(l, r, i) \
do { \
I = LR(cs->Km[i] ^ r, cs->Kr[i]); \
f = ((S1[IA(I)] - S2[IB(I)]) + S3[IC(I)]) ^ S4[ID(I)]; \
l = f ^ l; \
} while (0)
#define F1(l, r, i) \
do { \
I = LR(cs->Km[i] + r, cs->Kr[i]); \
f = ((S1[IA(I)] ^ S2[IB(I)]) - S3[IC(I)]) + S4[ID(I)]; \
l = f ^ l; \
} while (0)
#define COMPUTE_Z \
do { \
z[0] = x[0] ^ S5[IB(x[3])] ^ S6[ID(x[3])] ^ S7[IA(x[3])] ^ S8[IC(x[3])] ^ S7[IA(x[2])]; \
z[1] = x[2] ^ S5[IA(z[0])] ^ S6[IC(z[0])] ^ S7[IB(z[0])] ^ S8[ID(z[0])] ^ S8[IC(x[2])]; \
z[2] = x[3] ^ S5[ID(z[1])] ^ S6[IC(z[1])] ^ S7[IB(z[1])] ^ S8[IA(z[1])] ^ S5[IB(x[2])]; \
z[3] = x[1] ^ S5[IC(z[2])] ^ S6[IB(z[2])] ^ S7[ID(z[2])] ^ S8[IA(z[2])] ^ S6[ID(x[2])]; \
} while (0)
#define COMPUTE_X \
do { \
x[0] = z[2] ^ S5[IB(z[1])] ^ S6[ID(z[1])] ^ S7[IA(z[1])] ^ S8[IC(z[1])] ^ S7[IA(z[0])]; \
x[1] = z[0] ^ S5[IA(x[0])] ^ S6[IC(x[0])] ^ S7[IB(x[0])] ^ S8[ID(x[0])] ^ S8[IC(z[0])]; \
x[2] = z[1] ^ S5[ID(x[1])] ^ S6[IC(x[1])] ^ S7[IB(x[1])] ^ S8[IA(x[1])] ^ S5[IB(z[0])]; \
x[3] = z[3] ^ S5[IC(x[2])] ^ S6[IB(x[2])] ^ S7[ID(x[2])] ^ S8[IA(x[2])] ^ S6[ID(z[0])]; \
} while (0)
typedef struct AVCAST5 {
uint32_t Km[17];
uint32_t Kr[17];
int rounds;
} AVCAST5;
const int av_cast5_size = sizeof(AVCAST5);
static const uint32_t S1[256] = {
0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
};
static const uint32_t S2[256] = {
0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1
};
static const uint32_t S3[256] = {
0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783
};
static const uint32_t S4[256] = {
0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
};
static const uint32_t S5[256] = {
0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4
};
static const uint32_t S6[256] = {
0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f
};
static const uint32_t S7[256] = {
0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3
};
static const uint32_t S8[256] = {
0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e
};
static void generate_round_keys(int rnds, uint32_t* K, uint32_t* x, uint32_t* z)
{
COMPUTE_Z;
K[1] = S5[IA(z[2])] ^ S6[IB(z[2])] ^ S7[ID(z[1])] ^ S8[IC(z[1])] ^ S5[IC(z[0])];
K[2] = S5[IC(z[2])] ^ S6[ID(z[2])] ^ S7[IB(z[1])] ^ S8[IA(z[1])] ^ S6[IC(z[1])];
K[3] = S5[IA(z[3])] ^ S6[IB(z[3])] ^ S7[ID(z[0])] ^ S8[IC(z[0])] ^ S7[IB(z[2])];
K[4] = S5[IC(z[3])] ^ S6[ID(z[3])] ^ S7[IB(z[0])] ^ S8[IA(z[0])] ^ S8[IA(z[3])];
COMPUTE_X;
K[5] = S5[ID(x[0])] ^ S6[IC(x[0])] ^ S7[IA(x[3])] ^ S8[IB(x[3])] ^ S5[IA(x[2])];
K[6] = S5[IB(x[0])] ^ S6[IA(x[0])] ^ S7[IC(x[3])] ^ S8[ID(x[3])] ^ S6[IB(x[3])];
K[7] = S5[ID(x[1])] ^ S6[IC(x[1])] ^ S7[IA(x[2])] ^ S8[IB(x[2])] ^ S7[ID(x[0])];
K[8] = S5[IB(x[1])] ^ S6[IA(x[1])] ^ S7[IC(x[2])] ^ S8[ID(x[2])] ^ S8[ID(x[1])];
COMPUTE_Z;
K[9] = S5[ID(z[0])] ^ S6[IC(z[0])] ^ S7[IA(z[3])] ^ S8[IB(z[3])] ^ S5[IB(z[2])];
K[10] = S5[IB(z[0])] ^ S6[IA(z[0])] ^ S7[IC(z[3])] ^ S8[ID(z[3])] ^ S6[IA(z[3])];
K[11] = S5[ID(z[1])] ^ S6[IC(z[1])] ^ S7[IA(z[2])] ^ S8[IB(z[2])] ^ S7[IC(z[0])];
K[12] = S5[IB(z[1])] ^ S6[IA(z[1])] ^ S7[IC(z[2])] ^ S8[ID(z[2])] ^ S8[IC(z[1])];
COMPUTE_X;
if (rnds == 16) {
K[13] = S5[IA(x[2])] ^ S6[IB(x[2])] ^ S7[ID(x[1])] ^ S8[IC(x[1])] ^ S5[ID(x[0])];
K[14] = S5[IC(x[2])] ^ S6[ID(x[2])] ^ S7[IB(x[1])] ^ S8[IA(x[1])] ^ S6[ID(x[1])];
K[15] = S5[IA(x[3])] ^ S6[IB(x[3])] ^ S7[ID(x[0])] ^ S8[IC(x[0])] ^ S7[IA(x[2])];
K[16] = S5[IC(x[3])] ^ S6[ID(x[3])] ^ S7[IB(x[0])] ^ S8[IA(x[0])] ^ S8[IB(x[3])];
}
}
static void encipher(AVCAST5* cs, uint8_t* dst, const uint8_t* src)
{
uint32_t r, l, f, I;
l = AV_RB32(src);
r = AV_RB32(src + 4);
F1(l, r, 1);
F2(r, l, 2);
F3(l, r, 3);
F1(r, l, 4);
F2(l, r, 5);
F3(r, l, 6);
F1(l, r, 7);
F2(r, l, 8);
F3(l, r, 9);
F1(r, l, 10);
F2(l, r, 11);
F3(r, l, 12);
if (cs->rounds == 16) {
F1(l, r, 13);
F2(r, l, 14);
F3(l, r, 15);
F1(r, l, 16);
}
AV_WB32(dst, r);
AV_WB32(dst + 4, l);
}
static void decipher(AVCAST5* cs, uint8_t* dst, const uint8_t* src, uint8_t *iv)
{
uint32_t f, I, r, l;
l = AV_RB32(src);
r = AV_RB32(src + 4);
if (cs->rounds == 16) {
F1(l, r, 16);
F3(r, l, 15);
F2(l, r, 14);
F1(r, l, 13);
}
F3(l, r, 12);
F2(r, l, 11);
F1(l, r, 10);
F3(r, l, 9);
F2(l, r, 8);
F1(r, l, 7);
F3(l, r, 6);
F2(r, l, 5);
F1(l, r, 4);
F3(r, l, 3);
F2(l, r, 2);
F1(r, l, 1);
if (iv) {
r ^= AV_RB32(iv);
l ^= AV_RB32(iv + 4);
memcpy(iv, src, 8);
}
AV_WB32(dst, r);
AV_WB32(dst + 4, l);
}
struct AVCAST5 *av_cast5_alloc(void)
{
return av_mallocz(sizeof(struct AVCAST5));
}
av_cold int av_cast5_init(AVCAST5* cs, const uint8_t *key, int key_bits)
{
uint8_t newKey[16];
int i;
uint32_t p[4], q[4];
if (key_bits % 8 || key_bits < 40 || key_bits > 128)
return AVERROR(EINVAL);
memset(newKey, 0, sizeof(newKey));
memcpy(newKey, key, key_bits >> 3);
cs->rounds = key_bits <= 80 ? 12 : 16;
for (i = 0; i < 4; i++)
q[i] = AV_RB32(newKey + (4 * i));
generate_round_keys(cs->rounds, cs->Km, q, p);
generate_round_keys(cs->rounds, cs->Kr, q, p);
for (i = 0; i <= cs->rounds; i++)
cs->Kr[i] = cs->Kr[i] & 0x1f;
return 0;
}
void av_cast5_crypt2(AVCAST5* cs, uint8_t* dst, const uint8_t* src, int count, uint8_t *iv, int decrypt)
{
int i;
while (count--) {
if (decrypt) {
decipher(cs, dst, src, iv);
} else {
if (iv) {
for (i = 0; i < 8; i++)
dst[i] = src[i] ^ iv[i];
encipher(cs, dst, dst);
memcpy(iv, dst, 8);
} else {
encipher(cs, dst, src);
}
}
src = src + 8;
dst = dst + 8;
}
}
void av_cast5_crypt(AVCAST5* cs, uint8_t* dst, const uint8_t* src, int count, int decrypt)
{
while (count--) {
if (decrypt){
decipher(cs, dst, src, NULL);
} else {
encipher(cs, dst, src);
}
src = src + 8;
dst = dst + 8;
}
}

View file

@ -0,0 +1,80 @@
/*
* An implementation of the CAST128 algorithm as mentioned in RFC2144
* Copyright (c) 2014 Supraja Meedinti
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_CAST5_H
#define AVUTIL_CAST5_H
#include <stdint.h>
/**
* @file
* @brief Public header for libavutil CAST5 algorithm
* @defgroup lavu_cast5 CAST5
* @ingroup lavu_crypto
* @{
*/
extern const int av_cast5_size;
struct AVCAST5;
/**
* Allocate an AVCAST5 context
* To free the struct: av_free(ptr)
*/
struct AVCAST5 *av_cast5_alloc(void);
/**
* Initialize an AVCAST5 context.
*
* @param ctx an AVCAST5 context
* @param key a key of 5,6,...16 bytes used for encryption/decryption
* @param key_bits number of keybits: possible are 40,48,...,128
* @return 0 on success, less than 0 on failure
*/
int av_cast5_init(struct AVCAST5 *ctx, const uint8_t *key, int key_bits);
/**
* Encrypt or decrypt a buffer using a previously initialized context, ECB mode only
*
* @param ctx an AVCAST5 context
* @param dst destination array, can be equal to src
* @param src source array, can be equal to dst
* @param count number of 8 byte blocks
* @param decrypt 0 for encryption, 1 for decryption
*/
void av_cast5_crypt(struct AVCAST5 *ctx, uint8_t *dst, const uint8_t *src, int count, int decrypt);
/**
* Encrypt or decrypt a buffer using a previously initialized context
*
* @param ctx an AVCAST5 context
* @param dst destination array, can be equal to src
* @param src source array, can be equal to dst
* @param count number of 8 byte blocks
* @param iv initialization vector for CBC mode, NULL for ECB mode
* @param decrypt 0 for encryption, 1 for decryption
*/
void av_cast5_crypt2(struct AVCAST5 *ctx, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt);
/**
* @}
*/
#endif /* AVUTIL_CAST5_H */

View file

@ -0,0 +1,287 @@
/*
* Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* audio channel layout utility functions
*/
#include <stdint.h>
#include "avstring.h"
#include "avutil.h"
#include "channel_layout.h"
#include "bprint.h"
#include "common.h"
struct channel_name {
const char *name;
const char *description;
};
static const struct channel_name channel_names[] = {
[0] = { "FL", "front left" },
[1] = { "FR", "front right" },
[2] = { "FC", "front center" },
[3] = { "LFE", "low frequency" },
[4] = { "BL", "back left" },
[5] = { "BR", "back right" },
[6] = { "FLC", "front left-of-center" },
[7] = { "FRC", "front right-of-center" },
[8] = { "BC", "back center" },
[9] = { "SL", "side left" },
[10] = { "SR", "side right" },
[11] = { "TC", "top center" },
[12] = { "TFL", "top front left" },
[13] = { "TFC", "top front center" },
[14] = { "TFR", "top front right" },
[15] = { "TBL", "top back left" },
[16] = { "TBC", "top back center" },
[17] = { "TBR", "top back right" },
[29] = { "DL", "downmix left" },
[30] = { "DR", "downmix right" },
[31] = { "WL", "wide left" },
[32] = { "WR", "wide right" },
[33] = { "SDL", "surround direct left" },
[34] = { "SDR", "surround direct right" },
[35] = { "LFE2", "low frequency 2" },
};
static const char *get_channel_name(int channel_id)
{
if (channel_id < 0 || channel_id >= FF_ARRAY_ELEMS(channel_names))
return NULL;
return channel_names[channel_id].name;
}
static const struct {
const char *name;
int nb_channels;
uint64_t layout;
} channel_layout_map[] = {
{ "mono", 1, AV_CH_LAYOUT_MONO },
{ "stereo", 2, AV_CH_LAYOUT_STEREO },
{ "2.1", 3, AV_CH_LAYOUT_2POINT1 },
{ "3.0", 3, AV_CH_LAYOUT_SURROUND },
{ "3.0(back)", 3, AV_CH_LAYOUT_2_1 },
{ "4.0", 4, AV_CH_LAYOUT_4POINT0 },
{ "quad", 4, AV_CH_LAYOUT_QUAD },
{ "quad(side)", 4, AV_CH_LAYOUT_2_2 },
{ "3.1", 4, AV_CH_LAYOUT_3POINT1 },
{ "5.0", 5, AV_CH_LAYOUT_5POINT0_BACK },
{ "5.0(side)", 5, AV_CH_LAYOUT_5POINT0 },
{ "4.1", 5, AV_CH_LAYOUT_4POINT1 },
{ "5.1", 6, AV_CH_LAYOUT_5POINT1_BACK },
{ "5.1(side)", 6, AV_CH_LAYOUT_5POINT1 },
{ "6.0", 6, AV_CH_LAYOUT_6POINT0 },
{ "6.0(front)", 6, AV_CH_LAYOUT_6POINT0_FRONT },
{ "hexagonal", 6, AV_CH_LAYOUT_HEXAGONAL },
{ "6.1", 7, AV_CH_LAYOUT_6POINT1 },
{ "6.1(back)", 7, AV_CH_LAYOUT_6POINT1_BACK },
{ "6.1(front)", 7, AV_CH_LAYOUT_6POINT1_FRONT },
{ "7.0", 7, AV_CH_LAYOUT_7POINT0 },
{ "7.0(front)", 7, AV_CH_LAYOUT_7POINT0_FRONT },
{ "7.1", 8, AV_CH_LAYOUT_7POINT1 },
{ "7.1(wide)", 8, AV_CH_LAYOUT_7POINT1_WIDE_BACK },
{ "7.1(wide-side)", 8, AV_CH_LAYOUT_7POINT1_WIDE },
{ "octagonal", 8, AV_CH_LAYOUT_OCTAGONAL },
{ "hexadecagonal", 16, AV_CH_LAYOUT_HEXADECAGONAL },
{ "downmix", 2, AV_CH_LAYOUT_STEREO_DOWNMIX, },
};
static uint64_t get_channel_layout_single(const char *name, int name_len)
{
int i;
char *end;
int64_t layout;
for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) {
if (strlen(channel_layout_map[i].name) == name_len &&
!memcmp(channel_layout_map[i].name, name, name_len))
return channel_layout_map[i].layout;
}
for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++)
if (channel_names[i].name &&
strlen(channel_names[i].name) == name_len &&
!memcmp(channel_names[i].name, name, name_len))
return (int64_t)1 << i;
errno = 0;
i = strtol(name, &end, 10);
if (!errno && (end + 1 - name == name_len && *end == 'c'))
return av_get_default_channel_layout(i);
errno = 0;
layout = strtoll(name, &end, 0);
if (!errno && end - name == name_len)
return FFMAX(layout, 0);
return 0;
}
uint64_t av_get_channel_layout(const char *name)
{
const char *n, *e;
const char *name_end = name + strlen(name);
int64_t layout = 0, layout_single;
for (n = name; n < name_end; n = e + 1) {
for (e = n; e < name_end && *e != '+' && *e != '|'; e++);
layout_single = get_channel_layout_single(n, e - n);
if (!layout_single)
return 0;
layout |= layout_single;
}
return layout;
}
int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels)
{
int nb = 0;
char *end;
uint64_t layout = av_get_channel_layout(name);
if (layout) {
*channel_layout = layout;
*nb_channels = av_get_channel_layout_nb_channels(layout);
return 0;
}
nb = strtol(name, &end, 10);
if (!errno && *end == 'C' && *(end + 1) == '\0' && nb > 0 && nb < 64) {
*channel_layout = 0;
*nb_channels = nb;
return 0;
}
return AVERROR(EINVAL);
}
void av_bprint_channel_layout(struct AVBPrint *bp,
int nb_channels, uint64_t channel_layout)
{
int i;
if (nb_channels <= 0)
nb_channels = av_get_channel_layout_nb_channels(channel_layout);
for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
if (nb_channels == channel_layout_map[i].nb_channels &&
channel_layout == channel_layout_map[i].layout) {
av_bprintf(bp, "%s", channel_layout_map[i].name);
return;
}
av_bprintf(bp, "%d channels", nb_channels);
if (channel_layout) {
int i, ch;
av_bprintf(bp, " (");
for (i = 0, ch = 0; i < 64; i++) {
if ((channel_layout & (UINT64_C(1) << i))) {
const char *name = get_channel_name(i);
if (name) {
if (ch > 0)
av_bprintf(bp, "+");
av_bprintf(bp, "%s", name);
}
ch++;
}
}
av_bprintf(bp, ")");
}
}
void av_get_channel_layout_string(char *buf, int buf_size,
int nb_channels, uint64_t channel_layout)
{
AVBPrint bp;
av_bprint_init_for_buffer(&bp, buf, buf_size);
av_bprint_channel_layout(&bp, nb_channels, channel_layout);
}
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
{
return av_popcount64(channel_layout);
}
int64_t av_get_default_channel_layout(int nb_channels) {
int i;
for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
if (nb_channels == channel_layout_map[i].nb_channels)
return channel_layout_map[i].layout;
return 0;
}
int av_get_channel_layout_channel_index(uint64_t channel_layout,
uint64_t channel)
{
if (!(channel_layout & channel) ||
av_get_channel_layout_nb_channels(channel) != 1)
return AVERROR(EINVAL);
channel_layout &= channel - 1;
return av_get_channel_layout_nb_channels(channel_layout);
}
const char *av_get_channel_name(uint64_t channel)
{
int i;
if (av_get_channel_layout_nb_channels(channel) != 1)
return NULL;
for (i = 0; i < 64; i++)
if ((1ULL<<i) & channel)
return get_channel_name(i);
return NULL;
}
const char *av_get_channel_description(uint64_t channel)
{
int i;
if (av_get_channel_layout_nb_channels(channel) != 1)
return NULL;
for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++)
if ((1ULL<<i) & channel)
return channel_names[i].description;
return NULL;
}
uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index)
{
int i;
if (av_get_channel_layout_nb_channels(channel_layout) <= index)
return 0;
for (i = 0; i < 64; i++) {
if ((1ULL << i) & channel_layout && !index--)
return 1ULL << i;
}
return 0;
}
int av_get_standard_channel_layout(unsigned index, uint64_t *layout,
const char **name)
{
if (index >= FF_ARRAY_ELEMS(channel_layout_map))
return AVERROR_EOF;
if (layout) *layout = channel_layout_map[index].layout;
if (name) *name = channel_layout_map[index].name;
return 0;
}

View file

@ -0,0 +1,232 @@
/*
* Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
* Copyright (c) 2008 Peter Ross
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_CHANNEL_LAYOUT_H
#define AVUTIL_CHANNEL_LAYOUT_H
#include <stdint.h>
/**
* @file
* audio channel layout utility functions
*/
/**
* @addtogroup lavu_audio
* @{
*/
/**
* @defgroup channel_masks Audio channel masks
*
* A channel layout is a 64-bits integer with a bit set for every channel.
* The number of bits set must be equal to the number of channels.
* The value 0 means that the channel layout is not known.
* @note this data structure is not powerful enough to handle channels
* combinations that have the same channel multiple times, such as
* dual-mono.
*
* @{
*/
#define AV_CH_FRONT_LEFT 0x00000001
#define AV_CH_FRONT_RIGHT 0x00000002
#define AV_CH_FRONT_CENTER 0x00000004
#define AV_CH_LOW_FREQUENCY 0x00000008
#define AV_CH_BACK_LEFT 0x00000010
#define AV_CH_BACK_RIGHT 0x00000020
#define AV_CH_FRONT_LEFT_OF_CENTER 0x00000040
#define AV_CH_FRONT_RIGHT_OF_CENTER 0x00000080
#define AV_CH_BACK_CENTER 0x00000100
#define AV_CH_SIDE_LEFT 0x00000200
#define AV_CH_SIDE_RIGHT 0x00000400
#define AV_CH_TOP_CENTER 0x00000800
#define AV_CH_TOP_FRONT_LEFT 0x00001000
#define AV_CH_TOP_FRONT_CENTER 0x00002000
#define AV_CH_TOP_FRONT_RIGHT 0x00004000
#define AV_CH_TOP_BACK_LEFT 0x00008000
#define AV_CH_TOP_BACK_CENTER 0x00010000
#define AV_CH_TOP_BACK_RIGHT 0x00020000
#define AV_CH_STEREO_LEFT 0x20000000 ///< Stereo downmix.
#define AV_CH_STEREO_RIGHT 0x40000000 ///< See AV_CH_STEREO_LEFT.
#define AV_CH_WIDE_LEFT 0x0000000080000000ULL
#define AV_CH_WIDE_RIGHT 0x0000000100000000ULL
#define AV_CH_SURROUND_DIRECT_LEFT 0x0000000200000000ULL
#define AV_CH_SURROUND_DIRECT_RIGHT 0x0000000400000000ULL
#define AV_CH_LOW_FREQUENCY_2 0x0000000800000000ULL
/** Channel mask value used for AVCodecContext.request_channel_layout
to indicate that the user requests the channel order of the decoder output
to be the native codec channel order. */
#define AV_CH_LAYOUT_NATIVE 0x8000000000000000ULL
/**
* @}
* @defgroup channel_mask_c Audio channel layouts
* @{
* */
#define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER)
#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT)
#define AV_CH_LAYOUT_2POINT1 (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY)
#define AV_CH_LAYOUT_2_1 (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER)
#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER)
#define AV_CH_LAYOUT_3POINT1 (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY)
#define AV_CH_LAYOUT_4POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_CENTER)
#define AV_CH_LAYOUT_4POINT1 (AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY)
#define AV_CH_LAYOUT_2_2 (AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT)
#define AV_CH_LAYOUT_QUAD (AV_CH_LAYOUT_STEREO|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
#define AV_CH_LAYOUT_5POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT)
#define AV_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_5POINT0|AV_CH_LOW_FREQUENCY)
#define AV_CH_LAYOUT_5POINT0_BACK (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
#define AV_CH_LAYOUT_5POINT1_BACK (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_LOW_FREQUENCY)
#define AV_CH_LAYOUT_6POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_CENTER)
#define AV_CH_LAYOUT_6POINT0_FRONT (AV_CH_LAYOUT_2_2|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)
#define AV_CH_LAYOUT_HEXAGONAL (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER)
#define AV_CH_LAYOUT_6POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER)
#define AV_CH_LAYOUT_6POINT1_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER)
#define AV_CH_LAYOUT_6POINT1_FRONT (AV_CH_LAYOUT_6POINT0_FRONT|AV_CH_LOW_FREQUENCY)
#define AV_CH_LAYOUT_7POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
#define AV_CH_LAYOUT_7POINT0_FRONT (AV_CH_LAYOUT_5POINT0|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)
#define AV_CH_LAYOUT_7POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
#define AV_CH_LAYOUT_7POINT1_WIDE (AV_CH_LAYOUT_5POINT1|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)
#define AV_CH_LAYOUT_7POINT1_WIDE_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)
#define AV_CH_LAYOUT_OCTAGONAL (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT)
#define AV_CH_LAYOUT_HEXADECAGONAL (AV_CH_LAYOUT_OCTAGONAL|AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT)
#define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT)
enum AVMatrixEncoding {
AV_MATRIX_ENCODING_NONE,
AV_MATRIX_ENCODING_DOLBY,
AV_MATRIX_ENCODING_DPLII,
AV_MATRIX_ENCODING_DPLIIX,
AV_MATRIX_ENCODING_DPLIIZ,
AV_MATRIX_ENCODING_DOLBYEX,
AV_MATRIX_ENCODING_DOLBYHEADPHONE,
AV_MATRIX_ENCODING_NB
};
/**
* Return a channel layout id that matches name, or 0 if no match is found.
*
* name can be one or several of the following notations,
* separated by '+' or '|':
* - the name of an usual channel layout (mono, stereo, 4.0, quad, 5.0,
* 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix);
* - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC,
* SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR);
* - a number of channels, in decimal, followed by 'c', yielding
* the default channel layout for that number of channels (@see
* av_get_default_channel_layout);
* - a channel layout mask, in hexadecimal starting with "0x" (see the
* AV_CH_* macros).
*
* Example: "stereo+FC" = "2c+FC" = "2c+1c" = "0x7"
*/
uint64_t av_get_channel_layout(const char *name);
/**
* Return a channel layout and the number of channels based on the specified name.
*
* This function is similar to (@see av_get_channel_layout), but can also parse
* unknown channel layout specifications.
*
* @param[in] name channel layout specification string
* @param[out] channel_layout parsed channel layout (0 if unknown)
* @param[out] nb_channels number of channels
*
* @return 0 on success, AVERROR(EINVAL) if the parsing fails.
*/
int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels);
/**
* Return a description of a channel layout.
* If nb_channels is <= 0, it is guessed from the channel_layout.
*
* @param buf put here the string containing the channel layout
* @param buf_size size in bytes of the buffer
*/
void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout);
struct AVBPrint;
/**
* Append a description of a channel layout to a bprint buffer.
*/
void av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout);
/**
* Return the number of channels in the channel layout.
*/
int av_get_channel_layout_nb_channels(uint64_t channel_layout);
/**
* Return default channel layout for a given number of channels.
*/
int64_t av_get_default_channel_layout(int nb_channels);
/**
* Get the index of a channel in channel_layout.
*
* @param channel a channel layout describing exactly one channel which must be
* present in channel_layout.
*
* @return index of channel in channel_layout on success, a negative AVERROR
* on error.
*/
int av_get_channel_layout_channel_index(uint64_t channel_layout,
uint64_t channel);
/**
* Get the channel with the given index in channel_layout.
*/
uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index);
/**
* Get the name of a given channel.
*
* @return channel name on success, NULL on error.
*/
const char *av_get_channel_name(uint64_t channel);
/**
* Get the description of a given channel.
*
* @param channel a channel layout with a single channel
* @return channel description on success, NULL on error
*/
const char *av_get_channel_description(uint64_t channel);
/**
* Get the value and name of a standard channel layout.
*
* @param[in] index index in an internal list, starting at 0
* @param[out] layout channel layout mask
* @param[out] name name of the layout
* @return 0 if the layout exists,
* <0 if index is beyond the limits
*/
int av_get_standard_channel_layout(unsigned index, uint64_t *layout,
const char **name);
/**
* @}
* @}
*/
#endif /* AVUTIL_CHANNEL_LAYOUT_H */

View file

@ -0,0 +1,235 @@
/*
* Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stddef.h>
#include <math.h>
#include "common.h"
#include "libavutil/color_utils.h"
#include "libavutil/pixfmt.h"
double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc)
{
double gamma;
switch (trc) {
case AVCOL_TRC_BT709:
case AVCOL_TRC_SMPTE170M:
case AVCOL_TRC_SMPTE240M:
case AVCOL_TRC_BT1361_ECG:
case AVCOL_TRC_BT2020_10:
case AVCOL_TRC_BT2020_12:
/* these share a segmented TRC, but gamma 1.961 is a close
approximation, and also more correct for decoding content */
gamma = 1.961;
break;
case AVCOL_TRC_GAMMA22:
case AVCOL_TRC_IEC61966_2_1:
gamma = 2.2;
break;
case AVCOL_TRC_GAMMA28:
gamma = 2.8;
break;
case AVCOL_TRC_LINEAR:
gamma = 1.0;
break;
default:
gamma = 0.0; // Unknown value representation
}
return gamma;
}
#define BT709_alpha 1.099296826809442
#define BT709_beta 0.018053968510807
static double avpriv_trc_bt709(double Lc)
{
const double a = BT709_alpha;
const double b = BT709_beta;
return (0.0 > Lc) ? 0.0
: ( b > Lc) ? 4.500 * Lc
: a * pow(Lc, 0.45) - (a - 1.0);
}
static double avpriv_trc_gamma22(double Lc)
{
return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2);
}
static double avpriv_trc_gamma28(double Lc)
{
return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8);
}
static double avpriv_trc_smpte240M(double Lc)
{
const double a = 1.1115;
const double b = 0.0228;
return (0.0 > Lc) ? 0.0
: ( b > Lc) ? 4.000 * Lc
: a * pow(Lc, 0.45) - (a - 1.0);
}
static double avpriv_trc_linear(double Lc)
{
return Lc;
}
static double avpriv_trc_log(double Lc)
{
return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0;
}
static double avpriv_trc_log_sqrt(double Lc)
{
// sqrt(10) / 1000
return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5;
}
static double avpriv_trc_iec61966_2_4(double Lc)
{
const double a = BT709_alpha;
const double b = BT709_beta;
return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0)
: ( b > Lc) ? 4.500 * Lc
: a * pow( Lc, 0.45) - (a - 1.0);
}
static double avpriv_trc_bt1361(double Lc)
{
const double a = BT709_alpha;
const double b = BT709_beta;
return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / 4.0
: ( b > Lc) ? 4.500 * Lc
: a * pow( Lc, 0.45) - (a - 1.0);
}
static double avpriv_trc_iec61966_2_1(double Lc)
{
const double a = 1.055;
const double b = 0.0031308;
return (0.0 > Lc) ? 0.0
: ( b > Lc) ? 12.92 * Lc
: a * pow(Lc, 1.0 / 2.4) - (a - 1.0);
}
static double avpriv_trc_smpte_st2084(double Lc)
{
const double c1 = 3424.0 / 4096.0; // c3-c2 + 1
const double c2 = 32.0 * 2413.0 / 4096.0;
const double c3 = 32.0 * 2392.0 / 4096.0;
const double m = 128.0 * 2523.0 / 4096.0;
const double n = 0.25 * 2610.0 / 4096.0;
const double L = Lc / 10000.0;
const double Ln = pow(L, n);
return (0.0 > Lc) ? 0.0
: pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m);
}
static double avpriv_trc_smpte_st428_1(double Lc)
{
return (0.0 > Lc) ? 0.0
: pow(48.0 * Lc / 52.37, 1.0 / 2.6);
}
static double avpriv_trc_arib_std_b67(double Lc) {
// The function uses the definition from HEVC, which assumes that the peak
// white is input level = 1. (this is equivalent to scaling E = Lc * 12 and
// using the definition from the ARIB STD-B67 spec)
const double a = 0.17883277;
const double b = 0.28466892;
const double c = 0.55991073;
return (0.0 > Lc) ? 0.0 :
(Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c);
}
avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc)
{
avpriv_trc_function func = NULL;
switch (trc) {
case AVCOL_TRC_BT709:
case AVCOL_TRC_SMPTE170M:
case AVCOL_TRC_BT2020_10:
case AVCOL_TRC_BT2020_12:
func = avpriv_trc_bt709;
break;
case AVCOL_TRC_GAMMA22:
func = avpriv_trc_gamma22;
break;
case AVCOL_TRC_GAMMA28:
func = avpriv_trc_gamma28;
break;
case AVCOL_TRC_SMPTE240M:
func = avpriv_trc_smpte240M;
break;
case AVCOL_TRC_LINEAR:
func = avpriv_trc_linear;
break;
case AVCOL_TRC_LOG:
func = avpriv_trc_log;
break;
case AVCOL_TRC_LOG_SQRT:
func = avpriv_trc_log_sqrt;
break;
case AVCOL_TRC_IEC61966_2_4:
func = avpriv_trc_iec61966_2_4;
break;
case AVCOL_TRC_BT1361_ECG:
func = avpriv_trc_bt1361;
break;
case AVCOL_TRC_IEC61966_2_1:
func = avpriv_trc_iec61966_2_1;
break;
case AVCOL_TRC_SMPTEST2084:
func = avpriv_trc_smpte_st2084;
break;
case AVCOL_TRC_SMPTEST428_1:
func = avpriv_trc_smpte_st428_1;
break;
case AVCOL_TRC_ARIB_STD_B67:
func = avpriv_trc_arib_std_b67;
break;
case AVCOL_TRC_RESERVED0:
case AVCOL_TRC_UNSPECIFIED:
case AVCOL_TRC_RESERVED:
default:
break;
}
return func;
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_COLOR_UTILS_H
#define AVUTIL_COLOR_UTILS_H
#include "libavutil/pixfmt.h"
/**
* Determine a suitable 'gamma' value to match the supplied
* AVColorTransferCharacteristic.
*
* See Apple Technical Note TN2257 (https://developer.apple.com/library/mac/technotes/tn2257/_index.html)
*
* @return Will return an approximation to the simple gamma function matching
* the supplied Transfer Characteristic, Will return 0.0 for any
* we cannot reasonably match against.
*/
double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc);
typedef double (*avpriv_trc_function)(double);
/**
* Determine the function needed to apply the given
* AVColorTransferCharacteristic to linear input.
*
* The function returned should expect a nominal domain and range of [0.0-1.0]
* values outside of this range maybe valid depending on the chosen
* characteristic function.
*
* @return Will return pointer to the function matching the
* supplied Transfer Characteristic. If unspecified will
* return NULL:
*/
avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc);
#endif

View file

@ -0,0 +1,150 @@
/*
* Colorspace conversion defines
* Copyright (c) 2001, 2002, 2003 Fabrice Bellard
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Various defines for YUV<->RGB conversion
*/
#ifndef AVUTIL_COLORSPACE_H
#define AVUTIL_COLORSPACE_H
#define SCALEBITS 10
#define ONE_HALF (1 << (SCALEBITS - 1))
#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
#define YUV_TO_RGB1_CCIR(cb1, cr1)\
{\
cb = (cb1) - 128;\
cr = (cr1) - 128;\
r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;\
g_add = - FIX(0.34414*255.0/224.0) * cb - FIX(0.71414*255.0/224.0) * cr + \
ONE_HALF;\
b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;\
}
#define YUV_TO_RGB1_CCIR_BT709(cb1, cr1) \
{ \
cb = (cb1) - 128; \
cr = (cr1) - 128; \
r_add = ONE_HALF + FIX(1.5747 * 255.0 / 224.0) * cr; \
g_add = ONE_HALF - FIX(0.1873 * 255.0 / 224.0) * cb - \
FIX(0.4682 * 255.0 / 224.0) * cr; \
b_add = ONE_HALF + FIX(1.8556 * 255.0 / 224.0) * cb; \
}
// To be used for the BT709 variant as well
#define YUV_TO_RGB2_CCIR(r, g, b, y1)\
{\
y = ((y1) - 16) * FIX(255.0/219.0);\
r = cm[(y + r_add) >> SCALEBITS];\
g = cm[(y + g_add) >> SCALEBITS];\
b = cm[(y + b_add) >> SCALEBITS];\
}
#define YUV_TO_RGB1(cb1, cr1)\
{\
cb = (cb1) - 128;\
cr = (cr1) - 128;\
r_add = FIX(1.40200) * cr + ONE_HALF;\
g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\
b_add = FIX(1.77200) * cb + ONE_HALF;\
}
#define YUV_TO_RGB2(r, g, b, y1)\
{\
y = (y1) << SCALEBITS;\
r = cm[(y + r_add) >> SCALEBITS];\
g = cm[(y + g_add) >> SCALEBITS];\
b = cm[(y + b_add) >> SCALEBITS];\
}
#define Y_CCIR_TO_JPEG(y)\
cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS]
#define Y_JPEG_TO_CCIR(y)\
(((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
#define C_CCIR_TO_JPEG(y)\
cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS]
/* NOTE: the clamp is really necessary! */
static inline int C_JPEG_TO_CCIR(int y) {
y = (((y - 128) * FIX(112.0/127.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS);
if (y < 16)
y = 16;
return y;
}
#define RGB_TO_Y_CCIR(r, g, b) \
((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
#define RGB_TO_U_CCIR(r1, g1, b1, shift)\
(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \
FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
#define RGB_TO_V_CCIR(r1, g1, b1, shift)\
(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \
FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
#define RGB_TO_Y_JPEG(r, g, b) \
(FFMIN((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \
FIX(0.11400) * (b) + (ONE_HALF)) >> SCALEBITS, 255))
#define RGB_TO_U_JPEG(r1, g1, b1)\
(((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \
FIX(0.50000) * b1 + (ONE_HALF) - 1) >> (SCALEBITS)) + 128)
#define RGB_TO_V_JPEG(r1, g1, b1)\
(((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \
FIX(0.08131) * b1 + (ONE_HALF) - 1) >> (SCALEBITS)) + 128)
// Conversion macros for 8-bit RGB to YUV
// Derived from ITU-R BT.709-6 (06/2015) Item 3.5
// https://www.itu.int/rec/R-REC-BT.709-6-201506-I/en
#define RGB_TO_Y_BT709(r, g, b) \
((FIX(0.21260*219.0/255.0) * (r) + FIX(0.71520*219.0/255.0) * (g) + \
FIX(0.07220*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
#define RGB_TO_U_BT709(r1, g1, b1, shift)\
(((- FIX(0.11457*224.0/255.0) * r1 - FIX(0.38543*224.0/255.0) * g1 + \
FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
#define RGB_TO_V_BT709(r1, g1, b1, shift)\
(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.45415*224.0/255.0) * g1 - \
FIX(0.04585*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
#define RGB_TO_Y_BT709_FULL(r, g, b) \
(FFMIN((FIX(0.21260) * (r) + FIX(0.71520) * (g) + \
FIX(0.07220) * (b) + (ONE_HALF)) >> SCALEBITS, 255))
#define RGB_TO_U_BT709_FULL(r1, g1, b1)\
(((- FIX(0.11457) * r1 - FIX(0.38543) * g1 + \
FIX(0.50000) * b1 + (ONE_HALF) - 1) >> (SCALEBITS)) + 128)
#define RGB_TO_V_BT709_FULL(r1, g1, b1)\
(((FIX(0.50000) * r1 - FIX(0.45415) * g1 - \
FIX(0.04585) * b1 + (ONE_HALF) - 1) >> (SCALEBITS)) + 128)
#endif /* AVUTIL_COLORSPACE_H */

View file

@ -0,0 +1,560 @@
/*
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* common internal and external API header
*/
#ifndef AVUTIL_COMMON_H
#define AVUTIL_COMMON_H
#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) && !defined(UINT64_C)
#error missing -D__STDC_CONSTANT_MACROS / #define __STDC_CONSTANT_MACROS
#endif
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "attributes.h"
#include "macros.h"
#include "version.h"
#include "libavutil/avconfig.h"
#if AV_HAVE_BIGENDIAN
# define AV_NE(be, le) (be)
#else
# define AV_NE(be, le) (le)
#endif
//rounded division & shift
#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b))
/* assume b>0 */
#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))
/* Fast a/(1<<b) rounded toward +inf. Assume a>=0 and b>=0 */
#define AV_CEIL_RSHIFT(a,b) (!av_builtin_constant_p(b) ? -((-(a)) >> (b)) \
: ((a) + (1<<(b)) - 1) >> (b))
/* Backwards compat. */
#define FF_CEIL_RSHIFT AV_CEIL_RSHIFT
#define FFUDIV(a,b) (((a)>0 ?(a):(a)-(b)+1) / (b))
#define FFUMOD(a,b) ((a)-(b)*FFUDIV(a,b))
/**
* Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they
* are not representable as absolute values of their type. This is the same
* as with *abs()
* @see FFNABS()
*/
#define FFABS(a) ((a) >= 0 ? (a) : (-(a)))
#define FFSIGN(a) ((a) > 0 ? 1 : -1)
/**
* Negative Absolute value.
* this works for all integers of all types.
* As with many macros, this evaluates its argument twice, it thus must not have
* a sideeffect, that is FFNABS(x++) has undefined behavior.
*/
#define FFNABS(a) ((a) <= 0 ? (a) : (-(a)))
/**
* Comparator.
* For two numerical expressions x and y, gives 1 if x > y, -1 if x < y, and 0
* if x == y. This is useful for instance in a qsort comparator callback.
* Furthermore, compilers are able to optimize this to branchless code, and
* there is no risk of overflow with signed types.
* As with many macros, this evaluates its argument multiple times, it thus
* must not have a side-effect.
*/
#define FFDIFFSIGN(x,y) (((x)>(y)) - ((x)<(y)))
#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c)
#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c)
#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
/* misc math functions */
#ifdef HAVE_AV_CONFIG_H
# include "config.h"
# include "intmath.h"
#endif
/* Pull in unguarded fallback defines at the end of this file. */
#include "common.h"
#ifndef av_log2
av_const int av_log2(unsigned v);
#endif
#ifndef av_log2_16bit
av_const int av_log2_16bit(unsigned v);
#endif
/**
* Clip a signed integer value into the amin-amax range.
* @param a value to clip
* @param amin minimum value of the clip range
* @param amax maximum value of the clip range
* @return clipped value
*/
static av_always_inline av_const int av_clip_c(int a, int amin, int amax)
{
#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
if (amin > amax) abort();
#endif
if (a < amin) return amin;
else if (a > amax) return amax;
else return a;
}
/**
* Clip a signed 64bit integer value into the amin-amax range.
* @param a value to clip
* @param amin minimum value of the clip range
* @param amax maximum value of the clip range
* @return clipped value
*/
static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, int64_t amax)
{
#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
if (amin > amax) abort();
#endif
if (a < amin) return amin;
else if (a > amax) return amax;
else return a;
}
/**
* Clip a signed integer value into the 0-255 range.
* @param a value to clip
* @return clipped value
*/
static av_always_inline av_const uint8_t av_clip_uint8_c(int a)
{
if (a&(~0xFF)) return (~a)>>31;
else return a;
}
/**
* Clip a signed integer value into the -128,127 range.
* @param a value to clip
* @return clipped value
*/
static av_always_inline av_const int8_t av_clip_int8_c(int a)
{
if ((a+0x80U) & ~0xFF) return (a>>31) ^ 0x7F;
else return a;
}
/**
* Clip a signed integer value into the 0-65535 range.
* @param a value to clip
* @return clipped value
*/
static av_always_inline av_const uint16_t av_clip_uint16_c(int a)
{
if (a&(~0xFFFF)) return (~a)>>31;
else return a;
}
/**
* Clip a signed integer value into the -32768,32767 range.
* @param a value to clip
* @return clipped value
*/
static av_always_inline av_const int16_t av_clip_int16_c(int a)
{
if ((a+0x8000U) & ~0xFFFF) return (a>>31) ^ 0x7FFF;
else return a;
}
/**
* Clip a signed 64-bit integer value into the -2147483648,2147483647 range.
* @param a value to clip
* @return clipped value
*/
static av_always_inline av_const int32_t av_clipl_int32_c(int64_t a)
{
if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (int32_t)((a>>63) ^ 0x7FFFFFFF);
else return (int32_t)a;
}
/**
* Clip a signed integer into the -(2^p),(2^p-1) range.
* @param a value to clip
* @param p bit position to clip at
* @return clipped value
*/
static av_always_inline av_const int av_clip_intp2_c(int a, int p)
{
if (((unsigned)a + (1 << p)) & ~((2 << p) - 1))
return (a >> 31) ^ ((1 << p) - 1);
else
return a;
}
/**
* Clip a signed integer to an unsigned power of two range.
* @param a value to clip
* @param p bit position to clip at
* @return clipped value
*/
static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p)
{
if (a & ~((1<<p) - 1)) return (~a) >> 31 & ((1<<p) - 1);
else return a;
}
/**
* Clear high bits from an unsigned integer starting with specific bit position
* @param a value to clip
* @param p bit position to clip at
* @return clipped value
*/
static av_always_inline av_const unsigned av_mod_uintp2_c(unsigned a, unsigned p)
{
return a & ((1 << p) - 1);
}
/**
* Add two signed 32-bit values with saturation.
*
* @param a one value
* @param b another value
* @return sum with signed saturation
*/
static av_always_inline int av_sat_add32_c(int a, int b)
{
return av_clipl_int32((int64_t)a + b);
}
/**
* Add a doubled value to another value with saturation at both stages.
*
* @param a first value
* @param b value doubled and added to a
* @return sum sat(a + sat(2*b)) with signed saturation
*/
static av_always_inline int av_sat_dadd32_c(int a, int b)
{
return av_sat_add32(a, av_sat_add32(b, b));
}
/**
* Subtract two signed 32-bit values with saturation.
*
* @param a one value
* @param b another value
* @return difference with signed saturation
*/
static av_always_inline int av_sat_sub32_c(int a, int b)
{
return av_clipl_int32((int64_t)a - b);
}
/**
* Subtract a doubled value from another value with saturation at both stages.
*
* @param a first value
* @param b value doubled and subtracted from a
* @return difference sat(a - sat(2*b)) with signed saturation
*/
static av_always_inline int av_sat_dsub32_c(int a, int b)
{
return av_sat_sub32(a, av_sat_add32(b, b));
}
/**
* Clip a float value into the amin-amax range.
* @param a value to clip
* @param amin minimum value of the clip range
* @param amax maximum value of the clip range
* @return clipped value
*/
static av_always_inline av_const float av_clipf_c(float a, float amin, float amax)
{
#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
if (amin > amax) abort();
#endif
if (a < amin) return amin;
else if (a > amax) return amax;
else return a;
}
/**
* Clip a double value into the amin-amax range.
* @param a value to clip
* @param amin minimum value of the clip range
* @param amax maximum value of the clip range
* @return clipped value
*/
static av_always_inline av_const double av_clipd_c(double a, double amin, double amax)
{
#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
if (amin > amax) abort();
#endif
if (a < amin) return amin;
else if (a > amax) return amax;
else return a;
}
/** Compute ceil(log2(x)).
* @param x value used to compute ceil(log2(x))
* @return computed ceiling of log2(x)
*/
static av_always_inline av_const int av_ceil_log2_c(int x)
{
return av_log2((x - 1) << 1);
}
/**
* Count number of bits set to one in x
* @param x value to count bits of
* @return the number of bits set to one in x
*/
static av_always_inline av_const int av_popcount_c(uint32_t x)
{
x -= (x >> 1) & 0x55555555;
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x + (x >> 4)) & 0x0F0F0F0F;
x += x >> 8;
return (x + (x >> 16)) & 0x3F;
}
/**
* Count number of bits set to one in x
* @param x value to count bits of
* @return the number of bits set to one in x
*/
static av_always_inline av_const int av_popcount64_c(uint64_t x)
{
return av_popcount((uint32_t)x) + av_popcount((uint32_t)(x >> 32));
}
static av_always_inline av_const int av_parity_c(uint32_t v)
{
return av_popcount(v) & 1;
}
#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24))
#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((unsigned)(a) << 24))
/**
* Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form.
*
* @param val Output value, must be an lvalue of type uint32_t.
* @param GET_BYTE Expression reading one byte from the input.
* Evaluated up to 7 times (4 for the currently
* assigned Unicode range). With a memory buffer
* input, this could be *ptr++.
* @param ERROR Expression to be evaluated on invalid input,
* typically a goto statement.
*
* @warning ERROR should not contain a loop control statement which
* could interact with the internal while loop, and should force an
* exit from the macro code (e.g. through a goto or a return) in order
* to prevent undefined results.
*/
#define GET_UTF8(val, GET_BYTE, ERROR)\
val= (GET_BYTE);\
{\
uint32_t top = (val & 128) >> 1;\
if ((val & 0xc0) == 0x80 || val >= 0xFE)\
ERROR\
while (val & top) {\
int tmp= (GET_BYTE) - 128;\
if(tmp>>6)\
ERROR\
val= (val<<6) + tmp;\
top <<= 5;\
}\
val &= (top << 1) - 1;\
}
/**
* Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form.
*
* @param val Output value, must be an lvalue of type uint32_t.
* @param GET_16BIT Expression returning two bytes of UTF-16 data converted
* to native byte order. Evaluated one or two times.
* @param ERROR Expression to be evaluated on invalid input,
* typically a goto statement.
*/
#define GET_UTF16(val, GET_16BIT, ERROR)\
val = GET_16BIT;\
{\
unsigned int hi = val - 0xD800;\
if (hi < 0x800) {\
val = GET_16BIT - 0xDC00;\
if (val > 0x3FFU || hi > 0x3FFU)\
ERROR\
val += (hi<<10) + 0x10000;\
}\
}\
/**
* @def PUT_UTF8(val, tmp, PUT_BYTE)
* Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long).
* @param val is an input-only argument and should be of type uint32_t. It holds
* a UCS-4 encoded Unicode character that is to be converted to UTF-8. If
* val is given as a function it is executed only once.
* @param tmp is a temporary variable and should be of type uint8_t. It
* represents an intermediate value during conversion that is to be
* output by PUT_BYTE.
* @param PUT_BYTE writes the converted UTF-8 bytes to any proper destination.
* It could be a function or a statement, and uses tmp as the input byte.
* For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be
* executed up to 4 times for values in the valid UTF-8 range and up to
* 7 times in the general case, depending on the length of the converted
* Unicode character.
*/
#define PUT_UTF8(val, tmp, PUT_BYTE)\
{\
int bytes, shift;\
uint32_t in = val;\
if (in < 0x80) {\
tmp = in;\
PUT_BYTE\
} else {\
bytes = (av_log2(in) + 4) / 5;\
shift = (bytes - 1) * 6;\
tmp = (256 - (256 >> bytes)) | (in >> shift);\
PUT_BYTE\
while (shift >= 6) {\
shift -= 6;\
tmp = 0x80 | ((in >> shift) & 0x3f);\
PUT_BYTE\
}\
}\
}
/**
* @def PUT_UTF16(val, tmp, PUT_16BIT)
* Convert a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes).
* @param val is an input-only argument and should be of type uint32_t. It holds
* a UCS-4 encoded Unicode character that is to be converted to UTF-16. If
* val is given as a function it is executed only once.
* @param tmp is a temporary variable and should be of type uint16_t. It
* represents an intermediate value during conversion that is to be
* output by PUT_16BIT.
* @param PUT_16BIT writes the converted UTF-16 data to any proper destination
* in desired endianness. It could be a function or a statement, and uses tmp
* as the input byte. For example, PUT_BYTE could be "*output++ = tmp;"
* PUT_BYTE will be executed 1 or 2 times depending on input character.
*/
#define PUT_UTF16(val, tmp, PUT_16BIT)\
{\
uint32_t in = val;\
if (in < 0x10000) {\
tmp = in;\
PUT_16BIT\
} else {\
tmp = 0xD800 | ((in - 0x10000) >> 10);\
PUT_16BIT\
tmp = 0xDC00 | ((in - 0x10000) & 0x3FF);\
PUT_16BIT\
}\
}\
#include "mem.h"
#ifdef HAVE_AV_CONFIG_H
# include "internal.h"
#endif /* HAVE_AV_CONFIG_H */
#endif /* AVUTIL_COMMON_H */
/*
* The following definitions are outside the multiple inclusion guard
* to ensure they are immediately available in intmath.h.
*/
#ifndef av_ceil_log2
# define av_ceil_log2 av_ceil_log2_c
#endif
#ifndef av_clip
# define av_clip av_clip_c
#endif
#ifndef av_clip64
# define av_clip64 av_clip64_c
#endif
#ifndef av_clip_uint8
# define av_clip_uint8 av_clip_uint8_c
#endif
#ifndef av_clip_int8
# define av_clip_int8 av_clip_int8_c
#endif
#ifndef av_clip_uint16
# define av_clip_uint16 av_clip_uint16_c
#endif
#ifndef av_clip_int16
# define av_clip_int16 av_clip_int16_c
#endif
#ifndef av_clipl_int32
# define av_clipl_int32 av_clipl_int32_c
#endif
#ifndef av_clip_intp2
# define av_clip_intp2 av_clip_intp2_c
#endif
#ifndef av_clip_uintp2
# define av_clip_uintp2 av_clip_uintp2_c
#endif
#ifndef av_mod_uintp2
# define av_mod_uintp2 av_mod_uintp2_c
#endif
#ifndef av_sat_add32
# define av_sat_add32 av_sat_add32_c
#endif
#ifndef av_sat_dadd32
# define av_sat_dadd32 av_sat_dadd32_c
#endif
#ifndef av_sat_sub32
# define av_sat_sub32 av_sat_sub32_c
#endif
#ifndef av_sat_dsub32
# define av_sat_dsub32 av_sat_dsub32_c
#endif
#ifndef av_clipf
# define av_clipf av_clipf_c
#endif
#ifndef av_clipd
# define av_clipd av_clipd_c
#endif
#ifndef av_popcount
# define av_popcount av_popcount_c
#endif
#ifndef av_popcount64
# define av_popcount64 av_popcount64_c
#endif
#ifndef av_parity
# define av_parity av_parity_c
#endif

View file

@ -0,0 +1,321 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stddef.h>
#include <stdint.h>
#include <stdatomic.h>
#include "attributes.h"
#include "cpu.h"
#include "cpu_internal.h"
#include "config.h"
#include "opt.h"
#include "common.h"
#if HAVE_SCHED_GETAFFINITY
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <sched.h>
#endif
#if HAVE_GETPROCESSAFFINITYMASK || HAVE_WINRT
#include <windows.h>
#endif
#if HAVE_SYSCTL
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
static atomic_int cpu_flags = ATOMIC_VAR_INIT(-1);
static int get_cpu_flags(void)
{
if (ARCH_AARCH64)
return ff_get_cpu_flags_aarch64();
if (ARCH_ARM)
return ff_get_cpu_flags_arm();
if (ARCH_PPC)
return ff_get_cpu_flags_ppc();
if (ARCH_X86)
return ff_get_cpu_flags_x86();
return 0;
}
void av_force_cpu_flags(int arg){
if (ARCH_X86 &&
(arg & ( AV_CPU_FLAG_3DNOW |
AV_CPU_FLAG_3DNOWEXT |
AV_CPU_FLAG_MMXEXT |
AV_CPU_FLAG_SSE |
AV_CPU_FLAG_SSE2 |
AV_CPU_FLAG_SSE2SLOW |
AV_CPU_FLAG_SSE3 |
AV_CPU_FLAG_SSE3SLOW |
AV_CPU_FLAG_SSSE3 |
AV_CPU_FLAG_SSE4 |
AV_CPU_FLAG_SSE42 |
AV_CPU_FLAG_AVX |
AV_CPU_FLAG_AVXSLOW |
AV_CPU_FLAG_XOP |
AV_CPU_FLAG_FMA3 |
AV_CPU_FLAG_FMA4 |
AV_CPU_FLAG_AVX2 |
AV_CPU_FLAG_AVX512 ))
&& !(arg & AV_CPU_FLAG_MMX)) {
av_log(NULL, AV_LOG_WARNING, "MMX implied by specified flags\n");
arg |= AV_CPU_FLAG_MMX;
}
atomic_store_explicit(&cpu_flags, arg, memory_order_relaxed);
}
int av_get_cpu_flags(void)
{
int flags = atomic_load_explicit(&cpu_flags, memory_order_relaxed);
if (flags == -1) {
flags = get_cpu_flags();
atomic_store_explicit(&cpu_flags, flags, memory_order_relaxed);
}
return flags;
}
void av_set_cpu_flags_mask(int mask)
{
atomic_store_explicit(&cpu_flags, get_cpu_flags() & mask,
memory_order_relaxed);
}
int av_parse_cpu_flags(const char *s)
{
#define CPUFLAG_MMXEXT (AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMXEXT | AV_CPU_FLAG_CMOV)
#define CPUFLAG_3DNOW (AV_CPU_FLAG_3DNOW | AV_CPU_FLAG_MMX)
#define CPUFLAG_3DNOWEXT (AV_CPU_FLAG_3DNOWEXT | CPUFLAG_3DNOW)
#define CPUFLAG_SSE (AV_CPU_FLAG_SSE | CPUFLAG_MMXEXT)
#define CPUFLAG_SSE2 (AV_CPU_FLAG_SSE2 | CPUFLAG_SSE)
#define CPUFLAG_SSE2SLOW (AV_CPU_FLAG_SSE2SLOW | CPUFLAG_SSE2)
#define CPUFLAG_SSE3 (AV_CPU_FLAG_SSE3 | CPUFLAG_SSE2)
#define CPUFLAG_SSE3SLOW (AV_CPU_FLAG_SSE3SLOW | CPUFLAG_SSE3)
#define CPUFLAG_SSSE3 (AV_CPU_FLAG_SSSE3 | CPUFLAG_SSE3)
#define CPUFLAG_SSE4 (AV_CPU_FLAG_SSE4 | CPUFLAG_SSSE3)
#define CPUFLAG_SSE42 (AV_CPU_FLAG_SSE42 | CPUFLAG_SSE4)
#define CPUFLAG_AVX (AV_CPU_FLAG_AVX | CPUFLAG_SSE42)
#define CPUFLAG_AVXSLOW (AV_CPU_FLAG_AVXSLOW | CPUFLAG_AVX)
#define CPUFLAG_XOP (AV_CPU_FLAG_XOP | CPUFLAG_AVX)
#define CPUFLAG_FMA3 (AV_CPU_FLAG_FMA3 | CPUFLAG_AVX)
#define CPUFLAG_FMA4 (AV_CPU_FLAG_FMA4 | CPUFLAG_AVX)
#define CPUFLAG_AVX2 (AV_CPU_FLAG_AVX2 | CPUFLAG_AVX)
#define CPUFLAG_BMI2 (AV_CPU_FLAG_BMI2 | AV_CPU_FLAG_BMI1)
#define CPUFLAG_AESNI (AV_CPU_FLAG_AESNI | CPUFLAG_SSE42)
#define CPUFLAG_AVX512 (AV_CPU_FLAG_AVX512 | CPUFLAG_AVX2)
static const AVOption cpuflags_opts[] = {
{ "flags" , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" },
#if ARCH_PPC
{ "altivec" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ALTIVEC }, .unit = "flags" },
#elif ARCH_X86
{ "mmx" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMX }, .unit = "flags" },
{ "mmxext" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_MMXEXT }, .unit = "flags" },
{ "sse" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_SSE }, .unit = "flags" },
{ "sse2" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_SSE2 }, .unit = "flags" },
{ "sse2slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_SSE2SLOW }, .unit = "flags" },
{ "sse3" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_SSE3 }, .unit = "flags" },
{ "sse3slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_SSE3SLOW }, .unit = "flags" },
{ "ssse3" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_SSSE3 }, .unit = "flags" },
{ "atom" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ATOM }, .unit = "flags" },
{ "sse4.1" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_SSE4 }, .unit = "flags" },
{ "sse4.2" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_SSE42 }, .unit = "flags" },
{ "avx" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_AVX }, .unit = "flags" },
{ "avxslow" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_AVXSLOW }, .unit = "flags" },
{ "xop" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_XOP }, .unit = "flags" },
{ "fma3" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_FMA3 }, .unit = "flags" },
{ "fma4" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_FMA4 }, .unit = "flags" },
{ "avx2" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_AVX2 }, .unit = "flags" },
{ "bmi1" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_BMI1 }, .unit = "flags" },
{ "bmi2" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_BMI2 }, .unit = "flags" },
{ "3dnow" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_3DNOW }, .unit = "flags" },
{ "3dnowext", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_3DNOWEXT }, .unit = "flags" },
{ "cmov", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_CMOV }, .unit = "flags" },
{ "aesni" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_AESNI }, .unit = "flags" },
{ "avx512" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPUFLAG_AVX512 }, .unit = "flags" },
#elif ARCH_ARM
{ "armv5te", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV5TE }, .unit = "flags" },
{ "armv6", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV6 }, .unit = "flags" },
{ "armv6t2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV6T2 }, .unit = "flags" },
{ "vfp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP }, .unit = "flags" },
{ "vfp_vm", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP_VM }, .unit = "flags" },
{ "vfpv3", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFPV3 }, .unit = "flags" },
{ "neon", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON }, .unit = "flags" },
#elif ARCH_AARCH64
{ "armv8", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV8 }, .unit = "flags" },
{ "neon", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON }, .unit = "flags" },
{ "vfp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP }, .unit = "flags" },
#endif
{ NULL },
};
static const AVClass class = {
.class_name = "cpuflags",
.item_name = av_default_item_name,
.option = cpuflags_opts,
.version = LIBAVUTIL_VERSION_INT,
};
int flags = 0, ret;
const AVClass *pclass = &class;
if ((ret = av_opt_eval_flags(&pclass, &cpuflags_opts[0], s, &flags)) < 0)
return ret;
return flags & INT_MAX;
}
int av_parse_cpu_caps(unsigned *flags, const char *s)
{
static const AVOption cpuflags_opts[] = {
{ "flags" , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" },
#if ARCH_PPC
{ "altivec" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ALTIVEC }, .unit = "flags" },
#elif ARCH_X86
{ "mmx" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMX }, .unit = "flags" },
{ "mmx2" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMX2 }, .unit = "flags" },
{ "mmxext" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMX2 }, .unit = "flags" },
{ "sse" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE }, .unit = "flags" },
{ "sse2" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE2 }, .unit = "flags" },
{ "sse2slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE2SLOW }, .unit = "flags" },
{ "sse3" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE3 }, .unit = "flags" },
{ "sse3slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE3SLOW }, .unit = "flags" },
{ "ssse3" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSSE3 }, .unit = "flags" },
{ "atom" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ATOM }, .unit = "flags" },
{ "sse4.1" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE4 }, .unit = "flags" },
{ "sse4.2" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SSE42 }, .unit = "flags" },
{ "avx" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_AVX }, .unit = "flags" },
{ "avxslow" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_AVXSLOW }, .unit = "flags" },
{ "xop" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_XOP }, .unit = "flags" },
{ "fma3" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_FMA3 }, .unit = "flags" },
{ "fma4" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_FMA4 }, .unit = "flags" },
{ "avx2" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_AVX2 }, .unit = "flags" },
{ "bmi1" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_BMI1 }, .unit = "flags" },
{ "bmi2" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_BMI2 }, .unit = "flags" },
{ "3dnow" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_3DNOW }, .unit = "flags" },
{ "3dnowext", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_3DNOWEXT }, .unit = "flags" },
{ "cmov", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_CMOV }, .unit = "flags" },
{ "aesni", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_AESNI }, .unit = "flags" },
{ "avx512" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_AVX512 }, .unit = "flags" },
#define CPU_FLAG_P2 AV_CPU_FLAG_CMOV | AV_CPU_FLAG_MMX
#define CPU_FLAG_P3 CPU_FLAG_P2 | AV_CPU_FLAG_MMX2 | AV_CPU_FLAG_SSE
#define CPU_FLAG_P4 CPU_FLAG_P3| AV_CPU_FLAG_SSE2
{ "pentium2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPU_FLAG_P2 }, .unit = "flags" },
{ "pentium3", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPU_FLAG_P3 }, .unit = "flags" },
{ "pentium4", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPU_FLAG_P4 }, .unit = "flags" },
#define CPU_FLAG_K62 AV_CPU_FLAG_MMX | AV_CPU_FLAG_3DNOW
#define CPU_FLAG_ATHLON CPU_FLAG_K62 | AV_CPU_FLAG_CMOV | AV_CPU_FLAG_3DNOWEXT | AV_CPU_FLAG_MMX2
#define CPU_FLAG_ATHLONXP CPU_FLAG_ATHLON | AV_CPU_FLAG_SSE
#define CPU_FLAG_K8 CPU_FLAG_ATHLONXP | AV_CPU_FLAG_SSE2
{ "k6", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMX }, .unit = "flags" },
{ "k62", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPU_FLAG_K62 }, .unit = "flags" },
{ "athlon", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPU_FLAG_ATHLON }, .unit = "flags" },
{ "athlonxp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPU_FLAG_ATHLONXP }, .unit = "flags" },
{ "k8", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = CPU_FLAG_K8 }, .unit = "flags" },
#elif ARCH_ARM
{ "armv5te", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV5TE }, .unit = "flags" },
{ "armv6", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV6 }, .unit = "flags" },
{ "armv6t2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV6T2 }, .unit = "flags" },
{ "vfp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP }, .unit = "flags" },
{ "vfp_vm", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP_VM }, .unit = "flags" },
{ "vfpv3", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFPV3 }, .unit = "flags" },
{ "neon", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON }, .unit = "flags" },
{ "setend", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SETEND }, .unit = "flags" },
#elif ARCH_AARCH64
{ "armv8", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_ARMV8 }, .unit = "flags" },
{ "neon", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_NEON }, .unit = "flags" },
{ "vfp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_VFP }, .unit = "flags" },
#endif
{ NULL },
};
static const AVClass class = {
.class_name = "cpuflags",
.item_name = av_default_item_name,
.option = cpuflags_opts,
.version = LIBAVUTIL_VERSION_INT,
};
const AVClass *pclass = &class;
return av_opt_eval_flags(&pclass, &cpuflags_opts[0], s, flags);
}
int av_cpu_count(void)
{
static volatile int printed;
int nb_cpus = 1;
#if HAVE_WINRT
SYSTEM_INFO sysinfo;
#endif
#if HAVE_SCHED_GETAFFINITY && defined(CPU_COUNT)
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
if (!sched_getaffinity(0, sizeof(cpuset), &cpuset))
nb_cpus = CPU_COUNT(&cpuset);
#elif HAVE_GETPROCESSAFFINITYMASK
DWORD_PTR proc_aff, sys_aff;
if (GetProcessAffinityMask(GetCurrentProcess(), &proc_aff, &sys_aff))
nb_cpus = av_popcount64(proc_aff);
#elif HAVE_SYSCTL && defined(HW_NCPU)
int mib[2] = { CTL_HW, HW_NCPU };
size_t len = sizeof(nb_cpus);
if (sysctl(mib, 2, &nb_cpus, &len, NULL, 0) == -1)
nb_cpus = 0;
#elif HAVE_SYSCONF && defined(_SC_NPROC_ONLN)
nb_cpus = sysconf(_SC_NPROC_ONLN);
#elif HAVE_SYSCONF && defined(_SC_NPROCESSORS_ONLN)
nb_cpus = sysconf(_SC_NPROCESSORS_ONLN);
#elif HAVE_WINRT
GetNativeSystemInfo(&sysinfo);
nb_cpus = sysinfo.dwNumberOfProcessors;
#endif
if (!printed) {
av_log(NULL, AV_LOG_DEBUG, "detected %d logical cores\n", nb_cpus);
printed = 1;
}
return nb_cpus;
}
size_t av_cpu_max_align(void)
{
if (ARCH_AARCH64)
return ff_get_cpu_max_align_aarch64();
if (ARCH_ARM)
return ff_get_cpu_max_align_arm();
if (ARCH_PPC)
return ff_get_cpu_max_align_ppc();
if (ARCH_X86)
return ff_get_cpu_max_align_x86();
return 8;
}

View file

@ -0,0 +1,130 @@
/*
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_CPU_H
#define AVUTIL_CPU_H
#include <stddef.h>
#include "attributes.h"
#define AV_CPU_FLAG_FORCE 0x80000000 /* force usage of selected flags (OR) */
/* lower 16 bits - CPU features */
#define AV_CPU_FLAG_MMX 0x0001 ///< standard MMX
#define AV_CPU_FLAG_MMXEXT 0x0002 ///< SSE integer functions or AMD MMX ext
#define AV_CPU_FLAG_MMX2 0x0002 ///< SSE integer functions or AMD MMX ext
#define AV_CPU_FLAG_3DNOW 0x0004 ///< AMD 3DNOW
#define AV_CPU_FLAG_SSE 0x0008 ///< SSE functions
#define AV_CPU_FLAG_SSE2 0x0010 ///< PIV SSE2 functions
#define AV_CPU_FLAG_SSE2SLOW 0x40000000 ///< SSE2 supported, but usually not faster
///< than regular MMX/SSE (e.g. Core1)
#define AV_CPU_FLAG_3DNOWEXT 0x0020 ///< AMD 3DNowExt
#define AV_CPU_FLAG_SSE3 0x0040 ///< Prescott SSE3 functions
#define AV_CPU_FLAG_SSE3SLOW 0x20000000 ///< SSE3 supported, but usually not faster
///< than regular MMX/SSE (e.g. Core1)
#define AV_CPU_FLAG_SSSE3 0x0080 ///< Conroe SSSE3 functions
#define AV_CPU_FLAG_SSSE3SLOW 0x4000000 ///< SSSE3 supported, but usually not faster
#define AV_CPU_FLAG_ATOM 0x10000000 ///< Atom processor, some SSSE3 instructions are slower
#define AV_CPU_FLAG_SSE4 0x0100 ///< Penryn SSE4.1 functions
#define AV_CPU_FLAG_SSE42 0x0200 ///< Nehalem SSE4.2 functions
#define AV_CPU_FLAG_AESNI 0x80000 ///< Advanced Encryption Standard functions
#define AV_CPU_FLAG_AVX 0x4000 ///< AVX functions: requires OS support even if YMM registers aren't used
#define AV_CPU_FLAG_AVXSLOW 0x8000000 ///< AVX supported, but slow when using YMM registers (e.g. Bulldozer)
#define AV_CPU_FLAG_XOP 0x0400 ///< Bulldozer XOP functions
#define AV_CPU_FLAG_FMA4 0x0800 ///< Bulldozer FMA4 functions
#define AV_CPU_FLAG_CMOV 0x1000 ///< supports cmov instruction
#define AV_CPU_FLAG_AVX2 0x8000 ///< AVX2 functions: requires OS support even if YMM registers aren't used
#define AV_CPU_FLAG_FMA3 0x10000 ///< Haswell FMA3 functions
#define AV_CPU_FLAG_BMI1 0x20000 ///< Bit Manipulation Instruction Set 1
#define AV_CPU_FLAG_BMI2 0x40000 ///< Bit Manipulation Instruction Set 2
#define AV_CPU_FLAG_AVX512 0x100000 ///< AVX-512 functions: requires OS support even if YMM/ZMM registers aren't used
#define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard
#define AV_CPU_FLAG_VSX 0x0002 ///< ISA 2.06
#define AV_CPU_FLAG_POWER8 0x0004 ///< ISA 2.07
#define AV_CPU_FLAG_ARMV5TE (1 << 0)
#define AV_CPU_FLAG_ARMV6 (1 << 1)
#define AV_CPU_FLAG_ARMV6T2 (1 << 2)
#define AV_CPU_FLAG_VFP (1 << 3)
#define AV_CPU_FLAG_VFPV3 (1 << 4)
#define AV_CPU_FLAG_NEON (1 << 5)
#define AV_CPU_FLAG_ARMV8 (1 << 6)
#define AV_CPU_FLAG_VFP_VM (1 << 7) ///< VFPv2 vector mode, deprecated in ARMv7-A and unavailable in various CPUs implementations
#define AV_CPU_FLAG_SETEND (1 <<16)
/**
* Return the flags which specify extensions supported by the CPU.
* The returned value is affected by av_force_cpu_flags() if that was used
* before. So av_get_cpu_flags() can easily be used in an application to
* detect the enabled cpu flags.
*/
int av_get_cpu_flags(void);
/**
* Disables cpu detection and forces the specified flags.
* -1 is a special case that disables forcing of specific flags.
*/
void av_force_cpu_flags(int flags);
/**
* Set a mask on flags returned by av_get_cpu_flags().
* This function is mainly useful for testing.
* Please use av_force_cpu_flags() and av_get_cpu_flags() instead which are more flexible
*/
attribute_deprecated void av_set_cpu_flags_mask(int mask);
/**
* Parse CPU flags from a string.
*
* The returned flags contain the specified flags as well as related unspecified flags.
*
* This function exists only for compatibility with libav.
* Please use av_parse_cpu_caps() when possible.
* @return a combination of AV_CPU_* flags, negative on error.
*/
attribute_deprecated
int av_parse_cpu_flags(const char *s);
/**
* Parse CPU caps from a string and update the given AV_CPU_* flags based on that.
*
* @return negative on error.
*/
int av_parse_cpu_caps(unsigned *flags, const char *s);
/**
* @return the number of logical CPU cores present.
*/
int av_cpu_count(void);
/**
* Get the maximum data alignment that may be required by FFmpeg.
*
* Note that this is affected by the build configuration and the CPU flags mask,
* so e.g. if the CPU supports AVX, but libavutil has been built with
* --disable-avx or the AV_CPU_FLAG_AVX flag has been disabled through
* av_set_cpu_flags_mask(), then this function will behave as if AVX is not
* present.
*/
size_t av_cpu_max_align(void);
#endif /* AVUTIL_CPU_H */

View file

@ -0,0 +1,54 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_CPU_INTERNAL_H
#define AVUTIL_CPU_INTERNAL_H
#include "config.h"
#include "cpu.h"
#define CPUEXT_SUFFIX(flags, suffix, cpuext) \
(HAVE_ ## cpuext ## suffix && ((flags) & AV_CPU_FLAG_ ## cpuext))
#define CPUEXT_SUFFIX_FAST2(flags, suffix, cpuext, slow_cpuext) \
(HAVE_ ## cpuext ## suffix && ((flags) & AV_CPU_FLAG_ ## cpuext) && \
!((flags) & AV_CPU_FLAG_ ## slow_cpuext ## SLOW))
#define CPUEXT_SUFFIX_SLOW2(flags, suffix, cpuext, slow_cpuext) \
(HAVE_ ## cpuext ## suffix && ((flags) & AV_CPU_FLAG_ ## cpuext) && \
((flags) & AV_CPU_FLAG_ ## slow_cpuext ## SLOW))
#define CPUEXT_SUFFIX_FAST(flags, suffix, cpuext) CPUEXT_SUFFIX_FAST2(flags, suffix, cpuext, cpuext)
#define CPUEXT_SUFFIX_SLOW(flags, suffix, cpuext) CPUEXT_SUFFIX_SLOW2(flags, suffix, cpuext, cpuext)
#define CPUEXT(flags, cpuext) CPUEXT_SUFFIX(flags, , cpuext)
#define CPUEXT_FAST(flags, cpuext) CPUEXT_SUFFIX_FAST(flags, , cpuext)
#define CPUEXT_SLOW(flags, cpuext) CPUEXT_SUFFIX_SLOW(flags, , cpuext)
int ff_get_cpu_flags_aarch64(void);
int ff_get_cpu_flags_arm(void);
int ff_get_cpu_flags_ppc(void);
int ff_get_cpu_flags_x86(void);
size_t ff_get_cpu_max_align_aarch64(void);
size_t ff_get_cpu_max_align_arm(void);
size_t ff_get_cpu_max_align_ppc(void);
size_t ff_get_cpu_max_align_x86(void);
#endif /* AVUTIL_CPU_INTERNAL_H */

View file

@ -0,0 +1,415 @@
/*
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "thread.h"
#include "avassert.h"
#include "bswap.h"
#include "common.h"
#include "crc.h"
#if CONFIG_HARDCODED_TABLES
static const AVCRC av_crc_table[AV_CRC_MAX][257] = {
[AV_CRC_8_ATM] = {
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31,
0x24, 0x23, 0x2A, 0x2D, 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D, 0xE0, 0xE7, 0xEE, 0xE9,
0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1,
0xB4, 0xB3, 0xBA, 0xBD, 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA, 0xB7, 0xB0, 0xB9, 0xBE,
0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16,
0x03, 0x04, 0x0D, 0x0A, 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A, 0x89, 0x8E, 0x87, 0x80,
0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8,
0xDD, 0xDA, 0xD3, 0xD4, 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44, 0x19, 0x1E, 0x17, 0x10,
0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F,
0x6A, 0x6D, 0x64, 0x63, 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13, 0xAE, 0xA9, 0xA0, 0xA7,
0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF,
0xFA, 0xFD, 0xF4, 0xF3, 0x01
},
[AV_CRC_8_EBU] = {
0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53, 0xE8, 0xF5, 0xD2, 0xCF,
0x9C, 0x81, 0xA6, 0xBB, 0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E,
0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76, 0x87, 0x9A, 0xBD, 0xA0,
0xF3, 0xEE, 0xC9, 0xD4, 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C,
0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19, 0xA2, 0xBF, 0x98, 0x85,
0xD6, 0xCB, 0xEC, 0xF1, 0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40,
0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8, 0xDE, 0xC3, 0xE4, 0xF9,
0xAA, 0xB7, 0x90, 0x8D, 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65,
0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7, 0x7C, 0x61, 0x46, 0x5B,
0x08, 0x15, 0x32, 0x2F, 0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A,
0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2, 0x26, 0x3B, 0x1C, 0x01,
0x52, 0x4F, 0x68, 0x75, 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D,
0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8, 0x03, 0x1E, 0x39, 0x24,
0x77, 0x6A, 0x4D, 0x50, 0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2,
0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A, 0x6C, 0x71, 0x56, 0x4B,
0x18, 0x05, 0x22, 0x3F, 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7,
0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66, 0xDD, 0xC0, 0xE7, 0xFA,
0xA9, 0xB4, 0x93, 0x8E, 0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB,
0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43, 0xB2, 0xAF, 0x88, 0x95,
0xC6, 0xDB, 0xFC, 0xE1, 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09,
0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C, 0x97, 0x8A, 0xAD, 0xB0,
0xE3, 0xFE, 0xD9, 0xC4, 0x01
},
[AV_CRC_16_ANSI] = {
0x0000, 0x0580, 0x0F80, 0x0A00, 0x1B80, 0x1E00, 0x1400, 0x1180,
0x3380, 0x3600, 0x3C00, 0x3980, 0x2800, 0x2D80, 0x2780, 0x2200,
0x6380, 0x6600, 0x6C00, 0x6980, 0x7800, 0x7D80, 0x7780, 0x7200,
0x5000, 0x5580, 0x5F80, 0x5A00, 0x4B80, 0x4E00, 0x4400, 0x4180,
0xC380, 0xC600, 0xCC00, 0xC980, 0xD800, 0xDD80, 0xD780, 0xD200,
0xF000, 0xF580, 0xFF80, 0xFA00, 0xEB80, 0xEE00, 0xE400, 0xE180,
0xA000, 0xA580, 0xAF80, 0xAA00, 0xBB80, 0xBE00, 0xB400, 0xB180,
0x9380, 0x9600, 0x9C00, 0x9980, 0x8800, 0x8D80, 0x8780, 0x8200,
0x8381, 0x8601, 0x8C01, 0x8981, 0x9801, 0x9D81, 0x9781, 0x9201,
0xB001, 0xB581, 0xBF81, 0xBA01, 0xAB81, 0xAE01, 0xA401, 0xA181,
0xE001, 0xE581, 0xEF81, 0xEA01, 0xFB81, 0xFE01, 0xF401, 0xF181,
0xD381, 0xD601, 0xDC01, 0xD981, 0xC801, 0xCD81, 0xC781, 0xC201,
0x4001, 0x4581, 0x4F81, 0x4A01, 0x5B81, 0x5E01, 0x5401, 0x5181,
0x7381, 0x7601, 0x7C01, 0x7981, 0x6801, 0x6D81, 0x6781, 0x6201,
0x2381, 0x2601, 0x2C01, 0x2981, 0x3801, 0x3D81, 0x3781, 0x3201,
0x1001, 0x1581, 0x1F81, 0x1A01, 0x0B81, 0x0E01, 0x0401, 0x0181,
0x0383, 0x0603, 0x0C03, 0x0983, 0x1803, 0x1D83, 0x1783, 0x1203,
0x3003, 0x3583, 0x3F83, 0x3A03, 0x2B83, 0x2E03, 0x2403, 0x2183,
0x6003, 0x6583, 0x6F83, 0x6A03, 0x7B83, 0x7E03, 0x7403, 0x7183,
0x5383, 0x5603, 0x5C03, 0x5983, 0x4803, 0x4D83, 0x4783, 0x4203,
0xC003, 0xC583, 0xCF83, 0xCA03, 0xDB83, 0xDE03, 0xD403, 0xD183,
0xF383, 0xF603, 0xFC03, 0xF983, 0xE803, 0xED83, 0xE783, 0xE203,
0xA383, 0xA603, 0xAC03, 0xA983, 0xB803, 0xBD83, 0xB783, 0xB203,
0x9003, 0x9583, 0x9F83, 0x9A03, 0x8B83, 0x8E03, 0x8403, 0x8183,
0x8002, 0x8582, 0x8F82, 0x8A02, 0x9B82, 0x9E02, 0x9402, 0x9182,
0xB382, 0xB602, 0xBC02, 0xB982, 0xA802, 0xAD82, 0xA782, 0xA202,
0xE382, 0xE602, 0xEC02, 0xE982, 0xF802, 0xFD82, 0xF782, 0xF202,
0xD002, 0xD582, 0xDF82, 0xDA02, 0xCB82, 0xCE02, 0xC402, 0xC182,
0x4382, 0x4602, 0x4C02, 0x4982, 0x5802, 0x5D82, 0x5782, 0x5202,
0x7002, 0x7582, 0x7F82, 0x7A02, 0x6B82, 0x6E02, 0x6402, 0x6182,
0x2002, 0x2582, 0x2F82, 0x2A02, 0x3B82, 0x3E02, 0x3402, 0x3182,
0x1382, 0x1602, 0x1C02, 0x1982, 0x0802, 0x0D82, 0x0782, 0x0202,
0x0001
},
[AV_CRC_16_CCITT] = {
0x0000, 0x2110, 0x4220, 0x6330, 0x8440, 0xA550, 0xC660, 0xE770,
0x0881, 0x2991, 0x4AA1, 0x6BB1, 0x8CC1, 0xADD1, 0xCEE1, 0xEFF1,
0x3112, 0x1002, 0x7332, 0x5222, 0xB552, 0x9442, 0xF772, 0xD662,
0x3993, 0x1883, 0x7BB3, 0x5AA3, 0xBDD3, 0x9CC3, 0xFFF3, 0xDEE3,
0x6224, 0x4334, 0x2004, 0x0114, 0xE664, 0xC774, 0xA444, 0x8554,
0x6AA5, 0x4BB5, 0x2885, 0x0995, 0xEEE5, 0xCFF5, 0xACC5, 0x8DD5,
0x5336, 0x7226, 0x1116, 0x3006, 0xD776, 0xF666, 0x9556, 0xB446,
0x5BB7, 0x7AA7, 0x1997, 0x3887, 0xDFF7, 0xFEE7, 0x9DD7, 0xBCC7,
0xC448, 0xE558, 0x8668, 0xA778, 0x4008, 0x6118, 0x0228, 0x2338,
0xCCC9, 0xEDD9, 0x8EE9, 0xAFF9, 0x4889, 0x6999, 0x0AA9, 0x2BB9,
0xF55A, 0xD44A, 0xB77A, 0x966A, 0x711A, 0x500A, 0x333A, 0x122A,
0xFDDB, 0xDCCB, 0xBFFB, 0x9EEB, 0x799B, 0x588B, 0x3BBB, 0x1AAB,
0xA66C, 0x877C, 0xE44C, 0xC55C, 0x222C, 0x033C, 0x600C, 0x411C,
0xAEED, 0x8FFD, 0xECCD, 0xCDDD, 0x2AAD, 0x0BBD, 0x688D, 0x499D,
0x977E, 0xB66E, 0xD55E, 0xF44E, 0x133E, 0x322E, 0x511E, 0x700E,
0x9FFF, 0xBEEF, 0xDDDF, 0xFCCF, 0x1BBF, 0x3AAF, 0x599F, 0x788F,
0x8891, 0xA981, 0xCAB1, 0xEBA1, 0x0CD1, 0x2DC1, 0x4EF1, 0x6FE1,
0x8010, 0xA100, 0xC230, 0xE320, 0x0450, 0x2540, 0x4670, 0x6760,
0xB983, 0x9893, 0xFBA3, 0xDAB3, 0x3DC3, 0x1CD3, 0x7FE3, 0x5EF3,
0xB102, 0x9012, 0xF322, 0xD232, 0x3542, 0x1452, 0x7762, 0x5672,
0xEAB5, 0xCBA5, 0xA895, 0x8985, 0x6EF5, 0x4FE5, 0x2CD5, 0x0DC5,
0xE234, 0xC324, 0xA014, 0x8104, 0x6674, 0x4764, 0x2454, 0x0544,
0xDBA7, 0xFAB7, 0x9987, 0xB897, 0x5FE7, 0x7EF7, 0x1DC7, 0x3CD7,
0xD326, 0xF236, 0x9106, 0xB016, 0x5766, 0x7676, 0x1546, 0x3456,
0x4CD9, 0x6DC9, 0x0EF9, 0x2FE9, 0xC899, 0xE989, 0x8AB9, 0xABA9,
0x4458, 0x6548, 0x0678, 0x2768, 0xC018, 0xE108, 0x8238, 0xA328,
0x7DCB, 0x5CDB, 0x3FEB, 0x1EFB, 0xF98B, 0xD89B, 0xBBAB, 0x9ABB,
0x754A, 0x545A, 0x376A, 0x167A, 0xF10A, 0xD01A, 0xB32A, 0x923A,
0x2EFD, 0x0FED, 0x6CDD, 0x4DCD, 0xAABD, 0x8BAD, 0xE89D, 0xC98D,
0x267C, 0x076C, 0x645C, 0x454C, 0xA23C, 0x832C, 0xE01C, 0xC10C,
0x1FEF, 0x3EFF, 0x5DCF, 0x7CDF, 0x9BAF, 0xBABF, 0xD98F, 0xF89F,
0x176E, 0x367E, 0x554E, 0x745E, 0x932E, 0xB23E, 0xD10E, 0xF01E,
0x0001
},
[AV_CRC_24_IEEE] = {
0x000000, 0xFB4C86, 0x0DD58A, 0xF6990C, 0xE1E693, 0x1AAA15, 0xEC3319,
0x177F9F, 0x3981A1, 0xC2CD27, 0x34542B, 0xCF18AD, 0xD86732, 0x232BB4,
0xD5B2B8, 0x2EFE3E, 0x894EC5, 0x720243, 0x849B4F, 0x7FD7C9, 0x68A856,
0x93E4D0, 0x657DDC, 0x9E315A, 0xB0CF64, 0x4B83E2, 0xBD1AEE, 0x465668,
0x5129F7, 0xAA6571, 0x5CFC7D, 0xA7B0FB, 0xE9D10C, 0x129D8A, 0xE40486,
0x1F4800, 0x08379F, 0xF37B19, 0x05E215, 0xFEAE93, 0xD050AD, 0x2B1C2B,
0xDD8527, 0x26C9A1, 0x31B63E, 0xCAFAB8, 0x3C63B4, 0xC72F32, 0x609FC9,
0x9BD34F, 0x6D4A43, 0x9606C5, 0x81795A, 0x7A35DC, 0x8CACD0, 0x77E056,
0x591E68, 0xA252EE, 0x54CBE2, 0xAF8764, 0xB8F8FB, 0x43B47D, 0xB52D71,
0x4E61F7, 0xD2A319, 0x29EF9F, 0xDF7693, 0x243A15, 0x33458A, 0xC8090C,
0x3E9000, 0xC5DC86, 0xEB22B8, 0x106E3E, 0xE6F732, 0x1DBBB4, 0x0AC42B,
0xF188AD, 0x0711A1, 0xFC5D27, 0x5BEDDC, 0xA0A15A, 0x563856, 0xAD74D0,
0xBA0B4F, 0x4147C9, 0xB7DEC5, 0x4C9243, 0x626C7D, 0x9920FB, 0x6FB9F7,
0x94F571, 0x838AEE, 0x78C668, 0x8E5F64, 0x7513E2, 0x3B7215, 0xC03E93,
0x36A79F, 0xCDEB19, 0xDA9486, 0x21D800, 0xD7410C, 0x2C0D8A, 0x02F3B4,
0xF9BF32, 0x0F263E, 0xF46AB8, 0xE31527, 0x1859A1, 0xEEC0AD, 0x158C2B,
0xB23CD0, 0x497056, 0xBFE95A, 0x44A5DC, 0x53DA43, 0xA896C5, 0x5E0FC9,
0xA5434F, 0x8BBD71, 0x70F1F7, 0x8668FB, 0x7D247D, 0x6A5BE2, 0x911764,
0x678E68, 0x9CC2EE, 0xA44733, 0x5F0BB5, 0xA992B9, 0x52DE3F, 0x45A1A0,
0xBEED26, 0x48742A, 0xB338AC, 0x9DC692, 0x668A14, 0x901318, 0x6B5F9E,
0x7C2001, 0x876C87, 0x71F58B, 0x8AB90D, 0x2D09F6, 0xD64570, 0x20DC7C,
0xDB90FA, 0xCCEF65, 0x37A3E3, 0xC13AEF, 0x3A7669, 0x148857, 0xEFC4D1,
0x195DDD, 0xE2115B, 0xF56EC4, 0x0E2242, 0xF8BB4E, 0x03F7C8, 0x4D963F,
0xB6DAB9, 0x4043B5, 0xBB0F33, 0xAC70AC, 0x573C2A, 0xA1A526, 0x5AE9A0,
0x74179E, 0x8F5B18, 0x79C214, 0x828E92, 0x95F10D, 0x6EBD8B, 0x982487,
0x636801, 0xC4D8FA, 0x3F947C, 0xC90D70, 0x3241F6, 0x253E69, 0xDE72EF,
0x28EBE3, 0xD3A765, 0xFD595B, 0x0615DD, 0xF08CD1, 0x0BC057, 0x1CBFC8,
0xE7F34E, 0x116A42, 0xEA26C4, 0x76E42A, 0x8DA8AC, 0x7B31A0, 0x807D26,
0x9702B9, 0x6C4E3F, 0x9AD733, 0x619BB5, 0x4F658B, 0xB4290D, 0x42B001,
0xB9FC87, 0xAE8318, 0x55CF9E, 0xA35692, 0x581A14, 0xFFAAEF, 0x04E669,
0xF27F65, 0x0933E3, 0x1E4C7C, 0xE500FA, 0x1399F6, 0xE8D570, 0xC62B4E,
0x3D67C8, 0xCBFEC4, 0x30B242, 0x27CDDD, 0xDC815B, 0x2A1857, 0xD154D1,
0x9F3526, 0x6479A0, 0x92E0AC, 0x69AC2A, 0x7ED3B5, 0x859F33, 0x73063F,
0x884AB9, 0xA6B487, 0x5DF801, 0xAB610D, 0x502D8B, 0x475214, 0xBC1E92,
0x4A879E, 0xB1CB18, 0x167BE3, 0xED3765, 0x1BAE69, 0xE0E2EF, 0xF79D70,
0x0CD1F6, 0xFA48FA, 0x01047C, 0x2FFA42, 0xD4B6C4, 0x222FC8, 0xD9634E,
0xCE1CD1, 0x355057, 0xC3C95B, 0x3885DD, 0x000001,
},
[AV_CRC_32_IEEE] = {
0x00000000, 0xB71DC104, 0x6E3B8209, 0xD926430D, 0xDC760413, 0x6B6BC517,
0xB24D861A, 0x0550471E, 0xB8ED0826, 0x0FF0C922, 0xD6D68A2F, 0x61CB4B2B,
0x649B0C35, 0xD386CD31, 0x0AA08E3C, 0xBDBD4F38, 0x70DB114C, 0xC7C6D048,
0x1EE09345, 0xA9FD5241, 0xACAD155F, 0x1BB0D45B, 0xC2969756, 0x758B5652,
0xC836196A, 0x7F2BD86E, 0xA60D9B63, 0x11105A67, 0x14401D79, 0xA35DDC7D,
0x7A7B9F70, 0xCD665E74, 0xE0B62398, 0x57ABE29C, 0x8E8DA191, 0x39906095,
0x3CC0278B, 0x8BDDE68F, 0x52FBA582, 0xE5E66486, 0x585B2BBE, 0xEF46EABA,
0x3660A9B7, 0x817D68B3, 0x842D2FAD, 0x3330EEA9, 0xEA16ADA4, 0x5D0B6CA0,
0x906D32D4, 0x2770F3D0, 0xFE56B0DD, 0x494B71D9, 0x4C1B36C7, 0xFB06F7C3,
0x2220B4CE, 0x953D75CA, 0x28803AF2, 0x9F9DFBF6, 0x46BBB8FB, 0xF1A679FF,
0xF4F63EE1, 0x43EBFFE5, 0x9ACDBCE8, 0x2DD07DEC, 0x77708634, 0xC06D4730,
0x194B043D, 0xAE56C539, 0xAB068227, 0x1C1B4323, 0xC53D002E, 0x7220C12A,
0xCF9D8E12, 0x78804F16, 0xA1A60C1B, 0x16BBCD1F, 0x13EB8A01, 0xA4F64B05,
0x7DD00808, 0xCACDC90C, 0x07AB9778, 0xB0B6567C, 0x69901571, 0xDE8DD475,
0xDBDD936B, 0x6CC0526F, 0xB5E61162, 0x02FBD066, 0xBF469F5E, 0x085B5E5A,
0xD17D1D57, 0x6660DC53, 0x63309B4D, 0xD42D5A49, 0x0D0B1944, 0xBA16D840,
0x97C6A5AC, 0x20DB64A8, 0xF9FD27A5, 0x4EE0E6A1, 0x4BB0A1BF, 0xFCAD60BB,
0x258B23B6, 0x9296E2B2, 0x2F2BAD8A, 0x98366C8E, 0x41102F83, 0xF60DEE87,
0xF35DA999, 0x4440689D, 0x9D662B90, 0x2A7BEA94, 0xE71DB4E0, 0x500075E4,
0x892636E9, 0x3E3BF7ED, 0x3B6BB0F3, 0x8C7671F7, 0x555032FA, 0xE24DF3FE,
0x5FF0BCC6, 0xE8ED7DC2, 0x31CB3ECF, 0x86D6FFCB, 0x8386B8D5, 0x349B79D1,
0xEDBD3ADC, 0x5AA0FBD8, 0xEEE00C69, 0x59FDCD6D, 0x80DB8E60, 0x37C64F64,
0x3296087A, 0x858BC97E, 0x5CAD8A73, 0xEBB04B77, 0x560D044F, 0xE110C54B,
0x38368646, 0x8F2B4742, 0x8A7B005C, 0x3D66C158, 0xE4408255, 0x535D4351,
0x9E3B1D25, 0x2926DC21, 0xF0009F2C, 0x471D5E28, 0x424D1936, 0xF550D832,
0x2C769B3F, 0x9B6B5A3B, 0x26D61503, 0x91CBD407, 0x48ED970A, 0xFFF0560E,
0xFAA01110, 0x4DBDD014, 0x949B9319, 0x2386521D, 0x0E562FF1, 0xB94BEEF5,
0x606DADF8, 0xD7706CFC, 0xD2202BE2, 0x653DEAE6, 0xBC1BA9EB, 0x0B0668EF,
0xB6BB27D7, 0x01A6E6D3, 0xD880A5DE, 0x6F9D64DA, 0x6ACD23C4, 0xDDD0E2C0,
0x04F6A1CD, 0xB3EB60C9, 0x7E8D3EBD, 0xC990FFB9, 0x10B6BCB4, 0xA7AB7DB0,
0xA2FB3AAE, 0x15E6FBAA, 0xCCC0B8A7, 0x7BDD79A3, 0xC660369B, 0x717DF79F,
0xA85BB492, 0x1F467596, 0x1A163288, 0xAD0BF38C, 0x742DB081, 0xC3307185,
0x99908A5D, 0x2E8D4B59, 0xF7AB0854, 0x40B6C950, 0x45E68E4E, 0xF2FB4F4A,
0x2BDD0C47, 0x9CC0CD43, 0x217D827B, 0x9660437F, 0x4F460072, 0xF85BC176,
0xFD0B8668, 0x4A16476C, 0x93300461, 0x242DC565, 0xE94B9B11, 0x5E565A15,
0x87701918, 0x306DD81C, 0x353D9F02, 0x82205E06, 0x5B061D0B, 0xEC1BDC0F,
0x51A69337, 0xE6BB5233, 0x3F9D113E, 0x8880D03A, 0x8DD09724, 0x3ACD5620,
0xE3EB152D, 0x54F6D429, 0x7926A9C5, 0xCE3B68C1, 0x171D2BCC, 0xA000EAC8,
0xA550ADD6, 0x124D6CD2, 0xCB6B2FDF, 0x7C76EEDB, 0xC1CBA1E3, 0x76D660E7,
0xAFF023EA, 0x18EDE2EE, 0x1DBDA5F0, 0xAAA064F4, 0x738627F9, 0xC49BE6FD,
0x09FDB889, 0xBEE0798D, 0x67C63A80, 0xD0DBFB84, 0xD58BBC9A, 0x62967D9E,
0xBBB03E93, 0x0CADFF97, 0xB110B0AF, 0x060D71AB, 0xDF2B32A6, 0x6836F3A2,
0x6D66B4BC, 0xDA7B75B8, 0x035D36B5, 0xB440F7B1, 0x00000001
},
[AV_CRC_32_IEEE_LE] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, 0x00000001
},
[AV_CRC_16_ANSI_LE] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
0x0001
},
};
#else
#if CONFIG_SMALL
#define CRC_TABLE_SIZE 257
#else
#define CRC_TABLE_SIZE 1024
#endif
static AVCRC av_crc_table[AV_CRC_MAX][CRC_TABLE_SIZE];
#define DECLARE_CRC_INIT_TABLE_ONCE(id, le, bits, poly) \
static AVOnce id ## _once_control = AV_ONCE_INIT; \
static void id ## _init_table_once(void) \
{ \
av_assert0(av_crc_init(av_crc_table[id], le, bits, poly, sizeof(av_crc_table[id])) >= 0); \
}
#define CRC_INIT_TABLE_ONCE(id) ff_thread_once(&id ## _once_control, id ## _init_table_once)
DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_8_ATM, 0, 8, 0x07)
DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_8_EBU, 0, 8, 0x1D)
DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_16_ANSI, 0, 16, 0x8005)
DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_16_CCITT, 0, 16, 0x1021)
DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_24_IEEE, 0, 24, 0x864CFB)
DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_32_IEEE, 0, 32, 0x04C11DB7)
DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_32_IEEE_LE, 1, 32, 0xEDB88320)
DECLARE_CRC_INIT_TABLE_ONCE(AV_CRC_16_ANSI_LE, 1, 16, 0xA001)
#endif
int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size)
{
unsigned i, j;
uint32_t c;
if (bits < 8 || bits > 32 || poly >= (1LL << bits))
return AVERROR(EINVAL);
if (ctx_size != sizeof(AVCRC) * 257 && ctx_size != sizeof(AVCRC) * 1024)
return AVERROR(EINVAL);
for (i = 0; i < 256; i++) {
if (le) {
for (c = i, j = 0; j < 8; j++)
c = (c >> 1) ^ (poly & (-(c & 1)));
ctx[i] = c;
} else {
for (c = i << 24, j = 0; j < 8; j++)
c = (c << 1) ^ ((poly << (32 - bits)) & (((int32_t) c) >> 31));
ctx[i] = av_bswap32(c);
}
}
ctx[256] = 1;
#if !CONFIG_SMALL
if (ctx_size >= sizeof(AVCRC) * 1024)
for (i = 0; i < 256; i++)
for (j = 0; j < 3; j++)
ctx[256 * (j + 1) + i] =
(ctx[256 * j + i] >> 8) ^ ctx[ctx[256 * j + i] & 0xFF];
#endif
return 0;
}
const AVCRC *av_crc_get_table(AVCRCId crc_id)
{
#if !CONFIG_HARDCODED_TABLES
switch (crc_id) {
case AV_CRC_8_ATM: CRC_INIT_TABLE_ONCE(AV_CRC_8_ATM); break;
case AV_CRC_8_EBU: CRC_INIT_TABLE_ONCE(AV_CRC_8_EBU); break;
case AV_CRC_16_ANSI: CRC_INIT_TABLE_ONCE(AV_CRC_16_ANSI); break;
case AV_CRC_16_CCITT: CRC_INIT_TABLE_ONCE(AV_CRC_16_CCITT); break;
case AV_CRC_24_IEEE: CRC_INIT_TABLE_ONCE(AV_CRC_24_IEEE); break;
case AV_CRC_32_IEEE: CRC_INIT_TABLE_ONCE(AV_CRC_32_IEEE); break;
case AV_CRC_32_IEEE_LE: CRC_INIT_TABLE_ONCE(AV_CRC_32_IEEE_LE); break;
case AV_CRC_16_ANSI_LE: CRC_INIT_TABLE_ONCE(AV_CRC_16_ANSI_LE); break;
default: av_assert0(0);
}
#endif
return av_crc_table[crc_id];
}
uint32_t av_crc(const AVCRC *ctx, uint32_t crc,
const uint8_t *buffer, size_t length)
{
const uint8_t *end = buffer + length;
#if !CONFIG_SMALL
if (!ctx[256]) {
while (((intptr_t) buffer & 3) && buffer < end)
crc = ctx[((uint8_t) crc) ^ *buffer++] ^ (crc >> 8);
while (buffer < end - 3) {
crc ^= av_le2ne32(*(const uint32_t *) buffer); buffer += 4;
crc = ctx[3 * 256 + ( crc & 0xFF)] ^
ctx[2 * 256 + ((crc >> 8 ) & 0xFF)] ^
ctx[1 * 256 + ((crc >> 16) & 0xFF)] ^
ctx[0 * 256 + ((crc >> 24) )];
}
}
#endif
while (buffer < end)
crc = ctx[((uint8_t) crc) ^ *buffer++] ^ (crc >> 8);
return crc;
}

View file

@ -0,0 +1,100 @@
/*
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* @ingroup lavu_crc32
* Public header for CRC hash function implementation.
*/
#ifndef AVUTIL_CRC_H
#define AVUTIL_CRC_H
#include <stdint.h>
#include <stddef.h>
#include "attributes.h"
#include "version.h"
/**
* @defgroup lavu_crc32 CRC
* @ingroup lavu_hash
* CRC (Cyclic Redundancy Check) hash function implementation.
*
* This module supports numerous CRC polynomials, in addition to the most
* widely used CRC-32-IEEE. See @ref AVCRCId for a list of available
* polynomials.
*
* @{
*/
typedef uint32_t AVCRC;
typedef enum {
AV_CRC_8_ATM,
AV_CRC_16_ANSI,
AV_CRC_16_CCITT,
AV_CRC_32_IEEE,
AV_CRC_32_IEEE_LE, /*< reversed bitorder version of AV_CRC_32_IEEE */
AV_CRC_16_ANSI_LE, /*< reversed bitorder version of AV_CRC_16_ANSI */
AV_CRC_24_IEEE,
AV_CRC_8_EBU,
AV_CRC_MAX, /*< Not part of public API! Do not use outside libavutil. */
}AVCRCId;
/**
* Initialize a CRC table.
* @param ctx must be an array of size sizeof(AVCRC)*257 or sizeof(AVCRC)*1024
* @param le If 1, the lowest bit represents the coefficient for the highest
* exponent of the corresponding polynomial (both for poly and
* actual CRC).
* If 0, you must swap the CRC parameter and the result of av_crc
* if you need the standard representation (can be simplified in
* most cases to e.g. bswap16):
* av_bswap32(crc << (32-bits))
* @param bits number of bits for the CRC
* @param poly generator polynomial without the x**bits coefficient, in the
* representation as specified by le
* @param ctx_size size of ctx in bytes
* @return <0 on failure
*/
int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size);
/**
* Get an initialized standard CRC table.
* @param crc_id ID of a standard CRC
* @return a pointer to the CRC table or NULL on failure
*/
const AVCRC *av_crc_get_table(AVCRCId crc_id);
/**
* Calculate the CRC of a block.
* @param crc CRC of previous blocks if any or initial value for CRC
* @return CRC updated with the data from the given block
*
* @see av_crc_init() "le" parameter
*/
uint32_t av_crc(const AVCRC *ctx, uint32_t crc,
const uint8_t *buffer, size_t length) av_pure;
/**
* @}
*/
#endif /* AVUTIL_CRC_H */

View file

@ -0,0 +1,331 @@
/*
* DES encryption/decryption
* Copyright (c) 2007 Reimar Doeffinger
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include "avutil.h"
#include "common.h"
#include "intreadwrite.h"
#include "mem.h"
#include "des.h"
#define T(a, b, c, d, e, f, g, h) 64 - a, 64 - b, 64 - c, 64 - d, 64 - e, 64 - f, 64 - g, 64 - h
static const uint8_t IP_shuffle[] = {
T(58, 50, 42, 34, 26, 18, 10, 2),
T(60, 52, 44, 36, 28, 20, 12, 4),
T(62, 54, 46, 38, 30, 22, 14, 6),
T(64, 56, 48, 40, 32, 24, 16, 8),
T(57, 49, 41, 33, 25, 17, 9, 1),
T(59, 51, 43, 35, 27, 19, 11, 3),
T(61, 53, 45, 37, 29, 21, 13, 5),
T(63, 55, 47, 39, 31, 23, 15, 7)
};
#undef T
#if CONFIG_SMALL || defined(GENTABLES)
#define T(a, b, c, d) 32 - a, 32 - b, 32 - c, 32 - d
static const uint8_t P_shuffle[] = {
T(16, 7, 20, 21),
T(29, 12, 28, 17),
T( 1, 15, 23, 26),
T( 5, 18, 31, 10),
T( 2, 8, 24, 14),
T(32, 27, 3, 9),
T(19, 13, 30, 6),
T(22, 11, 4, 25)
};
#undef T
#endif
#define T(a, b, c, d, e, f, g) 64 - a, 64 - b, 64 - c, 64 - d, 64 - e, 64 - f, 64 - g
static const uint8_t PC1_shuffle[] = {
T(57, 49, 41, 33, 25, 17, 9),
T( 1, 58, 50, 42, 34, 26, 18),
T(10, 2, 59, 51, 43, 35, 27),
T(19, 11, 3, 60, 52, 44, 36),
T(63, 55, 47, 39, 31, 23, 15),
T( 7, 62, 54, 46, 38, 30, 22),
T(14, 6, 61, 53, 45, 37, 29),
T(21, 13, 5, 28, 20, 12, 4)
};
#undef T
#define T(a, b, c, d, e, f) 56 - a, 56 - b, 56 - c, 56 - d, 56 - e, 56 - f
static const uint8_t PC2_shuffle[] = {
T(14, 17, 11, 24, 1, 5),
T( 3, 28, 15, 6, 21, 10),
T(23, 19, 12, 4, 26, 8),
T(16, 7, 27, 20, 13, 2),
T(41, 52, 31, 37, 47, 55),
T(30, 40, 51, 45, 33, 48),
T(44, 49, 39, 56, 34, 53),
T(46, 42, 50, 36, 29, 32)
};
#undef T
#if CONFIG_SMALL
static const uint8_t S_boxes[8][32] = {
{ 0x0e, 0xf4, 0x7d, 0x41, 0xe2, 0x2f, 0xdb, 0x18, 0xa3, 0x6a, 0xc6, 0xbc, 0x95, 0x59, 0x30, 0x87,
0xf4, 0xc1, 0x8e, 0x28, 0x4d, 0x96, 0x12, 0x7b, 0x5f, 0xbc, 0x39, 0xe7, 0xa3, 0x0a, 0x65, 0xd0, },
{ 0x3f, 0xd1, 0x48, 0x7e, 0xf6, 0x2b, 0x83, 0xe4, 0xc9, 0x07, 0x12, 0xad, 0x6c, 0x90, 0xb5, 0x5a,
0xd0, 0x8e, 0xa7, 0x1b, 0x3a, 0xf4, 0x4d, 0x21, 0xb5, 0x68, 0x7c, 0xc6, 0x09, 0x53, 0xe2, 0x9f, },
{ 0xda, 0x70, 0x09, 0x9e, 0x36, 0x43, 0x6f, 0xa5, 0x21, 0x8d, 0x5c, 0xe7, 0xcb, 0xb4, 0xf2, 0x18,
0x1d, 0xa6, 0xd4, 0x09, 0x68, 0x9f, 0x83, 0x70, 0x4b, 0xf1, 0xe2, 0x3c, 0xb5, 0x5a, 0x2e, 0xc7, },
{ 0xd7, 0x8d, 0xbe, 0x53, 0x60, 0xf6, 0x09, 0x3a, 0x41, 0x72, 0x28, 0xc5, 0x1b, 0xac, 0xe4, 0x9f,
0x3a, 0xf6, 0x09, 0x60, 0xac, 0x1b, 0xd7, 0x8d, 0x9f, 0x41, 0x53, 0xbe, 0xc5, 0x72, 0x28, 0xe4, },
{ 0xe2, 0xbc, 0x24, 0xc1, 0x47, 0x7a, 0xdb, 0x16, 0x58, 0x05, 0xf3, 0xaf, 0x3d, 0x90, 0x8e, 0x69,
0xb4, 0x82, 0xc1, 0x7b, 0x1a, 0xed, 0x27, 0xd8, 0x6f, 0xf9, 0x0c, 0x95, 0xa6, 0x43, 0x50, 0x3e, },
{ 0xac, 0xf1, 0x4a, 0x2f, 0x79, 0xc2, 0x96, 0x58, 0x60, 0x1d, 0xd3, 0xe4, 0x0e, 0xb7, 0x35, 0x8b,
0x49, 0x3e, 0x2f, 0xc5, 0x92, 0x58, 0xfc, 0xa3, 0xb7, 0xe0, 0x14, 0x7a, 0x61, 0x0d, 0x8b, 0xd6, },
{ 0xd4, 0x0b, 0xb2, 0x7e, 0x4f, 0x90, 0x18, 0xad, 0xe3, 0x3c, 0x59, 0xc7, 0x25, 0xfa, 0x86, 0x61,
0x61, 0xb4, 0xdb, 0x8d, 0x1c, 0x43, 0xa7, 0x7e, 0x9a, 0x5f, 0x06, 0xf8, 0xe0, 0x25, 0x39, 0xc2, },
{ 0x1d, 0xf2, 0xd8, 0x84, 0xa6, 0x3f, 0x7b, 0x41, 0xca, 0x59, 0x63, 0xbe, 0x05, 0xe0, 0x9c, 0x27,
0x27, 0x1b, 0xe4, 0x71, 0x49, 0xac, 0x8e, 0xd2, 0xf0, 0xc6, 0x9a, 0x0d, 0x3f, 0x53, 0x65, 0xb8,
}
};
#else
/**
* This table contains the results of applying both the S-box and P-shuffle.
* It can be regenerated by compiling tests/des.c with "-DCONFIG_SMALL -DGENTABLES".
*/
static const uint32_t S_boxes_P_shuffle[8][64] = {
{ 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000,
0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002,
0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202,
0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000,
0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200,
0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202,
0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200,
0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002, },
{ 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010,
0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010,
0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000,
0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010,
0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000,
0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000,
0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010,
0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000, },
{ 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100,
0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104,
0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104,
0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000,
0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000,
0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004,
0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004,
0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100, },
{ 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000,
0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000,
0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040,
0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040,
0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000,
0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040,
0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040,
0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040, },
{ 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000,
0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000,
0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080,
0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080,
0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080,
0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000,
0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000,
0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080, },
{ 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000,
0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008,
0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008,
0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000,
0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008,
0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000,
0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008,
0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008, },
{ 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400,
0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401,
0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001,
0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400,
0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001,
0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400,
0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401,
0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001, },
{ 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000,
0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020,
0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800,
0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000,
0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820,
0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820,
0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000,
0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800, },
};
#endif
static uint64_t shuffle(uint64_t in, const uint8_t *shuffle, int shuffle_len)
{
int i;
uint64_t res = 0;
for (i = 0; i < shuffle_len; i++)
res += res + ((in >> *shuffle++) & 1);
return res;
}
static uint64_t shuffle_inv(uint64_t in, const uint8_t *shuffle, int shuffle_len)
{
int i;
uint64_t res = 0;
shuffle += shuffle_len - 1;
for (i = 0; i < shuffle_len; i++) {
res |= (in & 1) << *shuffle--;
in >>= 1;
}
return res;
}
static uint32_t f_func(uint32_t r, uint64_t k)
{
int i;
uint32_t out = 0;
// rotate to get first part of E-shuffle in the lowest 6 bits
r = (r << 1) | (r >> 31);
// apply S-boxes, those compress the data again from 8 * 6 to 8 * 4 bits
for (i = 7; i >= 0; i--) {
uint8_t tmp = (r ^ k) & 0x3f;
#if CONFIG_SMALL
uint8_t v = S_boxes[i][tmp >> 1];
if (tmp & 1)
v >>= 4;
out = (out >> 4) | (v << 28);
#else
out |= S_boxes_P_shuffle[i][tmp];
#endif
// get next 6 bits of E-shuffle and round key k into the lowest bits
r = (r >> 4) | (r << 28);
k >>= 6;
}
#if CONFIG_SMALL
out = shuffle(out, P_shuffle, sizeof(P_shuffle));
#endif
return out;
}
/**
* @brief rotate the two halves of the expanded 56 bit key each 1 bit left
*
* Note: the specification calls this "shift", so I kept it although
* it is confusing.
*/
static uint64_t key_shift_left(uint64_t CDn)
{
uint64_t carries = (CDn >> 27) & 0x10000001;
CDn <<= 1;
CDn &= ~0x10000001;
CDn |= carries;
return CDn;
}
static void gen_roundkeys(uint64_t K[16], uint64_t key)
{
int i;
// discard parity bits from key and shuffle it into C and D parts
uint64_t CDn = shuffle(key, PC1_shuffle, sizeof(PC1_shuffle));
// generate round keys
for (i = 0; i < 16; i++) {
CDn = key_shift_left(CDn);
if (i > 1 && i != 8 && i != 15)
CDn = key_shift_left(CDn);
K[i] = shuffle(CDn, PC2_shuffle, sizeof(PC2_shuffle));
}
}
static uint64_t des_encdec(uint64_t in, uint64_t K[16], int decrypt)
{
int i;
// used to apply round keys in reverse order for decryption
decrypt = decrypt ? 15 : 0;
// shuffle irrelevant to security but to ease hardware implementations
in = shuffle(in, IP_shuffle, sizeof(IP_shuffle));
for (i = 0; i < 16; i++) {
uint32_t f_res;
f_res = f_func(in, K[decrypt ^ i]);
in = (in << 32) | (in >> 32);
in ^= f_res;
}
in = (in << 32) | (in >> 32);
// reverse shuffle used to ease hardware implementations
in = shuffle_inv(in, IP_shuffle, sizeof(IP_shuffle));
return in;
}
AVDES *av_des_alloc(void)
{
return av_mallocz(sizeof(struct AVDES));
}
int av_des_init(AVDES *d, const uint8_t *key, int key_bits, av_unused int decrypt) {
if (key_bits != 64 && key_bits != 192)
return AVERROR(EINVAL);
d->triple_des = key_bits > 64;
gen_roundkeys(d->round_keys[0], AV_RB64(key));
if (d->triple_des) {
gen_roundkeys(d->round_keys[1], AV_RB64(key + 8));
gen_roundkeys(d->round_keys[2], AV_RB64(key + 16));
}
return 0;
}
static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const uint8_t *src,
int count, uint8_t *iv, int decrypt, int mac)
{
uint64_t iv_val = iv ? AV_RB64(iv) : 0;
while (count-- > 0) {
uint64_t dst_val;
uint64_t src_val = src ? AV_RB64(src) : 0;
if (decrypt) {
uint64_t tmp = src_val;
if (d->triple_des) {
src_val = des_encdec(src_val, d->round_keys[2], 1);
src_val = des_encdec(src_val, d->round_keys[1], 0);
}
dst_val = des_encdec(src_val, d->round_keys[0], 1) ^ iv_val;
iv_val = iv ? tmp : 0;
} else {
dst_val = des_encdec(src_val ^ iv_val, d->round_keys[0], 0);
if (d->triple_des) {
dst_val = des_encdec(dst_val, d->round_keys[1], 1);
dst_val = des_encdec(dst_val, d->round_keys[2], 0);
}
iv_val = iv ? dst_val : 0;
}
AV_WB64(dst, dst_val);
src += 8;
if (!mac)
dst += 8;
}
if (iv)
AV_WB64(iv, iv_val);
}
void av_des_crypt(AVDES *d, uint8_t *dst, const uint8_t *src,
int count, uint8_t *iv, int decrypt)
{
av_des_crypt_mac(d, dst, src, count, iv, decrypt, 0);
}
void av_des_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count)
{
av_des_crypt_mac(d, dst, src, count, (uint8_t[8]) { 0 }, 0, 1);
}

View file

@ -0,0 +1,77 @@
/*
* DES encryption/decryption
* Copyright (c) 2007 Reimar Doeffinger
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_DES_H
#define AVUTIL_DES_H
#include <stdint.h>
/**
* @defgroup lavu_des DES
* @ingroup lavu_crypto
* @{
*/
typedef struct AVDES {
uint64_t round_keys[3][16];
int triple_des;
} AVDES;
/**
* Allocate an AVDES context.
*/
AVDES *av_des_alloc(void);
/**
* @brief Initializes an AVDES context.
*
* @param key_bits must be 64 or 192
* @param decrypt 0 for encryption/CBC-MAC, 1 for decryption
* @return zero on success, negative value otherwise
*/
int av_des_init(struct AVDES *d, const uint8_t *key, int key_bits, int decrypt);
/**
* @brief Encrypts / decrypts using the DES algorithm.
*
* @param count number of 8 byte blocks
* @param dst destination array, can be equal to src, must be 8-byte aligned
* @param src source array, can be equal to dst, must be 8-byte aligned, may be NULL
* @param iv initialization vector for CBC mode, if NULL then ECB will be used,
* must be 8-byte aligned
* @param decrypt 0 for encryption, 1 for decryption
*/
void av_des_crypt(struct AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt);
/**
* @brief Calculates CBC-MAC using the DES algorithm.
*
* @param count number of 8 byte blocks
* @param dst destination array, can be equal to src, must be 8-byte aligned
* @param src source array, can be equal to dst, must be 8-byte aligned, may be NULL
*/
void av_des_mac(struct AVDES *d, uint8_t *dst, const uint8_t *src, int count);
/**
* @}
*/
#endif /* AVUTIL_DES_H */

View file

@ -0,0 +1,272 @@
/*
* copyright (c) 2009 Michael Niedermayer
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <string.h>
#include "avstring.h"
#include "dict.h"
#include "internal.h"
#include "mem.h"
#include "time_internal.h"
#include "bprint.h"
struct AVDictionary {
int count;
AVDictionaryEntry *elems;
};
int av_dict_count(const AVDictionary *m)
{
return m ? m->count : 0;
}
AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
const AVDictionaryEntry *prev, int flags)
{
unsigned int i, j;
if (!m)
return NULL;
if (prev)
i = prev - m->elems + 1;
else
i = 0;
for (; i < m->count; i++) {
const char *s = m->elems[i].key;
if (flags & AV_DICT_MATCH_CASE)
for (j = 0; s[j] == key[j] && key[j]; j++)
;
else
for (j = 0; av_toupper(s[j]) == av_toupper(key[j]) && key[j]; j++)
;
if (key[j])
continue;
if (s[j] && !(flags & AV_DICT_IGNORE_SUFFIX))
continue;
return &m->elems[i];
}
return NULL;
}
int av_dict_set(AVDictionary **pm, const char *key, const char *value,
int flags)
{
AVDictionary *m = *pm;
AVDictionaryEntry *tag = NULL;
char *oldval = NULL, *copy_key = NULL, *copy_value = NULL;
if (!(flags & AV_DICT_MULTIKEY)) {
tag = av_dict_get(m, key, NULL, flags);
}
if (flags & AV_DICT_DONT_STRDUP_KEY)
copy_key = (void *)key;
else
copy_key = av_strdup(key);
if (flags & AV_DICT_DONT_STRDUP_VAL)
copy_value = (void *)value;
else if (copy_key)
copy_value = av_strdup(value);
if (!m)
m = *pm = av_mallocz(sizeof(*m));
if (!m || (key && !copy_key) || (value && !copy_value))
goto err_out;
if (tag) {
if (flags & AV_DICT_DONT_OVERWRITE) {
av_free(copy_key);
av_free(copy_value);
return 0;
}
if (flags & AV_DICT_APPEND)
oldval = tag->value;
else
av_free(tag->value);
av_free(tag->key);
*tag = m->elems[--m->count];
} else if (copy_value) {
AVDictionaryEntry *tmp = av_realloc(m->elems,
(m->count + 1) * sizeof(*m->elems));
if (!tmp)
goto err_out;
m->elems = tmp;
}
if (copy_value) {
m->elems[m->count].key = copy_key;
m->elems[m->count].value = copy_value;
if (oldval && flags & AV_DICT_APPEND) {
size_t len = strlen(oldval) + strlen(copy_value) + 1;
char *newval = av_mallocz(len);
if (!newval)
goto err_out;
av_strlcat(newval, oldval, len);
av_freep(&oldval);
av_strlcat(newval, copy_value, len);
m->elems[m->count].value = newval;
av_freep(&copy_value);
}
m->count++;
} else {
av_freep(&copy_key);
}
if (!m->count) {
av_freep(&m->elems);
av_freep(pm);
}
return 0;
err_out:
if (m && !m->count) {
av_freep(&m->elems);
av_freep(pm);
}
av_free(copy_key);
av_free(copy_value);
return AVERROR(ENOMEM);
}
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value,
int flags)
{
char valuestr[22];
snprintf(valuestr, sizeof(valuestr), "%"PRId64, value);
flags &= ~AV_DICT_DONT_STRDUP_VAL;
return av_dict_set(pm, key, valuestr, flags);
}
static int parse_key_value_pair(AVDictionary **pm, const char **buf,
const char *key_val_sep, const char *pairs_sep,
int flags)
{
char *key = av_get_token(buf, key_val_sep);
char *val = NULL;
int ret;
if (key && *key && strspn(*buf, key_val_sep)) {
(*buf)++;
val = av_get_token(buf, pairs_sep);
}
if (key && *key && val && *val)
ret = av_dict_set(pm, key, val, flags);
else
ret = AVERROR(EINVAL);
av_freep(&key);
av_freep(&val);
return ret;
}
int av_dict_parse_string(AVDictionary **pm, const char *str,
const char *key_val_sep, const char *pairs_sep,
int flags)
{
int ret;
if (!str)
return 0;
/* ignore STRDUP flags */
flags &= ~(AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
while (*str) {
if ((ret = parse_key_value_pair(pm, &str, key_val_sep, pairs_sep, flags)) < 0)
return ret;
if (*str)
str++;
}
return 0;
}
void av_dict_free(AVDictionary **pm)
{
AVDictionary *m = *pm;
if (m) {
while (m->count--) {
av_freep(&m->elems[m->count].key);
av_freep(&m->elems[m->count].value);
}
av_freep(&m->elems);
}
av_freep(pm);
}
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
{
AVDictionaryEntry *t = NULL;
while ((t = av_dict_get(src, "", t, AV_DICT_IGNORE_SUFFIX))) {
int ret = av_dict_set(dst, t->key, t->value, flags);
if (ret < 0)
return ret;
}
return 0;
}
int av_dict_get_string(const AVDictionary *m, char **buffer,
const char key_val_sep, const char pairs_sep)
{
AVDictionaryEntry *t = NULL;
AVBPrint bprint;
int cnt = 0;
char special_chars[] = {pairs_sep, key_val_sep, '\0'};
if (!buffer || pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep ||
pairs_sep == '\\' || key_val_sep == '\\')
return AVERROR(EINVAL);
if (!av_dict_count(m)) {
*buffer = av_strdup("");
return *buffer ? 0 : AVERROR(ENOMEM);
}
av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) {
if (cnt++)
av_bprint_append_data(&bprint, &pairs_sep, 1);
av_bprint_escape(&bprint, t->key, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
av_bprint_append_data(&bprint, &key_val_sep, 1);
av_bprint_escape(&bprint, t->value, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
}
return av_bprint_finalize(&bprint, buffer);
}
int avpriv_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestamp)
{
time_t seconds = timestamp / 1000000;
struct tm *ptm, tmbuf;
ptm = gmtime_r(&seconds, &tmbuf);
if (ptm) {
char buf[32];
if (!strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", ptm))
return AVERROR_EXTERNAL;
av_strlcatf(buf, sizeof(buf), ".%06dZ", (int)(timestamp % 1000000));
return av_dict_set(dict, key, buf, 0);
} else {
return AVERROR_EXTERNAL;
}
}

View file

@ -0,0 +1,200 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Public dictionary API.
* @deprecated
* AVDictionary is provided for compatibility with libav. It is both in
* implementation as well as API inefficient. It does not scale and is
* extremely slow with large dictionaries.
* It is recommended that new code uses our tree container from tree.c/h
* where applicable, which uses AVL trees to achieve O(log n) performance.
*/
#ifndef AVUTIL_DICT_H
#define AVUTIL_DICT_H
#include <stdint.h>
#include "version.h"
/**
* @addtogroup lavu_dict AVDictionary
* @ingroup lavu_data
*
* @brief Simple key:value store
*
* @{
* Dictionaries are used for storing key:value pairs. To create
* an AVDictionary, simply pass an address of a NULL pointer to
* av_dict_set(). NULL can be used as an empty dictionary wherever
* a pointer to an AVDictionary is required.
* Use av_dict_get() to retrieve an entry or iterate over all
* entries and finally av_dict_free() to free the dictionary
* and all its contents.
*
@code
AVDictionary *d = NULL; // "create" an empty dictionary
AVDictionaryEntry *t = NULL;
av_dict_set(&d, "foo", "bar", 0); // add an entry
char *k = av_strdup("key"); // if your strings are already allocated,
char *v = av_strdup("value"); // you can avoid copying them like this
av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
while (t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX)) {
<....> // iterate over all entries in d
}
av_dict_free(&d);
@endcode
*/
#define AV_DICT_MATCH_CASE 1 /**< Only get an entry with exact-case key match. Only relevant in av_dict_get(). */
#define AV_DICT_IGNORE_SUFFIX 2 /**< Return first entry in a dictionary whose first part corresponds to the search key,
ignoring the suffix of the found key string. Only relevant in av_dict_get(). */
#define AV_DICT_DONT_STRDUP_KEY 4 /**< Take ownership of a key that's been
allocated with av_malloc() or another memory allocation function. */
#define AV_DICT_DONT_STRDUP_VAL 8 /**< Take ownership of a value that's been
allocated with av_malloc() or another memory allocation function. */
#define AV_DICT_DONT_OVERWRITE 16 ///< Don't overwrite existing entries.
#define AV_DICT_APPEND 32 /**< If the entry already exists, append to it. Note that no
delimiter is added, the strings are simply concatenated. */
#define AV_DICT_MULTIKEY 64 /**< Allow to store several equal keys in the dictionary */
typedef struct AVDictionaryEntry {
char *key;
char *value;
} AVDictionaryEntry;
typedef struct AVDictionary AVDictionary;
/**
* Get a dictionary entry with matching key.
*
* The returned entry key or value must not be changed, or it will
* cause undefined behavior.
*
* To iterate through all the dictionary entries, you can set the matching key
* to the null string "" and set the AV_DICT_IGNORE_SUFFIX flag.
*
* @param prev Set to the previous matching element to find the next.
* If set to NULL the first matching element is returned.
* @param key matching key
* @param flags a collection of AV_DICT_* flags controlling how the entry is retrieved
* @return found entry or NULL in case no matching entry was found in the dictionary
*/
AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
const AVDictionaryEntry *prev, int flags);
/**
* Get number of entries in dictionary.
*
* @param m dictionary
* @return number of entries in dictionary
*/
int av_dict_count(const AVDictionary *m);
/**
* Set the given entry in *pm, overwriting an existing entry.
*
* Note: If AV_DICT_DONT_STRDUP_KEY or AV_DICT_DONT_STRDUP_VAL is set,
* these arguments will be freed on error.
*
* Warning: Adding a new entry to a dictionary invalidates all existing entries
* previously returned with av_dict_get.
*
* @param pm pointer to a pointer to a dictionary struct. If *pm is NULL
* a dictionary struct is allocated and put in *pm.
* @param key entry key to add to *pm (will either be av_strduped or added as a new key depending on flags)
* @param value entry value to add to *pm (will be av_strduped or added as a new key depending on flags).
* Passing a NULL value will cause an existing entry to be deleted.
* @return >= 0 on success otherwise an error code <0
*/
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags);
/**
* Convenience wrapper for av_dict_set that converts the value to a string
* and stores it.
*
* Note: If AV_DICT_DONT_STRDUP_KEY is set, key will be freed on error.
*/
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags);
/**
* Parse the key/value pairs list and add the parsed entries to a dictionary.
*
* In case of failure, all the successfully set entries are stored in
* *pm. You may need to manually free the created dictionary.
*
* @param key_val_sep a 0-terminated list of characters used to separate
* key from value
* @param pairs_sep a 0-terminated list of characters used to separate
* two pairs from each other
* @param flags flags to use when adding to dictionary.
* AV_DICT_DONT_STRDUP_KEY and AV_DICT_DONT_STRDUP_VAL
* are ignored since the key/value tokens will always
* be duplicated.
* @return 0 on success, negative AVERROR code on failure
*/
int av_dict_parse_string(AVDictionary **pm, const char *str,
const char *key_val_sep, const char *pairs_sep,
int flags);
/**
* Copy entries from one AVDictionary struct into another.
* @param dst pointer to a pointer to a AVDictionary struct. If *dst is NULL,
* this function will allocate a struct for you and put it in *dst
* @param src pointer to source AVDictionary struct
* @param flags flags to use when setting entries in *dst
* @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag
* @return 0 on success, negative AVERROR code on failure. If dst was allocated
* by this function, callers should free the associated memory.
*/
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags);
/**
* Free all the memory allocated for an AVDictionary struct
* and all keys and values.
*/
void av_dict_free(AVDictionary **m);
/**
* Get dictionary entries as a string.
*
* Create a string containing dictionary's entries.
* Such string may be passed back to av_dict_parse_string().
* @note String is escaped with backslashes ('\').
*
* @param[in] m dictionary
* @param[out] buffer Pointer to buffer that will be allocated with string containg entries.
* Buffer must be freed by the caller when is no longer needed.
* @param[in] key_val_sep character used to separate key from value
* @param[in] pairs_sep character used to separate two pairs from each other
* @return >= 0 on success, negative on error
* @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same.
*/
int av_dict_get_string(const AVDictionary *m, char **buffer,
const char key_val_sep, const char pairs_sep);
/**
* @}
*/
#endif /* AVUTIL_DICT_H */

View file

@ -0,0 +1,73 @@
/*
* Copyright (c) 2014 Vittorio Giovara <vittorio.giovara@gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include <string.h>
#include <math.h>
#include "display.h"
#include "mathematics.h"
// fixed point to double
#define CONV_FP(x) ((double) (x)) / (1 << 16)
// double to fixed point
#define CONV_DB(x) (int32_t) ((x) * (1 << 16))
double av_display_rotation_get(const int32_t matrix[9])
{
double rotation, scale[2];
scale[0] = hypot(CONV_FP(matrix[0]), CONV_FP(matrix[3]));
scale[1] = hypot(CONV_FP(matrix[1]), CONV_FP(matrix[4]));
if (scale[0] == 0.0 || scale[1] == 0.0)
return NAN;
rotation = atan2(CONV_FP(matrix[1]) / scale[1],
CONV_FP(matrix[0]) / scale[0]) * 180 / M_PI;
return -rotation;
}
void av_display_rotation_set(int32_t matrix[9], double angle)
{
double radians = -angle * M_PI / 180.0f;
double c = cos(radians);
double s = sin(radians);
memset(matrix, 0, 9 * sizeof(int32_t));
matrix[0] = CONV_DB(c);
matrix[1] = CONV_DB(-s);
matrix[3] = CONV_DB(s);
matrix[4] = CONV_DB(c);
matrix[8] = 1 << 30;
}
void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip)
{
int i;
const int flip[] = { 1 - 2 * (!!hflip), 1 - 2 * (!!vflip), 1 };
if (hflip || vflip)
for (i = 0; i < 9; i++)
matrix[i] *= flip[i % 3];
}

View file

@ -0,0 +1,114 @@
/*
* Copyright (c) 2014 Vittorio Giovara <vittorio.giovara@gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Display matrix
*/
#ifndef AVUTIL_DISPLAY_H
#define AVUTIL_DISPLAY_H
#include <stdint.h>
#include "common.h"
/**
* @addtogroup lavu_video
* @{
*
* @defgroup lavu_video_display Display transformation matrix functions
* @{
*/
/**
* @addtogroup lavu_video_display
* The display transformation matrix specifies an affine transformation that
* should be applied to video frames for correct presentation. It is compatible
* with the matrices stored in the ISO/IEC 14496-12 container format.
*
* The data is a 3x3 matrix represented as a 9-element array:
*
* @code{.unparsed}
* | a b u |
* (a, b, u, c, d, v, x, y, w) -> | c d v |
* | x y w |
* @endcode
*
* All numbers are stored in native endianness, as 16.16 fixed-point values,
* except for u, v and w, which are stored as 2.30 fixed-point values.
*
* The transformation maps a point (p, q) in the source (pre-transformation)
* frame to the point (p', q') in the destination (post-transformation) frame as
* follows:
*
* @code{.unparsed}
* | a b u |
* (p, q, 1) . | c d v | = z * (p', q', 1)
* | x y w |
* @endcode
*
* The transformation can also be more explicitly written in components as
* follows:
*
* @code{.unparsed}
* p' = (a * p + c * q + x) / z;
* q' = (b * p + d * q + y) / z;
* z = u * p + v * q + w
* @endcode
*/
/**
* Extract the rotation component of the transformation matrix.
*
* @param matrix the transformation matrix
* @return the angle (in degrees) by which the transformation rotates the frame
* counterclockwise. The angle will be in range [-180.0, 180.0],
* or NaN if the matrix is singular.
*
* @note floating point numbers are inherently inexact, so callers are
* recommended to round the return value to nearest integer before use.
*/
double av_display_rotation_get(const int32_t matrix[9]);
/**
* Initialize a transformation matrix describing a pure counterclockwise
* rotation by the specified angle (in degrees).
*
* @param matrix an allocated transformation matrix (will be fully overwritten
* by this function)
* @param angle rotation angle in degrees.
*/
void av_display_rotation_set(int32_t matrix[9], double angle);
/**
* Flip the input matrix horizontally and/or vertically.
*
* @param matrix an allocated transformation matrix
* @param hflip whether the matrix should be flipped horizontally
* @param vflip whether the matrix should be flipped vertically
*/
void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip);
/**
* @}
* @}
*/
#endif /* AVUTIL_DISPLAY_H */

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2014 Tim Walker <tdskywalker@gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "downmix_info.h"
#include "frame.h"
AVDownmixInfo *av_downmix_info_update_side_data(AVFrame *frame)
{
AVFrameSideData *side_data;
side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_DOWNMIX_INFO);
if (!side_data)
side_data = av_frame_new_side_data(frame, AV_FRAME_DATA_DOWNMIX_INFO,
sizeof(AVDownmixInfo));
if (!side_data)
return NULL;
return (AVDownmixInfo*)side_data->data;
}

View file

@ -0,0 +1,115 @@
/*
* Copyright (c) 2014 Tim Walker <tdskywalker@gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_DOWNMIX_INFO_H
#define AVUTIL_DOWNMIX_INFO_H
#include "frame.h"
/**
* @file
* audio downmix medatata
*/
/**
* @addtogroup lavu_audio
* @{
*/
/**
* @defgroup downmix_info Audio downmix metadata
* @{
*/
/**
* Possible downmix types.
*/
enum AVDownmixType {
AV_DOWNMIX_TYPE_UNKNOWN, /**< Not indicated. */
AV_DOWNMIX_TYPE_LORO, /**< Lo/Ro 2-channel downmix (Stereo). */
AV_DOWNMIX_TYPE_LTRT, /**< Lt/Rt 2-channel downmix, Dolby Surround compatible. */
AV_DOWNMIX_TYPE_DPLII, /**< Lt/Rt 2-channel downmix, Dolby Pro Logic II compatible. */
AV_DOWNMIX_TYPE_NB /**< Number of downmix types. Not part of ABI. */
};
/**
* This structure describes optional metadata relevant to a downmix procedure.
*
* All fields are set by the decoder to the value indicated in the audio
* bitstream (if present), or to a "sane" default otherwise.
*/
typedef struct AVDownmixInfo {
/**
* Type of downmix preferred by the mastering engineer.
*/
enum AVDownmixType preferred_downmix_type;
/**
* Absolute scale factor representing the nominal level of the center
* channel during a regular downmix.
*/
double center_mix_level;
/**
* Absolute scale factor representing the nominal level of the center
* channel during an Lt/Rt compatible downmix.
*/
double center_mix_level_ltrt;
/**
* Absolute scale factor representing the nominal level of the surround
* channels during a regular downmix.
*/
double surround_mix_level;
/**
* Absolute scale factor representing the nominal level of the surround
* channels during an Lt/Rt compatible downmix.
*/
double surround_mix_level_ltrt;
/**
* Absolute scale factor representing the level at which the LFE data is
* mixed into L/R channels during downmixing.
*/
double lfe_mix_level;
} AVDownmixInfo;
/**
* Get a frame's AV_FRAME_DATA_DOWNMIX_INFO side data for editing.
*
* If the side data is absent, it is created and added to the frame.
*
* @param frame the frame for which the side data is to be obtained or created
*
* @return the AVDownmixInfo structure to be edited by the caller, or NULL if
* the structure cannot be allocated.
*/
AVDownmixInfo *av_downmix_info_update_side_data(AVFrame *frame);
/**
* @}
*/
/**
* @}
*/
#endif /* AVUTIL_DOWNMIX_INFO_H */

View file

@ -0,0 +1,70 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_DYNARRAY_H
#define AVUTIL_DYNARRAY_H
#include "log.h"
#include "mem.h"
/**
* Add an element to a dynamic array.
*
* The array is reallocated when its number of elements reaches powers of 2.
* Therefore, the amortized cost of adding an element is constant.
*
* In case of success, the pointer to the array is updated in order to
* point to the new grown array, and the size is incremented.
*
* @param av_size_max maximum size of the array, usually the MAX macro of
* the type of the size
* @param av_elt_size size of the elements in the array, in bytes
* @param av_array pointer to the array, must be a lvalue
* @param av_size size of the array, must be an integer lvalue
* @param av_success statement to execute on success; at this point, the
* size variable is not yet incremented
* @param av_failure statement to execute on failure; if this happens, the
* array and size are not changed; the statement can end
* with a return or a goto
*/
#define FF_DYNARRAY_ADD(av_size_max, av_elt_size, av_array, av_size, \
av_success, av_failure) \
do { \
size_t av_size_new = (av_size); \
if (!((av_size) & ((av_size) - 1))) { \
av_size_new = (av_size) ? (av_size) << 1 : 1; \
if (av_size_new > (av_size_max) / (av_elt_size)) { \
av_size_new = 0; \
} else { \
void *av_array_new = \
av_realloc((av_array), av_size_new * (av_elt_size)); \
if (!av_array_new) \
av_size_new = 0; \
else \
(av_array) = av_array_new; \
} \
} \
if (av_size_new) { \
{ av_success } \
(av_size)++; \
} else { \
av_failure \
} \
} while (0)
#endif /* AVUTIL_DYNARRAY_H */

View file

@ -0,0 +1,339 @@
/**
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "encryption_info.h"
#include "mem.h"
#include "intreadwrite.h"
#define FF_ENCRYPTION_INFO_EXTRA 24
// The format of the AVEncryptionInfo side data:
// u32be scheme
// u32be crypt_byte_block
// u32be skip_byte_block
// u32be key_id_size
// u32be iv_size
// u32be subsample_count
// u8[key_id_size] key_id
// u8[iv_size] iv
// {
// u32be bytes_of_clear_data
// u32be bytes_of_protected_data
// }[subsample_count]
AVEncryptionInfo *av_encryption_info_alloc(uint32_t subsample_count, uint32_t key_id_size, uint32_t iv_size)
{
AVEncryptionInfo *info;
info = av_mallocz(sizeof(*info));
if (!info)
return NULL;
info->key_id = av_mallocz(key_id_size);
info->key_id_size = key_id_size;
info->iv = av_mallocz(iv_size);
info->iv_size = iv_size;
info->subsamples = av_mallocz_array(subsample_count, sizeof(*info->subsamples));
info->subsample_count = subsample_count;
// Allow info->subsamples to be NULL if there are no subsamples.
if (!info->key_id || !info->iv || (!info->subsamples && subsample_count)) {
av_encryption_info_free(info);
return NULL;
}
return info;
}
AVEncryptionInfo *av_encryption_info_clone(const AVEncryptionInfo *info)
{
AVEncryptionInfo *ret;
ret = av_encryption_info_alloc(info->subsample_count, info->key_id_size, info->iv_size);
if (!ret)
return NULL;
ret->scheme = info->scheme;
ret->crypt_byte_block = info->crypt_byte_block;
ret->skip_byte_block = info->skip_byte_block;
memcpy(ret->iv, info->iv, info->iv_size);
memcpy(ret->key_id, info->key_id, info->key_id_size);
memcpy(ret->subsamples, info->subsamples, sizeof(*info->subsamples) * info->subsample_count);
return ret;
}
void av_encryption_info_free(AVEncryptionInfo *info)
{
if (info) {
av_free(info->key_id);
av_free(info->iv);
av_free(info->subsamples);
av_free(info);
}
}
AVEncryptionInfo *av_encryption_info_get_side_data(const uint8_t* buffer, size_t size)
{
AVEncryptionInfo *info;
uint64_t key_id_size, iv_size, subsample_count, i;
if (!buffer || size < FF_ENCRYPTION_INFO_EXTRA)
return NULL;
key_id_size = AV_RB32(buffer + 12);
iv_size = AV_RB32(buffer + 16);
subsample_count = AV_RB32(buffer + 20);
if (size < FF_ENCRYPTION_INFO_EXTRA + key_id_size + iv_size + subsample_count * 8)
return NULL;
info = av_encryption_info_alloc(subsample_count, key_id_size, iv_size);
if (!info)
return NULL;
info->scheme = AV_RB32(buffer);
info->crypt_byte_block = AV_RB32(buffer + 4);
info->skip_byte_block = AV_RB32(buffer + 8);
memcpy(info->key_id, buffer + 24, key_id_size);
memcpy(info->iv, buffer + key_id_size + 24, iv_size);
buffer += key_id_size + iv_size + 24;
for (i = 0; i < subsample_count; i++) {
info->subsamples[i].bytes_of_clear_data = AV_RB32(buffer);
info->subsamples[i].bytes_of_protected_data = AV_RB32(buffer + 4);
buffer += 8;
}
return info;
}
uint8_t *av_encryption_info_add_side_data(const AVEncryptionInfo *info, size_t *size)
{
uint8_t *buffer, *cur_buffer;
uint32_t i;
if (UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA < info->key_id_size ||
UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size < info->iv_size ||
(UINT32_MAX - FF_ENCRYPTION_INFO_EXTRA - info->key_id_size - info->iv_size) / 8 < info->subsample_count) {
return NULL;
}
*size = FF_ENCRYPTION_INFO_EXTRA + info->key_id_size + info->iv_size +
(info->subsample_count * 8);
cur_buffer = buffer = av_malloc(*size);
if (!buffer)
return NULL;
AV_WB32(cur_buffer, info->scheme);
AV_WB32(cur_buffer + 4, info->crypt_byte_block);
AV_WB32(cur_buffer + 8, info->skip_byte_block);
AV_WB32(cur_buffer + 12, info->key_id_size);
AV_WB32(cur_buffer + 16, info->iv_size);
AV_WB32(cur_buffer + 20, info->subsample_count);
cur_buffer += 24;
memcpy(cur_buffer, info->key_id, info->key_id_size);
cur_buffer += info->key_id_size;
memcpy(cur_buffer, info->iv, info->iv_size);
cur_buffer += info->iv_size;
for (i = 0; i < info->subsample_count; i++) {
AV_WB32(cur_buffer, info->subsamples[i].bytes_of_clear_data);
AV_WB32(cur_buffer + 4, info->subsamples[i].bytes_of_protected_data);
cur_buffer += 8;
}
return buffer;
}
// The format of the AVEncryptionInitInfo side data:
// u32be init_info_count
// {
// u32be system_id_size
// u32be num_key_ids
// u32be key_id_size
// u32be data_size
// u8[system_id_size] system_id
// u8[key_id_size][num_key_id] key_ids
// u8[data_size] data
// }[init_info_count]
#define FF_ENCRYPTION_INIT_INFO_EXTRA 16
AVEncryptionInitInfo *av_encryption_init_info_alloc(
uint32_t system_id_size, uint32_t num_key_ids, uint32_t key_id_size, uint32_t data_size)
{
AVEncryptionInitInfo *info;
uint32_t i;
info = av_mallocz(sizeof(*info));
if (!info)
return NULL;
info->system_id = av_mallocz(system_id_size);
info->system_id_size = system_id_size;
info->key_ids = key_id_size ? av_mallocz_array(num_key_ids, sizeof(*info->key_ids)) : NULL;
info->num_key_ids = num_key_ids;
info->key_id_size = key_id_size;
info->data = av_mallocz(data_size);
info->data_size = data_size;
// Allow pointers to be NULL if the size is 0.
if ((!info->system_id && system_id_size) || (!info->data && data_size) ||
(!info->key_ids && num_key_ids && key_id_size)) {
av_encryption_init_info_free(info);
return NULL;
}
if (key_id_size) {
for (i = 0; i < num_key_ids; i++) {
info->key_ids[i] = av_mallocz(key_id_size);
if (!info->key_ids[i]) {
av_encryption_init_info_free(info);
return NULL;
}
}
}
return info;
}
void av_encryption_init_info_free(AVEncryptionInitInfo *info)
{
uint32_t i;
if (info) {
for (i = 0; i < info->num_key_ids; i++) {
av_free(info->key_ids[i]);
}
av_encryption_init_info_free(info->next);
av_free(info->system_id);
av_free(info->key_ids);
av_free(info->data);
av_free(info);
}
}
AVEncryptionInitInfo *av_encryption_init_info_get_side_data(
const uint8_t *side_data, size_t side_data_size)
{
// |ret| tracks the front of the list, |info| tracks the back.
AVEncryptionInitInfo *ret = NULL, *info, *temp_info;
uint64_t system_id_size, num_key_ids, key_id_size, data_size, i, j;
uint64_t init_info_count;
if (!side_data || side_data_size < 4)
return NULL;
init_info_count = AV_RB32(side_data);
side_data += 4;
side_data_size -= 4;
for (i = 0; i < init_info_count; i++) {
if (side_data_size < FF_ENCRYPTION_INIT_INFO_EXTRA) {
av_encryption_init_info_free(ret);
return NULL;
}
system_id_size = AV_RB32(side_data);
num_key_ids = AV_RB32(side_data + 4);
key_id_size = AV_RB32(side_data + 8);
data_size = AV_RB32(side_data + 12);
// UINT32_MAX + UINT32_MAX + UINT32_MAX * UINT32_MAX == UINT64_MAX
if (side_data_size - FF_ENCRYPTION_INIT_INFO_EXTRA < system_id_size + data_size + num_key_ids * key_id_size) {
av_encryption_init_info_free(ret);
return NULL;
}
side_data += FF_ENCRYPTION_INIT_INFO_EXTRA;
side_data_size -= FF_ENCRYPTION_INIT_INFO_EXTRA;
temp_info = av_encryption_init_info_alloc(system_id_size, num_key_ids, key_id_size, data_size);
if (!temp_info) {
av_encryption_init_info_free(ret);
return NULL;
}
if (i == 0) {
info = ret = temp_info;
} else {
info->next = temp_info;
info = temp_info;
}
memcpy(info->system_id, side_data, system_id_size);
side_data += system_id_size;
side_data_size -= system_id_size;
for (j = 0; j < num_key_ids; j++) {
memcpy(info->key_ids[j], side_data, key_id_size);
side_data += key_id_size;
side_data_size -= key_id_size;
}
memcpy(info->data, side_data, data_size);
side_data += data_size;
side_data_size -= data_size;
}
return ret;
}
uint8_t *av_encryption_init_info_add_side_data(const AVEncryptionInitInfo *info, size_t *side_data_size)
{
const AVEncryptionInitInfo *cur_info;
uint8_t *buffer, *cur_buffer;
uint32_t i, init_info_count;
uint64_t temp_side_data_size;
temp_side_data_size = 4;
init_info_count = 0;
for (cur_info = info; cur_info; cur_info = cur_info->next) {
temp_side_data_size += (uint64_t)FF_ENCRYPTION_INIT_INFO_EXTRA + cur_info->system_id_size + cur_info->data_size;
if (init_info_count == UINT32_MAX || temp_side_data_size > UINT32_MAX) {
return NULL;
}
init_info_count++;
if (cur_info->num_key_ids) {
temp_side_data_size += (uint64_t)cur_info->num_key_ids * cur_info->key_id_size;
if (temp_side_data_size > UINT32_MAX) {
return NULL;
}
}
}
*side_data_size = temp_side_data_size;
cur_buffer = buffer = av_malloc(*side_data_size);
if (!buffer)
return NULL;
AV_WB32(cur_buffer, init_info_count);
cur_buffer += 4;
for (cur_info = info; cur_info; cur_info = cur_info->next) {
AV_WB32(cur_buffer, cur_info->system_id_size);
AV_WB32(cur_buffer + 4, cur_info->num_key_ids);
AV_WB32(cur_buffer + 8, cur_info->key_id_size);
AV_WB32(cur_buffer + 12, cur_info->data_size);
cur_buffer += 16;
memcpy(cur_buffer, cur_info->system_id, cur_info->system_id_size);
cur_buffer += cur_info->system_id_size;
for (i = 0; i < cur_info->num_key_ids; i++) {
memcpy(cur_buffer, cur_info->key_ids[i], cur_info->key_id_size);
cur_buffer += cur_info->key_id_size;
}
memcpy(cur_buffer, cur_info->data, cur_info->data_size);
cur_buffer += cur_info->data_size;
}
return buffer;
}

View file

@ -0,0 +1,205 @@
/**
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_ENCRYPTION_INFO_H
#define AVUTIL_ENCRYPTION_INFO_H
#include <stddef.h>
#include <stdint.h>
typedef struct AVSubsampleEncryptionInfo {
/** The number of bytes that are clear. */
unsigned int bytes_of_clear_data;
/**
* The number of bytes that are protected. If using pattern encryption,
* the pattern applies to only the protected bytes; if not using pattern
* encryption, all these bytes are encrypted.
*/
unsigned int bytes_of_protected_data;
} AVSubsampleEncryptionInfo;
/**
* This describes encryption info for a packet. This contains frame-specific
* info for how to decrypt the packet before passing it to the decoder.
*
* The size of this struct is not part of the public ABI.
*/
typedef struct AVEncryptionInfo {
/** The fourcc encryption scheme, in big-endian byte order. */
uint32_t scheme;
/**
* Only used for pattern encryption. This is the number of 16-byte blocks
* that are encrypted.
*/
uint32_t crypt_byte_block;
/**
* Only used for pattern encryption. This is the number of 16-byte blocks
* that are clear.
*/
uint32_t skip_byte_block;
/**
* The ID of the key used to encrypt the packet. This should always be
* 16 bytes long, but may be changed in the future.
*/
uint8_t *key_id;
uint32_t key_id_size;
/**
* The initialization vector. This may have been zero-filled to be the
* correct block size. This should always be 16 bytes long, but may be
* changed in the future.
*/
uint8_t *iv;
uint32_t iv_size;
/**
* An array of subsample encryption info specifying how parts of the sample
* are encrypted. If there are no subsamples, then the whole sample is
* encrypted.
*/
AVSubsampleEncryptionInfo *subsamples;
uint32_t subsample_count;
} AVEncryptionInfo;
/**
* This describes info used to initialize an encryption key system.
*
* The size of this struct is not part of the public ABI.
*/
typedef struct AVEncryptionInitInfo {
/**
* A unique identifier for the key system this is for, can be NULL if it
* is not known. This should always be 16 bytes, but may change in the
* future.
*/
uint8_t* system_id;
uint32_t system_id_size;
/**
* An array of key IDs this initialization data is for. All IDs are the
* same length. Can be NULL if there are no known key IDs.
*/
uint8_t** key_ids;
/** The number of key IDs. */
uint32_t num_key_ids;
/**
* The number of bytes in each key ID. This should always be 16, but may
* change in the future.
*/
uint32_t key_id_size;
/**
* Key-system specific initialization data. This data is copied directly
* from the file and the format depends on the specific key system. This
* can be NULL if there is no initialization data; in that case, there
* will be at least one key ID.
*/
uint8_t* data;
uint32_t data_size;
/**
* An optional pointer to the next initialization info in the list.
*/
struct AVEncryptionInitInfo *next;
} AVEncryptionInitInfo;
/**
* Allocates an AVEncryptionInfo structure and sub-pointers to hold the given
* number of subsamples. This will allocate pointers for the key ID, IV,
* and subsample entries, set the size members, and zero-initialize the rest.
*
* @param subsample_count The number of subsamples.
* @param key_id_size The number of bytes in the key ID, should be 16.
* @param iv_size The number of bytes in the IV, should be 16.
*
* @return The new AVEncryptionInfo structure, or NULL on error.
*/
AVEncryptionInfo *av_encryption_info_alloc(uint32_t subsample_count, uint32_t key_id_size, uint32_t iv_size);
/**
* Allocates an AVEncryptionInfo structure with a copy of the given data.
* @return The new AVEncryptionInfo structure, or NULL on error.
*/
AVEncryptionInfo *av_encryption_info_clone(const AVEncryptionInfo *info);
/**
* Frees the given encryption info object. This MUST NOT be used to free the
* side-data data pointer, that should use normal side-data methods.
*/
void av_encryption_info_free(AVEncryptionInfo *info);
/**
* Creates a copy of the AVEncryptionInfo that is contained in the given side
* data. The resulting object should be passed to av_encryption_info_free()
* when done.
*
* @return The new AVEncryptionInfo structure, or NULL on error.
*/
AVEncryptionInfo *av_encryption_info_get_side_data(const uint8_t *side_data, size_t side_data_size);
/**
* Allocates and initializes side data that holds a copy of the given encryption
* info. The resulting pointer should be either freed using av_free or given
* to av_packet_add_side_data().
*
* @return The new side-data pointer, or NULL.
*/
uint8_t *av_encryption_info_add_side_data(
const AVEncryptionInfo *info, size_t *side_data_size);
/**
* Allocates an AVEncryptionInitInfo structure and sub-pointers to hold the
* given sizes. This will allocate pointers and set all the fields.
*
* @return The new AVEncryptionInitInfo structure, or NULL on error.
*/
AVEncryptionInitInfo *av_encryption_init_info_alloc(
uint32_t system_id_size, uint32_t num_key_ids, uint32_t key_id_size, uint32_t data_size);
/**
* Frees the given encryption init info object. This MUST NOT be used to free
* the side-data data pointer, that should use normal side-data methods.
*/
void av_encryption_init_info_free(AVEncryptionInitInfo* info);
/**
* Creates a copy of the AVEncryptionInitInfo that is contained in the given
* side data. The resulting object should be passed to
* av_encryption_init_info_free() when done.
*
* @return The new AVEncryptionInitInfo structure, or NULL on error.
*/
AVEncryptionInitInfo *av_encryption_init_info_get_side_data(
const uint8_t* side_data, size_t side_data_size);
/**
* Allocates and initializes side data that holds a copy of the given encryption
* init info. The resulting pointer should be either freed using av_free or
* given to av_packet_add_side_data().
*
* @return The new side-data pointer, or NULL.
*/
uint8_t *av_encryption_init_info_add_side_data(
const AVEncryptionInitInfo *info, size_t *side_data_size);
#endif /* AVUTIL_ENCRYPTION_INFO_H */

View file

@ -0,0 +1,129 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#undef _GNU_SOURCE
#define _XOPEN_SOURCE 600 /* XSI-compliant version of strerror_r */
#include "avutil.h"
#include "avstring.h"
#include "common.h"
struct error_entry {
int num;
const char *tag;
const char *str;
};
#define ERROR_TAG(tag) AVERROR_##tag, #tag
#define EERROR_TAG(tag) AVERROR(tag), #tag
#define AVERROR_INPUT_AND_OUTPUT_CHANGED (AVERROR_INPUT_CHANGED | AVERROR_OUTPUT_CHANGED)
static const struct error_entry error_entries[] = {
{ ERROR_TAG(BSF_NOT_FOUND), "Bitstream filter not found" },
{ ERROR_TAG(BUG), "Internal bug, should not have happened" },
{ ERROR_TAG(BUG2), "Internal bug, should not have happened" },
{ ERROR_TAG(BUFFER_TOO_SMALL), "Buffer too small" },
{ ERROR_TAG(DECODER_NOT_FOUND), "Decoder not found" },
{ ERROR_TAG(DEMUXER_NOT_FOUND), "Demuxer not found" },
{ ERROR_TAG(ENCODER_NOT_FOUND), "Encoder not found" },
{ ERROR_TAG(EOF), "End of file" },
{ ERROR_TAG(EXIT), "Immediate exit requested" },
{ ERROR_TAG(EXTERNAL), "Generic error in an external library" },
{ ERROR_TAG(FILTER_NOT_FOUND), "Filter not found" },
{ ERROR_TAG(INPUT_CHANGED), "Input changed" },
{ ERROR_TAG(INVALIDDATA), "Invalid data found when processing input" },
{ ERROR_TAG(MUXER_NOT_FOUND), "Muxer not found" },
{ ERROR_TAG(OPTION_NOT_FOUND), "Option not found" },
{ ERROR_TAG(OUTPUT_CHANGED), "Output changed" },
{ ERROR_TAG(PATCHWELCOME), "Not yet implemented in FFmpeg, patches welcome" },
{ ERROR_TAG(PROTOCOL_NOT_FOUND), "Protocol not found" },
{ ERROR_TAG(STREAM_NOT_FOUND), "Stream not found" },
{ ERROR_TAG(UNKNOWN), "Unknown error occurred" },
{ ERROR_TAG(EXPERIMENTAL), "Experimental feature" },
{ ERROR_TAG(INPUT_AND_OUTPUT_CHANGED), "Input and output changed" },
{ ERROR_TAG(HTTP_BAD_REQUEST), "Server returned 400 Bad Request" },
{ ERROR_TAG(HTTP_UNAUTHORIZED), "Server returned 401 Unauthorized (authorization failed)" },
{ ERROR_TAG(HTTP_FORBIDDEN), "Server returned 403 Forbidden (access denied)" },
{ ERROR_TAG(HTTP_NOT_FOUND), "Server returned 404 Not Found" },
{ ERROR_TAG(HTTP_OTHER_4XX), "Server returned 4XX Client Error, but not one of 40{0,1,3,4}" },
{ ERROR_TAG(HTTP_SERVER_ERROR), "Server returned 5XX Server Error reply" },
#if !HAVE_STRERROR_R
{ EERROR_TAG(E2BIG), "Argument list too long" },
{ EERROR_TAG(EACCES), "Permission denied" },
{ EERROR_TAG(EAGAIN), "Resource temporarily unavailable" },
{ EERROR_TAG(EBADF), "Bad file descriptor" },
{ EERROR_TAG(EBUSY), "Device or resource busy" },
{ EERROR_TAG(ECHILD), "No child processes" },
{ EERROR_TAG(EDEADLK), "Resource deadlock avoided" },
{ EERROR_TAG(EDOM), "Numerical argument out of domain" },
{ EERROR_TAG(EEXIST), "File exists" },
{ EERROR_TAG(EFAULT), "Bad address" },
{ EERROR_TAG(EFBIG), "File too large" },
{ EERROR_TAG(EILSEQ), "Illegal byte sequence" },
{ EERROR_TAG(EINTR), "Interrupted system call" },
{ EERROR_TAG(EINVAL), "Invalid argument" },
{ EERROR_TAG(EIO), "I/O error" },
{ EERROR_TAG(EISDIR), "Is a directory" },
{ EERROR_TAG(EMFILE), "Too many open files" },
{ EERROR_TAG(EMLINK), "Too many links" },
{ EERROR_TAG(ENAMETOOLONG), "File name too long" },
{ EERROR_TAG(ENFILE), "Too many open files in system" },
{ EERROR_TAG(ENODEV), "No such device" },
{ EERROR_TAG(ENOENT), "No such file or directory" },
{ EERROR_TAG(ENOEXEC), "Exec format error" },
{ EERROR_TAG(ENOLCK), "No locks available" },
{ EERROR_TAG(ENOMEM), "Cannot allocate memory" },
{ EERROR_TAG(ENOSPC), "No space left on device" },
{ EERROR_TAG(ENOSYS), "Function not implemented" },
{ EERROR_TAG(ENOTDIR), "Not a directory" },
{ EERROR_TAG(ENOTEMPTY), "Directory not empty" },
{ EERROR_TAG(ENOTTY), "Inappropriate I/O control operation" },
{ EERROR_TAG(ENXIO), "No such device or address" },
{ EERROR_TAG(EPERM), "Operation not permitted" },
{ EERROR_TAG(EPIPE), "Broken pipe" },
{ EERROR_TAG(ERANGE), "Result too large" },
{ EERROR_TAG(EROFS), "Read-only file system" },
{ EERROR_TAG(ESPIPE), "Illegal seek" },
{ EERROR_TAG(ESRCH), "No such process" },
{ EERROR_TAG(EXDEV), "Cross-device link" },
#endif
};
int av_strerror(int errnum, char *errbuf, size_t errbuf_size)
{
int ret = 0, i;
const struct error_entry *entry = NULL;
for (i = 0; i < FF_ARRAY_ELEMS(error_entries); i++) {
if (errnum == error_entries[i].num) {
entry = &error_entries[i];
break;
}
}
if (entry) {
av_strlcpy(errbuf, entry->str, errbuf_size);
} else {
#if HAVE_STRERROR_R
ret = AVERROR(strerror_r(AVUNERROR(errnum), errbuf, errbuf_size));
#else
ret = -1;
#endif
if (ret < 0)
snprintf(errbuf, errbuf_size, "Error number %d occurred", errnum);
}
return ret;
}

View file

@ -0,0 +1,126 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* error code definitions
*/
#ifndef AVUTIL_ERROR_H
#define AVUTIL_ERROR_H
#include <errno.h>
#include <stddef.h>
/**
* @addtogroup lavu_error
*
* @{
*/
/* error handling */
#if EDOM > 0
#define AVERROR(e) (-(e)) ///< Returns a negative error code from a POSIX error code, to return from library functions.
#define AVUNERROR(e) (-(e)) ///< Returns a POSIX error code from a library function error return value.
#else
/* Some platforms have E* and errno already negated. */
#define AVERROR(e) (e)
#define AVUNERROR(e) (e)
#endif
#define FFERRTAG(a, b, c, d) (-(int)MKTAG(a, b, c, d))
#define AVERROR_BSF_NOT_FOUND FFERRTAG(0xF8,'B','S','F') ///< Bitstream filter not found
#define AVERROR_BUG FFERRTAG( 'B','U','G','!') ///< Internal bug, also see AVERROR_BUG2
#define AVERROR_BUFFER_TOO_SMALL FFERRTAG( 'B','U','F','S') ///< Buffer too small
#define AVERROR_DECODER_NOT_FOUND FFERRTAG(0xF8,'D','E','C') ///< Decoder not found
#define AVERROR_DEMUXER_NOT_FOUND FFERRTAG(0xF8,'D','E','M') ///< Demuxer not found
#define AVERROR_ENCODER_NOT_FOUND FFERRTAG(0xF8,'E','N','C') ///< Encoder not found
#define AVERROR_EOF FFERRTAG( 'E','O','F',' ') ///< End of file
#define AVERROR_EXIT FFERRTAG( 'E','X','I','T') ///< Immediate exit was requested; the called function should not be restarted
#define AVERROR_EXTERNAL FFERRTAG( 'E','X','T',' ') ///< Generic error in an external library
#define AVERROR_FILTER_NOT_FOUND FFERRTAG(0xF8,'F','I','L') ///< Filter not found
#define AVERROR_INVALIDDATA FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input
#define AVERROR_MUXER_NOT_FOUND FFERRTAG(0xF8,'M','U','X') ///< Muxer not found
#define AVERROR_OPTION_NOT_FOUND FFERRTAG(0xF8,'O','P','T') ///< Option not found
#define AVERROR_PATCHWELCOME FFERRTAG( 'P','A','W','E') ///< Not yet implemented in FFmpeg, patches welcome
#define AVERROR_PROTOCOL_NOT_FOUND FFERRTAG(0xF8,'P','R','O') ///< Protocol not found
#define AVERROR_STREAM_NOT_FOUND FFERRTAG(0xF8,'S','T','R') ///< Stream not found
/**
* This is semantically identical to AVERROR_BUG
* it has been introduced in Libav after our AVERROR_BUG and with a modified value.
*/
#define AVERROR_BUG2 FFERRTAG( 'B','U','G',' ')
#define AVERROR_UNKNOWN FFERRTAG( 'U','N','K','N') ///< Unknown error, typically from an external library
#define AVERROR_EXPERIMENTAL (-0x2bb2afa8) ///< Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it.
#define AVERROR_INPUT_CHANGED (-0x636e6701) ///< Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED)
#define AVERROR_OUTPUT_CHANGED (-0x636e6702) ///< Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED)
/* HTTP & RTSP errors */
#define AVERROR_HTTP_BAD_REQUEST FFERRTAG(0xF8,'4','0','0')
#define AVERROR_HTTP_UNAUTHORIZED FFERRTAG(0xF8,'4','0','1')
#define AVERROR_HTTP_FORBIDDEN FFERRTAG(0xF8,'4','0','3')
#define AVERROR_HTTP_NOT_FOUND FFERRTAG(0xF8,'4','0','4')
#define AVERROR_HTTP_OTHER_4XX FFERRTAG(0xF8,'4','X','X')
#define AVERROR_HTTP_SERVER_ERROR FFERRTAG(0xF8,'5','X','X')
#define AV_ERROR_MAX_STRING_SIZE 64
/**
* Put a description of the AVERROR code errnum in errbuf.
* In case of failure the global variable errno is set to indicate the
* error. Even in case of failure av_strerror() will print a generic
* error message indicating the errnum provided to errbuf.
*
* @param errnum error code to describe
* @param errbuf buffer to which description is written
* @param errbuf_size the size in bytes of errbuf
* @return 0 on success, a negative value if a description for errnum
* cannot be found
*/
int av_strerror(int errnum, char *errbuf, size_t errbuf_size);
/**
* Fill the provided buffer with a string containing an error string
* corresponding to the AVERROR code errnum.
*
* @param errbuf a buffer
* @param errbuf_size size in bytes of errbuf
* @param errnum error code to describe
* @return the buffer in input, filled with the error description
* @see av_strerror()
*/
static inline char *av_make_error_string(char *errbuf, size_t errbuf_size, int errnum)
{
av_strerror(errnum, errbuf, errbuf_size);
return errbuf;
}
/**
* Convenience macro, the return value should be used only directly in
* function arguments but never stand-alone.
*/
#define av_err2str(errnum) \
av_make_error_string((char[AV_ERROR_MAX_STRING_SIZE]){0}, AV_ERROR_MAX_STRING_SIZE, errnum)
/**
* @}
*/
#endif /* AVUTIL_ERROR_H */

View file

@ -0,0 +1,760 @@
/*
* Copyright (c) 2002-2006 Michael Niedermayer <michaelni@gmx.at>
* Copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.org>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* simple arithmetic expression evaluator.
*
* see http://joe.hotchkiss.com/programming/eval/eval.html
*/
#include <float.h>
#include "attributes.h"
#include "avutil.h"
#include "common.h"
#include "eval.h"
#include "ffmath.h"
#include "internal.h"
#include "log.h"
#include "mathematics.h"
#include "time.h"
#include "avstring.h"
#include "timer.h"
#include "reverse.h"
typedef struct Parser {
const AVClass *class;
int stack_index;
char *s;
const double *const_values;
const char * const *const_names; // NULL terminated
double (* const *funcs1)(void *, double a); // NULL terminated
const char * const *func1_names; // NULL terminated
double (* const *funcs2)(void *, double a, double b); // NULL terminated
const char * const *func2_names; // NULL terminated
void *opaque;
int log_offset;
void *log_ctx;
#define VARS 10
double *var;
} Parser;
static const AVClass eval_class = {
.class_name = "Eval",
.item_name = av_default_item_name,
.option = NULL,
.version = LIBAVUTIL_VERSION_INT,
.log_level_offset_offset = offsetof(Parser, log_offset),
.parent_log_context_offset = offsetof(Parser, log_ctx),
};
static const struct {
double bin_val;
double dec_val;
int8_t exp;
} si_prefixes['z' - 'E' + 1] = {
['y'-'E']= { 8.271806125530276749e-25, 1e-24, -24 },
['z'-'E']= { 8.4703294725430034e-22, 1e-21, -21 },
['a'-'E']= { 8.6736173798840355e-19, 1e-18, -18 },
['f'-'E']= { 8.8817841970012523e-16, 1e-15, -15 },
['p'-'E']= { 9.0949470177292824e-13, 1e-12, -12 },
['n'-'E']= { 9.3132257461547852e-10, 1e-9, -9 },
['u'-'E']= { 9.5367431640625e-7, 1e-6, -6 },
['m'-'E']= { 9.765625e-4, 1e-3, -3 },
['c'-'E']= { 9.8431332023036951e-3, 1e-2, -2 },
['d'-'E']= { 9.921256574801246e-2, 1e-1, -1 },
['h'-'E']= { 1.0159366732596479e2, 1e2, 2 },
['k'-'E']= { 1.024e3, 1e3, 3 },
['K'-'E']= { 1.024e3, 1e3, 3 },
['M'-'E']= { 1.048576e6, 1e6, 6 },
['G'-'E']= { 1.073741824e9, 1e9, 9 },
['T'-'E']= { 1.099511627776e12, 1e12, 12 },
['P'-'E']= { 1.125899906842624e15, 1e15, 15 },
['E'-'E']= { 1.152921504606847e18, 1e18, 18 },
['Z'-'E']= { 1.1805916207174113e21, 1e21, 21 },
['Y'-'E']= { 1.2089258196146292e24, 1e24, 24 },
};
static const struct {
const char *name;
double value;
} constants[] = {
{ "E", M_E },
{ "PI", M_PI },
{ "PHI", M_PHI },
{ "QP2LAMBDA", FF_QP2LAMBDA },
};
double av_strtod(const char *numstr, char **tail)
{
double d;
char *next;
if(numstr[0]=='0' && (numstr[1]|0x20)=='x') {
d = strtoul(numstr, &next, 16);
} else
d = strtod(numstr, &next);
/* if parsing succeeded, check for and interpret postfixes */
if (next!=numstr) {
if (next[0] == 'd' && next[1] == 'B') {
/* treat dB as decibels instead of decibytes */
d = ff_exp10(d / 20);
next += 2;
} else if (*next >= 'E' && *next <= 'z') {
int e= si_prefixes[*next - 'E'].exp;
if (e) {
if (next[1] == 'i') {
d*= si_prefixes[*next - 'E'].bin_val;
next+=2;
} else {
d*= si_prefixes[*next - 'E'].dec_val;
next++;
}
}
}
if (*next=='B') {
d*=8;
next++;
}
}
/* if requested, fill in tail with the position after the last parsed
character */
if (tail)
*tail = next;
return d;
}
#define IS_IDENTIFIER_CHAR(c) ((c) - '0' <= 9U || (c) - 'a' <= 25U || (c) - 'A' <= 25U || (c) == '_')
static int strmatch(const char *s, const char *prefix)
{
int i;
for (i=0; prefix[i]; i++) {
if (prefix[i] != s[i]) return 0;
}
/* return 1 only if the s identifier is terminated */
return !IS_IDENTIFIER_CHAR(s[i]);
}
struct AVExpr {
enum {
e_value, e_const, e_func0, e_func1, e_func2,
e_squish, e_gauss, e_ld, e_isnan, e_isinf,
e_mod, e_max, e_min, e_eq, e_gt, e_gte, e_lte, e_lt,
e_pow, e_mul, e_div, e_add,
e_last, e_st, e_while, e_taylor, e_root, e_floor, e_ceil, e_trunc, e_round,
e_sqrt, e_not, e_random, e_hypot, e_gcd,
e_if, e_ifnot, e_print, e_bitand, e_bitor, e_between, e_clip, e_atan2, e_lerp,
} type;
double value; // is sign in other types
union {
int const_index;
double (*func0)(double);
double (*func1)(void *, double);
double (*func2)(void *, double, double);
} a;
struct AVExpr *param[3];
double *var;
};
static double etime(double v)
{
return av_gettime() * 0.000001;
}
static double eval_expr(Parser *p, AVExpr *e)
{
switch (e->type) {
case e_value: return e->value;
case e_const: return e->value * p->const_values[e->a.const_index];
case e_func0: return e->value * e->a.func0(eval_expr(p, e->param[0]));
case e_func1: return e->value * e->a.func1(p->opaque, eval_expr(p, e->param[0]));
case e_func2: return e->value * e->a.func2(p->opaque, eval_expr(p, e->param[0]), eval_expr(p, e->param[1]));
case e_squish: return 1/(1+exp(4*eval_expr(p, e->param[0])));
case e_gauss: { double d = eval_expr(p, e->param[0]); return exp(-d*d/2)/sqrt(2*M_PI); }
case e_ld: return e->value * p->var[av_clip(eval_expr(p, e->param[0]), 0, VARS-1)];
case e_isnan: return e->value * !!isnan(eval_expr(p, e->param[0]));
case e_isinf: return e->value * !!isinf(eval_expr(p, e->param[0]));
case e_floor: return e->value * floor(eval_expr(p, e->param[0]));
case e_ceil : return e->value * ceil (eval_expr(p, e->param[0]));
case e_trunc: return e->value * trunc(eval_expr(p, e->param[0]));
case e_round: return e->value * round(eval_expr(p, e->param[0]));
case e_sqrt: return e->value * sqrt (eval_expr(p, e->param[0]));
case e_not: return e->value * (eval_expr(p, e->param[0]) == 0);
case e_if: return e->value * (eval_expr(p, e->param[0]) ? eval_expr(p, e->param[1]) :
e->param[2] ? eval_expr(p, e->param[2]) : 0);
case e_ifnot: return e->value * (!eval_expr(p, e->param[0]) ? eval_expr(p, e->param[1]) :
e->param[2] ? eval_expr(p, e->param[2]) : 0);
case e_clip: {
double x = eval_expr(p, e->param[0]);
double min = eval_expr(p, e->param[1]), max = eval_expr(p, e->param[2]);
if (isnan(min) || isnan(max) || isnan(x) || min > max)
return NAN;
return e->value * av_clipd(eval_expr(p, e->param[0]), min, max);
}
case e_between: {
double d = eval_expr(p, e->param[0]);
return e->value * (d >= eval_expr(p, e->param[1]) &&
d <= eval_expr(p, e->param[2]));
}
case e_lerp: {
double v0 = eval_expr(p, e->param[0]);
double v1 = eval_expr(p, e->param[1]);
double f = eval_expr(p, e->param[2]);
return v0 + (v1 - v0) * f;
}
case e_print: {
double x = eval_expr(p, e->param[0]);
int level = e->param[1] ? av_clip(eval_expr(p, e->param[1]), INT_MIN, INT_MAX) : AV_LOG_INFO;
av_log(p, level, "%f\n", x);
return x;
}
case e_random:{
int idx= av_clip(eval_expr(p, e->param[0]), 0, VARS-1);
uint64_t r= isnan(p->var[idx]) ? 0 : p->var[idx];
r= r*1664525+1013904223;
p->var[idx]= r;
return e->value * (r * (1.0/UINT64_MAX));
}
case e_while: {
double d = NAN;
while (eval_expr(p, e->param[0]))
d=eval_expr(p, e->param[1]);
return d;
}
case e_taylor: {
double t = 1, d = 0, v;
double x = eval_expr(p, e->param[1]);
int id = e->param[2] ? av_clip(eval_expr(p, e->param[2]), 0, VARS-1) : 0;
int i;
double var0 = p->var[id];
for(i=0; i<1000; i++) {
double ld = d;
p->var[id] = i;
v = eval_expr(p, e->param[0]);
d += t*v;
if(ld==d && v)
break;
t *= x / (i+1);
}
p->var[id] = var0;
return d;
}
case e_root: {
int i, j;
double low = -1, high = -1, v, low_v = -DBL_MAX, high_v = DBL_MAX;
double var0 = p->var[0];
double x_max = eval_expr(p, e->param[1]);
for(i=-1; i<1024; i++) {
if(i<255) {
p->var[0] = ff_reverse[i&255]*x_max/255;
} else {
p->var[0] = x_max*pow(0.9, i-255);
if (i&1) p->var[0] *= -1;
if (i&2) p->var[0] += low;
else p->var[0] += high;
}
v = eval_expr(p, e->param[0]);
if (v<=0 && v>low_v) {
low = p->var[0];
low_v = v;
}
if (v>=0 && v<high_v) {
high = p->var[0];
high_v = v;
}
if (low>=0 && high>=0){
for (j=0; j<1000; j++) {
p->var[0] = (low+high)*0.5;
if (low == p->var[0] || high == p->var[0])
break;
v = eval_expr(p, e->param[0]);
if (v<=0) low = p->var[0];
if (v>=0) high= p->var[0];
if (isnan(v)) {
low = high = v;
break;
}
}
break;
}
}
p->var[0] = var0;
return -low_v<high_v ? low : high;
}
default: {
double d = eval_expr(p, e->param[0]);
double d2 = eval_expr(p, e->param[1]);
switch (e->type) {
case e_mod: return e->value * (d - floor((!CONFIG_FTRAPV || d2) ? d / d2 : d * INFINITY) * d2);
case e_gcd: return e->value * av_gcd(d,d2);
case e_max: return e->value * (d > d2 ? d : d2);
case e_min: return e->value * (d < d2 ? d : d2);
case e_eq: return e->value * (d == d2 ? 1.0 : 0.0);
case e_gt: return e->value * (d > d2 ? 1.0 : 0.0);
case e_gte: return e->value * (d >= d2 ? 1.0 : 0.0);
case e_lt: return e->value * (d < d2 ? 1.0 : 0.0);
case e_lte: return e->value * (d <= d2 ? 1.0 : 0.0);
case e_pow: return e->value * pow(d, d2);
case e_mul: return e->value * (d * d2);
case e_div: return e->value * ((!CONFIG_FTRAPV || d2 ) ? (d / d2) : d * INFINITY);
case e_add: return e->value * (d + d2);
case e_last:return e->value * d2;
case e_st : return e->value * (p->var[av_clip(d, 0, VARS-1)]= d2);
case e_hypot:return e->value * hypot(d, d2);
case e_atan2:return e->value * atan2(d, d2);
case e_bitand: return isnan(d) || isnan(d2) ? NAN : e->value * ((long int)d & (long int)d2);
case e_bitor: return isnan(d) || isnan(d2) ? NAN : e->value * ((long int)d | (long int)d2);
}
}
}
return NAN;
}
static int parse_expr(AVExpr **e, Parser *p);
void av_expr_free(AVExpr *e)
{
if (!e) return;
av_expr_free(e->param[0]);
av_expr_free(e->param[1]);
av_expr_free(e->param[2]);
av_freep(&e->var);
av_freep(&e);
}
static int parse_primary(AVExpr **e, Parser *p)
{
AVExpr *d = av_mallocz(sizeof(AVExpr));
char *next = p->s, *s0 = p->s;
int ret, i;
if (!d)
return AVERROR(ENOMEM);
/* number */
d->value = av_strtod(p->s, &next);
if (next != p->s) {
d->type = e_value;
p->s= next;
*e = d;
return 0;
}
d->value = 1;
/* named constants */
for (i=0; p->const_names && p->const_names[i]; i++) {
if (strmatch(p->s, p->const_names[i])) {
p->s+= strlen(p->const_names[i]);
d->type = e_const;
d->a.const_index = i;
*e = d;
return 0;
}
}
for (i = 0; i < FF_ARRAY_ELEMS(constants); i++) {
if (strmatch(p->s, constants[i].name)) {
p->s += strlen(constants[i].name);
d->type = e_value;
d->value = constants[i].value;
*e = d;
return 0;
}
}
p->s= strchr(p->s, '(');
if (!p->s) {
av_log(p, AV_LOG_ERROR, "Undefined constant or missing '(' in '%s'\n", s0);
p->s= next;
av_expr_free(d);
return AVERROR(EINVAL);
}
p->s++; // "("
if (*next == '(') { // special case do-nothing
av_freep(&d);
if ((ret = parse_expr(&d, p)) < 0)
return ret;
if (p->s[0] != ')') {
av_log(p, AV_LOG_ERROR, "Missing ')' in '%s'\n", s0);
av_expr_free(d);
return AVERROR(EINVAL);
}
p->s++; // ")"
*e = d;
return 0;
}
if ((ret = parse_expr(&(d->param[0]), p)) < 0) {
av_expr_free(d);
return ret;
}
if (p->s[0]== ',') {
p->s++; // ","
parse_expr(&d->param[1], p);
}
if (p->s[0]== ',') {
p->s++; // ","
parse_expr(&d->param[2], p);
}
if (p->s[0] != ')') {
av_log(p, AV_LOG_ERROR, "Missing ')' or too many args in '%s'\n", s0);
av_expr_free(d);
return AVERROR(EINVAL);
}
p->s++; // ")"
d->type = e_func0;
if (strmatch(next, "sinh" )) d->a.func0 = sinh;
else if (strmatch(next, "cosh" )) d->a.func0 = cosh;
else if (strmatch(next, "tanh" )) d->a.func0 = tanh;
else if (strmatch(next, "sin" )) d->a.func0 = sin;
else if (strmatch(next, "cos" )) d->a.func0 = cos;
else if (strmatch(next, "tan" )) d->a.func0 = tan;
else if (strmatch(next, "atan" )) d->a.func0 = atan;
else if (strmatch(next, "asin" )) d->a.func0 = asin;
else if (strmatch(next, "acos" )) d->a.func0 = acos;
else if (strmatch(next, "exp" )) d->a.func0 = exp;
else if (strmatch(next, "log" )) d->a.func0 = log;
else if (strmatch(next, "abs" )) d->a.func0 = fabs;
else if (strmatch(next, "time" )) d->a.func0 = etime;
else if (strmatch(next, "squish")) d->type = e_squish;
else if (strmatch(next, "gauss" )) d->type = e_gauss;
else if (strmatch(next, "mod" )) d->type = e_mod;
else if (strmatch(next, "max" )) d->type = e_max;
else if (strmatch(next, "min" )) d->type = e_min;
else if (strmatch(next, "eq" )) d->type = e_eq;
else if (strmatch(next, "gte" )) d->type = e_gte;
else if (strmatch(next, "gt" )) d->type = e_gt;
else if (strmatch(next, "lte" )) d->type = e_lte;
else if (strmatch(next, "lt" )) d->type = e_lt;
else if (strmatch(next, "ld" )) d->type = e_ld;
else if (strmatch(next, "isnan" )) d->type = e_isnan;
else if (strmatch(next, "isinf" )) d->type = e_isinf;
else if (strmatch(next, "st" )) d->type = e_st;
else if (strmatch(next, "while" )) d->type = e_while;
else if (strmatch(next, "taylor")) d->type = e_taylor;
else if (strmatch(next, "root" )) d->type = e_root;
else if (strmatch(next, "floor" )) d->type = e_floor;
else if (strmatch(next, "ceil" )) d->type = e_ceil;
else if (strmatch(next, "trunc" )) d->type = e_trunc;
else if (strmatch(next, "round" )) d->type = e_round;
else if (strmatch(next, "sqrt" )) d->type = e_sqrt;
else if (strmatch(next, "not" )) d->type = e_not;
else if (strmatch(next, "pow" )) d->type = e_pow;
else if (strmatch(next, "print" )) d->type = e_print;
else if (strmatch(next, "random")) d->type = e_random;
else if (strmatch(next, "hypot" )) d->type = e_hypot;
else if (strmatch(next, "gcd" )) d->type = e_gcd;
else if (strmatch(next, "if" )) d->type = e_if;
else if (strmatch(next, "ifnot" )) d->type = e_ifnot;
else if (strmatch(next, "bitand")) d->type = e_bitand;
else if (strmatch(next, "bitor" )) d->type = e_bitor;
else if (strmatch(next, "between"))d->type = e_between;
else if (strmatch(next, "clip" )) d->type = e_clip;
else if (strmatch(next, "atan2" )) d->type = e_atan2;
else if (strmatch(next, "lerp" )) d->type = e_lerp;
else {
for (i=0; p->func1_names && p->func1_names[i]; i++) {
if (strmatch(next, p->func1_names[i])) {
d->a.func1 = p->funcs1[i];
d->type = e_func1;
*e = d;
return 0;
}
}
for (i=0; p->func2_names && p->func2_names[i]; i++) {
if (strmatch(next, p->func2_names[i])) {
d->a.func2 = p->funcs2[i];
d->type = e_func2;
*e = d;
return 0;
}
}
av_log(p, AV_LOG_ERROR, "Unknown function in '%s'\n", s0);
av_expr_free(d);
return AVERROR(EINVAL);
}
*e = d;
return 0;
}
static AVExpr *make_eval_expr(int type, int value, AVExpr *p0, AVExpr *p1)
{
AVExpr *e = av_mallocz(sizeof(AVExpr));
if (!e)
return NULL;
e->type =type ;
e->value =value ;
e->param[0] =p0 ;
e->param[1] =p1 ;
return e;
}
static int parse_pow(AVExpr **e, Parser *p, int *sign)
{
*sign= (*p->s == '+') - (*p->s == '-');
p->s += *sign&1;
return parse_primary(e, p);
}
static int parse_dB(AVExpr **e, Parser *p, int *sign)
{
/* do not filter out the negative sign when parsing a dB value.
for example, -3dB is not the same as -(3dB) */
if (*p->s == '-') {
char *next;
double av_unused ignored = strtod(p->s, &next);
if (next != p->s && next[0] == 'd' && next[1] == 'B') {
*sign = 0;
return parse_primary(e, p);
}
}
return parse_pow(e, p, sign);
}
static int parse_factor(AVExpr **e, Parser *p)
{
int sign, sign2, ret;
AVExpr *e0, *e1, *e2;
if ((ret = parse_dB(&e0, p, &sign)) < 0)
return ret;
while(p->s[0]=='^'){
e1 = e0;
p->s++;
if ((ret = parse_dB(&e2, p, &sign2)) < 0) {
av_expr_free(e1);
return ret;
}
e0 = make_eval_expr(e_pow, 1, e1, e2);
if (!e0) {
av_expr_free(e1);
av_expr_free(e2);
return AVERROR(ENOMEM);
}
if (e0->param[1]) e0->param[1]->value *= (sign2|1);
}
if (e0) e0->value *= (sign|1);
*e = e0;
return 0;
}
static int parse_term(AVExpr **e, Parser *p)
{
int ret;
AVExpr *e0, *e1, *e2;
if ((ret = parse_factor(&e0, p)) < 0)
return ret;
while (p->s[0]=='*' || p->s[0]=='/') {
int c= *p->s++;
e1 = e0;
if ((ret = parse_factor(&e2, p)) < 0) {
av_expr_free(e1);
return ret;
}
e0 = make_eval_expr(c == '*' ? e_mul : e_div, 1, e1, e2);
if (!e0) {
av_expr_free(e1);
av_expr_free(e2);
return AVERROR(ENOMEM);
}
}
*e = e0;
return 0;
}
static int parse_subexpr(AVExpr **e, Parser *p)
{
int ret;
AVExpr *e0, *e1, *e2;
if ((ret = parse_term(&e0, p)) < 0)
return ret;
while (*p->s == '+' || *p->s == '-') {
e1 = e0;
if ((ret = parse_term(&e2, p)) < 0) {
av_expr_free(e1);
return ret;
}
e0 = make_eval_expr(e_add, 1, e1, e2);
if (!e0) {
av_expr_free(e1);
av_expr_free(e2);
return AVERROR(ENOMEM);
}
};
*e = e0;
return 0;
}
static int parse_expr(AVExpr **e, Parser *p)
{
int ret;
AVExpr *e0, *e1, *e2;
if (p->stack_index <= 0) //protect against stack overflows
return AVERROR(EINVAL);
p->stack_index--;
if ((ret = parse_subexpr(&e0, p)) < 0)
return ret;
while (*p->s == ';') {
p->s++;
e1 = e0;
if ((ret = parse_subexpr(&e2, p)) < 0) {
av_expr_free(e1);
return ret;
}
e0 = make_eval_expr(e_last, 1, e1, e2);
if (!e0) {
av_expr_free(e1);
av_expr_free(e2);
return AVERROR(ENOMEM);
}
};
p->stack_index++;
*e = e0;
return 0;
}
static int verify_expr(AVExpr *e)
{
if (!e) return 0;
switch (e->type) {
case e_value:
case e_const: return 1;
case e_func0:
case e_func1:
case e_squish:
case e_ld:
case e_gauss:
case e_isnan:
case e_isinf:
case e_floor:
case e_ceil:
case e_trunc:
case e_round:
case e_sqrt:
case e_not:
case e_random:
return verify_expr(e->param[0]) && !e->param[1];
case e_print:
return verify_expr(e->param[0])
&& (!e->param[1] || verify_expr(e->param[1]));
case e_if:
case e_ifnot:
case e_taylor:
return verify_expr(e->param[0]) && verify_expr(e->param[1])
&& (!e->param[2] || verify_expr(e->param[2]));
case e_between:
case e_clip:
case e_lerp:
return verify_expr(e->param[0]) &&
verify_expr(e->param[1]) &&
verify_expr(e->param[2]);
default: return verify_expr(e->param[0]) && verify_expr(e->param[1]) && !e->param[2];
}
}
int av_expr_parse(AVExpr **expr, const char *s,
const char * const *const_names,
const char * const *func1_names, double (* const *funcs1)(void *, double),
const char * const *func2_names, double (* const *funcs2)(void *, double, double),
int log_offset, void *log_ctx)
{
Parser p = { 0 };
AVExpr *e = NULL;
char *w = av_malloc(strlen(s) + 1);
char *wp = w;
const char *s0 = s;
int ret = 0;
if (!w)
return AVERROR(ENOMEM);
while (*s)
if (!av_isspace(*s++)) *wp++ = s[-1];
*wp++ = 0;
p.class = &eval_class;
p.stack_index=100;
p.s= w;
p.const_names = const_names;
p.funcs1 = funcs1;
p.func1_names = func1_names;
p.funcs2 = funcs2;
p.func2_names = func2_names;
p.log_offset = log_offset;
p.log_ctx = log_ctx;
if ((ret = parse_expr(&e, &p)) < 0)
goto end;
if (*p.s) {
av_log(&p, AV_LOG_ERROR, "Invalid chars '%s' at the end of expression '%s'\n", p.s, s0);
ret = AVERROR(EINVAL);
goto end;
}
if (!verify_expr(e)) {
ret = AVERROR(EINVAL);
goto end;
}
e->var= av_mallocz(sizeof(double) *VARS);
if (!e->var) {
ret = AVERROR(ENOMEM);
goto end;
}
*expr = e;
e = NULL;
end:
av_expr_free(e);
av_free(w);
return ret;
}
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
{
Parser p = { 0 };
p.var= e->var;
p.const_values = const_values;
p.opaque = opaque;
return eval_expr(&p, e);
}
int av_expr_parse_and_eval(double *d, const char *s,
const char * const *const_names, const double *const_values,
const char * const *func1_names, double (* const *funcs1)(void *, double),
const char * const *func2_names, double (* const *funcs2)(void *, double, double),
void *opaque, int log_offset, void *log_ctx)
{
AVExpr *e = NULL;
int ret = av_expr_parse(&e, s, const_names, func1_names, funcs1, func2_names, funcs2, log_offset, log_ctx);
if (ret < 0) {
*d = NAN;
return ret;
}
*d = av_expr_eval(e, const_values, opaque);
av_expr_free(e);
return isnan(*d) ? AVERROR(EINVAL) : 0;
}

View file

@ -0,0 +1,113 @@
/*
* Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* simple arithmetic expression evaluator
*/
#ifndef AVUTIL_EVAL_H
#define AVUTIL_EVAL_H
#include "avutil.h"
typedef struct AVExpr AVExpr;
/**
* Parse and evaluate an expression.
* Note, this is significantly slower than av_expr_eval().
*
* @param res a pointer to a double where is put the result value of
* the expression, or NAN in case of error
* @param s expression as a zero terminated string, for example "1+2^3+5*5+sin(2/3)"
* @param const_names NULL terminated array of zero terminated strings of constant identifiers, for example {"PI", "E", 0}
* @param const_values a zero terminated array of values for the identifiers from const_names
* @param func1_names NULL terminated array of zero terminated strings of funcs1 identifiers
* @param funcs1 NULL terminated array of function pointers for functions which take 1 argument
* @param func2_names NULL terminated array of zero terminated strings of funcs2 identifiers
* @param funcs2 NULL terminated array of function pointers for functions which take 2 arguments
* @param opaque a pointer which will be passed to all functions from funcs1 and funcs2
* @param log_ctx parent logging context
* @return >= 0 in case of success, a negative value corresponding to an
* AVERROR code otherwise
*/
int av_expr_parse_and_eval(double *res, const char *s,
const char * const *const_names, const double *const_values,
const char * const *func1_names, double (* const *funcs1)(void *, double),
const char * const *func2_names, double (* const *funcs2)(void *, double, double),
void *opaque, int log_offset, void *log_ctx);
/**
* Parse an expression.
*
* @param expr a pointer where is put an AVExpr containing the parsed
* value in case of successful parsing, or NULL otherwise.
* The pointed to AVExpr must be freed with av_expr_free() by the user
* when it is not needed anymore.
* @param s expression as a zero terminated string, for example "1+2^3+5*5+sin(2/3)"
* @param const_names NULL terminated array of zero terminated strings of constant identifiers, for example {"PI", "E", 0}
* @param func1_names NULL terminated array of zero terminated strings of funcs1 identifiers
* @param funcs1 NULL terminated array of function pointers for functions which take 1 argument
* @param func2_names NULL terminated array of zero terminated strings of funcs2 identifiers
* @param funcs2 NULL terminated array of function pointers for functions which take 2 arguments
* @param log_ctx parent logging context
* @return >= 0 in case of success, a negative value corresponding to an
* AVERROR code otherwise
*/
int av_expr_parse(AVExpr **expr, const char *s,
const char * const *const_names,
const char * const *func1_names, double (* const *funcs1)(void *, double),
const char * const *func2_names, double (* const *funcs2)(void *, double, double),
int log_offset, void *log_ctx);
/**
* Evaluate a previously parsed expression.
*
* @param const_values a zero terminated array of values for the identifiers from av_expr_parse() const_names
* @param opaque a pointer which will be passed to all functions from funcs1 and funcs2
* @return the value of the expression
*/
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque);
/**
* Free a parsed expression previously created with av_expr_parse().
*/
void av_expr_free(AVExpr *e);
/**
* Parse the string in numstr and return its value as a double. If
* the string is empty, contains only whitespaces, or does not contain
* an initial substring that has the expected syntax for a
* floating-point number, no conversion is performed. In this case,
* returns a value of zero and the value returned in tail is the value
* of numstr.
*
* @param numstr a string representing a number, may contain one of
* the International System number postfixes, for example 'K', 'M',
* 'G'. If 'i' is appended after the postfix, powers of 2 are used
* instead of powers of 10. The 'B' postfix multiplies the value by
* 8, and can be appended after another postfix or used alone. This
* allows using for example 'KB', 'MiB', 'G' and 'B' as postfix.
* @param tail if non-NULL puts here the pointer to the char next
* after the last parsed character
*/
double av_strtod(const char *numstr, char **tail);
#endif /* AVUTIL_EVAL_H */

View file

@ -0,0 +1,67 @@
/*
* copyright (c) 2016 Ganesh Ajjanagadde <gajjanag@gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* internal math functions header
*/
#ifndef AVUTIL_FFMATH_H
#define AVUTIL_FFMATH_H
#include "attributes.h"
#include "libm.h"
/**
* Compute 10^x for floating point values. Note: this function is by no means
* "correctly rounded", and is meant as a fast, reasonably accurate approximation.
* For instance, maximum relative error for the double precision variant is
* ~ 1e-13 for very small and very large values.
* This is ~2x faster than GNU libm's approach, which is still off by 2ulp on
* some inputs.
* @param x exponent
* @return 10^x
*/
static av_always_inline double ff_exp10(double x)
{
return exp2(M_LOG2_10 * x);
}
static av_always_inline float ff_exp10f(float x)
{
return exp2f(M_LOG2_10 * x);
}
/**
* Compute x^y for floating point x, y. Note: this function is faster than the
* libm variant due to mainly 2 reasons:
* 1. It does not handle any edge cases. In particular, this is only guaranteed
* to work correctly for x > 0.
* 2. It is not as accurate as a standard nearly "correctly rounded" libm variant.
* @param x base
* @param y exponent
* @return x^y
*/
static av_always_inline float ff_fast_powf(float x, float y)
{
return expf(logf(x) * y);
}
#endif /* AVUTIL_FFMATH_H */

View file

@ -0,0 +1,240 @@
/*
* a very simple circular buffer FIFO implementation
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
* Copyright (c) 2006 Roman Shaposhnik
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avassert.h"
#include "common.h"
#include "fifo.h"
static AVFifoBuffer *fifo_alloc_common(void *buffer, size_t size)
{
AVFifoBuffer *f;
if (!buffer)
return NULL;
f = av_mallocz(sizeof(AVFifoBuffer));
if (!f) {
av_free(buffer);
return NULL;
}
f->buffer = buffer;
f->end = f->buffer + size;
av_fifo_reset(f);
return f;
}
AVFifoBuffer *av_fifo_alloc(unsigned int size)
{
void *buffer = av_malloc(size);
return fifo_alloc_common(buffer, size);
}
AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size)
{
void *buffer = av_malloc_array(nmemb, size);
return fifo_alloc_common(buffer, nmemb * size);
}
void av_fifo_free(AVFifoBuffer *f)
{
if (f) {
av_freep(&f->buffer);
av_free(f);
}
}
void av_fifo_freep(AVFifoBuffer **f)
{
if (f) {
av_fifo_free(*f);
*f = NULL;
}
}
void av_fifo_reset(AVFifoBuffer *f)
{
f->wptr = f->rptr = f->buffer;
f->wndx = f->rndx = 0;
}
int av_fifo_size(const AVFifoBuffer *f)
{
return (uint32_t)(f->wndx - f->rndx);
}
int av_fifo_space(const AVFifoBuffer *f)
{
return f->end - f->buffer - av_fifo_size(f);
}
int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size)
{
unsigned int old_size = f->end - f->buffer;
if (old_size < new_size) {
int len = av_fifo_size(f);
AVFifoBuffer *f2 = av_fifo_alloc(new_size);
if (!f2)
return AVERROR(ENOMEM);
av_fifo_generic_read(f, f2->buffer, len, NULL);
f2->wptr += len;
f2->wndx += len;
av_free(f->buffer);
*f = *f2;
av_free(f2);
}
return 0;
}
int av_fifo_grow(AVFifoBuffer *f, unsigned int size)
{
unsigned int old_size = f->end - f->buffer;
if(size + (unsigned)av_fifo_size(f) < size)
return AVERROR(EINVAL);
size += av_fifo_size(f);
if (old_size < size)
return av_fifo_realloc2(f, FFMAX(size, 2*old_size));
return 0;
}
/* src must NOT be const as it can be a context for func that may need
* updating (like a pointer or byte counter) */
int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size,
int (*func)(void *, void *, int))
{
int total = size;
uint32_t wndx= f->wndx;
uint8_t *wptr= f->wptr;
do {
int len = FFMIN(f->end - wptr, size);
if (func) {
len = func(src, wptr, len);
if (len <= 0)
break;
} else {
memcpy(wptr, src, len);
src = (uint8_t *)src + len;
}
// Write memory barrier needed for SMP here in theory
wptr += len;
if (wptr >= f->end)
wptr = f->buffer;
wndx += len;
size -= len;
} while (size > 0);
f->wndx= wndx;
f->wptr= wptr;
return total - size;
}
int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void (*func)(void*, void*, int))
{
uint8_t *rptr = f->rptr;
av_assert2(offset >= 0);
/*
* *ndx are indexes modulo 2^32, they are intended to overflow,
* to handle *ndx greater than 4gb.
*/
av_assert2(buf_size + (unsigned)offset <= f->wndx - f->rndx);
if (offset >= f->end - rptr)
rptr += offset - (f->end - f->buffer);
else
rptr += offset;
while (buf_size > 0) {
int len;
if (rptr >= f->end)
rptr -= f->end - f->buffer;
len = FFMIN(f->end - rptr, buf_size);
if (func)
func(dest, rptr, len);
else {
memcpy(dest, rptr, len);
dest = (uint8_t *)dest + len;
}
buf_size -= len;
rptr += len;
}
return 0;
}
int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size,
void (*func)(void *, void *, int))
{
// Read memory barrier needed for SMP here in theory
uint8_t *rptr = f->rptr;
do {
int len = FFMIN(f->end - rptr, buf_size);
if (func)
func(dest, rptr, len);
else {
memcpy(dest, rptr, len);
dest = (uint8_t *)dest + len;
}
// memory barrier needed for SMP here in theory
rptr += len;
if (rptr >= f->end)
rptr -= f->end - f->buffer;
buf_size -= len;
} while (buf_size > 0);
return 0;
}
int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size,
void (*func)(void *, void *, int))
{
// Read memory barrier needed for SMP here in theory
do {
int len = FFMIN(f->end - f->rptr, buf_size);
if (func)
func(dest, f->rptr, len);
else {
memcpy(dest, f->rptr, len);
dest = (uint8_t *)dest + len;
}
// memory barrier needed for SMP here in theory
av_fifo_drain(f, len);
buf_size -= len;
} while (buf_size > 0);
return 0;
}
/** Discard data from the FIFO. */
void av_fifo_drain(AVFifoBuffer *f, int size)
{
av_assert2(av_fifo_size(f) >= size);
f->rptr += size;
if (f->rptr >= f->end)
f->rptr -= f->end - f->buffer;
f->rndx += size;
}

View file

@ -0,0 +1,179 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* a very simple circular buffer FIFO implementation
*/
#ifndef AVUTIL_FIFO_H
#define AVUTIL_FIFO_H
#include <stdint.h>
#include "avutil.h"
#include "attributes.h"
typedef struct AVFifoBuffer {
uint8_t *buffer;
uint8_t *rptr, *wptr, *end;
uint32_t rndx, wndx;
} AVFifoBuffer;
/**
* Initialize an AVFifoBuffer.
* @param size of FIFO
* @return AVFifoBuffer or NULL in case of memory allocation failure
*/
AVFifoBuffer *av_fifo_alloc(unsigned int size);
/**
* Initialize an AVFifoBuffer.
* @param nmemb number of elements
* @param size size of the single element
* @return AVFifoBuffer or NULL in case of memory allocation failure
*/
AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size);
/**
* Free an AVFifoBuffer.
* @param f AVFifoBuffer to free
*/
void av_fifo_free(AVFifoBuffer *f);
/**
* Free an AVFifoBuffer and reset pointer to NULL.
* @param f AVFifoBuffer to free
*/
void av_fifo_freep(AVFifoBuffer **f);
/**
* Reset the AVFifoBuffer to the state right after av_fifo_alloc, in particular it is emptied.
* @param f AVFifoBuffer to reset
*/
void av_fifo_reset(AVFifoBuffer *f);
/**
* Return the amount of data in bytes in the AVFifoBuffer, that is the
* amount of data you can read from it.
* @param f AVFifoBuffer to read from
* @return size
*/
int av_fifo_size(const AVFifoBuffer *f);
/**
* Return the amount of space in bytes in the AVFifoBuffer, that is the
* amount of data you can write into it.
* @param f AVFifoBuffer to write into
* @return size
*/
int av_fifo_space(const AVFifoBuffer *f);
/**
* Feed data at specific position from an AVFifoBuffer to a user-supplied callback.
* Similar as av_fifo_gereric_read but without discarding data.
* @param f AVFifoBuffer to read from
* @param offset offset from current read position
* @param buf_size number of bytes to read
* @param func generic read function
* @param dest data destination
*/
int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void (*func)(void*, void*, int));
/**
* Feed data from an AVFifoBuffer to a user-supplied callback.
* Similar as av_fifo_gereric_read but without discarding data.
* @param f AVFifoBuffer to read from
* @param buf_size number of bytes to read
* @param func generic read function
* @param dest data destination
*/
int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int));
/**
* Feed data from an AVFifoBuffer to a user-supplied callback.
* @param f AVFifoBuffer to read from
* @param buf_size number of bytes to read
* @param func generic read function
* @param dest data destination
*/
int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int));
/**
* Feed data from a user-supplied callback to an AVFifoBuffer.
* @param f AVFifoBuffer to write to
* @param src data source; non-const since it may be used as a
* modifiable context by the function defined in func
* @param size number of bytes to write
* @param func generic write function; the first parameter is src,
* the second is dest_buf, the third is dest_buf_size.
* func must return the number of bytes written to dest_buf, or <= 0 to
* indicate no more data available to write.
* If func is NULL, src is interpreted as a simple byte array for source data.
* @return the number of bytes written to the FIFO
*/
int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int));
/**
* Resize an AVFifoBuffer.
* In case of reallocation failure, the old FIFO is kept unchanged.
*
* @param f AVFifoBuffer to resize
* @param size new AVFifoBuffer size in bytes
* @return <0 for failure, >=0 otherwise
*/
int av_fifo_realloc2(AVFifoBuffer *f, unsigned int size);
/**
* Enlarge an AVFifoBuffer.
* In case of reallocation failure, the old FIFO is kept unchanged.
* The new fifo size may be larger than the requested size.
*
* @param f AVFifoBuffer to resize
* @param additional_space the amount of space in bytes to allocate in addition to av_fifo_size()
* @return <0 for failure, >=0 otherwise
*/
int av_fifo_grow(AVFifoBuffer *f, unsigned int additional_space);
/**
* Read and discard the specified amount of data from an AVFifoBuffer.
* @param f AVFifoBuffer to read from
* @param size amount of data to read in bytes
*/
void av_fifo_drain(AVFifoBuffer *f, int size);
/**
* Return a pointer to the data stored in a FIFO buffer at a certain offset.
* The FIFO buffer is not modified.
*
* @param f AVFifoBuffer to peek at, f must be non-NULL
* @param offs an offset in bytes, its absolute value must be less
* than the used buffer size or the returned pointer will
* point outside to the buffer data.
* The used buffer size can be checked with av_fifo_size().
*/
static inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs)
{
uint8_t *ptr = f->rptr + offs;
if (ptr >= f->end)
ptr = f->buffer + (ptr - f->end);
else if (ptr < f->buffer)
ptr = f->end - (f->buffer - ptr);
return ptr;
}
#endif /* AVUTIL_FIFO_H */

View file

@ -0,0 +1,154 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "file.h"
#include "internal.h"
#include "log.h"
#include "mem.h"
#include <fcntl.h>
#include <sys/stat.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_IO_H
#include <io.h>
#endif
#if HAVE_MMAP
#include <sys/mman.h>
#elif HAVE_MAPVIEWOFFILE
#include <windows.h>
#endif
typedef struct FileLogContext {
const AVClass *class;
int log_offset;
void *log_ctx;
} FileLogContext;
static const AVClass file_log_ctx_class = {
.class_name = "FILE",
.item_name = av_default_item_name,
.option = NULL,
.version = LIBAVUTIL_VERSION_INT,
.log_level_offset_offset = offsetof(FileLogContext, log_offset),
.parent_log_context_offset = offsetof(FileLogContext, log_ctx),
};
int av_file_map(const char *filename, uint8_t **bufptr, size_t *size,
int log_offset, void *log_ctx)
{
FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx };
int err, fd = avpriv_open(filename, O_RDONLY);
struct stat st;
av_unused void *ptr;
off_t off_size;
char errbuf[128];
*bufptr = NULL;
if (fd < 0) {
err = AVERROR(errno);
av_strerror(err, errbuf, sizeof(errbuf));
av_log(&file_log_ctx, AV_LOG_ERROR, "Cannot read file '%s': %s\n", filename, errbuf);
return err;
}
if (fstat(fd, &st) < 0) {
err = AVERROR(errno);
av_strerror(err, errbuf, sizeof(errbuf));
av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in fstat(): %s\n", errbuf);
close(fd);
return err;
}
off_size = st.st_size;
if (off_size > SIZE_MAX) {
av_log(&file_log_ctx, AV_LOG_ERROR,
"File size for file '%s' is too big\n", filename);
close(fd);
return AVERROR(EINVAL);
}
*size = off_size;
if (!*size) {
*bufptr = NULL;
goto out;
}
#if HAVE_MMAP
ptr = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
if (ptr == MAP_FAILED) {
err = AVERROR(errno);
av_strerror(err, errbuf, sizeof(errbuf));
av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in mmap(): %s\n", errbuf);
close(fd);
return err;
}
*bufptr = ptr;
#elif HAVE_MAPVIEWOFFILE
{
HANDLE mh, fh = (HANDLE)_get_osfhandle(fd);
mh = CreateFileMapping(fh, NULL, PAGE_READONLY, 0, 0, NULL);
if (!mh) {
av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in CreateFileMapping()\n");
close(fd);
return -1;
}
ptr = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, *size);
CloseHandle(mh);
if (!ptr) {
av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in MapViewOfFile()\n");
close(fd);
return -1;
}
*bufptr = ptr;
}
#else
*bufptr = av_malloc(*size);
if (!*bufptr) {
av_log(&file_log_ctx, AV_LOG_ERROR, "Memory allocation error occurred\n");
close(fd);
return AVERROR(ENOMEM);
}
read(fd, *bufptr, *size);
#endif
out:
close(fd);
return 0;
}
void av_file_unmap(uint8_t *bufptr, size_t size)
{
if (!size)
return;
#if HAVE_MMAP
munmap(bufptr, size);
#elif HAVE_MAPVIEWOFFILE
UnmapViewOfFile(bufptr);
#else
av_free(bufptr);
#endif
}
int av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx) {
return avpriv_tempfile(prefix, filename, log_offset, log_ctx);
}

View file

@ -0,0 +1,71 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_FILE_H
#define AVUTIL_FILE_H
#include <stdint.h>
#include "avutil.h"
/**
* @file
* Misc file utilities.
*/
/**
* Read the file with name filename, and put its content in a newly
* allocated buffer or map it with mmap() when available.
* In case of success set *bufptr to the read or mmapped buffer, and
* *size to the size in bytes of the buffer in *bufptr.
* Unlike mmap this function succeeds with zero sized files, in this
* case *bufptr will be set to NULL and *size will be set to 0.
* The returned buffer must be released with av_file_unmap().
*
* @param log_offset loglevel offset used for logging
* @param log_ctx context used for logging
* @return a non negative number in case of success, a negative value
* corresponding to an AVERROR error code in case of failure
*/
av_warn_unused_result
int av_file_map(const char *filename, uint8_t **bufptr, size_t *size,
int log_offset, void *log_ctx);
/**
* Unmap or free the buffer bufptr created by av_file_map().
*
* @param size size in bytes of bufptr, must be the same as returned
* by av_file_map()
*/
void av_file_unmap(uint8_t *bufptr, size_t size);
/**
* Wrapper to work around the lack of mkstemp() on mingw.
* Also, tries to create file in /tmp first, if possible.
* *prefix can be a character constant; *filename will be allocated internally.
* @return file descriptor of opened file (or negative value corresponding to an
* AVERROR code on error)
* and opened file name in **filename.
* @note On very old libcs it is necessary to set a secure umask before
* calling this, av_tempfile() can't call umask itself as it is used in
* libraries and could interfere with the calling application.
* @deprecated as fd numbers cannot be passed saftely between libs on some platforms
*/
int av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx);
#endif /* AVUTIL_FILE_H */

View file

@ -0,0 +1,190 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "internal.h"
#include "mem.h"
#include <stdarg.h>
#include <fcntl.h>
#include <sys/stat.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_IO_H
#include <io.h>
#endif
#ifdef _WIN32
#undef open
#undef lseek
#undef stat
#undef fstat
#include <windows.h>
#include <share.h>
#include <errno.h>
#include "wchar_filename.h"
static int win32_open(const char *filename_utf8, int oflag, int pmode)
{
int fd;
wchar_t *filename_w;
/* convert UTF-8 to wide chars */
if (utf8towchar(filename_utf8, &filename_w))
return -1;
if (!filename_w)
goto fallback;
fd = _wsopen(filename_w, oflag, SH_DENYNO, pmode);
av_freep(&filename_w);
if (fd != -1 || (oflag & O_CREAT))
return fd;
fallback:
/* filename may be in CP_ACP */
return _sopen(filename_utf8, oflag, SH_DENYNO, pmode);
}
#define open win32_open
#endif
int avpriv_open(const char *filename, int flags, ...)
{
int fd;
unsigned int mode = 0;
va_list ap;
va_start(ap, flags);
if (flags & O_CREAT)
mode = va_arg(ap, unsigned int);
va_end(ap);
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
#ifdef O_NOINHERIT
flags |= O_NOINHERIT;
#endif
fd = open(filename, flags, mode);
#if HAVE_FCNTL
if (fd != -1) {
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
av_log(NULL, AV_LOG_DEBUG, "Failed to set close on exec\n");
}
#endif
return fd;
}
typedef struct FileLogContext {
const AVClass *class;
int log_offset;
void *log_ctx;
} FileLogContext;
static const AVClass file_log_ctx_class = {
.class_name = "TEMPFILE",
.item_name = av_default_item_name,
.option = NULL,
.version = LIBAVUTIL_VERSION_INT,
.log_level_offset_offset = offsetof(FileLogContext, log_offset),
.parent_log_context_offset = offsetof(FileLogContext, log_ctx),
};
int avpriv_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx)
{
FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx };
int fd = -1;
#if !HAVE_MKSTEMP
void *ptr= tempnam(NULL, prefix);
if(!ptr)
ptr= tempnam(".", prefix);
*filename = av_strdup(ptr);
#undef free
free(ptr);
#else
size_t len = strlen(prefix) + 12; /* room for "/tmp/" and "XXXXXX\0" */
*filename = av_malloc(len);
#endif
/* -----common section-----*/
if (!*filename) {
av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot allocate file name\n");
return AVERROR(ENOMEM);
}
#if !HAVE_MKSTEMP
# ifndef O_BINARY
# define O_BINARY 0
# endif
# ifndef O_EXCL
# define O_EXCL 0
# endif
fd = open(*filename, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600);
#else
snprintf(*filename, len, "/tmp/%sXXXXXX", prefix);
fd = mkstemp(*filename);
#if defined(_WIN32) || defined (__ANDROID__) || defined(__DJGPP__)
if (fd < 0) {
snprintf(*filename, len, "./%sXXXXXX", prefix);
fd = mkstemp(*filename);
}
#endif
#endif
/* -----common section-----*/
if (fd < 0) {
int err = AVERROR(errno);
av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot open temporary file %s\n", *filename);
av_freep(filename);
return err;
}
return fd; /* success */
}
FILE *av_fopen_utf8(const char *path, const char *mode)
{
int fd;
int access;
const char *m = mode;
switch (*m++) {
case 'r': access = O_RDONLY; break;
case 'w': access = O_CREAT|O_WRONLY|O_TRUNC; break;
case 'a': access = O_CREAT|O_WRONLY|O_APPEND; break;
default :
errno = EINVAL;
return NULL;
}
while (*m) {
if (*m == '+') {
access &= ~(O_RDONLY | O_WRONLY);
access |= O_RDWR;
} else if (*m == 'b') {
#ifdef O_BINARY
access |= O_BINARY;
#endif
} else if (*m) {
errno = EINVAL;
return NULL;
}
m++;
}
fd = avpriv_open(path, access, 0666);
if (fd == -1)
return NULL;
return fdopen(fd, mode);
}

View file

@ -0,0 +1,167 @@
/*
* Copyright (c) 2012
* MIPS Technologies, Inc., California.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Nedeljko Babic (nedeljko.babic imgtec com)
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "fixed_dsp.h"
static void vector_fmul_add_c(int *dst, const int *src0, const int *src1, const int *src2, int len){
int i;
int64_t accu;
for (i=0; i<len; i++) {
accu = (int64_t)src0[i] * src1[i];
dst[i] = src2[i] + (int)((accu + 0x40000000) >> 31);
}
}
static void vector_fmul_reverse_c(int *dst, const int *src0, const int *src1, int len)
{
int i;
int64_t accu;
src1 += len-1;
for (i=0; i<len; i++) {
accu = (int64_t)src0[i] * src1[-i];
dst[i] = (int)((accu+0x40000000) >> 31);
}
}
static void vector_fmul_window_scaled_c(int16_t *dst, const int32_t *src0,
const int32_t *src1, const int32_t *win,
int len, uint8_t bits)
{
int32_t s0, s1, wi, wj, i,j, round;
dst += len;
win += len;
src0+= len;
round = bits? 1 << (bits-1) : 0;
for (i=-len, j=len-1; i<0; i++, j--) {
s0 = src0[i];
s1 = src1[j];
wi = win[i];
wj = win[j];
dst[i] = av_clip_int16(((((int64_t)s0*wj - (int64_t)s1*wi + 0x40000000) >> 31) + round) >> bits);
dst[j] = av_clip_int16(((((int64_t)s0*wi + (int64_t)s1*wj + 0x40000000) >> 31) + round) >> bits);
}
}
static void vector_fmul_window_c(int32_t *dst, const int32_t *src0,
const int32_t *src1, const int32_t *win,
int len)
{
int32_t s0, s1, wi, wj, i, j;
dst += len;
win += len;
src0+= len;
for (i=-len, j=len-1; i<0; i++, j--) {
s0 = src0[i];
s1 = src1[j];
wi = win[i];
wj = win[j];
dst[i] = ((int64_t)s0*wj - (int64_t)s1*wi + 0x40000000) >> 31;
dst[j] = ((int64_t)s0*wi + (int64_t)s1*wj + 0x40000000) >> 31;
}
}
static void vector_fmul_c(int *dst, const int *src0, const int *src1, int len)
{
int i;
int64_t accu;
for (i = 0; i < len; i++){
accu = (int64_t)src0[i] * src1[i];
dst[i] = (int)((accu+0x40000000) >> 31);
}
}
static int scalarproduct_fixed_c(const int *v1, const int *v2, int len)
{
/** p is initialized with 0x40000000 so that the proper rounding will occur
* at the end */
int64_t p = 0x40000000;
int i;
for (i = 0; i < len; i++)
p += (int64_t)v1[i] * v2[i];
return (int)(p >> 31);
}
static void butterflies_fixed_c(int *v1, int *v2, int len)
{
int i;
for (i = 0; i < len; i++){
int t = v1[i] - v2[i];
v1[i] += v2[i];
v2[i] = t;
}
}
AVFixedDSPContext * avpriv_alloc_fixed_dsp(int bit_exact)
{
AVFixedDSPContext * fdsp = av_malloc(sizeof(AVFixedDSPContext));
if (!fdsp)
return NULL;
fdsp->vector_fmul_window_scaled = vector_fmul_window_scaled_c;
fdsp->vector_fmul_window = vector_fmul_window_c;
fdsp->vector_fmul = vector_fmul_c;
fdsp->vector_fmul_add = vector_fmul_add_c;
fdsp->vector_fmul_reverse = vector_fmul_reverse_c;
fdsp->butterflies_fixed = butterflies_fixed_c;
fdsp->scalarproduct_fixed = scalarproduct_fixed_c;
if (ARCH_X86)
ff_fixed_dsp_init_x86(fdsp);
return fdsp;
}

View file

@ -0,0 +1,205 @@
/*
* Copyright (c) 2012
* MIPS Technologies, Inc., California.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Author: Nedeljko Babic (nbabic@mips.com)
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_FIXED_DSP_H
#define AVUTIL_FIXED_DSP_H
#include <stdint.h>
#include "attributes.h"
#include "common.h"
#include "libavcodec/mathops.h"
typedef struct AVFixedDSPContext {
/* Assume len is a multiple of 16, and arrays are 32-byte aligned */
/* Results of multiplications are scaled down by 31 bit (and rounded) if not
* stated otherwise */
/**
* Overlap/add with window function.
* Result is scaled down by "bits" bits.
* Used primarily by MDCT-based audio codecs.
* Source and destination vectors must overlap exactly or not at all.
*
* @param dst result vector
* constraints: 16-byte aligned
* @param src0 first source vector
* constraints: 16-byte aligned
* @param src1 second source vector
* constraints: 16-byte aligned
* @param win half-window vector
* constraints: 16-byte aligned
* @param len length of vector
* constraints: multiple of 4
* @param bits scaling parameter
*
*/
void (*vector_fmul_window_scaled)(int16_t *dst, const int32_t *src0, const int32_t *src1, const int32_t *win, int len, uint8_t bits);
/**
* Overlap/add with window function.
* Used primarily by MDCT-based audio codecs.
* Source and destination vectors must overlap exactly or not at all.
*
* @param dst result vector
* constraints: 32-byte aligned
* @param src0 first source vector
* constraints: 16-byte aligned
* @param src1 second source vector
* constraints: 16-byte aligned
* @param win half-window vector
* constraints: 16-byte aligned
* @param len length of vector
* constraints: multiple of 4
*/
void (*vector_fmul_window)(int32_t *dst, const int32_t *src0, const int32_t *src1, const int32_t *win, int len);
/**
* Fixed-point multiplication that calculates the entry wise product of two
* vectors of integers and stores the result in a vector of integers.
*
* @param dst output vector
* constraints: 32-byte aligned
* @param src0 first input vector
* constraints: 32-byte aligned
* @param src1 second input vector
* constraints: 32-byte aligned
* @param len number of elements in the input
* constraints: multiple of 16
*/
void (*vector_fmul)(int *dst, const int *src0, const int *src1,
int len);
void (*vector_fmul_reverse)(int *dst, const int *src0, const int *src1, int len);
/**
* Calculate the entry wise product of two vectors of integers, add a third vector of
* integers and store the result in a vector of integers.
*
* @param dst output vector
* constraints: 32-byte aligned
* @param src0 first input vector
* constraints: 32-byte aligned
* @param src1 second input vector
* constraints: 32-byte aligned
* @param src2 third input vector
* constraints: 32-byte aligned
* @param len number of elements in the input
* constraints: multiple of 16
*/
void (*vector_fmul_add)(int *dst, const int *src0, const int *src1,
const int *src2, int len);
/**
* Calculate the scalar product of two vectors of integers.
*
* @param v1 first vector, 16-byte aligned
* @param v2 second vector, 16-byte aligned
* @param len length of vectors, multiple of 4
*
* @return sum of elementwise products
*/
int (*scalarproduct_fixed)(const int *v1, const int *v2, int len);
/**
* Calculate the sum and difference of two vectors of integers.
*
* @param v1 first input vector, sum output, 16-byte aligned
* @param v2 second input vector, difference output, 16-byte aligned
* @param len length of vectors, multiple of 4
*/
void (*butterflies_fixed)(int *av_restrict v1, int *av_restrict v2, int len);
} AVFixedDSPContext;
/**
* Allocate and initialize a fixed DSP context.
* note: should be freed with a av_free call when no longer needed.
*
* @param strict setting to non-zero avoids using functions which may not be IEEE-754 compliant
*/
AVFixedDSPContext * avpriv_alloc_fixed_dsp(int strict);
void ff_fixed_dsp_init_x86(AVFixedDSPContext *fdsp);
/**
* Calculate the square root
*
* @param x input fixed point number
*
* @param bits format of fixed point number (32 - bits).bits
*
* note: input is normalized to (0, 1) fixed point value
*/
static av_always_inline int fixed_sqrt(int x, int bits)
{
int retval, bit_mask, guess, square, i;
int64_t accu;
int shift1 = 30 - bits;
int shift2 = bits - 15;
if (shift1 > 0) retval = ff_sqrt(x << shift1);
else retval = ff_sqrt(x >> -shift1);
if (shift2 > 0) {
retval = retval << shift2;
bit_mask = (1 << (shift2 - 1));
for (i=0; i<shift2; i++){
guess = retval + bit_mask;
accu = (int64_t)guess * guess;
square = (int)((accu + bit_mask) >> bits);
if (x >= square)
retval += bit_mask;
bit_mask >>= 1;
}
}
else retval >>= (-shift2);
return retval;
}
#endif /* AVUTIL_FIXED_DSP_H */

View file

@ -0,0 +1,164 @@
/*
* Copyright 2005 Balatoni Denes
* Copyright 2006 Loren Merritt
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "attributes.h"
#include "float_dsp.h"
#include "mem.h"
static void vector_fmul_c(float *dst, const float *src0, const float *src1,
int len)
{
int i;
for (i = 0; i < len; i++)
dst[i] = src0[i] * src1[i];
}
static void vector_dmul_c(double *dst, const double *src0, const double *src1,
int len)
{
int i;
for (i = 0; i < len; i++)
dst[i] = src0[i] * src1[i];
}
static void vector_fmac_scalar_c(float *dst, const float *src, float mul,
int len)
{
int i;
for (i = 0; i < len; i++)
dst[i] += src[i] * mul;
}
static void vector_dmac_scalar_c(double *dst, const double *src, double mul,
int len)
{
int i;
for (i = 0; i < len; i++)
dst[i] += src[i] * mul;
}
static void vector_fmul_scalar_c(float *dst, const float *src, float mul,
int len)
{
int i;
for (i = 0; i < len; i++)
dst[i] = src[i] * mul;
}
static void vector_dmul_scalar_c(double *dst, const double *src, double mul,
int len)
{
int i;
for (i = 0; i < len; i++)
dst[i] = src[i] * mul;
}
static void vector_fmul_window_c(float *dst, const float *src0,
const float *src1, const float *win, int len)
{
int i, j;
dst += len;
win += len;
src0 += len;
for (i = -len, j = len - 1; i < 0; i++, j--) {
float s0 = src0[i];
float s1 = src1[j];
float wi = win[i];
float wj = win[j];
dst[i] = s0 * wj - s1 * wi;
dst[j] = s0 * wi + s1 * wj;
}
}
static void vector_fmul_add_c(float *dst, const float *src0, const float *src1,
const float *src2, int len){
int i;
for (i = 0; i < len; i++)
dst[i] = src0[i] * src1[i] + src2[i];
}
static void vector_fmul_reverse_c(float *dst, const float *src0,
const float *src1, int len)
{
int i;
src1 += len-1;
for (i = 0; i < len; i++)
dst[i] = src0[i] * src1[-i];
}
static void butterflies_float_c(float *av_restrict v1, float *av_restrict v2,
int len)
{
int i;
for (i = 0; i < len; i++) {
float t = v1[i] - v2[i];
v1[i] += v2[i];
v2[i] = t;
}
}
float avpriv_scalarproduct_float_c(const float *v1, const float *v2, int len)
{
float p = 0.0;
int i;
for (i = 0; i < len; i++)
p += v1[i] * v2[i];
return p;
}
av_cold AVFloatDSPContext *avpriv_float_dsp_alloc(int bit_exact)
{
AVFloatDSPContext *fdsp = av_mallocz(sizeof(AVFloatDSPContext));
if (!fdsp)
return NULL;
fdsp->vector_fmul = vector_fmul_c;
fdsp->vector_dmul = vector_dmul_c;
fdsp->vector_fmac_scalar = vector_fmac_scalar_c;
fdsp->vector_fmul_scalar = vector_fmul_scalar_c;
fdsp->vector_dmac_scalar = vector_dmac_scalar_c;
fdsp->vector_dmul_scalar = vector_dmul_scalar_c;
fdsp->vector_fmul_window = vector_fmul_window_c;
fdsp->vector_fmul_add = vector_fmul_add_c;
fdsp->vector_fmul_reverse = vector_fmul_reverse_c;
fdsp->butterflies_float = butterflies_float_c;
fdsp->scalarproduct_float = avpriv_scalarproduct_float_c;
if (ARCH_AARCH64)
ff_float_dsp_init_aarch64(fdsp);
if (ARCH_ARM)
ff_float_dsp_init_arm(fdsp);
if (ARCH_PPC)
ff_float_dsp_init_ppc(fdsp, bit_exact);
if (ARCH_X86)
ff_float_dsp_init_x86(fdsp);
if (ARCH_MIPS)
ff_float_dsp_init_mips(fdsp);
return fdsp;
}

View file

@ -0,0 +1,218 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_FLOAT_DSP_H
#define AVUTIL_FLOAT_DSP_H
#include "config.h"
typedef struct AVFloatDSPContext {
/**
* Calculate the entry wise product of two vectors of floats and store the result in
* a vector of floats.
*
* @param dst output vector
* constraints: 32-byte aligned
* @param src0 first input vector
* constraints: 32-byte aligned
* @param src1 second input vector
* constraints: 32-byte aligned
* @param len number of elements in the input
* constraints: multiple of 16
*/
void (*vector_fmul)(float *dst, const float *src0, const float *src1,
int len);
/**
* Multiply a vector of floats by a scalar float and add to
* destination vector. Source and destination vectors must
* overlap exactly or not at all.
*
* @param dst result vector
* constraints: 32-byte aligned
* @param src input vector
* constraints: 32-byte aligned
* @param mul scalar value
* @param len length of vector
* constraints: multiple of 16
*/
void (*vector_fmac_scalar)(float *dst, const float *src, float mul,
int len);
/**
* Multiply a vector of doubles by a scalar double and add to
* destination vector. Source and destination vectors must
* overlap exactly or not at all.
*
* @param dst result vector
* constraints: 32-byte aligned
* @param src input vector
* constraints: 32-byte aligned
* @param mul scalar value
* @param len length of vector
* constraints: multiple of 16
*/
void (*vector_dmac_scalar)(double *dst, const double *src, double mul,
int len);
/**
* Multiply a vector of floats by a scalar float. Source and
* destination vectors must overlap exactly or not at all.
*
* @param dst result vector
* constraints: 16-byte aligned
* @param src input vector
* constraints: 16-byte aligned
* @param mul scalar value
* @param len length of vector
* constraints: multiple of 4
*/
void (*vector_fmul_scalar)(float *dst, const float *src, float mul,
int len);
/**
* Multiply a vector of double by a scalar double. Source and
* destination vectors must overlap exactly or not at all.
*
* @param dst result vector
* constraints: 32-byte aligned
* @param src input vector
* constraints: 32-byte aligned
* @param mul scalar value
* @param len length of vector
* constraints: multiple of 8
*/
void (*vector_dmul_scalar)(double *dst, const double *src, double mul,
int len);
/**
* Overlap/add with window function.
* Used primarily by MDCT-based audio codecs.
* Source and destination vectors must overlap exactly or not at all.
*
* @param dst result vector
* constraints: 16-byte aligned
* @param src0 first source vector
* constraints: 16-byte aligned
* @param src1 second source vector
* constraints: 16-byte aligned
* @param win half-window vector
* constraints: 16-byte aligned
* @param len length of vector
* constraints: multiple of 4
*/
void (*vector_fmul_window)(float *dst, const float *src0,
const float *src1, const float *win, int len);
/**
* Calculate the entry wise product of two vectors of floats, add a third vector of
* floats and store the result in a vector of floats.
*
* @param dst output vector
* constraints: 32-byte aligned
* @param src0 first input vector
* constraints: 32-byte aligned
* @param src1 second input vector
* constraints: 32-byte aligned
* @param src2 third input vector
* constraints: 32-byte aligned
* @param len number of elements in the input
* constraints: multiple of 16
*/
void (*vector_fmul_add)(float *dst, const float *src0, const float *src1,
const float *src2, int len);
/**
* Calculate the entry wise product of two vectors of floats, and store the result
* in a vector of floats. The second vector of floats is iterated over
* in reverse order.
*
* @param dst output vector
* constraints: 32-byte aligned
* @param src0 first input vector
* constraints: 32-byte aligned
* @param src1 second input vector
* constraints: 32-byte aligned
* @param len number of elements in the input
* constraints: multiple of 16
*/
void (*vector_fmul_reverse)(float *dst, const float *src0,
const float *src1, int len);
/**
* Calculate the sum and difference of two vectors of floats.
*
* @param v1 first input vector, sum output, 16-byte aligned
* @param v2 second input vector, difference output, 16-byte aligned
* @param len length of vectors, multiple of 4
*/
void (*butterflies_float)(float *av_restrict v1, float *av_restrict v2, int len);
/**
* Calculate the scalar product of two vectors of floats.
*
* @param v1 first vector, 16-byte aligned
* @param v2 second vector, 16-byte aligned
* @param len length of vectors, multiple of 4
*
* @return sum of elementwise products
*/
float (*scalarproduct_float)(const float *v1, const float *v2, int len);
/**
* Calculate the entry wise product of two vectors of doubles and store the result in
* a vector of doubles.
*
* @param dst output vector
* constraints: 32-byte aligned
* @param src0 first input vector
* constraints: 32-byte aligned
* @param src1 second input vector
* constraints: 32-byte aligned
* @param len number of elements in the input
* constraints: multiple of 16
*/
void (*vector_dmul)(double *dst, const double *src0, const double *src1,
int len);
} AVFloatDSPContext;
/**
* Return the scalar product of two vectors.
*
* @param v1 first input vector
* @param v2 first input vector
* @param len number of elements
*
* @return sum of elementwise products
*/
float avpriv_scalarproduct_float_c(const float *v1, const float *v2, int len);
void ff_float_dsp_init_aarch64(AVFloatDSPContext *fdsp);
void ff_float_dsp_init_arm(AVFloatDSPContext *fdsp);
void ff_float_dsp_init_ppc(AVFloatDSPContext *fdsp, int strict);
void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp);
void ff_float_dsp_init_mips(AVFloatDSPContext *fdsp);
/**
* Allocate a float DSP context.
*
* @param strict setting to non-zero avoids using functions which may not be IEEE-754 compliant
*/
AVFloatDSPContext *avpriv_float_dsp_alloc(int strict);
#endif /* AVUTIL_FLOAT_DSP_H */

View file

@ -0,0 +1,947 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "channel_layout.h"
#include "avassert.h"
#include "buffer.h"
#include "common.h"
#include "dict.h"
#include "frame.h"
#include "imgutils.h"
#include "mem.h"
#include "samplefmt.h"
#if FF_API_FRAME_GET_SET
MAKE_ACCESSORS(AVFrame, frame, int64_t, best_effort_timestamp)
MAKE_ACCESSORS(AVFrame, frame, int64_t, pkt_duration)
MAKE_ACCESSORS(AVFrame, frame, int64_t, pkt_pos)
MAKE_ACCESSORS(AVFrame, frame, int64_t, channel_layout)
MAKE_ACCESSORS(AVFrame, frame, int, channels)
MAKE_ACCESSORS(AVFrame, frame, int, sample_rate)
MAKE_ACCESSORS(AVFrame, frame, AVDictionary *, metadata)
MAKE_ACCESSORS(AVFrame, frame, int, decode_error_flags)
MAKE_ACCESSORS(AVFrame, frame, int, pkt_size)
MAKE_ACCESSORS(AVFrame, frame, enum AVColorSpace, colorspace)
MAKE_ACCESSORS(AVFrame, frame, enum AVColorRange, color_range)
#endif
#define CHECK_CHANNELS_CONSISTENCY(frame) \
av_assert2(!(frame)->channel_layout || \
(frame)->channels == \
av_get_channel_layout_nb_channels((frame)->channel_layout))
#if FF_API_FRAME_QP
struct qp_properties {
int stride;
int type;
};
int av_frame_set_qp_table(AVFrame *f, AVBufferRef *buf, int stride, int qp_type)
{
struct qp_properties *p;
AVFrameSideData *sd;
AVBufferRef *ref;
FF_DISABLE_DEPRECATION_WARNINGS
av_buffer_unref(&f->qp_table_buf);
f->qp_table_buf = buf;
f->qscale_table = buf->data;
f->qstride = stride;
f->qscale_type = qp_type;
FF_ENABLE_DEPRECATION_WARNINGS
av_frame_remove_side_data(f, AV_FRAME_DATA_QP_TABLE_PROPERTIES);
av_frame_remove_side_data(f, AV_FRAME_DATA_QP_TABLE_DATA);
ref = av_buffer_ref(buf);
if (!av_frame_new_side_data_from_buf(f, AV_FRAME_DATA_QP_TABLE_DATA, ref)) {
av_buffer_unref(&ref);
return AVERROR(ENOMEM);
}
sd = av_frame_new_side_data(f, AV_FRAME_DATA_QP_TABLE_PROPERTIES,
sizeof(struct qp_properties));
if (!sd)
return AVERROR(ENOMEM);
p = (struct qp_properties *)sd->data;
p->stride = stride;
p->type = qp_type;
return 0;
}
int8_t *av_frame_get_qp_table(AVFrame *f, int *stride, int *type)
{
AVBufferRef *buf = NULL;
*stride = 0;
*type = 0;
FF_DISABLE_DEPRECATION_WARNINGS
if (f->qp_table_buf) {
*stride = f->qstride;
*type = f->qscale_type;
buf = f->qp_table_buf;
FF_ENABLE_DEPRECATION_WARNINGS
} else {
AVFrameSideData *sd;
struct qp_properties *p;
sd = av_frame_get_side_data(f, AV_FRAME_DATA_QP_TABLE_PROPERTIES);
if (!sd)
return NULL;
p = (struct qp_properties *)sd->data;
sd = av_frame_get_side_data(f, AV_FRAME_DATA_QP_TABLE_DATA);
if (!sd)
return NULL;
*stride = p->stride;
*type = p->type;
buf = sd->buf;
}
return buf ? buf->data : NULL;
}
#endif
const char *av_get_colorspace_name(enum AVColorSpace val)
{
static const char * const name[] = {
[AVCOL_SPC_RGB] = "GBR",
[AVCOL_SPC_BT709] = "bt709",
[AVCOL_SPC_FCC] = "fcc",
[AVCOL_SPC_BT470BG] = "bt470bg",
[AVCOL_SPC_SMPTE170M] = "smpte170m",
[AVCOL_SPC_SMPTE240M] = "smpte240m",
[AVCOL_SPC_YCOCG] = "YCgCo",
};
if ((unsigned)val >= FF_ARRAY_ELEMS(name))
return NULL;
return name[val];
}
static void get_frame_defaults(AVFrame *frame)
{
if (frame->extended_data != frame->data)
av_freep(&frame->extended_data);
memset(frame, 0, sizeof(*frame));
frame->pts =
frame->pkt_dts = AV_NOPTS_VALUE;
#if FF_API_PKT_PTS
FF_DISABLE_DEPRECATION_WARNINGS
frame->pkt_pts = AV_NOPTS_VALUE;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
frame->best_effort_timestamp = AV_NOPTS_VALUE;
frame->pkt_duration = 0;
frame->pkt_pos = -1;
frame->pkt_size = -1;
frame->key_frame = 1;
frame->sample_aspect_ratio = (AVRational){ 0, 1 };
frame->format = -1; /* unknown */
frame->extended_data = frame->data;
frame->color_primaries = AVCOL_PRI_UNSPECIFIED;
frame->color_trc = AVCOL_TRC_UNSPECIFIED;
frame->colorspace = AVCOL_SPC_UNSPECIFIED;
frame->color_range = AVCOL_RANGE_UNSPECIFIED;
frame->chroma_location = AVCHROMA_LOC_UNSPECIFIED;
frame->flags = 0;
}
static void free_side_data(AVFrameSideData **ptr_sd)
{
AVFrameSideData *sd = *ptr_sd;
av_buffer_unref(&sd->buf);
av_dict_free(&sd->metadata);
av_freep(ptr_sd);
}
static void wipe_side_data(AVFrame *frame)
{
int i;
for (i = 0; i < frame->nb_side_data; i++) {
free_side_data(&frame->side_data[i]);
}
frame->nb_side_data = 0;
av_freep(&frame->side_data);
}
AVFrame *av_frame_alloc(void)
{
AVFrame *frame = av_mallocz(sizeof(*frame));
if (!frame)
return NULL;
frame->extended_data = NULL;
get_frame_defaults(frame);
return frame;
}
void av_frame_free(AVFrame **frame)
{
if (!frame || !*frame)
return;
av_frame_unref(*frame);
av_freep(frame);
}
static int get_video_buffer(AVFrame *frame, int align)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
int ret, i, padded_height;
int plane_padding = FFMAX(16 + 16/*STRIDE_ALIGN*/, align);
if (!desc)
return AVERROR(EINVAL);
if ((ret = av_image_check_size(frame->width, frame->height, 0, NULL)) < 0)
return ret;
if (!frame->linesize[0]) {
if (align <= 0)
align = 32; /* STRIDE_ALIGN. Should be av_cpu_max_align() */
for(i=1; i<=align; i+=i) {
ret = av_image_fill_linesizes(frame->linesize, frame->format,
FFALIGN(frame->width, i));
if (ret < 0)
return ret;
if (!(frame->linesize[0] & (align-1)))
break;
}
for (i = 0; i < 4 && frame->linesize[i]; i++)
frame->linesize[i] = FFALIGN(frame->linesize[i], align);
}
padded_height = FFALIGN(frame->height, 32);
if ((ret = av_image_fill_pointers(frame->data, frame->format, padded_height,
NULL, frame->linesize)) < 0)
return ret;
frame->buf[0] = av_buffer_alloc(ret + 4*plane_padding);
if (!frame->buf[0]) {
ret = AVERROR(ENOMEM);
goto fail;
}
if ((ret = av_image_fill_pointers(frame->data, frame->format, padded_height,
frame->buf[0]->data, frame->linesize)) < 0)
goto fail;
for (i = 1; i < 4; i++) {
if (frame->data[i])
frame->data[i] += i * plane_padding;
}
frame->extended_data = frame->data;
return 0;
fail:
av_frame_unref(frame);
return ret;
}
static int get_audio_buffer(AVFrame *frame, int align)
{
int channels;
int planar = av_sample_fmt_is_planar(frame->format);
int planes;
int ret, i;
if (!frame->channels)
frame->channels = av_get_channel_layout_nb_channels(frame->channel_layout);
channels = frame->channels;
planes = planar ? channels : 1;
CHECK_CHANNELS_CONSISTENCY(frame);
if (!frame->linesize[0]) {
ret = av_samples_get_buffer_size(&frame->linesize[0], channels,
frame->nb_samples, frame->format,
align);
if (ret < 0)
return ret;
}
if (planes > AV_NUM_DATA_POINTERS) {
frame->extended_data = av_mallocz_array(planes,
sizeof(*frame->extended_data));
frame->extended_buf = av_mallocz_array((planes - AV_NUM_DATA_POINTERS),
sizeof(*frame->extended_buf));
if (!frame->extended_data || !frame->extended_buf) {
av_freep(&frame->extended_data);
av_freep(&frame->extended_buf);
return AVERROR(ENOMEM);
}
frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS;
} else
frame->extended_data = frame->data;
for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) {
frame->buf[i] = av_buffer_alloc(frame->linesize[0]);
if (!frame->buf[i]) {
av_frame_unref(frame);
return AVERROR(ENOMEM);
}
frame->extended_data[i] = frame->data[i] = frame->buf[i]->data;
}
for (i = 0; i < planes - AV_NUM_DATA_POINTERS; i++) {
frame->extended_buf[i] = av_buffer_alloc(frame->linesize[0]);
if (!frame->extended_buf[i]) {
av_frame_unref(frame);
return AVERROR(ENOMEM);
}
frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data;
}
return 0;
}
int av_frame_get_buffer(AVFrame *frame, int align)
{
if (frame->format < 0)
return AVERROR(EINVAL);
if (frame->width > 0 && frame->height > 0)
return get_video_buffer(frame, align);
else if (frame->nb_samples > 0 && (frame->channel_layout || frame->channels > 0))
return get_audio_buffer(frame, align);
return AVERROR(EINVAL);
}
static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy)
{
int i;
dst->key_frame = src->key_frame;
dst->pict_type = src->pict_type;
dst->sample_aspect_ratio = src->sample_aspect_ratio;
dst->crop_top = src->crop_top;
dst->crop_bottom = src->crop_bottom;
dst->crop_left = src->crop_left;
dst->crop_right = src->crop_right;
dst->pts = src->pts;
dst->repeat_pict = src->repeat_pict;
dst->interlaced_frame = src->interlaced_frame;
dst->top_field_first = src->top_field_first;
dst->palette_has_changed = src->palette_has_changed;
dst->sample_rate = src->sample_rate;
dst->opaque = src->opaque;
#if FF_API_PKT_PTS
FF_DISABLE_DEPRECATION_WARNINGS
dst->pkt_pts = src->pkt_pts;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
dst->pkt_dts = src->pkt_dts;
dst->pkt_pos = src->pkt_pos;
dst->pkt_size = src->pkt_size;
dst->pkt_duration = src->pkt_duration;
dst->reordered_opaque = src->reordered_opaque;
dst->quality = src->quality;
dst->best_effort_timestamp = src->best_effort_timestamp;
dst->coded_picture_number = src->coded_picture_number;
dst->display_picture_number = src->display_picture_number;
dst->flags = src->flags;
dst->decode_error_flags = src->decode_error_flags;
dst->color_primaries = src->color_primaries;
dst->color_trc = src->color_trc;
dst->colorspace = src->colorspace;
dst->color_range = src->color_range;
dst->chroma_location = src->chroma_location;
av_dict_copy(&dst->metadata, src->metadata, 0);
#if FF_API_ERROR_FRAME
FF_DISABLE_DEPRECATION_WARNINGS
memcpy(dst->error, src->error, sizeof(dst->error));
FF_ENABLE_DEPRECATION_WARNINGS
#endif
for (i = 0; i < src->nb_side_data; i++) {
const AVFrameSideData *sd_src = src->side_data[i];
AVFrameSideData *sd_dst;
if ( sd_src->type == AV_FRAME_DATA_PANSCAN
&& (src->width != dst->width || src->height != dst->height))
continue;
if (force_copy) {
sd_dst = av_frame_new_side_data(dst, sd_src->type,
sd_src->size);
if (!sd_dst) {
wipe_side_data(dst);
return AVERROR(ENOMEM);
}
memcpy(sd_dst->data, sd_src->data, sd_src->size);
} else {
AVBufferRef *ref = av_buffer_ref(sd_src->buf);
sd_dst = av_frame_new_side_data_from_buf(dst, sd_src->type, ref);
if (!sd_dst) {
av_buffer_unref(&ref);
wipe_side_data(dst);
return AVERROR(ENOMEM);
}
}
av_dict_copy(&sd_dst->metadata, sd_src->metadata, 0);
}
#if FF_API_FRAME_QP
FF_DISABLE_DEPRECATION_WARNINGS
dst->qscale_table = NULL;
dst->qstride = 0;
dst->qscale_type = 0;
av_buffer_unref(&dst->qp_table_buf);
if (src->qp_table_buf) {
dst->qp_table_buf = av_buffer_ref(src->qp_table_buf);
if (dst->qp_table_buf) {
dst->qscale_table = dst->qp_table_buf->data;
dst->qstride = src->qstride;
dst->qscale_type = src->qscale_type;
}
}
FF_ENABLE_DEPRECATION_WARNINGS
#endif
av_buffer_unref(&dst->opaque_ref);
av_buffer_unref(&dst->private_ref);
if (src->opaque_ref) {
dst->opaque_ref = av_buffer_ref(src->opaque_ref);
if (!dst->opaque_ref)
return AVERROR(ENOMEM);
}
if (src->private_ref) {
dst->private_ref = av_buffer_ref(src->private_ref);
if (!dst->private_ref)
return AVERROR(ENOMEM);
}
return 0;
}
int av_frame_ref(AVFrame *dst, const AVFrame *src)
{
int i, ret = 0;
av_assert1(dst->width == 0 && dst->height == 0);
av_assert1(dst->channels == 0);
dst->format = src->format;
dst->width = src->width;
dst->height = src->height;
dst->channels = src->channels;
dst->channel_layout = src->channel_layout;
dst->nb_samples = src->nb_samples;
ret = frame_copy_props(dst, src, 0);
if (ret < 0)
return ret;
/* duplicate the frame data if it's not refcounted */
if (!src->buf[0]) {
ret = av_frame_get_buffer(dst, 32);
if (ret < 0)
return ret;
ret = av_frame_copy(dst, src);
if (ret < 0)
av_frame_unref(dst);
return ret;
}
/* ref the buffers */
for (i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) {
if (!src->buf[i])
continue;
dst->buf[i] = av_buffer_ref(src->buf[i]);
if (!dst->buf[i]) {
ret = AVERROR(ENOMEM);
goto fail;
}
}
if (src->extended_buf) {
dst->extended_buf = av_mallocz_array(sizeof(*dst->extended_buf),
src->nb_extended_buf);
if (!dst->extended_buf) {
ret = AVERROR(ENOMEM);
goto fail;
}
dst->nb_extended_buf = src->nb_extended_buf;
for (i = 0; i < src->nb_extended_buf; i++) {
dst->extended_buf[i] = av_buffer_ref(src->extended_buf[i]);
if (!dst->extended_buf[i]) {
ret = AVERROR(ENOMEM);
goto fail;
}
}
}
if (src->hw_frames_ctx) {
dst->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx);
if (!dst->hw_frames_ctx) {
ret = AVERROR(ENOMEM);
goto fail;
}
}
/* duplicate extended data */
if (src->extended_data != src->data) {
int ch = src->channels;
if (!ch) {
ret = AVERROR(EINVAL);
goto fail;
}
CHECK_CHANNELS_CONSISTENCY(src);
dst->extended_data = av_malloc_array(sizeof(*dst->extended_data), ch);
if (!dst->extended_data) {
ret = AVERROR(ENOMEM);
goto fail;
}
memcpy(dst->extended_data, src->extended_data, sizeof(*src->extended_data) * ch);
} else
dst->extended_data = dst->data;
memcpy(dst->data, src->data, sizeof(src->data));
memcpy(dst->linesize, src->linesize, sizeof(src->linesize));
return 0;
fail:
av_frame_unref(dst);
return ret;
}
AVFrame *av_frame_clone(const AVFrame *src)
{
AVFrame *ret = av_frame_alloc();
if (!ret)
return NULL;
if (av_frame_ref(ret, src) < 0)
av_frame_free(&ret);
return ret;
}
void av_frame_unref(AVFrame *frame)
{
int i;
if (!frame)
return;
wipe_side_data(frame);
for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)
av_buffer_unref(&frame->buf[i]);
for (i = 0; i < frame->nb_extended_buf; i++)
av_buffer_unref(&frame->extended_buf[i]);
av_freep(&frame->extended_buf);
av_dict_free(&frame->metadata);
#if FF_API_FRAME_QP
FF_DISABLE_DEPRECATION_WARNINGS
av_buffer_unref(&frame->qp_table_buf);
FF_ENABLE_DEPRECATION_WARNINGS
#endif
av_buffer_unref(&frame->hw_frames_ctx);
av_buffer_unref(&frame->opaque_ref);
av_buffer_unref(&frame->private_ref);
get_frame_defaults(frame);
}
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
{
av_assert1(dst->width == 0 && dst->height == 0);
av_assert1(dst->channels == 0);
*dst = *src;
if (src->extended_data == src->data)
dst->extended_data = dst->data;
memset(src, 0, sizeof(*src));
get_frame_defaults(src);
}
int av_frame_is_writable(AVFrame *frame)
{
int i, ret = 1;
/* assume non-refcounted frames are not writable */
if (!frame->buf[0])
return 0;
for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)
if (frame->buf[i])
ret &= !!av_buffer_is_writable(frame->buf[i]);
for (i = 0; i < frame->nb_extended_buf; i++)
ret &= !!av_buffer_is_writable(frame->extended_buf[i]);
return ret;
}
int av_frame_make_writable(AVFrame *frame)
{
AVFrame tmp;
int ret;
if (!frame->buf[0])
return AVERROR(EINVAL);
if (av_frame_is_writable(frame))
return 0;
memset(&tmp, 0, sizeof(tmp));
tmp.format = frame->format;
tmp.width = frame->width;
tmp.height = frame->height;
tmp.channels = frame->channels;
tmp.channel_layout = frame->channel_layout;
tmp.nb_samples = frame->nb_samples;
ret = av_frame_get_buffer(&tmp, 32);
if (ret < 0)
return ret;
ret = av_frame_copy(&tmp, frame);
if (ret < 0) {
av_frame_unref(&tmp);
return ret;
}
ret = av_frame_copy_props(&tmp, frame);
if (ret < 0) {
av_frame_unref(&tmp);
return ret;
}
av_frame_unref(frame);
*frame = tmp;
if (tmp.data == tmp.extended_data)
frame->extended_data = frame->data;
return 0;
}
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
{
return frame_copy_props(dst, src, 1);
}
AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane)
{
uint8_t *data;
int planes, i;
if (frame->nb_samples) {
int channels = frame->channels;
if (!channels)
return NULL;
CHECK_CHANNELS_CONSISTENCY(frame);
planes = av_sample_fmt_is_planar(frame->format) ? channels : 1;
} else
planes = 4;
if (plane < 0 || plane >= planes || !frame->extended_data[plane])
return NULL;
data = frame->extended_data[plane];
for (i = 0; i < FF_ARRAY_ELEMS(frame->buf) && frame->buf[i]; i++) {
AVBufferRef *buf = frame->buf[i];
if (data >= buf->data && data < buf->data + buf->size)
return buf;
}
for (i = 0; i < frame->nb_extended_buf; i++) {
AVBufferRef *buf = frame->extended_buf[i];
if (data >= buf->data && data < buf->data + buf->size)
return buf;
}
return NULL;
}
AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame,
enum AVFrameSideDataType type,
AVBufferRef *buf)
{
AVFrameSideData *ret, **tmp;
if (!buf)
return NULL;
if (frame->nb_side_data > INT_MAX / sizeof(*frame->side_data) - 1)
return NULL;
tmp = av_realloc(frame->side_data,
(frame->nb_side_data + 1) * sizeof(*frame->side_data));
if (!tmp)
return NULL;
frame->side_data = tmp;
ret = av_mallocz(sizeof(*ret));
if (!ret)
return NULL;
ret->buf = buf;
ret->data = ret->buf->data;
ret->size = buf->size;
ret->type = type;
frame->side_data[frame->nb_side_data++] = ret;
return ret;
}
AVFrameSideData *av_frame_new_side_data(AVFrame *frame,
enum AVFrameSideDataType type,
int size)
{
AVFrameSideData *ret;
AVBufferRef *buf = av_buffer_alloc(size);
ret = av_frame_new_side_data_from_buf(frame, type, buf);
if (!ret)
av_buffer_unref(&buf);
return ret;
}
AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
enum AVFrameSideDataType type)
{
int i;
for (i = 0; i < frame->nb_side_data; i++) {
if (frame->side_data[i]->type == type)
return frame->side_data[i];
}
return NULL;
}
static int frame_copy_video(AVFrame *dst, const AVFrame *src)
{
const uint8_t *src_data[4];
int i, planes;
if (dst->width < src->width ||
dst->height < src->height)
return AVERROR(EINVAL);
planes = av_pix_fmt_count_planes(dst->format);
for (i = 0; i < planes; i++)
if (!dst->data[i] || !src->data[i])
return AVERROR(EINVAL);
memcpy(src_data, src->data, sizeof(src_data));
av_image_copy(dst->data, dst->linesize,
src_data, src->linesize,
dst->format, src->width, src->height);
return 0;
}
static int frame_copy_audio(AVFrame *dst, const AVFrame *src)
{
int planar = av_sample_fmt_is_planar(dst->format);
int channels = dst->channels;
int planes = planar ? channels : 1;
int i;
if (dst->nb_samples != src->nb_samples ||
dst->channels != src->channels ||
dst->channel_layout != src->channel_layout)
return AVERROR(EINVAL);
CHECK_CHANNELS_CONSISTENCY(src);
for (i = 0; i < planes; i++)
if (!dst->extended_data[i] || !src->extended_data[i])
return AVERROR(EINVAL);
av_samples_copy(dst->extended_data, src->extended_data, 0, 0,
dst->nb_samples, channels, dst->format);
return 0;
}
int av_frame_copy(AVFrame *dst, const AVFrame *src)
{
if (dst->format != src->format || dst->format < 0)
return AVERROR(EINVAL);
if (dst->width > 0 && dst->height > 0)
return frame_copy_video(dst, src);
else if (dst->nb_samples > 0 && dst->channels > 0)
return frame_copy_audio(dst, src);
return AVERROR(EINVAL);
}
void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type)
{
int i;
for (i = 0; i < frame->nb_side_data; i++) {
AVFrameSideData *sd = frame->side_data[i];
if (sd->type == type) {
free_side_data(&frame->side_data[i]);
frame->side_data[i] = frame->side_data[frame->nb_side_data - 1];
frame->nb_side_data--;
}
}
}
const char *av_frame_side_data_name(enum AVFrameSideDataType type)
{
switch(type) {
case AV_FRAME_DATA_PANSCAN: return "AVPanScan";
case AV_FRAME_DATA_A53_CC: return "ATSC A53 Part 4 Closed Captions";
case AV_FRAME_DATA_STEREO3D: return "Stereo 3D";
case AV_FRAME_DATA_MATRIXENCODING: return "AVMatrixEncoding";
case AV_FRAME_DATA_DOWNMIX_INFO: return "Metadata relevant to a downmix procedure";
case AV_FRAME_DATA_REPLAYGAIN: return "AVReplayGain";
case AV_FRAME_DATA_DISPLAYMATRIX: return "3x3 displaymatrix";
case AV_FRAME_DATA_AFD: return "Active format description";
case AV_FRAME_DATA_MOTION_VECTORS: return "Motion vectors";
case AV_FRAME_DATA_SKIP_SAMPLES: return "Skip samples";
case AV_FRAME_DATA_AUDIO_SERVICE_TYPE: return "Audio service type";
case AV_FRAME_DATA_MASTERING_DISPLAY_METADATA: return "Mastering display metadata";
case AV_FRAME_DATA_CONTENT_LIGHT_LEVEL: return "Content light level metadata";
case AV_FRAME_DATA_GOP_TIMECODE: return "GOP timecode";
case AV_FRAME_DATA_S12M_TIMECODE: return "SMPTE 12-1 timecode";
case AV_FRAME_DATA_SPHERICAL: return "Spherical Mapping";
case AV_FRAME_DATA_ICC_PROFILE: return "ICC profile";
#if FF_API_FRAME_QP
case AV_FRAME_DATA_QP_TABLE_PROPERTIES: return "QP table properties";
case AV_FRAME_DATA_QP_TABLE_DATA: return "QP table data";
#endif
case AV_FRAME_DATA_DYNAMIC_HDR_PLUS: return "HDR Dynamic Metadata SMPTE2094-40 (HDR10+)";
case AV_FRAME_DATA_REGIONS_OF_INTEREST: return "Regions Of Interest";
}
return NULL;
}
static int calc_cropping_offsets(size_t offsets[4], const AVFrame *frame,
const AVPixFmtDescriptor *desc)
{
int i, j;
for (i = 0; frame->data[i]; i++) {
const AVComponentDescriptor *comp = NULL;
int shift_x = (i == 1 || i == 2) ? desc->log2_chroma_w : 0;
int shift_y = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
if (desc->flags & (AV_PIX_FMT_FLAG_PAL | FF_PSEUDOPAL) && i == 1) {
offsets[i] = 0;
break;
}
/* find any component descriptor for this plane */
for (j = 0; j < desc->nb_components; j++) {
if (desc->comp[j].plane == i) {
comp = &desc->comp[j];
break;
}
}
if (!comp)
return AVERROR_BUG;
offsets[i] = (frame->crop_top >> shift_y) * frame->linesize[i] +
(frame->crop_left >> shift_x) * comp->step;
}
return 0;
}
int av_frame_apply_cropping(AVFrame *frame, int flags)
{
const AVPixFmtDescriptor *desc;
size_t offsets[4];
int i;
if (!(frame->width > 0 && frame->height > 0))
return AVERROR(EINVAL);
if (frame->crop_left >= INT_MAX - frame->crop_right ||
frame->crop_top >= INT_MAX - frame->crop_bottom ||
(frame->crop_left + frame->crop_right) >= frame->width ||
(frame->crop_top + frame->crop_bottom) >= frame->height)
return AVERROR(ERANGE);
desc = av_pix_fmt_desc_get(frame->format);
if (!desc)
return AVERROR_BUG;
/* Apply just the right/bottom cropping for hwaccel formats. Bitstream
* formats cannot be easily handled here either (and corresponding decoders
* should not export any cropping anyway), so do the same for those as well.
* */
if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) {
frame->width -= frame->crop_right;
frame->height -= frame->crop_bottom;
frame->crop_right = 0;
frame->crop_bottom = 0;
return 0;
}
/* calculate the offsets for each plane */
calc_cropping_offsets(offsets, frame, desc);
/* adjust the offsets to avoid breaking alignment */
if (!(flags & AV_FRAME_CROP_UNALIGNED)) {
int log2_crop_align = frame->crop_left ? ff_ctz(frame->crop_left) : INT_MAX;
int min_log2_align = INT_MAX;
for (i = 0; frame->data[i]; i++) {
int log2_align = offsets[i] ? ff_ctz(offsets[i]) : INT_MAX;
min_log2_align = FFMIN(log2_align, min_log2_align);
}
/* we assume, and it should always be true, that the data alignment is
* related to the cropping alignment by a constant power-of-2 factor */
if (log2_crop_align < min_log2_align)
return AVERROR_BUG;
if (min_log2_align < 5) {
frame->crop_left &= ~((1 << (5 + log2_crop_align - min_log2_align)) - 1);
calc_cropping_offsets(offsets, frame, desc);
}
}
for (i = 0; frame->data[i]; i++)
frame->data[i] += offsets[i];
frame->width -= (frame->crop_left + frame->crop_right);
frame->height -= (frame->crop_top + frame->crop_bottom);
frame->crop_left = 0;
frame->crop_right = 0;
frame->crop_top = 0;
frame->crop_bottom = 0;
return 0;
}

View file

@ -0,0 +1,971 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* @ingroup lavu_frame
* reference-counted frame API
*/
#ifndef AVUTIL_FRAME_H
#define AVUTIL_FRAME_H
#include <stddef.h>
#include <stdint.h>
#include "avutil.h"
#include "buffer.h"
#include "dict.h"
#include "rational.h"
#include "samplefmt.h"
#include "pixfmt.h"
#include "version.h"
/**
* @defgroup lavu_frame AVFrame
* @ingroup lavu_data
*
* @{
* AVFrame is an abstraction for reference-counted raw multimedia data.
*/
enum AVFrameSideDataType {
/**
* The data is the AVPanScan struct defined in libavcodec.
*/
AV_FRAME_DATA_PANSCAN,
/**
* ATSC A53 Part 4 Closed Captions.
* A53 CC bitstream is stored as uint8_t in AVFrameSideData.data.
* The number of bytes of CC data is AVFrameSideData.size.
*/
AV_FRAME_DATA_A53_CC,
/**
* Stereoscopic 3d metadata.
* The data is the AVStereo3D struct defined in libavutil/stereo3d.h.
*/
AV_FRAME_DATA_STEREO3D,
/**
* The data is the AVMatrixEncoding enum defined in libavutil/channel_layout.h.
*/
AV_FRAME_DATA_MATRIXENCODING,
/**
* Metadata relevant to a downmix procedure.
* The data is the AVDownmixInfo struct defined in libavutil/downmix_info.h.
*/
AV_FRAME_DATA_DOWNMIX_INFO,
/**
* ReplayGain information in the form of the AVReplayGain struct.
*/
AV_FRAME_DATA_REPLAYGAIN,
/**
* This side data contains a 3x3 transformation matrix describing an affine
* transformation that needs to be applied to the frame for correct
* presentation.
*
* See libavutil/display.h for a detailed description of the data.
*/
AV_FRAME_DATA_DISPLAYMATRIX,
/**
* Active Format Description data consisting of a single byte as specified
* in ETSI TS 101 154 using AVActiveFormatDescription enum.
*/
AV_FRAME_DATA_AFD,
/**
* Motion vectors exported by some codecs (on demand through the export_mvs
* flag set in the libavcodec AVCodecContext flags2 option).
* The data is the AVMotionVector struct defined in
* libavutil/motion_vector.h.
*/
AV_FRAME_DATA_MOTION_VECTORS,
/**
* Recommmends skipping the specified number of samples. This is exported
* only if the "skip_manual" AVOption is set in libavcodec.
* This has the same format as AV_PKT_DATA_SKIP_SAMPLES.
* @code
* u32le number of samples to skip from start of this packet
* u32le number of samples to skip from end of this packet
* u8 reason for start skip
* u8 reason for end skip (0=padding silence, 1=convergence)
* @endcode
*/
AV_FRAME_DATA_SKIP_SAMPLES,
/**
* This side data must be associated with an audio frame and corresponds to
* enum AVAudioServiceType defined in avcodec.h.
*/
AV_FRAME_DATA_AUDIO_SERVICE_TYPE,
/**
* Mastering display metadata associated with a video frame. The payload is
* an AVMasteringDisplayMetadata type and contains information about the
* mastering display color volume.
*/
AV_FRAME_DATA_MASTERING_DISPLAY_METADATA,
/**
* The GOP timecode in 25 bit timecode format. Data format is 64-bit integer.
* This is set on the first frame of a GOP that has a temporal reference of 0.
*/
AV_FRAME_DATA_GOP_TIMECODE,
/**
* The data represents the AVSphericalMapping structure defined in
* libavutil/spherical.h.
*/
AV_FRAME_DATA_SPHERICAL,
/**
* Content light level (based on CTA-861.3). This payload contains data in
* the form of the AVContentLightMetadata struct.
*/
AV_FRAME_DATA_CONTENT_LIGHT_LEVEL,
/**
* The data contains an ICC profile as an opaque octet buffer following the
* format described by ISO 15076-1 with an optional name defined in the
* metadata key entry "name".
*/
AV_FRAME_DATA_ICC_PROFILE,
#if FF_API_FRAME_QP
/**
* Implementation-specific description of the format of AV_FRAME_QP_TABLE_DATA.
* The contents of this side data are undocumented and internal; use
* av_frame_set_qp_table() and av_frame_get_qp_table() to access this in a
* meaningful way instead.
*/
AV_FRAME_DATA_QP_TABLE_PROPERTIES,
/**
* Raw QP table data. Its format is described by
* AV_FRAME_DATA_QP_TABLE_PROPERTIES. Use av_frame_set_qp_table() and
* av_frame_get_qp_table() to access this instead.
*/
AV_FRAME_DATA_QP_TABLE_DATA,
#endif
/**
* Timecode which conforms to SMPTE ST 12-1. The data is an array of 4 uint32_t
* where the first uint32_t describes how many (1-3) of the other timecodes are used.
* The timecode format is described in the av_timecode_get_smpte_from_framenum()
* function in libavutil/timecode.c.
*/
AV_FRAME_DATA_S12M_TIMECODE,
/**
* HDR dynamic metadata associated with a video frame. The payload is
* an AVDynamicHDRPlus type and contains information for color
* volume transform - application 4 of SMPTE 2094-40:2016 standard.
*/
AV_FRAME_DATA_DYNAMIC_HDR_PLUS,
/**
* Regions Of Interest, the data is an array of AVRegionOfInterest type, the number of
* array element is implied by AVFrameSideData.size / AVRegionOfInterest.self_size.
*/
AV_FRAME_DATA_REGIONS_OF_INTEREST,
};
enum AVActiveFormatDescription {
AV_AFD_SAME = 8,
AV_AFD_4_3 = 9,
AV_AFD_16_9 = 10,
AV_AFD_14_9 = 11,
AV_AFD_4_3_SP_14_9 = 13,
AV_AFD_16_9_SP_14_9 = 14,
AV_AFD_SP_4_3 = 15,
};
/**
* Structure to hold side data for an AVFrame.
*
* sizeof(AVFrameSideData) is not a part of the public ABI, so new fields may be added
* to the end with a minor bump.
*/
typedef struct AVFrameSideData {
enum AVFrameSideDataType type;
uint8_t *data;
int size;
AVDictionary *metadata;
AVBufferRef *buf;
} AVFrameSideData;
/**
* Structure describing a single Region Of Interest.
*
* When multiple regions are defined in a single side-data block, they
* should be ordered from most to least important - some encoders are only
* capable of supporting a limited number of distinct regions, so will have
* to truncate the list.
*
* When overlapping regions are defined, the first region containing a given
* area of the frame applies.
*/
typedef struct AVRegionOfInterest {
/**
* Must be set to the size of this data structure (that is,
* sizeof(AVRegionOfInterest)).
*/
uint32_t self_size;
/**
* Distance in pixels from the top edge of the frame to the top and
* bottom edges and from the left edge of the frame to the left and
* right edges of the rectangle defining this region of interest.
*
* The constraints on a region are encoder dependent, so the region
* actually affected may be slightly larger for alignment or other
* reasons.
*/
int top;
int bottom;
int left;
int right;
/**
* Quantisation offset.
*
* Must be in the range -1 to +1. A value of zero indicates no quality
* change. A negative value asks for better quality (less quantisation),
* while a positive value asks for worse quality (greater quantisation).
*
* The range is calibrated so that the extreme values indicate the
* largest possible offset - if the rest of the frame is encoded with the
* worst possible quality, an offset of -1 indicates that this region
* should be encoded with the best possible quality anyway. Intermediate
* values are then interpolated in some codec-dependent way.
*
* For example, in 10-bit H.264 the quantisation parameter varies between
* -12 and 51. A typical qoffset value of -1/10 therefore indicates that
* this region should be encoded with a QP around one-tenth of the full
* range better than the rest of the frame. So, if most of the frame
* were to be encoded with a QP of around 30, this region would get a QP
* of around 24 (an offset of approximately -1/10 * (51 - -12) = -6.3).
* An extreme value of -1 would indicate that this region should be
* encoded with the best possible quality regardless of the treatment of
* the rest of the frame - that is, should be encoded at a QP of -12.
*/
AVRational qoffset;
} AVRegionOfInterest;
/**
* This structure describes decoded (raw) audio or video data.
*
* AVFrame must be allocated using av_frame_alloc(). Note that this only
* allocates the AVFrame itself, the buffers for the data must be managed
* through other means (see below).
* AVFrame must be freed with av_frame_free().
*
* AVFrame is typically allocated once and then reused multiple times to hold
* different data (e.g. a single AVFrame to hold frames received from a
* decoder). In such a case, av_frame_unref() will free any references held by
* the frame and reset it to its original clean state before it
* is reused again.
*
* The data described by an AVFrame is usually reference counted through the
* AVBuffer API. The underlying buffer references are stored in AVFrame.buf /
* AVFrame.extended_buf. An AVFrame is considered to be reference counted if at
* least one reference is set, i.e. if AVFrame.buf[0] != NULL. In such a case,
* every single data plane must be contained in one of the buffers in
* AVFrame.buf or AVFrame.extended_buf.
* There may be a single buffer for all the data, or one separate buffer for
* each plane, or anything in between.
*
* sizeof(AVFrame) is not a part of the public ABI, so new fields may be added
* to the end with a minor bump.
*
* Fields can be accessed through AVOptions, the name string used, matches the
* C structure field name for fields accessible through AVOptions. The AVClass
* for AVFrame can be obtained from avcodec_get_frame_class()
*/
typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8
/**
* pointer to the picture/channel planes.
* This might be different from the first allocated byte
*
* Some decoders access areas outside 0,0 - width,height, please
* see avcodec_align_dimensions2(). Some filters and swscale can read
* up to 16 bytes beyond the planes, if these filters are to be used,
* then 16 extra bytes must be allocated.
*
* NOTE: Except for hwaccel formats, pointers not needed by the format
* MUST be set to NULL.
*/
uint8_t *data[AV_NUM_DATA_POINTERS];
/**
* For video, size in bytes of each picture line.
* For audio, size in bytes of each plane.
*
* For audio, only linesize[0] may be set. For planar audio, each channel
* plane must be the same size.
*
* For video the linesizes should be multiples of the CPUs alignment
* preference, this is 16 or 32 for modern desktop CPUs.
* Some code requires such alignment other code can be slower without
* correct alignment, for yet other it makes no difference.
*
* @note The linesize may be larger than the size of usable data -- there
* may be extra padding present for performance reasons.
*/
int linesize[AV_NUM_DATA_POINTERS];
/**
* pointers to the data planes/channels.
*
* For video, this should simply point to data[].
*
* For planar audio, each channel has a separate data pointer, and
* linesize[0] contains the size of each channel buffer.
* For packed audio, there is just one data pointer, and linesize[0]
* contains the total size of the buffer for all channels.
*
* Note: Both data and extended_data should always be set in a valid frame,
* but for planar audio with more channels that can fit in data,
* extended_data must be used in order to access all channels.
*/
uint8_t **extended_data;
/**
* @name Video dimensions
* Video frames only. The coded dimensions (in pixels) of the video frame,
* i.e. the size of the rectangle that contains some well-defined values.
*
* @note The part of the frame intended for display/presentation is further
* restricted by the @ref cropping "Cropping rectangle".
* @{
*/
int width, height;
/**
* @}
*/
/**
* number of audio samples (per channel) described by this frame
*/
int nb_samples;
/**
* format of the frame, -1 if unknown or unset
* Values correspond to enum AVPixelFormat for video frames,
* enum AVSampleFormat for audio)
*/
int format;
/**
* 1 -> keyframe, 0-> not
*/
int key_frame;
/**
* Picture type of the frame.
*/
enum AVPictureType pict_type;
/**
* Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
*/
AVRational sample_aspect_ratio;
/**
* Presentation timestamp in time_base units (time when frame should be shown to user).
*/
int64_t pts;
#if FF_API_PKT_PTS
/**
* PTS copied from the AVPacket that was decoded to produce this frame.
* @deprecated use the pts field instead
*/
attribute_deprecated
int64_t pkt_pts;
#endif
/**
* DTS copied from the AVPacket that triggered returning this frame. (if frame threading isn't used)
* This is also the Presentation time of this AVFrame calculated from
* only AVPacket.dts values without pts values.
*/
int64_t pkt_dts;
/**
* picture number in bitstream order
*/
int coded_picture_number;
/**
* picture number in display order
*/
int display_picture_number;
/**
* quality (between 1 (good) and FF_LAMBDA_MAX (bad))
*/
int quality;
/**
* for some private data of the user
*/
void *opaque;
#if FF_API_ERROR_FRAME
/**
* @deprecated unused
*/
attribute_deprecated
uint64_t error[AV_NUM_DATA_POINTERS];
#endif
/**
* When decoding, this signals how much the picture must be delayed.
* extra_delay = repeat_pict / (2*fps)
*/
int repeat_pict;
/**
* The content of the picture is interlaced.
*/
int interlaced_frame;
/**
* If the content is interlaced, is top field displayed first.
*/
int top_field_first;
/**
* Tell user application that palette has changed from previous frame.
*/
int palette_has_changed;
/**
* reordered opaque 64 bits (generally an integer or a double precision float
* PTS but can be anything).
* The user sets AVCodecContext.reordered_opaque to represent the input at
* that time,
* the decoder reorders values as needed and sets AVFrame.reordered_opaque
* to exactly one of the values provided by the user through AVCodecContext.reordered_opaque
*/
int64_t reordered_opaque;
/**
* Sample rate of the audio data.
*/
int sample_rate;
/**
* Channel layout of the audio data.
*/
uint64_t channel_layout;
/**
* AVBuffer references backing the data for this frame. If all elements of
* this array are NULL, then this frame is not reference counted. This array
* must be filled contiguously -- if buf[i] is non-NULL then buf[j] must
* also be non-NULL for all j < i.
*
* There may be at most one AVBuffer per data plane, so for video this array
* always contains all the references. For planar audio with more than
* AV_NUM_DATA_POINTERS channels, there may be more buffers than can fit in
* this array. Then the extra AVBufferRef pointers are stored in the
* extended_buf array.
*/
AVBufferRef *buf[AV_NUM_DATA_POINTERS];
/**
* For planar audio which requires more than AV_NUM_DATA_POINTERS
* AVBufferRef pointers, this array will hold all the references which
* cannot fit into AVFrame.buf.
*
* Note that this is different from AVFrame.extended_data, which always
* contains all the pointers. This array only contains the extra pointers,
* which cannot fit into AVFrame.buf.
*
* This array is always allocated using av_malloc() by whoever constructs
* the frame. It is freed in av_frame_unref().
*/
AVBufferRef **extended_buf;
/**
* Number of elements in extended_buf.
*/
int nb_extended_buf;
AVFrameSideData **side_data;
int nb_side_data;
/**
* @defgroup lavu_frame_flags AV_FRAME_FLAGS
* @ingroup lavu_frame
* Flags describing additional frame properties.
*
* @{
*/
/**
* The frame data may be corrupted, e.g. due to decoding errors.
*/
#define AV_FRAME_FLAG_CORRUPT (1 << 0)
/**
* A flag to mark the frames which need to be decoded, but shouldn't be output.
*/
#define AV_FRAME_FLAG_DISCARD (1 << 2)
/**
* @}
*/
/**
* Frame flags, a combination of @ref lavu_frame_flags
*/
int flags;
/**
* MPEG vs JPEG YUV range.
* - encoding: Set by user
* - decoding: Set by libavcodec
*/
enum AVColorRange color_range;
enum AVColorPrimaries color_primaries;
enum AVColorTransferCharacteristic color_trc;
/**
* YUV colorspace type.
* - encoding: Set by user
* - decoding: Set by libavcodec
*/
enum AVColorSpace colorspace;
enum AVChromaLocation chroma_location;
/**
* frame timestamp estimated using various heuristics, in stream time base
* - encoding: unused
* - decoding: set by libavcodec, read by user.
*/
int64_t best_effort_timestamp;
/**
* reordered pos from the last AVPacket that has been input into the decoder
* - encoding: unused
* - decoding: Read by user.
*/
int64_t pkt_pos;
/**
* duration of the corresponding packet, expressed in
* AVStream->time_base units, 0 if unknown.
* - encoding: unused
* - decoding: Read by user.
*/
int64_t pkt_duration;
/**
* metadata.
* - encoding: Set by user.
* - decoding: Set by libavcodec.
*/
AVDictionary *metadata;
/**
* decode error flags of the frame, set to a combination of
* FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there
* were errors during the decoding.
* - encoding: unused
* - decoding: set by libavcodec, read by user.
*/
int decode_error_flags;
#define FF_DECODE_ERROR_INVALID_BITSTREAM 1
#define FF_DECODE_ERROR_MISSING_REFERENCE 2
#define FF_DECODE_ERROR_CONCEALMENT_ACTIVE 4
#define FF_DECODE_ERROR_DECODE_SLICES 8
/**
* number of audio channels, only used for audio.
* - encoding: unused
* - decoding: Read by user.
*/
int channels;
/**
* size of the corresponding packet containing the compressed
* frame.
* It is set to a negative value if unknown.
* - encoding: unused
* - decoding: set by libavcodec, read by user.
*/
int pkt_size;
#if FF_API_FRAME_QP
/**
* QP table
*/
attribute_deprecated
int8_t *qscale_table;
/**
* QP store stride
*/
attribute_deprecated
int qstride;
attribute_deprecated
int qscale_type;
attribute_deprecated
AVBufferRef *qp_table_buf;
#endif
/**
* For hwaccel-format frames, this should be a reference to the
* AVHWFramesContext describing the frame.
*/
AVBufferRef *hw_frames_ctx;
/**
* AVBufferRef for free use by the API user. FFmpeg will never check the
* contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when
* the frame is unreferenced. av_frame_copy_props() calls create a new
* reference with av_buffer_ref() for the target frame's opaque_ref field.
*
* This is unrelated to the opaque field, although it serves a similar
* purpose.
*/
AVBufferRef *opaque_ref;
/**
* @anchor cropping
* @name Cropping
* Video frames only. The number of pixels to discard from the the
* top/bottom/left/right border of the frame to obtain the sub-rectangle of
* the frame intended for presentation.
* @{
*/
size_t crop_top;
size_t crop_bottom;
size_t crop_left;
size_t crop_right;
/**
* @}
*/
/**
* AVBufferRef for internal use by a single libav* library.
* Must not be used to transfer data between libraries.
* Has to be NULL when ownership of the frame leaves the respective library.
*
* Code outside the FFmpeg libs should never check or change the contents of the buffer ref.
*
* FFmpeg calls av_buffer_unref() on it when the frame is unreferenced.
* av_frame_copy_props() calls create a new reference with av_buffer_ref()
* for the target frame's private_ref field.
*/
AVBufferRef *private_ref;
} AVFrame;
#if FF_API_FRAME_GET_SET
/**
* Accessors for some AVFrame fields. These used to be provided for ABI
* compatibility, and do not need to be used anymore.
*/
attribute_deprecated
int64_t av_frame_get_best_effort_timestamp(const AVFrame *frame);
attribute_deprecated
void av_frame_set_best_effort_timestamp(AVFrame *frame, int64_t val);
attribute_deprecated
int64_t av_frame_get_pkt_duration (const AVFrame *frame);
attribute_deprecated
void av_frame_set_pkt_duration (AVFrame *frame, int64_t val);
attribute_deprecated
int64_t av_frame_get_pkt_pos (const AVFrame *frame);
attribute_deprecated
void av_frame_set_pkt_pos (AVFrame *frame, int64_t val);
attribute_deprecated
int64_t av_frame_get_channel_layout (const AVFrame *frame);
attribute_deprecated
void av_frame_set_channel_layout (AVFrame *frame, int64_t val);
attribute_deprecated
int av_frame_get_channels (const AVFrame *frame);
attribute_deprecated
void av_frame_set_channels (AVFrame *frame, int val);
attribute_deprecated
int av_frame_get_sample_rate (const AVFrame *frame);
attribute_deprecated
void av_frame_set_sample_rate (AVFrame *frame, int val);
attribute_deprecated
AVDictionary *av_frame_get_metadata (const AVFrame *frame);
attribute_deprecated
void av_frame_set_metadata (AVFrame *frame, AVDictionary *val);
attribute_deprecated
int av_frame_get_decode_error_flags (const AVFrame *frame);
attribute_deprecated
void av_frame_set_decode_error_flags (AVFrame *frame, int val);
attribute_deprecated
int av_frame_get_pkt_size(const AVFrame *frame);
attribute_deprecated
void av_frame_set_pkt_size(AVFrame *frame, int val);
#if FF_API_FRAME_QP
attribute_deprecated
int8_t *av_frame_get_qp_table(AVFrame *f, int *stride, int *type);
attribute_deprecated
int av_frame_set_qp_table(AVFrame *f, AVBufferRef *buf, int stride, int type);
#endif
attribute_deprecated
enum AVColorSpace av_frame_get_colorspace(const AVFrame *frame);
attribute_deprecated
void av_frame_set_colorspace(AVFrame *frame, enum AVColorSpace val);
attribute_deprecated
enum AVColorRange av_frame_get_color_range(const AVFrame *frame);
attribute_deprecated
void av_frame_set_color_range(AVFrame *frame, enum AVColorRange val);
#endif
/**
* Get the name of a colorspace.
* @return a static string identifying the colorspace; can be NULL.
*/
const char *av_get_colorspace_name(enum AVColorSpace val);
/**
* Allocate an AVFrame and set its fields to default values. The resulting
* struct must be freed using av_frame_free().
*
* @return An AVFrame filled with default values or NULL on failure.
*
* @note this only allocates the AVFrame itself, not the data buffers. Those
* must be allocated through other means, e.g. with av_frame_get_buffer() or
* manually.
*/
AVFrame *av_frame_alloc(void);
/**
* Free the frame and any dynamically allocated objects in it,
* e.g. extended_data. If the frame is reference counted, it will be
* unreferenced first.
*
* @param frame frame to be freed. The pointer will be set to NULL.
*/
void av_frame_free(AVFrame **frame);
/**
* Set up a new reference to the data described by the source frame.
*
* Copy frame properties from src to dst and create a new reference for each
* AVBufferRef from src.
*
* If src is not reference counted, new buffers are allocated and the data is
* copied.
*
* @warning: dst MUST have been either unreferenced with av_frame_unref(dst),
* or newly allocated with av_frame_alloc() before calling this
* function, or undefined behavior will occur.
*
* @return 0 on success, a negative AVERROR on error
*/
int av_frame_ref(AVFrame *dst, const AVFrame *src);
/**
* Create a new frame that references the same data as src.
*
* This is a shortcut for av_frame_alloc()+av_frame_ref().
*
* @return newly created AVFrame on success, NULL on error.
*/
AVFrame *av_frame_clone(const AVFrame *src);
/**
* Unreference all the buffers referenced by frame and reset the frame fields.
*/
void av_frame_unref(AVFrame *frame);
/**
* Move everything contained in src to dst and reset src.
*
* @warning: dst is not unreferenced, but directly overwritten without reading
* or deallocating its contents. Call av_frame_unref(dst) manually
* before calling this function to ensure that no memory is leaked.
*/
void av_frame_move_ref(AVFrame *dst, AVFrame *src);
/**
* Allocate new buffer(s) for audio or video data.
*
* The following fields must be set on frame before calling this function:
* - format (pixel format for video, sample format for audio)
* - width and height for video
* - nb_samples and channel_layout for audio
*
* This function will fill AVFrame.data and AVFrame.buf arrays and, if
* necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf.
* For planar formats, one buffer will be allocated for each plane.
*
* @warning: if frame already has been allocated, calling this function will
* leak memory. In addition, undefined behavior can occur in certain
* cases.
*
* @param frame frame in which to store the new buffers.
* @param align Required buffer size alignment. If equal to 0, alignment will be
* chosen automatically for the current CPU. It is highly
* recommended to pass 0 here unless you know what you are doing.
*
* @return 0 on success, a negative AVERROR on error.
*/
int av_frame_get_buffer(AVFrame *frame, int align);
/**
* Check if the frame data is writable.
*
* @return A positive value if the frame data is writable (which is true if and
* only if each of the underlying buffers has only one reference, namely the one
* stored in this frame). Return 0 otherwise.
*
* If 1 is returned the answer is valid until av_buffer_ref() is called on any
* of the underlying AVBufferRefs (e.g. through av_frame_ref() or directly).
*
* @see av_frame_make_writable(), av_buffer_is_writable()
*/
int av_frame_is_writable(AVFrame *frame);
/**
* Ensure that the frame data is writable, avoiding data copy if possible.
*
* Do nothing if the frame is writable, allocate new buffers and copy the data
* if it is not.
*
* @return 0 on success, a negative AVERROR on error.
*
* @see av_frame_is_writable(), av_buffer_is_writable(),
* av_buffer_make_writable()
*/
int av_frame_make_writable(AVFrame *frame);
/**
* Copy the frame data from src to dst.
*
* This function does not allocate anything, dst must be already initialized and
* allocated with the same parameters as src.
*
* This function only copies the frame data (i.e. the contents of the data /
* extended data arrays), not any other properties.
*
* @return >= 0 on success, a negative AVERROR on error.
*/
int av_frame_copy(AVFrame *dst, const AVFrame *src);
/**
* Copy only "metadata" fields from src to dst.
*
* Metadata for the purpose of this function are those fields that do not affect
* the data layout in the buffers. E.g. pts, sample rate (for audio) or sample
* aspect ratio (for video), but not width/height or channel layout.
* Side data is also copied.
*/
int av_frame_copy_props(AVFrame *dst, const AVFrame *src);
/**
* Get the buffer reference a given data plane is stored in.
*
* @param plane index of the data plane of interest in frame->extended_data.
*
* @return the buffer reference that contains the plane or NULL if the input
* frame is not valid.
*/
AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane);
/**
* Add a new side data to a frame.
*
* @param frame a frame to which the side data should be added
* @param type type of the added side data
* @param size size of the side data
*
* @return newly added side data on success, NULL on error
*/
AVFrameSideData *av_frame_new_side_data(AVFrame *frame,
enum AVFrameSideDataType type,
int size);
/**
* Add a new side data to a frame from an existing AVBufferRef
*
* @param frame a frame to which the side data should be added
* @param type the type of the added side data
* @param buf an AVBufferRef to add as side data. The ownership of
* the reference is transferred to the frame.
*
* @return newly added side data on success, NULL on error. On failure
* the frame is unchanged and the AVBufferRef remains owned by
* the caller.
*/
AVFrameSideData *av_frame_new_side_data_from_buf(AVFrame *frame,
enum AVFrameSideDataType type,
AVBufferRef *buf);
/**
* @return a pointer to the side data of a given type on success, NULL if there
* is no side data with such type in this frame.
*/
AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
enum AVFrameSideDataType type);
/**
* If side data of the supplied type exists in the frame, free it and remove it
* from the frame.
*/
void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type);
/**
* Flags for frame cropping.
*/
enum {
/**
* Apply the maximum possible cropping, even if it requires setting the
* AVFrame.data[] entries to unaligned pointers. Passing unaligned data
* to FFmpeg API is generally not allowed, and causes undefined behavior
* (such as crashes). You can pass unaligned data only to FFmpeg APIs that
* are explicitly documented to accept it. Use this flag only if you
* absolutely know what you are doing.
*/
AV_FRAME_CROP_UNALIGNED = 1 << 0,
};
/**
* Crop the given video AVFrame according to its crop_left/crop_top/crop_right/
* crop_bottom fields. If cropping is successful, the function will adjust the
* data pointers and the width/height fields, and set the crop fields to 0.
*
* In all cases, the cropping boundaries will be rounded to the inherent
* alignment of the pixel format. In some cases, such as for opaque hwaccel
* formats, the left/top cropping is ignored. The crop fields are set to 0 even
* if the cropping was rounded or ignored.
*
* @param frame the frame which should be cropped
* @param flags Some combination of AV_FRAME_CROP_* flags, or 0.
*
* @return >= 0 on success, a negative AVERROR on error. If the cropping fields
* were invalid, AVERROR(ERANGE) is returned, and nothing is changed.
*/
int av_frame_apply_cropping(AVFrame *frame, int flags);
/**
* @return a string identifying the side data type
*/
const char *av_frame_side_data_name(enum AVFrameSideDataType type);
/**
* @}
*/
#endif /* AVUTIL_FRAME_H */

View file

@ -0,0 +1,243 @@
/*
* Copyright (C) 2013 Reimar Döffinger <Reimar.Doeffinger@gmx.de>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdint.h>
#include "hash.h"
#include "adler32.h"
#include "crc.h"
#include "md5.h"
#include "murmur3.h"
#include "ripemd.h"
#include "sha.h"
#include "sha512.h"
#include "avstring.h"
#include "base64.h"
#include "error.h"
#include "intreadwrite.h"
#include "mem.h"
enum hashtype {
MD5,
MURMUR3,
RIPEMD128,
RIPEMD160,
RIPEMD256,
RIPEMD320,
SHA160,
SHA224,
SHA256,
SHA512_224,
SHA512_256,
SHA384,
SHA512,
CRC32,
ADLER32,
NUM_HASHES
};
typedef struct AVHashContext {
void *ctx;
enum hashtype type;
const AVCRC *crctab;
uint32_t crc;
} AVHashContext;
static const struct {
const char *name;
int size;
} hashdesc[] = {
[MD5] = {"MD5", 16},
[MURMUR3] = {"murmur3", 16},
[RIPEMD128] = {"RIPEMD128", 16},
[RIPEMD160] = {"RIPEMD160", 20},
[RIPEMD256] = {"RIPEMD256", 32},
[RIPEMD320] = {"RIPEMD320", 40},
[SHA160] = {"SHA160", 20},
[SHA224] = {"SHA224", 28},
[SHA256] = {"SHA256", 32},
[SHA512_224] = {"SHA512/224", 28},
[SHA512_256] = {"SHA512/256", 32},
[SHA384] = {"SHA384", 48},
[SHA512] = {"SHA512", 64},
[CRC32] = {"CRC32", 4},
[ADLER32] = {"adler32", 4},
};
const char *av_hash_names(int i)
{
if (i < 0 || i >= NUM_HASHES) return NULL;
return hashdesc[i].name;
}
const char *av_hash_get_name(const AVHashContext *ctx)
{
return hashdesc[ctx->type].name;
}
int av_hash_get_size(const AVHashContext *ctx)
{
return hashdesc[ctx->type].size;
}
int av_hash_alloc(AVHashContext **ctx, const char *name)
{
AVHashContext *res;
int i;
*ctx = NULL;
for (i = 0; i < NUM_HASHES; i++)
if (av_strcasecmp(name, hashdesc[i].name) == 0)
break;
if (i >= NUM_HASHES) return AVERROR(EINVAL);
res = av_mallocz(sizeof(*res));
if (!res) return AVERROR(ENOMEM);
res->type = i;
switch (i) {
case MD5: res->ctx = av_md5_alloc(); break;
case MURMUR3: res->ctx = av_murmur3_alloc(); break;
case RIPEMD128:
case RIPEMD160:
case RIPEMD256:
case RIPEMD320: res->ctx = av_ripemd_alloc(); break;
case SHA160:
case SHA224:
case SHA256: res->ctx = av_sha_alloc(); break;
case SHA512_224:
case SHA512_256:
case SHA384:
case SHA512: res->ctx = av_sha512_alloc(); break;
case CRC32: res->crctab = av_crc_get_table(AV_CRC_32_IEEE_LE); break;
case ADLER32: break;
}
if (i != ADLER32 && i != CRC32 && !res->ctx) {
av_free(res);
return AVERROR(ENOMEM);
}
*ctx = res;
return 0;
}
void av_hash_init(AVHashContext *ctx)
{
switch (ctx->type) {
case MD5: av_md5_init(ctx->ctx); break;
case MURMUR3: av_murmur3_init(ctx->ctx); break;
case RIPEMD128: av_ripemd_init(ctx->ctx, 128); break;
case RIPEMD160: av_ripemd_init(ctx->ctx, 160); break;
case RIPEMD256: av_ripemd_init(ctx->ctx, 256); break;
case RIPEMD320: av_ripemd_init(ctx->ctx, 320); break;
case SHA160: av_sha_init(ctx->ctx, 160); break;
case SHA224: av_sha_init(ctx->ctx, 224); break;
case SHA256: av_sha_init(ctx->ctx, 256); break;
case SHA512_224: av_sha512_init(ctx->ctx, 224); break;
case SHA512_256: av_sha512_init(ctx->ctx, 256); break;
case SHA384: av_sha512_init(ctx->ctx, 384); break;
case SHA512: av_sha512_init(ctx->ctx, 512); break;
case CRC32: ctx->crc = UINT32_MAX; break;
case ADLER32: ctx->crc = 1; break;
}
}
#if FF_API_CRYPTO_SIZE_T
void av_hash_update(AVHashContext *ctx, const uint8_t *src, int len)
#else
void av_hash_update(AVHashContext *ctx, const uint8_t *src, size_t len)
#endif
{
switch (ctx->type) {
case MD5: av_md5_update(ctx->ctx, src, len); break;
case MURMUR3: av_murmur3_update(ctx->ctx, src, len); break;
case RIPEMD128:
case RIPEMD160:
case RIPEMD256:
case RIPEMD320: av_ripemd_update(ctx->ctx, src, len); break;
case SHA160:
case SHA224:
case SHA256: av_sha_update(ctx->ctx, src, len); break;
case SHA512_224:
case SHA512_256:
case SHA384:
case SHA512: av_sha512_update(ctx->ctx, src, len); break;
case CRC32: ctx->crc = av_crc(ctx->crctab, ctx->crc, src, len); break;
case ADLER32: ctx->crc = av_adler32_update(ctx->crc, src, len); break;
}
}
void av_hash_final(AVHashContext *ctx, uint8_t *dst)
{
switch (ctx->type) {
case MD5: av_md5_final(ctx->ctx, dst); break;
case MURMUR3: av_murmur3_final(ctx->ctx, dst); break;
case RIPEMD128:
case RIPEMD160:
case RIPEMD256:
case RIPEMD320: av_ripemd_final(ctx->ctx, dst); break;
case SHA160:
case SHA224:
case SHA256: av_sha_final(ctx->ctx, dst); break;
case SHA512_224:
case SHA512_256:
case SHA384:
case SHA512: av_sha512_final(ctx->ctx, dst); break;
case CRC32: AV_WB32(dst, ctx->crc ^ UINT32_MAX); break;
case ADLER32: AV_WB32(dst, ctx->crc); break;
}
}
void av_hash_final_bin(struct AVHashContext *ctx, uint8_t *dst, int size)
{
uint8_t buf[AV_HASH_MAX_SIZE];
unsigned rsize = av_hash_get_size(ctx);
av_hash_final(ctx, buf);
memcpy(dst, buf, FFMIN(size, rsize));
if (size > rsize)
memset(dst + rsize, 0, size - rsize);
}
void av_hash_final_hex(struct AVHashContext *ctx, uint8_t *dst, int size)
{
uint8_t buf[AV_HASH_MAX_SIZE];
unsigned rsize = av_hash_get_size(ctx), i;
av_hash_final(ctx, buf);
for (i = 0; i < FFMIN(rsize, size / 2); i++)
snprintf(dst + i * 2, size - i * 2, "%02x", buf[i]);
}
void av_hash_final_b64(struct AVHashContext *ctx, uint8_t *dst, int size)
{
uint8_t buf[AV_HASH_MAX_SIZE], b64[AV_BASE64_SIZE(AV_HASH_MAX_SIZE)];
unsigned rsize = av_hash_get_size(ctx), osize;
av_hash_final(ctx, buf);
av_base64_encode(b64, sizeof(b64), buf, rsize);
osize = AV_BASE64_SIZE(rsize);
memcpy(dst, b64, FFMIN(osize, size));
if (size < osize)
dst[size - 1] = 0;
}
void av_hash_freep(AVHashContext **ctx)
{
if (*ctx)
av_freep(&(*ctx)->ctx);
av_freep(ctx);
}

View file

@ -0,0 +1,269 @@
/*
* Copyright (C) 2013 Reimar Döffinger <Reimar.Doeffinger@gmx.de>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* @ingroup lavu_hash_generic
* Generic hashing API
*/
#ifndef AVUTIL_HASH_H
#define AVUTIL_HASH_H
#include <stdint.h>
#include "version.h"
/**
* @defgroup lavu_hash Hash Functions
* @ingroup lavu_crypto
* Hash functions useful in multimedia.
*
* Hash functions are widely used in multimedia, from error checking and
* concealment to internal regression testing. libavutil has efficient
* implementations of a variety of hash functions that may be useful for
* FFmpeg and other multimedia applications.
*
* @{
*
* @defgroup lavu_hash_generic Generic Hashing API
* An abstraction layer for all hash functions supported by libavutil.
*
* If your application needs to support a wide range of different hash
* functions, then the Generic Hashing API is for you. It provides a generic,
* reusable API for @ref lavu_hash "all hash functions" implemented in libavutil.
* If you just need to use one particular hash function, use the @ref lavu_hash
* "individual hash" directly.
*
* @section Sample Code
*
* A basic template for using the Generic Hashing API follows:
*
* @code
* struct AVHashContext *ctx = NULL;
* const char *hash_name = NULL;
* uint8_t *output_buf = NULL;
*
* // Select from a string returned by av_hash_names()
* hash_name = ...;
*
* // Allocate a hash context
* ret = av_hash_alloc(&ctx, hash_name);
* if (ret < 0)
* return ret;
*
* // Initialize the hash context
* av_hash_init(ctx);
*
* // Update the hash context with data
* while (data_left) {
* av_hash_update(ctx, data, size);
* }
*
* // Now we have no more data, so it is time to finalize the hash and get the
* // output. But we need to first allocate an output buffer. Note that you can
* // use any memory allocation function, including malloc(), not just
* // av_malloc().
* output_buf = av_malloc(av_hash_get_size(ctx));
* if (!output_buf)
* return AVERROR(ENOMEM);
*
* // Finalize the hash context.
* // You can use any of the av_hash_final*() functions provided, for other
* // output formats. If you do so, be sure to adjust the memory allocation
* // above. See the function documentation below for the exact amount of extra
* // memory needed.
* av_hash_final(ctx, output_buffer);
*
* // Free the context
* av_hash_freep(&ctx);
* @endcode
*
* @section Hash Function-Specific Information
* If the CRC32 hash is selected, the #AV_CRC_32_IEEE polynomial will be
* used.
*
* If the Murmur3 hash is selected, the default seed will be used. See @ref
* lavu_murmur3_seedinfo "Murmur3" for more information.
*
* @{
*/
/**
* @example ffhash.c
* This example is a simple command line application that takes one or more
* arguments. It demonstrates a typical use of the hashing API with allocation,
* initialization, updating, and finalizing.
*/
struct AVHashContext;
/**
* Allocate a hash context for the algorithm specified by name.
*
* @return >= 0 for success, a negative error code for failure
*
* @note The context is not initialized after a call to this function; you must
* call av_hash_init() to do so.
*/
int av_hash_alloc(struct AVHashContext **ctx, const char *name);
/**
* Get the names of available hash algorithms.
*
* This function can be used to enumerate the algorithms.
*
* @param[in] i Index of the hash algorithm, starting from 0
* @return Pointer to a static string or `NULL` if `i` is out of range
*/
const char *av_hash_names(int i);
/**
* Get the name of the algorithm corresponding to the given hash context.
*/
const char *av_hash_get_name(const struct AVHashContext *ctx);
/**
* Maximum value that av_hash_get_size() will currently return.
*
* You can use this if you absolutely want or need to use static allocation for
* the output buffer and are fine with not supporting hashes newly added to
* libavutil without recompilation.
*
* @warning
* Adding new hashes with larger sizes, and increasing the macro while doing
* so, will not be considered an ABI change. To prevent your code from
* overflowing a buffer, either dynamically allocate the output buffer with
* av_hash_get_size(), or limit your use of the Hashing API to hashes that are
* already in FFmpeg during the time of compilation.
*/
#define AV_HASH_MAX_SIZE 64
/**
* Get the size of the resulting hash value in bytes.
*
* The maximum value this function will currently return is available as macro
* #AV_HASH_MAX_SIZE.
*
* @param[in] ctx Hash context
* @return Size of the hash value in bytes
*/
int av_hash_get_size(const struct AVHashContext *ctx);
/**
* Initialize or reset a hash context.
*
* @param[in,out] ctx Hash context
*/
void av_hash_init(struct AVHashContext *ctx);
/**
* Update a hash context with additional data.
*
* @param[in,out] ctx Hash context
* @param[in] src Data to be added to the hash context
* @param[in] len Size of the additional data
*/
#if FF_API_CRYPTO_SIZE_T
void av_hash_update(struct AVHashContext *ctx, const uint8_t *src, int len);
#else
void av_hash_update(struct AVHashContext *ctx, const uint8_t *src, size_t len);
#endif
/**
* Finalize a hash context and compute the actual hash value.
*
* The minimum size of `dst` buffer is given by av_hash_get_size() or
* #AV_HASH_MAX_SIZE. The use of the latter macro is discouraged.
*
* It is not safe to update or finalize a hash context again, if it has already
* been finalized.
*
* @param[in,out] ctx Hash context
* @param[out] dst Where the final hash value will be stored
*
* @see av_hash_final_bin() provides an alternative API
*/
void av_hash_final(struct AVHashContext *ctx, uint8_t *dst);
/**
* Finalize a hash context and store the actual hash value in a buffer.
*
* It is not safe to update or finalize a hash context again, if it has already
* been finalized.
*
* If `size` is smaller than the hash size (given by av_hash_get_size()), the
* hash is truncated; if size is larger, the buffer is padded with 0.
*
* @param[in,out] ctx Hash context
* @param[out] dst Where the final hash value will be stored
* @param[in] size Number of bytes to write to `dst`
*/
void av_hash_final_bin(struct AVHashContext *ctx, uint8_t *dst, int size);
/**
* Finalize a hash context and store the hexadecimal representation of the
* actual hash value as a string.
*
* It is not safe to update or finalize a hash context again, if it has already
* been finalized.
*
* The string is always 0-terminated.
*
* If `size` is smaller than `2 * hash_size + 1`, where `hash_size` is the
* value returned by av_hash_get_size(), the string will be truncated.
*
* @param[in,out] ctx Hash context
* @param[out] dst Where the string will be stored
* @param[in] size Maximum number of bytes to write to `dst`
*/
void av_hash_final_hex(struct AVHashContext *ctx, uint8_t *dst, int size);
/**
* Finalize a hash context and store the Base64 representation of the
* actual hash value as a string.
*
* It is not safe to update or finalize a hash context again, if it has already
* been finalized.
*
* The string is always 0-terminated.
*
* If `size` is smaller than AV_BASE64_SIZE(hash_size), where `hash_size` is
* the value returned by av_hash_get_size(), the string will be truncated.
*
* @param[in,out] ctx Hash context
* @param[out] dst Where the final hash value will be stored
* @param[in] size Maximum number of bytes to write to `dst`
*/
void av_hash_final_b64(struct AVHashContext *ctx, uint8_t *dst, int size);
/**
* Free hash context and set hash context pointer to `NULL`.
*
* @param[in,out] ctx Pointer to hash context
*/
void av_hash_freep(struct AVHashContext **ctx);
/**
* @}
* @}
*/
#endif /* AVUTIL_HASH_H */

View file

@ -0,0 +1,47 @@
/**
* Copyright (c) 2018 Mohammad Izadi <moh.izadi at gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "hdr_dynamic_metadata.h"
#include "mem.h"
AVDynamicHDRPlus *av_dynamic_hdr_plus_alloc(size_t *size)
{
AVDynamicHDRPlus *hdr_plus = av_mallocz(sizeof(AVDynamicHDRPlus));
if (!hdr_plus)
return NULL;
if (size)
*size = sizeof(*hdr_plus);
return hdr_plus;
}
AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame)
{
AVFrameSideData *side_data = av_frame_new_side_data(frame,
AV_FRAME_DATA_DYNAMIC_HDR_PLUS,
sizeof(AVDynamicHDRPlus));
if (!side_data)
return NULL;
memset(side_data->data, 0, sizeof(AVDynamicHDRPlus));
return (AVDynamicHDRPlus *)side_data->data;
}

View file

@ -0,0 +1,343 @@
/*
* Copyright (c) 2018 Mohammad Izadi <moh.izadi at gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_HDR_DYNAMIC_METADATA_H
#define AVUTIL_HDR_DYNAMIC_METADATA_H
#include "frame.h"
#include "rational.h"
/**
* Option for overlapping elliptical pixel selectors in an image.
*/
enum AVHDRPlusOverlapProcessOption {
AV_HDR_PLUS_OVERLAP_PROCESS_WEIGHTED_AVERAGING = 0,
AV_HDR_PLUS_OVERLAP_PROCESS_LAYERING = 1,
};
/**
* Represents the percentile at a specific percentage in
* a distribution.
*/
typedef struct AVHDRPlusPercentile {
/**
* The percentage value corresponding to a specific percentile linearized
* RGB value in the processing window in the scene. The value shall be in
* the range of 0 to100, inclusive.
*/
uint8_t percentage;
/**
* The linearized maxRGB value at a specific percentile in the processing
* window in the scene. The value shall be in the range of 0 to 1, inclusive
* and in multiples of 0.00001.
*/
AVRational percentile;
} AVHDRPlusPercentile;
/**
* Color transform parameters at a processing window in a dynamic metadata for
* SMPTE 2094-40.
*/
typedef struct AVHDRPlusColorTransformParams {
/**
* The relative x coordinate of the top left pixel of the processing
* window. The value shall be in the range of 0 and 1, inclusive and
* in multiples of 1/(width of Picture - 1). The value 1 corresponds
* to the absolute coordinate of width of Picture - 1. The value for
* first processing window shall be 0.
*/
AVRational window_upper_left_corner_x;
/**
* The relative y coordinate of the top left pixel of the processing
* window. The value shall be in the range of 0 and 1, inclusive and
* in multiples of 1/(height of Picture - 1). The value 1 corresponds
* to the absolute coordinate of height of Picture - 1. The value for
* first processing window shall be 0.
*/
AVRational window_upper_left_corner_y;
/**
* The relative x coordinate of the bottom right pixel of the processing
* window. The value shall be in the range of 0 and 1, inclusive and
* in multiples of 1/(width of Picture - 1). The value 1 corresponds
* to the absolute coordinate of width of Picture - 1. The value for
* first processing window shall be 1.
*/
AVRational window_lower_right_corner_x;
/**
* The relative y coordinate of the bottom right pixel of the processing
* window. The value shall be in the range of 0 and 1, inclusive and
* in multiples of 1/(height of Picture - 1). The value 1 corresponds
* to the absolute coordinate of height of Picture - 1. The value for
* first processing window shall be 1.
*/
AVRational window_lower_right_corner_y;
/**
* The x coordinate of the center position of the concentric internal and
* external ellipses of the elliptical pixel selector in the processing
* window. The value shall be in the range of 0 to (width of Picture - 1),
* inclusive and in multiples of 1 pixel.
*/
uint16_t center_of_ellipse_x;
/**
* The y coordinate of the center position of the concentric internal and
* external ellipses of the elliptical pixel selector in the processing
* window. The value shall be in the range of 0 to (height of Picture - 1),
* inclusive and in multiples of 1 pixel.
*/
uint16_t center_of_ellipse_y;
/**
* The clockwise rotation angle in degree of arc with respect to the
* positive direction of the x-axis of the concentric internal and external
* ellipses of the elliptical pixel selector in the processing window. The
* value shall be in the range of 0 to 180, inclusive and in multiples of 1.
*/
uint8_t rotation_angle;
/**
* The semi-major axis value of the internal ellipse of the elliptical pixel
* selector in amount of pixels in the processing window. The value shall be
* in the range of 1 to 65535, inclusive and in multiples of 1 pixel.
*/
uint16_t semimajor_axis_internal_ellipse;
/**
* The semi-major axis value of the external ellipse of the elliptical pixel
* selector in amount of pixels in the processing window. The value
* shall not be less than semimajor_axis_internal_ellipse of the current
* processing window. The value shall be in the range of 1 to 65535,
* inclusive and in multiples of 1 pixel.
*/
uint16_t semimajor_axis_external_ellipse;
/**
* The semi-minor axis value of the external ellipse of the elliptical pixel
* selector in amount of pixels in the processing window. The value shall be
* in the range of 1 to 65535, inclusive and in multiples of 1 pixel.
*/
uint16_t semiminor_axis_external_ellipse;
/**
* Overlap process option indicates one of the two methods of combining
* rendered pixels in the processing window in an image with at least one
* elliptical pixel selector. For overlapping elliptical pixel selectors
* in an image, overlap_process_option shall have the same value.
*/
enum AVHDRPlusOverlapProcessOption overlap_process_option;
/**
* The maximum of the color components of linearized RGB values in the
* processing window in the scene. The values should be in the range of 0 to
* 1, inclusive and in multiples of 0.00001. maxscl[ 0 ], maxscl[ 1 ], and
* maxscl[ 2 ] are corresponding to R, G, B color components respectively.
*/
AVRational maxscl[3];
/**
* The average of linearized maxRGB values in the processing window in the
* scene. The value should be in the range of 0 to 1, inclusive and in
* multiples of 0.00001.
*/
AVRational average_maxrgb;
/**
* The number of linearized maxRGB values at given percentiles in the
* processing window in the scene. The maximum value shall be 15.
*/
uint8_t num_distribution_maxrgb_percentiles;
/**
* The linearized maxRGB values at given percentiles in the
* processing window in the scene.
*/
AVHDRPlusPercentile distribution_maxrgb[15];
/**
* The fraction of selected pixels in the image that contains the brightest
* pixel in the scene. The value shall be in the range of 0 to 1, inclusive
* and in multiples of 0.001.
*/
AVRational fraction_bright_pixels;
/**
* This flag indicates that the metadata for the tone mapping function in
* the processing window is present (for value of 1).
*/
uint8_t tone_mapping_flag;
/**
* The x coordinate of the separation point between the linear part and the
* curved part of the tone mapping function. The value shall be in the range
* of 0 to 1, excluding 0 and in multiples of 1/4095.
*/
AVRational knee_point_x;
/**
* The y coordinate of the separation point between the linear part and the
* curved part of the tone mapping function. The value shall be in the range
* of 0 to 1, excluding 0 and in multiples of 1/4095.
*/
AVRational knee_point_y;
/**
* The number of the intermediate anchor parameters of the tone mapping
* function in the processing window. The maximum value shall be 15.
*/
uint8_t num_bezier_curve_anchors;
/**
* The intermediate anchor parameters of the tone mapping function in the
* processing window in the scene. The values should be in the range of 0
* to 1, inclusive and in multiples of 1/1023.
*/
AVRational bezier_curve_anchors[15];
/**
* This flag shall be equal to 0 in bitstreams conforming to this version of
* this Specification. Other values are reserved for future use.
*/
uint8_t color_saturation_mapping_flag;
/**
* The color saturation gain in the processing window in the scene. The
* value shall be in the range of 0 to 63/8, inclusive and in multiples of
* 1/8. The default value shall be 1.
*/
AVRational color_saturation_weight;
} AVHDRPlusColorTransformParams;
/**
* This struct represents dynamic metadata for color volume transform -
* application 4 of SMPTE 2094-40:2016 standard.
*
* To be used as payload of a AVFrameSideData or AVPacketSideData with the
* appropriate type.
*
* @note The struct should be allocated with
* av_dynamic_hdr_plus_alloc() and its size is not a part of
* the public ABI.
*/
typedef struct AVDynamicHDRPlus {
/**
* Country code by Rec. ITU-T T.35 Annex A. The value shall be 0xB5.
*/
uint8_t itu_t_t35_country_code;
/**
* Application version in the application defining document in ST-2094
* suite. The value shall be set to 0.
*/
uint8_t application_version;
/**
* The number of processing windows. The value shall be in the range
* of 1 to 3, inclusive.
*/
uint8_t num_windows;
/**
* The color transform parameters for every processing window.
*/
AVHDRPlusColorTransformParams params[3];
/**
* The nominal maximum display luminance of the targeted system display,
* in units of 0.0001 candelas per square metre. The value shall be in
* the range of 0 to 10000, inclusive.
*/
AVRational targeted_system_display_maximum_luminance;
/**
* This flag shall be equal to 0 in bit streams conforming to this version
* of this Specification. The value 1 is reserved for future use.
*/
uint8_t targeted_system_display_actual_peak_luminance_flag;
/**
* The number of rows in the targeted system_display_actual_peak_luminance
* array. The value shall be in the range of 2 to 25, inclusive.
*/
uint8_t num_rows_targeted_system_display_actual_peak_luminance;
/**
* The number of columns in the
* targeted_system_display_actual_peak_luminance array. The value shall be
* in the range of 2 to 25, inclusive.
*/
uint8_t num_cols_targeted_system_display_actual_peak_luminance;
/**
* The normalized actual peak luminance of the targeted system display. The
* values should be in the range of 0 to 1, inclusive and in multiples of
* 1/15.
*/
AVRational targeted_system_display_actual_peak_luminance[25][25];
/**
* This flag shall be equal to 0 in bitstreams conforming to this version of
* this Specification. The value 1 is reserved for future use.
*/
uint8_t mastering_display_actual_peak_luminance_flag;
/**
* The number of rows in the mastering_display_actual_peak_luminance array.
* The value shall be in the range of 2 to 25, inclusive.
*/
uint8_t num_rows_mastering_display_actual_peak_luminance;
/**
* The number of columns in the mastering_display_actual_peak_luminance
* array. The value shall be in the range of 2 to 25, inclusive.
*/
uint8_t num_cols_mastering_display_actual_peak_luminance;
/**
* The normalized actual peak luminance of the mastering display used for
* mastering the image essence. The values should be in the range of 0 to 1,
* inclusive and in multiples of 1/15.
*/
AVRational mastering_display_actual_peak_luminance[25][25];
} AVDynamicHDRPlus;
/**
* Allocate an AVDynamicHDRPlus structure and set its fields to
* default values. The resulting struct can be freed using av_freep().
*
* @return An AVDynamicHDRPlus filled with default values or NULL
* on failure.
*/
AVDynamicHDRPlus *av_dynamic_hdr_plus_alloc(size_t *size);
/**
* Allocate a complete AVDynamicHDRPlus and add it to the frame.
* @param frame The frame which side data is added to.
*
* @return The AVDynamicHDRPlus structure to be filled by caller or NULL
* on failure.
*/
AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame);
#endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */

View file

@ -0,0 +1,196 @@
/*
* Copyright (C) 2012 Martin Storsjo
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "attributes.h"
#include "hmac.h"
#include "md5.h"
#include "sha.h"
#include "sha512.h"
#include "mem.h"
#include "version.h"
#define MAX_HASHLEN 64
#define MAX_BLOCKLEN 128
typedef void (*hmac_final)(void *ctx, uint8_t *dst);
#if FF_API_CRYPTO_SIZE_T
typedef void (*hmac_update)(void *ctx, const uint8_t *src, int len);
#else
typedef void (*hmac_update)(void *ctx, const uint8_t *src, size_t len);
#endif
typedef void (*hmac_init)(void *ctx);
struct AVHMAC {
void *hash;
int blocklen, hashlen;
hmac_final final;
hmac_update update;
hmac_init init;
uint8_t key[MAX_BLOCKLEN];
int keylen;
};
#define DEFINE_SHA(bits) \
static av_cold void sha ## bits ##_init(void *ctx) \
{ \
av_sha_init(ctx, bits); \
}
#define DEFINE_SHA512(bits) \
static av_cold void sha ## bits ##_init(void *ctx) \
{ \
av_sha512_init(ctx, bits); \
}
DEFINE_SHA(160)
DEFINE_SHA(224)
DEFINE_SHA(256)
DEFINE_SHA512(384)
DEFINE_SHA512(512)
AVHMAC *av_hmac_alloc(enum AVHMACType type)
{
AVHMAC *c = av_mallocz(sizeof(*c));
if (!c)
return NULL;
switch (type) {
case AV_HMAC_MD5:
c->blocklen = 64;
c->hashlen = 16;
c->init = (hmac_init) av_md5_init;
c->update = (hmac_update) av_md5_update;
c->final = (hmac_final) av_md5_final;
c->hash = av_md5_alloc();
break;
case AV_HMAC_SHA1:
c->blocklen = 64;
c->hashlen = 20;
c->init = sha160_init;
c->update = (hmac_update) av_sha_update;
c->final = (hmac_final) av_sha_final;
c->hash = av_sha_alloc();
break;
case AV_HMAC_SHA224:
c->blocklen = 64;
c->hashlen = 28;
c->init = sha224_init;
c->update = (hmac_update) av_sha_update;
c->final = (hmac_final) av_sha_final;
c->hash = av_sha_alloc();
break;
case AV_HMAC_SHA256:
c->blocklen = 64;
c->hashlen = 32;
c->init = sha256_init;
c->update = (hmac_update) av_sha_update;
c->final = (hmac_final) av_sha_final;
c->hash = av_sha_alloc();
break;
case AV_HMAC_SHA384:
c->blocklen = 128;
c->hashlen = 48;
c->init = sha384_init;
c->update = (hmac_update) av_sha512_update;
c->final = (hmac_final) av_sha512_final;
c->hash = av_sha512_alloc();
break;
case AV_HMAC_SHA512:
c->blocklen = 128;
c->hashlen = 64;
c->init = sha512_init;
c->update = (hmac_update) av_sha512_update;
c->final = (hmac_final) av_sha512_final;
c->hash = av_sha512_alloc();
break;
default:
av_free(c);
return NULL;
}
if (!c->hash) {
av_free(c);
return NULL;
}
return c;
}
void av_hmac_free(AVHMAC *c)
{
if (!c)
return;
av_freep(&c->hash);
av_free(c);
}
void av_hmac_init(AVHMAC *c, const uint8_t *key, unsigned int keylen)
{
int i;
uint8_t block[MAX_BLOCKLEN];
if (keylen > c->blocklen) {
c->init(c->hash);
c->update(c->hash, key, keylen);
c->final(c->hash, c->key);
c->keylen = c->hashlen;
} else {
memcpy(c->key, key, keylen);
c->keylen = keylen;
}
c->init(c->hash);
for (i = 0; i < c->keylen; i++)
block[i] = c->key[i] ^ 0x36;
for (i = c->keylen; i < c->blocklen; i++)
block[i] = 0x36;
c->update(c->hash, block, c->blocklen);
}
void av_hmac_update(AVHMAC *c, const uint8_t *data, unsigned int len)
{
c->update(c->hash, data, len);
}
int av_hmac_final(AVHMAC *c, uint8_t *out, unsigned int outlen)
{
uint8_t block[MAX_BLOCKLEN];
int i;
if (outlen < c->hashlen)
return AVERROR(EINVAL);
c->final(c->hash, out);
c->init(c->hash);
for (i = 0; i < c->keylen; i++)
block[i] = c->key[i] ^ 0x5C;
for (i = c->keylen; i < c->blocklen; i++)
block[i] = 0x5C;
c->update(c->hash, block, c->blocklen);
c->update(c->hash, out, c->hashlen);
c->final(c->hash, out);
return c->hashlen;
}
int av_hmac_calc(AVHMAC *c, const uint8_t *data, unsigned int len,
const uint8_t *key, unsigned int keylen,
uint8_t *out, unsigned int outlen)
{
av_hmac_init(c, key, keylen);
av_hmac_update(c, data, len);
return av_hmac_final(c, out, outlen);
}

View file

@ -0,0 +1,100 @@
/*
* Copyright (C) 2012 Martin Storsjo
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_HMAC_H
#define AVUTIL_HMAC_H
#include <stdint.h>
#include "version.h"
/**
* @defgroup lavu_hmac HMAC
* @ingroup lavu_crypto
* @{
*/
enum AVHMACType {
AV_HMAC_MD5,
AV_HMAC_SHA1,
AV_HMAC_SHA224,
AV_HMAC_SHA256,
AV_HMAC_SHA384,
AV_HMAC_SHA512,
};
typedef struct AVHMAC AVHMAC;
/**
* Allocate an AVHMAC context.
* @param type The hash function used for the HMAC.
*/
AVHMAC *av_hmac_alloc(enum AVHMACType type);
/**
* Free an AVHMAC context.
* @param ctx The context to free, may be NULL
*/
void av_hmac_free(AVHMAC *ctx);
/**
* Initialize an AVHMAC context with an authentication key.
* @param ctx The HMAC context
* @param key The authentication key
* @param keylen The length of the key, in bytes
*/
void av_hmac_init(AVHMAC *ctx, const uint8_t *key, unsigned int keylen);
/**
* Hash data with the HMAC.
* @param ctx The HMAC context
* @param data The data to hash
* @param len The length of the data, in bytes
*/
void av_hmac_update(AVHMAC *ctx, const uint8_t *data, unsigned int len);
/**
* Finish hashing and output the HMAC digest.
* @param ctx The HMAC context
* @param out The output buffer to write the digest into
* @param outlen The length of the out buffer, in bytes
* @return The number of bytes written to out, or a negative error code.
*/
int av_hmac_final(AVHMAC *ctx, uint8_t *out, unsigned int outlen);
/**
* Hash an array of data with a key.
* @param ctx The HMAC context
* @param data The data to hash
* @param len The length of the data, in bytes
* @param key The authentication key
* @param keylen The length of the key, in bytes
* @param out The output buffer to write the digest into
* @param outlen The length of the out buffer, in bytes
* @return The number of bytes written to out, or a negative error code.
*/
int av_hmac_calc(AVHMAC *ctx, const uint8_t *data, unsigned int len,
const uint8_t *key, unsigned int keylen,
uint8_t *out, unsigned int outlen);
/**
* @}
*/
#endif /* AVUTIL_HMAC_H */

View file

@ -0,0 +1,879 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "buffer.h"
#include "common.h"
#include "hwcontext.h"
#include "hwcontext_internal.h"
#include "imgutils.h"
#include "log.h"
#include "mem.h"
#include "pixdesc.h"
#include "pixfmt.h"
static const HWContextType * const hw_table[] = {
#if CONFIG_CUDA
&ff_hwcontext_type_cuda,
#endif
#if CONFIG_D3D11VA
&ff_hwcontext_type_d3d11va,
#endif
#if CONFIG_LIBDRM
&ff_hwcontext_type_drm,
#endif
#if CONFIG_DXVA2
&ff_hwcontext_type_dxva2,
#endif
#if CONFIG_OPENCL
&ff_hwcontext_type_opencl,
#endif
#if CONFIG_QSV
&ff_hwcontext_type_qsv,
#endif
#if CONFIG_VAAPI
&ff_hwcontext_type_vaapi,
#endif
#if CONFIG_VDPAU
&ff_hwcontext_type_vdpau,
#endif
#if CONFIG_VIDEOTOOLBOX
&ff_hwcontext_type_videotoolbox,
#endif
#if CONFIG_MEDIACODEC
&ff_hwcontext_type_mediacodec,
#endif
NULL,
};
static const char *const hw_type_names[] = {
[AV_HWDEVICE_TYPE_CUDA] = "cuda",
[AV_HWDEVICE_TYPE_DRM] = "drm",
[AV_HWDEVICE_TYPE_DXVA2] = "dxva2",
[AV_HWDEVICE_TYPE_D3D11VA] = "d3d11va",
[AV_HWDEVICE_TYPE_OPENCL] = "opencl",
[AV_HWDEVICE_TYPE_QSV] = "qsv",
[AV_HWDEVICE_TYPE_VAAPI] = "vaapi",
[AV_HWDEVICE_TYPE_VDPAU] = "vdpau",
[AV_HWDEVICE_TYPE_VIDEOTOOLBOX] = "videotoolbox",
[AV_HWDEVICE_TYPE_MEDIACODEC] = "mediacodec",
};
enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name)
{
int type;
for (type = 0; type < FF_ARRAY_ELEMS(hw_type_names); type++) {
if (hw_type_names[type] && !strcmp(hw_type_names[type], name))
return type;
}
return AV_HWDEVICE_TYPE_NONE;
}
const char *av_hwdevice_get_type_name(enum AVHWDeviceType type)
{
if (type > AV_HWDEVICE_TYPE_NONE &&
type < FF_ARRAY_ELEMS(hw_type_names))
return hw_type_names[type];
else
return NULL;
}
enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev)
{
enum AVHWDeviceType next;
int i, set = 0;
for (i = 0; hw_table[i]; i++) {
if (prev != AV_HWDEVICE_TYPE_NONE && hw_table[i]->type <= prev)
continue;
if (!set || hw_table[i]->type < next) {
next = hw_table[i]->type;
set = 1;
}
}
return set ? next : AV_HWDEVICE_TYPE_NONE;
}
static const AVClass hwdevice_ctx_class = {
.class_name = "AVHWDeviceContext",
.item_name = av_default_item_name,
.version = LIBAVUTIL_VERSION_INT,
};
static void hwdevice_ctx_free(void *opaque, uint8_t *data)
{
AVHWDeviceContext *ctx = (AVHWDeviceContext*)data;
/* uninit might still want access the hw context and the user
* free() callback might destroy it, so uninit has to be called first */
if (ctx->internal->hw_type->device_uninit)
ctx->internal->hw_type->device_uninit(ctx);
if (ctx->free)
ctx->free(ctx);
av_buffer_unref(&ctx->internal->source_device);
av_freep(&ctx->hwctx);
av_freep(&ctx->internal->priv);
av_freep(&ctx->internal);
av_freep(&ctx);
}
AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
{
AVHWDeviceContext *ctx;
AVBufferRef *buf;
const HWContextType *hw_type = NULL;
int i;
for (i = 0; hw_table[i]; i++) {
if (hw_table[i]->type == type) {
hw_type = hw_table[i];
break;
}
}
if (!hw_type)
return NULL;
ctx = av_mallocz(sizeof(*ctx));
if (!ctx)
return NULL;
ctx->internal = av_mallocz(sizeof(*ctx->internal));
if (!ctx->internal)
goto fail;
if (hw_type->device_priv_size) {
ctx->internal->priv = av_mallocz(hw_type->device_priv_size);
if (!ctx->internal->priv)
goto fail;
}
if (hw_type->device_hwctx_size) {
ctx->hwctx = av_mallocz(hw_type->device_hwctx_size);
if (!ctx->hwctx)
goto fail;
}
buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
hwdevice_ctx_free, NULL,
AV_BUFFER_FLAG_READONLY);
if (!buf)
goto fail;
ctx->type = type;
ctx->av_class = &hwdevice_ctx_class;
ctx->internal->hw_type = hw_type;
return buf;
fail:
if (ctx->internal)
av_freep(&ctx->internal->priv);
av_freep(&ctx->internal);
av_freep(&ctx->hwctx);
av_freep(&ctx);
return NULL;
}
int av_hwdevice_ctx_init(AVBufferRef *ref)
{
AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
int ret;
if (ctx->internal->hw_type->device_init) {
ret = ctx->internal->hw_type->device_init(ctx);
if (ret < 0)
goto fail;
}
return 0;
fail:
if (ctx->internal->hw_type->device_uninit)
ctx->internal->hw_type->device_uninit(ctx);
return ret;
}
static const AVClass hwframe_ctx_class = {
.class_name = "AVHWFramesContext",
.item_name = av_default_item_name,
.version = LIBAVUTIL_VERSION_INT,
};
static void hwframe_ctx_free(void *opaque, uint8_t *data)
{
AVHWFramesContext *ctx = (AVHWFramesContext*)data;
if (ctx->internal->pool_internal)
av_buffer_pool_uninit(&ctx->internal->pool_internal);
if (ctx->internal->hw_type->frames_uninit)
ctx->internal->hw_type->frames_uninit(ctx);
if (ctx->free)
ctx->free(ctx);
av_buffer_unref(&ctx->internal->source_frames);
av_buffer_unref(&ctx->device_ref);
av_freep(&ctx->hwctx);
av_freep(&ctx->internal->priv);
av_freep(&ctx->internal);
av_freep(&ctx);
}
AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
{
AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref_in->data;
const HWContextType *hw_type = device_ctx->internal->hw_type;
AVHWFramesContext *ctx;
AVBufferRef *buf, *device_ref = NULL;
ctx = av_mallocz(sizeof(*ctx));
if (!ctx)
return NULL;
ctx->internal = av_mallocz(sizeof(*ctx->internal));
if (!ctx->internal)
goto fail;
if (hw_type->frames_priv_size) {
ctx->internal->priv = av_mallocz(hw_type->frames_priv_size);
if (!ctx->internal->priv)
goto fail;
}
if (hw_type->frames_hwctx_size) {
ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size);
if (!ctx->hwctx)
goto fail;
}
device_ref = av_buffer_ref(device_ref_in);
if (!device_ref)
goto fail;
buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
hwframe_ctx_free, NULL,
AV_BUFFER_FLAG_READONLY);
if (!buf)
goto fail;
ctx->av_class = &hwframe_ctx_class;
ctx->device_ref = device_ref;
ctx->device_ctx = device_ctx;
ctx->format = AV_PIX_FMT_NONE;
ctx->sw_format = AV_PIX_FMT_NONE;
ctx->internal->hw_type = hw_type;
return buf;
fail:
if (device_ref)
av_buffer_unref(&device_ref);
if (ctx->internal)
av_freep(&ctx->internal->priv);
av_freep(&ctx->internal);
av_freep(&ctx->hwctx);
av_freep(&ctx);
return NULL;
}
static int hwframe_pool_prealloc(AVBufferRef *ref)
{
AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
AVFrame **frames;
int i, ret = 0;
frames = av_mallocz_array(ctx->initial_pool_size, sizeof(*frames));
if (!frames)
return AVERROR(ENOMEM);
for (i = 0; i < ctx->initial_pool_size; i++) {
frames[i] = av_frame_alloc();
if (!frames[i])
goto fail;
ret = av_hwframe_get_buffer(ref, frames[i], 0);
if (ret < 0)
goto fail;
}
fail:
for (i = 0; i < ctx->initial_pool_size; i++)
av_frame_free(&frames[i]);
av_freep(&frames);
return ret;
}
int av_hwframe_ctx_init(AVBufferRef *ref)
{
AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
const enum AVPixelFormat *pix_fmt;
int ret;
if (ctx->internal->source_frames) {
/* A derived frame context is already initialised. */
return 0;
}
/* validate the pixel format */
for (pix_fmt = ctx->internal->hw_type->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) {
if (*pix_fmt == ctx->format)
break;
}
if (*pix_fmt == AV_PIX_FMT_NONE) {
av_log(ctx, AV_LOG_ERROR,
"The hardware pixel format '%s' is not supported by the device type '%s'\n",
av_get_pix_fmt_name(ctx->format), ctx->internal->hw_type->name);
return AVERROR(ENOSYS);
}
/* validate the dimensions */
ret = av_image_check_size(ctx->width, ctx->height, 0, ctx);
if (ret < 0)
return ret;
/* format-specific init */
if (ctx->internal->hw_type->frames_init) {
ret = ctx->internal->hw_type->frames_init(ctx);
if (ret < 0)
goto fail;
}
if (ctx->internal->pool_internal && !ctx->pool)
ctx->pool = ctx->internal->pool_internal;
/* preallocate the frames in the pool, if requested */
if (ctx->initial_pool_size > 0) {
ret = hwframe_pool_prealloc(ref);
if (ret < 0)
goto fail;
}
return 0;
fail:
if (ctx->internal->hw_type->frames_uninit)
ctx->internal->hw_type->frames_uninit(ctx);
return ret;
}
int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref,
enum AVHWFrameTransferDirection dir,
enum AVPixelFormat **formats, int flags)
{
AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
if (!ctx->internal->hw_type->transfer_get_formats)
return AVERROR(ENOSYS);
return ctx->internal->hw_type->transfer_get_formats(ctx, dir, formats);
}
static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags)
{
AVHWFramesContext *ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
AVFrame *frame_tmp;
int ret = 0;
frame_tmp = av_frame_alloc();
if (!frame_tmp)
return AVERROR(ENOMEM);
/* if the format is set, use that
* otherwise pick the first supported one */
if (dst->format >= 0) {
frame_tmp->format = dst->format;
} else {
enum AVPixelFormat *formats;
ret = av_hwframe_transfer_get_formats(src->hw_frames_ctx,
AV_HWFRAME_TRANSFER_DIRECTION_FROM,
&formats, 0);
if (ret < 0)
goto fail;
frame_tmp->format = formats[0];
av_freep(&formats);
}
frame_tmp->width = ctx->width;
frame_tmp->height = ctx->height;
ret = av_frame_get_buffer(frame_tmp, 32);
if (ret < 0)
goto fail;
ret = av_hwframe_transfer_data(frame_tmp, src, flags);
if (ret < 0)
goto fail;
frame_tmp->width = src->width;
frame_tmp->height = src->height;
av_frame_move_ref(dst, frame_tmp);
fail:
av_frame_free(&frame_tmp);
return ret;
}
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
{
AVHWFramesContext *ctx;
int ret;
if (!dst->buf[0])
return transfer_data_alloc(dst, src, flags);
if (src->hw_frames_ctx) {
ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src);
if (ret < 0)
return ret;
} else if (dst->hw_frames_ctx) {
ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data;
ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src);
if (ret < 0)
return ret;
} else
return AVERROR(ENOSYS);
return 0;
}
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
{
AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
int ret;
if (ctx->internal->source_frames) {
// This is a derived frame context, so we allocate in the source
// and map the frame immediately.
AVFrame *src_frame;
frame->format = ctx->format;
frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
if (!frame->hw_frames_ctx)
return AVERROR(ENOMEM);
src_frame = av_frame_alloc();
if (!src_frame)
return AVERROR(ENOMEM);
ret = av_hwframe_get_buffer(ctx->internal->source_frames,
src_frame, 0);
if (ret < 0) {
av_frame_free(&src_frame);
return ret;
}
ret = av_hwframe_map(frame, src_frame,
ctx->internal->source_allocation_map_flags);
if (ret) {
av_log(ctx, AV_LOG_ERROR, "Failed to map frame into derived "
"frame context: %d.\n", ret);
av_frame_free(&src_frame);
return ret;
}
// Free the source frame immediately - the mapped frame still
// contains a reference to it.
av_frame_free(&src_frame);
return 0;
}
if (!ctx->internal->hw_type->frames_get_buffer)
return AVERROR(ENOSYS);
if (!ctx->pool)
return AVERROR(EINVAL);
frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
if (!frame->hw_frames_ctx)
return AVERROR(ENOMEM);
ret = ctx->internal->hw_type->frames_get_buffer(ctx, frame);
if (ret < 0) {
av_buffer_unref(&frame->hw_frames_ctx);
return ret;
}
return 0;
}
void *av_hwdevice_hwconfig_alloc(AVBufferRef *ref)
{
AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
const HWContextType *hw_type = ctx->internal->hw_type;
if (hw_type->device_hwconfig_size == 0)
return NULL;
return av_mallocz(hw_type->device_hwconfig_size);
}
AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref,
const void *hwconfig)
{
AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
const HWContextType *hw_type = ctx->internal->hw_type;
AVHWFramesConstraints *constraints;
if (!hw_type->frames_get_constraints)
return NULL;
constraints = av_mallocz(sizeof(*constraints));
if (!constraints)
return NULL;
constraints->min_width = constraints->min_height = 0;
constraints->max_width = constraints->max_height = INT_MAX;
if (hw_type->frames_get_constraints(ctx, hwconfig, constraints) >= 0) {
return constraints;
} else {
av_hwframe_constraints_free(&constraints);
return NULL;
}
}
void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
{
if (*constraints) {
av_freep(&(*constraints)->valid_hw_formats);
av_freep(&(*constraints)->valid_sw_formats);
}
av_freep(constraints);
}
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type,
const char *device, AVDictionary *opts, int flags)
{
AVBufferRef *device_ref = NULL;
AVHWDeviceContext *device_ctx;
int ret = 0;
device_ref = av_hwdevice_ctx_alloc(type);
if (!device_ref) {
ret = AVERROR(ENOMEM);
goto fail;
}
device_ctx = (AVHWDeviceContext*)device_ref->data;
if (!device_ctx->internal->hw_type->device_create) {
ret = AVERROR(ENOSYS);
goto fail;
}
ret = device_ctx->internal->hw_type->device_create(device_ctx, device,
opts, flags);
if (ret < 0)
goto fail;
ret = av_hwdevice_ctx_init(device_ref);
if (ret < 0)
goto fail;
*pdevice_ref = device_ref;
return 0;
fail:
av_buffer_unref(&device_ref);
*pdevice_ref = NULL;
return ret;
}
int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr,
enum AVHWDeviceType type,
AVBufferRef *src_ref, int flags)
{
AVBufferRef *dst_ref = NULL, *tmp_ref;
AVHWDeviceContext *dst_ctx, *tmp_ctx;
int ret = 0;
tmp_ref = src_ref;
while (tmp_ref) {
tmp_ctx = (AVHWDeviceContext*)tmp_ref->data;
if (tmp_ctx->type == type) {
dst_ref = av_buffer_ref(tmp_ref);
if (!dst_ref) {
ret = AVERROR(ENOMEM);
goto fail;
}
goto done;
}
tmp_ref = tmp_ctx->internal->source_device;
}
dst_ref = av_hwdevice_ctx_alloc(type);
if (!dst_ref) {
ret = AVERROR(ENOMEM);
goto fail;
}
dst_ctx = (AVHWDeviceContext*)dst_ref->data;
tmp_ref = src_ref;
while (tmp_ref) {
tmp_ctx = (AVHWDeviceContext*)tmp_ref->data;
if (dst_ctx->internal->hw_type->device_derive) {
ret = dst_ctx->internal->hw_type->device_derive(dst_ctx,
tmp_ctx,
flags);
if (ret == 0) {
dst_ctx->internal->source_device = av_buffer_ref(src_ref);
if (!dst_ctx->internal->source_device) {
ret = AVERROR(ENOMEM);
goto fail;
}
ret = av_hwdevice_ctx_init(dst_ref);
if (ret < 0)
goto fail;
goto done;
}
if (ret != AVERROR(ENOSYS))
goto fail;
}
tmp_ref = tmp_ctx->internal->source_device;
}
ret = AVERROR(ENOSYS);
goto fail;
done:
*dst_ref_ptr = dst_ref;
return 0;
fail:
av_buffer_unref(&dst_ref);
*dst_ref_ptr = NULL;
return ret;
}
static void ff_hwframe_unmap(void *opaque, uint8_t *data)
{
HWMapDescriptor *hwmap = (HWMapDescriptor*)data;
AVHWFramesContext *ctx = opaque;
if (hwmap->unmap)
hwmap->unmap(ctx, hwmap);
av_frame_free(&hwmap->source);
av_buffer_unref(&hwmap->hw_frames_ctx);
av_free(hwmap);
}
int ff_hwframe_map_create(AVBufferRef *hwframe_ref,
AVFrame *dst, const AVFrame *src,
void (*unmap)(AVHWFramesContext *ctx,
HWMapDescriptor *hwmap),
void *priv)
{
AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
HWMapDescriptor *hwmap;
int ret;
hwmap = av_mallocz(sizeof(*hwmap));
if (!hwmap) {
ret = AVERROR(ENOMEM);
goto fail;
}
hwmap->source = av_frame_alloc();
if (!hwmap->source) {
ret = AVERROR(ENOMEM);
goto fail;
}
ret = av_frame_ref(hwmap->source, src);
if (ret < 0)
goto fail;
hwmap->hw_frames_ctx = av_buffer_ref(hwframe_ref);
if (!hwmap->hw_frames_ctx) {
ret = AVERROR(ENOMEM);
goto fail;
}
hwmap->unmap = unmap;
hwmap->priv = priv;
dst->buf[0] = av_buffer_create((uint8_t*)hwmap, sizeof(*hwmap),
&ff_hwframe_unmap, ctx, 0);
if (!dst->buf[0]) {
ret = AVERROR(ENOMEM);
goto fail;
}
return 0;
fail:
if (hwmap) {
av_buffer_unref(&hwmap->hw_frames_ctx);
av_frame_free(&hwmap->source);
}
av_free(hwmap);
return ret;
}
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
{
AVHWFramesContext *src_frames, *dst_frames;
HWMapDescriptor *hwmap;
int ret;
if (src->hw_frames_ctx && dst->hw_frames_ctx) {
src_frames = (AVHWFramesContext*)src->hw_frames_ctx->data;
dst_frames = (AVHWFramesContext*)dst->hw_frames_ctx->data;
if ((src_frames == dst_frames &&
src->format == dst_frames->sw_format &&
dst->format == dst_frames->format) ||
(src_frames->internal->source_frames &&
src_frames->internal->source_frames->data ==
(uint8_t*)dst_frames)) {
// This is an unmap operation. We don't need to directly
// do anything here other than fill in the original frame,
// because the real unmap will be invoked when the last
// reference to the mapped frame disappears.
if (!src->buf[0]) {
av_log(src_frames, AV_LOG_ERROR, "Invalid mapping "
"found when attempting unmap.\n");
return AVERROR(EINVAL);
}
hwmap = (HWMapDescriptor*)src->buf[0]->data;
av_frame_unref(dst);
return av_frame_ref(dst, hwmap->source);
}
}
if (src->hw_frames_ctx) {
src_frames = (AVHWFramesContext*)src->hw_frames_ctx->data;
if (src_frames->format == src->format &&
src_frames->internal->hw_type->map_from) {
ret = src_frames->internal->hw_type->map_from(src_frames,
dst, src, flags);
if (ret != AVERROR(ENOSYS))
return ret;
}
}
if (dst->hw_frames_ctx) {
dst_frames = (AVHWFramesContext*)dst->hw_frames_ctx->data;
if (dst_frames->format == dst->format &&
dst_frames->internal->hw_type->map_to) {
ret = dst_frames->internal->hw_type->map_to(dst_frames,
dst, src, flags);
if (ret != AVERROR(ENOSYS))
return ret;
}
}
return AVERROR(ENOSYS);
}
int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx,
enum AVPixelFormat format,
AVBufferRef *derived_device_ctx,
AVBufferRef *source_frame_ctx,
int flags)
{
AVBufferRef *dst_ref = NULL;
AVHWFramesContext *dst = NULL;
AVHWFramesContext *src = (AVHWFramesContext*)source_frame_ctx->data;
int ret;
if (src->internal->source_frames) {
AVHWFramesContext *src_src =
(AVHWFramesContext*)src->internal->source_frames->data;
AVHWDeviceContext *dst_dev =
(AVHWDeviceContext*)derived_device_ctx->data;
if (src_src->device_ctx == dst_dev) {
// This is actually an unmapping, so we just return a
// reference to the source frame context.
*derived_frame_ctx =
av_buffer_ref(src->internal->source_frames);
if (!*derived_frame_ctx) {
ret = AVERROR(ENOMEM);
goto fail;
}
return 0;
}
}
dst_ref = av_hwframe_ctx_alloc(derived_device_ctx);
if (!dst_ref) {
ret = AVERROR(ENOMEM);
goto fail;
}
dst = (AVHWFramesContext*)dst_ref->data;
dst->format = format;
dst->sw_format = src->sw_format;
dst->width = src->width;
dst->height = src->height;
dst->internal->source_frames = av_buffer_ref(source_frame_ctx);
if (!dst->internal->source_frames) {
ret = AVERROR(ENOMEM);
goto fail;
}
dst->internal->source_allocation_map_flags =
flags & (AV_HWFRAME_MAP_READ |
AV_HWFRAME_MAP_WRITE |
AV_HWFRAME_MAP_OVERWRITE |
AV_HWFRAME_MAP_DIRECT);
ret = AVERROR(ENOSYS);
if (src->internal->hw_type->frames_derive_from)
ret = src->internal->hw_type->frames_derive_from(dst, src, flags);
if (ret == AVERROR(ENOSYS) &&
dst->internal->hw_type->frames_derive_to)
ret = dst->internal->hw_type->frames_derive_to(dst, src, flags);
if (ret == AVERROR(ENOSYS))
ret = 0;
if (ret)
goto fail;
*derived_frame_ctx = dst_ref;
return 0;
fail:
if (dst)
av_buffer_unref(&dst->internal->source_frames);
av_buffer_unref(&dst_ref);
return ret;
}
int ff_hwframe_map_replace(AVFrame *dst, const AVFrame *src)
{
HWMapDescriptor *hwmap = (HWMapDescriptor*)dst->buf[0]->data;
av_frame_unref(hwmap->source);
return av_frame_ref(hwmap->source, src);
}

View file

@ -0,0 +1,584 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_HWCONTEXT_H
#define AVUTIL_HWCONTEXT_H
#include "buffer.h"
#include "frame.h"
#include "log.h"
#include "pixfmt.h"
enum AVHWDeviceType {
AV_HWDEVICE_TYPE_NONE,
AV_HWDEVICE_TYPE_VDPAU,
AV_HWDEVICE_TYPE_CUDA,
AV_HWDEVICE_TYPE_VAAPI,
AV_HWDEVICE_TYPE_DXVA2,
AV_HWDEVICE_TYPE_QSV,
AV_HWDEVICE_TYPE_VIDEOTOOLBOX,
AV_HWDEVICE_TYPE_D3D11VA,
AV_HWDEVICE_TYPE_DRM,
AV_HWDEVICE_TYPE_OPENCL,
AV_HWDEVICE_TYPE_MEDIACODEC,
};
typedef struct AVHWDeviceInternal AVHWDeviceInternal;
/**
* This struct aggregates all the (hardware/vendor-specific) "high-level" state,
* i.e. state that is not tied to a concrete processing configuration.
* E.g., in an API that supports hardware-accelerated encoding and decoding,
* this struct will (if possible) wrap the state that is common to both encoding
* and decoding and from which specific instances of encoders or decoders can be
* derived.
*
* This struct is reference-counted with the AVBuffer mechanism. The
* av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
* points to the actual AVHWDeviceContext. Further objects derived from
* AVHWDeviceContext (such as AVHWFramesContext, describing a frame pool with
* specific properties) will hold an internal reference to it. After all the
* references are released, the AVHWDeviceContext itself will be freed,
* optionally invoking a user-specified callback for uninitializing the hardware
* state.
*/
typedef struct AVHWDeviceContext {
/**
* A class for logging. Set by av_hwdevice_ctx_alloc().
*/
const AVClass *av_class;
/**
* Private data used internally by libavutil. Must not be accessed in any
* way by the caller.
*/
AVHWDeviceInternal *internal;
/**
* This field identifies the underlying API used for hardware access.
*
* This field is set when this struct is allocated and never changed
* afterwards.
*/
enum AVHWDeviceType type;
/**
* The format-specific data, allocated and freed by libavutil along with
* this context.
*
* Should be cast by the user to the format-specific context defined in the
* corresponding header (hwcontext_*.h) and filled as described in the
* documentation before calling av_hwdevice_ctx_init().
*
* After calling av_hwdevice_ctx_init() this struct should not be modified
* by the caller.
*/
void *hwctx;
/**
* This field may be set by the caller before calling av_hwdevice_ctx_init().
*
* If non-NULL, this callback will be called when the last reference to
* this context is unreferenced, immediately before it is freed.
*
* @note when other objects (e.g an AVHWFramesContext) are derived from this
* struct, this callback will be invoked after all such child objects
* are fully uninitialized and their respective destructors invoked.
*/
void (*free)(struct AVHWDeviceContext *ctx);
/**
* Arbitrary user data, to be used e.g. by the free() callback.
*/
void *user_opaque;
} AVHWDeviceContext;
typedef struct AVHWFramesInternal AVHWFramesInternal;
/**
* This struct describes a set or pool of "hardware" frames (i.e. those with
* data not located in normal system memory). All the frames in the pool are
* assumed to be allocated in the same way and interchangeable.
*
* This struct is reference-counted with the AVBuffer mechanism and tied to a
* given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
* yields a reference, whose data field points to the actual AVHWFramesContext
* struct.
*/
typedef struct AVHWFramesContext {
/**
* A class for logging.
*/
const AVClass *av_class;
/**
* Private data used internally by libavutil. Must not be accessed in any
* way by the caller.
*/
AVHWFramesInternal *internal;
/**
* A reference to the parent AVHWDeviceContext. This reference is owned and
* managed by the enclosing AVHWFramesContext, but the caller may derive
* additional references from it.
*/
AVBufferRef *device_ref;
/**
* The parent AVHWDeviceContext. This is simply a pointer to
* device_ref->data provided for convenience.
*
* Set by libavutil in av_hwframe_ctx_init().
*/
AVHWDeviceContext *device_ctx;
/**
* The format-specific data, allocated and freed automatically along with
* this context.
*
* Should be cast by the user to the format-specific context defined in the
* corresponding header (hwframe_*.h) and filled as described in the
* documentation before calling av_hwframe_ctx_init().
*
* After any frames using this context are created, the contents of this
* struct should not be modified by the caller.
*/
void *hwctx;
/**
* This field may be set by the caller before calling av_hwframe_ctx_init().
*
* If non-NULL, this callback will be called when the last reference to
* this context is unreferenced, immediately before it is freed.
*/
void (*free)(struct AVHWFramesContext *ctx);
/**
* Arbitrary user data, to be used e.g. by the free() callback.
*/
void *user_opaque;
/**
* A pool from which the frames are allocated by av_hwframe_get_buffer().
* This field may be set by the caller before calling av_hwframe_ctx_init().
* The buffers returned by calling av_buffer_pool_get() on this pool must
* have the properties described in the documentation in the corresponding hw
* type's header (hwcontext_*.h). The pool will be freed strictly before
* this struct's free() callback is invoked.
*
* This field may be NULL, then libavutil will attempt to allocate a pool
* internally. Note that certain device types enforce pools allocated at
* fixed size (frame count), which cannot be extended dynamically. In such a
* case, initial_pool_size must be set appropriately.
*/
AVBufferPool *pool;
/**
* Initial size of the frame pool. If a device type does not support
* dynamically resizing the pool, then this is also the maximum pool size.
*
* May be set by the caller before calling av_hwframe_ctx_init(). Must be
* set if pool is NULL and the device type does not support dynamic pools.
*/
int initial_pool_size;
/**
* The pixel format identifying the underlying HW surface type.
*
* Must be a hwaccel format, i.e. the corresponding descriptor must have the
* AV_PIX_FMT_FLAG_HWACCEL flag set.
*
* Must be set by the user before calling av_hwframe_ctx_init().
*/
enum AVPixelFormat format;
/**
* The pixel format identifying the actual data layout of the hardware
* frames.
*
* Must be set by the caller before calling av_hwframe_ctx_init().
*
* @note when the underlying API does not provide the exact data layout, but
* only the colorspace/bit depth, this field should be set to the fully
* planar version of that format (e.g. for 8-bit 420 YUV it should be
* AV_PIX_FMT_YUV420P, not AV_PIX_FMT_NV12 or anything else).
*/
enum AVPixelFormat sw_format;
/**
* The allocated dimensions of the frames in this pool.
*
* Must be set by the user before calling av_hwframe_ctx_init().
*/
int width, height;
} AVHWFramesContext;
/**
* Look up an AVHWDeviceType by name.
*
* @param name String name of the device type (case-insensitive).
* @return The type from enum AVHWDeviceType, or AV_HWDEVICE_TYPE_NONE if
* not found.
*/
enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name);
/** Get the string name of an AVHWDeviceType.
*
* @param type Type from enum AVHWDeviceType.
* @return Pointer to a static string containing the name, or NULL if the type
* is not valid.
*/
const char *av_hwdevice_get_type_name(enum AVHWDeviceType type);
/**
* Iterate over supported device types.
*
* @param type AV_HWDEVICE_TYPE_NONE initially, then the previous type
* returned by this function in subsequent iterations.
* @return The next usable device type from enum AVHWDeviceType, or
* AV_HWDEVICE_TYPE_NONE if there are no more.
*/
enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev);
/**
* Allocate an AVHWDeviceContext for a given hardware type.
*
* @param type the type of the hardware device to allocate.
* @return a reference to the newly created AVHWDeviceContext on success or NULL
* on failure.
*/
AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type);
/**
* Finalize the device context before use. This function must be called after
* the context is filled with all the required information and before it is
* used in any way.
*
* @param ref a reference to the AVHWDeviceContext
* @return 0 on success, a negative AVERROR code on failure
*/
int av_hwdevice_ctx_init(AVBufferRef *ref);
/**
* Open a device of the specified type and create an AVHWDeviceContext for it.
*
* This is a convenience function intended to cover the simple cases. Callers
* who need to fine-tune device creation/management should open the device
* manually and then wrap it in an AVHWDeviceContext using
* av_hwdevice_ctx_alloc()/av_hwdevice_ctx_init().
*
* The returned context is already initialized and ready for use, the caller
* should not call av_hwdevice_ctx_init() on it. The user_opaque/free fields of
* the created AVHWDeviceContext are set by this function and should not be
* touched by the caller.
*
* @param device_ctx On success, a reference to the newly-created device context
* will be written here. The reference is owned by the caller
* and must be released with av_buffer_unref() when no longer
* needed. On failure, NULL will be written to this pointer.
* @param type The type of the device to create.
* @param device A type-specific string identifying the device to open.
* @param opts A dictionary of additional (type-specific) options to use in
* opening the device. The dictionary remains owned by the caller.
* @param flags currently unused
*
* @return 0 on success, a negative AVERROR code on failure.
*/
int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type,
const char *device, AVDictionary *opts, int flags);
/**
* Create a new device of the specified type from an existing device.
*
* If the source device is a device of the target type or was originally
* derived from such a device (possibly through one or more intermediate
* devices of other types), then this will return a reference to the
* existing device of the same type as is requested.
*
* Otherwise, it will attempt to derive a new device from the given source
* device. If direct derivation to the new type is not implemented, it will
* attempt the same derivation from each ancestor of the source device in
* turn looking for an implemented derivation method.
*
* @param dst_ctx On success, a reference to the newly-created
* AVHWDeviceContext.
* @param type The type of the new device to create.
* @param src_ctx A reference to an existing AVHWDeviceContext which will be
* used to create the new device.
* @param flags Currently unused; should be set to zero.
* @return Zero on success, a negative AVERROR code on failure.
*/
int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ctx,
enum AVHWDeviceType type,
AVBufferRef *src_ctx, int flags);
/**
* Allocate an AVHWFramesContext tied to a given device context.
*
* @param device_ctx a reference to a AVHWDeviceContext. This function will make
* a new reference for internal use, the one passed to the
* function remains owned by the caller.
* @return a reference to the newly created AVHWFramesContext on success or NULL
* on failure.
*/
AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ctx);
/**
* Finalize the context before use. This function must be called after the
* context is filled with all the required information and before it is attached
* to any frames.
*
* @param ref a reference to the AVHWFramesContext
* @return 0 on success, a negative AVERROR code on failure
*/
int av_hwframe_ctx_init(AVBufferRef *ref);
/**
* Allocate a new frame attached to the given AVHWFramesContext.
*
* @param hwframe_ctx a reference to an AVHWFramesContext
* @param frame an empty (freshly allocated or unreffed) frame to be filled with
* newly allocated buffers.
* @param flags currently unused, should be set to zero
* @return 0 on success, a negative AVERROR code on failure
*/
int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags);
/**
* Copy data to or from a hw surface. At least one of dst/src must have an
* AVHWFramesContext attached.
*
* If src has an AVHWFramesContext attached, then the format of dst (if set)
* must use one of the formats returned by av_hwframe_transfer_get_formats(src,
* AV_HWFRAME_TRANSFER_DIRECTION_FROM).
* If dst has an AVHWFramesContext attached, then the format of src must use one
* of the formats returned by av_hwframe_transfer_get_formats(dst,
* AV_HWFRAME_TRANSFER_DIRECTION_TO)
*
* dst may be "clean" (i.e. with data/buf pointers unset), in which case the
* data buffers will be allocated by this function using av_frame_get_buffer().
* If dst->format is set, then this format will be used, otherwise (when
* dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen.
*
* The two frames must have matching allocated dimensions (i.e. equal to
* AVHWFramesContext.width/height), since not all device types support
* transferring a sub-rectangle of the whole surface. The display dimensions
* (i.e. AVFrame.width/height) may be smaller than the allocated dimensions, but
* also have to be equal for both frames. When the display dimensions are
* smaller than the allocated dimensions, the content of the padding in the
* destination frame is unspecified.
*
* @param dst the destination frame. dst is not touched on failure.
* @param src the source frame.
* @param flags currently unused, should be set to zero
* @return 0 on success, a negative AVERROR error code on failure.
*/
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags);
enum AVHWFrameTransferDirection {
/**
* Transfer the data from the queried hw frame.
*/
AV_HWFRAME_TRANSFER_DIRECTION_FROM,
/**
* Transfer the data to the queried hw frame.
*/
AV_HWFRAME_TRANSFER_DIRECTION_TO,
};
/**
* Get a list of possible source or target formats usable in
* av_hwframe_transfer_data().
*
* @param hwframe_ctx the frame context to obtain the information for
* @param dir the direction of the transfer
* @param formats the pointer to the output format list will be written here.
* The list is terminated with AV_PIX_FMT_NONE and must be freed
* by the caller when no longer needed using av_free().
* If this function returns successfully, the format list will
* have at least one item (not counting the terminator).
* On failure, the contents of this pointer are unspecified.
* @param flags currently unused, should be set to zero
* @return 0 on success, a negative AVERROR code on failure.
*/
int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ctx,
enum AVHWFrameTransferDirection dir,
enum AVPixelFormat **formats, int flags);
/**
* This struct describes the constraints on hardware frames attached to
* a given device with a hardware-specific configuration. This is returned
* by av_hwdevice_get_hwframe_constraints() and must be freed by
* av_hwframe_constraints_free() after use.
*/
typedef struct AVHWFramesConstraints {
/**
* A list of possible values for format in the hw_frames_ctx,
* terminated by AV_PIX_FMT_NONE. This member will always be filled.
*/
enum AVPixelFormat *valid_hw_formats;
/**
* A list of possible values for sw_format in the hw_frames_ctx,
* terminated by AV_PIX_FMT_NONE. Can be NULL if this information is
* not known.
*/
enum AVPixelFormat *valid_sw_formats;
/**
* The minimum size of frames in this hw_frames_ctx.
* (Zero if not known.)
*/
int min_width;
int min_height;
/**
* The maximum size of frames in this hw_frames_ctx.
* (INT_MAX if not known / no limit.)
*/
int max_width;
int max_height;
} AVHWFramesConstraints;
/**
* Allocate a HW-specific configuration structure for a given HW device.
* After use, the user must free all members as required by the specific
* hardware structure being used, then free the structure itself with
* av_free().
*
* @param device_ctx a reference to the associated AVHWDeviceContext.
* @return The newly created HW-specific configuration structure on
* success or NULL on failure.
*/
void *av_hwdevice_hwconfig_alloc(AVBufferRef *device_ctx);
/**
* Get the constraints on HW frames given a device and the HW-specific
* configuration to be used with that device. If no HW-specific
* configuration is provided, returns the maximum possible capabilities
* of the device.
*
* @param ref a reference to the associated AVHWDeviceContext.
* @param hwconfig a filled HW-specific configuration structure, or NULL
* to return the maximum possible capabilities of the device.
* @return AVHWFramesConstraints structure describing the constraints
* on the device, or NULL if not available.
*/
AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref,
const void *hwconfig);
/**
* Free an AVHWFrameConstraints structure.
*
* @param constraints The (filled or unfilled) AVHWFrameConstraints structure.
*/
void av_hwframe_constraints_free(AVHWFramesConstraints **constraints);
/**
* Flags to apply to frame mappings.
*/
enum {
/**
* The mapping must be readable.
*/
AV_HWFRAME_MAP_READ = 1 << 0,
/**
* The mapping must be writeable.
*/
AV_HWFRAME_MAP_WRITE = 1 << 1,
/**
* The mapped frame will be overwritten completely in subsequent
* operations, so the current frame data need not be loaded. Any values
* which are not overwritten are unspecified.
*/
AV_HWFRAME_MAP_OVERWRITE = 1 << 2,
/**
* The mapping must be direct. That is, there must not be any copying in
* the map or unmap steps. Note that performance of direct mappings may
* be much lower than normal memory.
*/
AV_HWFRAME_MAP_DIRECT = 1 << 3,
};
/**
* Map a hardware frame.
*
* This has a number of different possible effects, depending on the format
* and origin of the src and dst frames. On input, src should be a usable
* frame with valid buffers and dst should be blank (typically as just created
* by av_frame_alloc()). src should have an associated hwframe context, and
* dst may optionally have a format and associated hwframe context.
*
* If src was created by mapping a frame from the hwframe context of dst,
* then this function undoes the mapping - dst is replaced by a reference to
* the frame that src was originally mapped from.
*
* If both src and dst have an associated hwframe context, then this function
* attempts to map the src frame from its hardware context to that of dst and
* then fill dst with appropriate data to be usable there. This will only be
* possible if the hwframe contexts and associated devices are compatible -
* given compatible devices, av_hwframe_ctx_create_derived() can be used to
* create a hwframe context for dst in which mapping should be possible.
*
* If src has a hwframe context but dst does not, then the src frame is
* mapped to normal memory and should thereafter be usable as a normal frame.
* If the format is set on dst, then the mapping will attempt to create dst
* with that format and fail if it is not possible. If format is unset (is
* AV_PIX_FMT_NONE) then dst will be mapped with whatever the most appropriate
* format to use is (probably the sw_format of the src hwframe context).
*
* A return value of AVERROR(ENOSYS) indicates that the mapping is not
* possible with the given arguments and hwframe setup, while other return
* values indicate that it failed somehow.
*
* @param dst Destination frame, to contain the mapping.
* @param src Source frame, to be mapped.
* @param flags Some combination of AV_HWFRAME_MAP_* flags.
* @return Zero on success, negative AVERROR code on failure.
*/
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags);
/**
* Create and initialise an AVHWFramesContext as a mapping of another existing
* AVHWFramesContext on a different device.
*
* av_hwframe_ctx_init() should not be called after this.
*
* @param derived_frame_ctx On success, a reference to the newly created
* AVHWFramesContext.
* @param derived_device_ctx A reference to the device to create the new
* AVHWFramesContext on.
* @param source_frame_ctx A reference to an existing AVHWFramesContext
* which will be mapped to the derived context.
* @param flags Some combination of AV_HWFRAME_MAP_* flags, defining the
* mapping parameters to apply to frames which are allocated
* in the derived device.
* @return Zero on success, negative AVERROR code on failure.
*/
int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx,
enum AVPixelFormat format,
AVBufferRef *derived_device_ctx,
AVBufferRef *source_frame_ctx,
int flags);
#endif /* AVUTIL_HWCONTEXT_H */

View file

@ -0,0 +1,381 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "buffer.h"
#include "common.h"
#include "hwcontext.h"
#include "hwcontext_internal.h"
#include "hwcontext_cuda_internal.h"
#include "cuda_check.h"
#include "mem.h"
#include "pixdesc.h"
#include "pixfmt.h"
#include "imgutils.h"
#define CUDA_FRAME_ALIGNMENT 256
typedef struct CUDAFramesContext {
int shift_width, shift_height;
} CUDAFramesContext;
static const enum AVPixelFormat supported_formats[] = {
AV_PIX_FMT_NV12,
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_YUV444P,
AV_PIX_FMT_P010,
AV_PIX_FMT_P016,
AV_PIX_FMT_YUV444P16,
AV_PIX_FMT_0RGB32,
AV_PIX_FMT_0BGR32,
};
#define CHECK_CU(x) FF_CUDA_CHECK_DL(device_ctx, cu, x)
static int cuda_frames_get_constraints(AVHWDeviceContext *ctx,
const void *hwconfig,
AVHWFramesConstraints *constraints)
{
int i;
constraints->valid_sw_formats = av_malloc_array(FF_ARRAY_ELEMS(supported_formats) + 1,
sizeof(*constraints->valid_sw_formats));
if (!constraints->valid_sw_formats)
return AVERROR(ENOMEM);
for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++)
constraints->valid_sw_formats[i] = supported_formats[i];
constraints->valid_sw_formats[FF_ARRAY_ELEMS(supported_formats)] = AV_PIX_FMT_NONE;
constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
if (!constraints->valid_hw_formats)
return AVERROR(ENOMEM);
constraints->valid_hw_formats[0] = AV_PIX_FMT_CUDA;
constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
return 0;
}
static void cuda_buffer_free(void *opaque, uint8_t *data)
{
AVHWFramesContext *ctx = opaque;
AVHWDeviceContext *device_ctx = ctx->device_ctx;
AVCUDADeviceContext *hwctx = device_ctx->hwctx;
CudaFunctions *cu = hwctx->internal->cuda_dl;
CUcontext dummy;
CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
CHECK_CU(cu->cuMemFree((CUdeviceptr)data));
CHECK_CU(cu->cuCtxPopCurrent(&dummy));
}
static AVBufferRef *cuda_pool_alloc(void *opaque, int size)
{
AVHWFramesContext *ctx = opaque;
AVHWDeviceContext *device_ctx = ctx->device_ctx;
AVCUDADeviceContext *hwctx = device_ctx->hwctx;
CudaFunctions *cu = hwctx->internal->cuda_dl;
AVBufferRef *ret = NULL;
CUcontext dummy = NULL;
CUdeviceptr data;
int err;
err = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
if (err < 0)
return NULL;
err = CHECK_CU(cu->cuMemAlloc(&data, size));
if (err < 0)
goto fail;
ret = av_buffer_create((uint8_t*)data, size, cuda_buffer_free, ctx, 0);
if (!ret) {
CHECK_CU(cu->cuMemFree(data));
goto fail;
}
fail:
CHECK_CU(cu->cuCtxPopCurrent(&dummy));
return ret;
}
static int cuda_frames_init(AVHWFramesContext *ctx)
{
CUDAFramesContext *priv = ctx->internal->priv;
int i;
for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
if (ctx->sw_format == supported_formats[i])
break;
}
if (i == FF_ARRAY_ELEMS(supported_formats)) {
av_log(ctx, AV_LOG_ERROR, "Pixel format '%s' is not supported\n",
av_get_pix_fmt_name(ctx->sw_format));
return AVERROR(ENOSYS);
}
av_pix_fmt_get_chroma_sub_sample(ctx->sw_format, &priv->shift_width, &priv->shift_height);
if (!ctx->pool) {
int size = av_image_get_buffer_size(ctx->sw_format, ctx->width, ctx->height, CUDA_FRAME_ALIGNMENT);
if (size < 0)
return size;
ctx->internal->pool_internal = av_buffer_pool_init2(size, ctx, cuda_pool_alloc, NULL);
if (!ctx->internal->pool_internal)
return AVERROR(ENOMEM);
}
return 0;
}
static int cuda_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
{
int res;
frame->buf[0] = av_buffer_pool_get(ctx->pool);
if (!frame->buf[0])
return AVERROR(ENOMEM);
res = av_image_fill_arrays(frame->data, frame->linesize, frame->buf[0]->data,
ctx->sw_format, ctx->width, ctx->height, CUDA_FRAME_ALIGNMENT);
if (res < 0)
return res;
// YUV420P is a special case.
// Nvenc expects the U/V planes in swapped order from how ffmpeg expects them, also chroma is half-aligned
if (ctx->sw_format == AV_PIX_FMT_YUV420P) {
frame->linesize[1] = frame->linesize[2] = frame->linesize[0] / 2;
frame->data[2] = frame->data[1];
frame->data[1] = frame->data[2] + frame->linesize[2] * ctx->height / 2;
}
frame->format = AV_PIX_FMT_CUDA;
frame->width = ctx->width;
frame->height = ctx->height;
return 0;
}
static int cuda_transfer_get_formats(AVHWFramesContext *ctx,
enum AVHWFrameTransferDirection dir,
enum AVPixelFormat **formats)
{
enum AVPixelFormat *fmts;
fmts = av_malloc_array(2, sizeof(*fmts));
if (!fmts)
return AVERROR(ENOMEM);
fmts[0] = ctx->sw_format;
fmts[1] = AV_PIX_FMT_NONE;
*formats = fmts;
return 0;
}
static int cuda_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst,
const AVFrame *src)
{
CUDAFramesContext *priv = ctx->internal->priv;
AVHWDeviceContext *device_ctx = ctx->device_ctx;
AVCUDADeviceContext *hwctx = device_ctx->hwctx;
CudaFunctions *cu = hwctx->internal->cuda_dl;
CUcontext dummy;
int i, ret;
ret = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
if (ret < 0)
return ret;
for (i = 0; i < FF_ARRAY_ELEMS(src->data) && src->data[i]; i++) {
CUDA_MEMCPY2D cpy = {
.srcMemoryType = CU_MEMORYTYPE_DEVICE,
.dstMemoryType = CU_MEMORYTYPE_HOST,
.srcDevice = (CUdeviceptr)src->data[i],
.dstHost = dst->data[i],
.srcPitch = src->linesize[i],
.dstPitch = dst->linesize[i],
.WidthInBytes = FFMIN(src->linesize[i], dst->linesize[i]),
.Height = src->height >> (i ? priv->shift_height : 0),
};
ret = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, hwctx->stream));
if (ret < 0)
goto exit;
}
ret = CHECK_CU(cu->cuStreamSynchronize(hwctx->stream));
if (ret < 0)
goto exit;
exit:
CHECK_CU(cu->cuCtxPopCurrent(&dummy));
return 0;
}
static int cuda_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
const AVFrame *src)
{
CUDAFramesContext *priv = ctx->internal->priv;
AVHWDeviceContext *device_ctx = ctx->device_ctx;
AVCUDADeviceContext *hwctx = device_ctx->hwctx;
CudaFunctions *cu = hwctx->internal->cuda_dl;
CUcontext dummy;
int i, ret;
ret = CHECK_CU(cu->cuCtxPushCurrent(hwctx->cuda_ctx));
if (ret < 0)
return ret;
for (i = 0; i < FF_ARRAY_ELEMS(src->data) && src->data[i]; i++) {
CUDA_MEMCPY2D cpy = {
.srcMemoryType = CU_MEMORYTYPE_HOST,
.dstMemoryType = CU_MEMORYTYPE_DEVICE,
.srcHost = src->data[i],
.dstDevice = (CUdeviceptr)dst->data[i],
.srcPitch = src->linesize[i],
.dstPitch = dst->linesize[i],
.WidthInBytes = FFMIN(src->linesize[i], dst->linesize[i]),
.Height = src->height >> (i ? priv->shift_height : 0),
};
ret = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, hwctx->stream));
if (ret < 0)
goto exit;
}
exit:
CHECK_CU(cu->cuCtxPopCurrent(&dummy));
return 0;
}
static void cuda_device_uninit(AVHWDeviceContext *device_ctx)
{
AVCUDADeviceContext *hwctx = device_ctx->hwctx;
if (hwctx->internal) {
CudaFunctions *cu = hwctx->internal->cuda_dl;
if (hwctx->internal->is_allocated && hwctx->cuda_ctx) {
CHECK_CU(cu->cuCtxDestroy(hwctx->cuda_ctx));
hwctx->cuda_ctx = NULL;
}
cuda_free_functions(&hwctx->internal->cuda_dl);
}
av_freep(&hwctx->internal);
}
static int cuda_device_init(AVHWDeviceContext *ctx)
{
AVCUDADeviceContext *hwctx = ctx->hwctx;
int ret;
if (!hwctx->internal) {
hwctx->internal = av_mallocz(sizeof(*hwctx->internal));
if (!hwctx->internal)
return AVERROR(ENOMEM);
}
if (!hwctx->internal->cuda_dl) {
ret = cuda_load_functions(&hwctx->internal->cuda_dl, ctx);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Could not dynamically load CUDA\n");
goto error;
}
}
return 0;
error:
cuda_device_uninit(ctx);
return ret;
}
static int cuda_device_create(AVHWDeviceContext *device_ctx,
const char *device,
AVDictionary *opts, int flags)
{
AVCUDADeviceContext *hwctx = device_ctx->hwctx;
CudaFunctions *cu;
CUdevice cu_device;
CUcontext dummy;
int ret, device_idx = 0;
if (device)
device_idx = strtol(device, NULL, 0);
if (cuda_device_init(device_ctx) < 0)
goto error;
cu = hwctx->internal->cuda_dl;
ret = CHECK_CU(cu->cuInit(0));
if (ret < 0)
goto error;
ret = CHECK_CU(cu->cuDeviceGet(&cu_device, device_idx));
if (ret < 0)
goto error;
ret = CHECK_CU(cu->cuCtxCreate(&hwctx->cuda_ctx, CU_CTX_SCHED_BLOCKING_SYNC, cu_device));
if (ret < 0)
goto error;
// Setting stream to NULL will make functions automatically use the default CUstream
hwctx->stream = NULL;
CHECK_CU(cu->cuCtxPopCurrent(&dummy));
hwctx->internal->is_allocated = 1;
return 0;
error:
cuda_device_uninit(device_ctx);
return AVERROR_UNKNOWN;
}
const HWContextType ff_hwcontext_type_cuda = {
.type = AV_HWDEVICE_TYPE_CUDA,
.name = "CUDA",
.device_hwctx_size = sizeof(AVCUDADeviceContext),
.frames_priv_size = sizeof(CUDAFramesContext),
.device_create = cuda_device_create,
.device_init = cuda_device_init,
.device_uninit = cuda_device_uninit,
.frames_get_constraints = cuda_frames_get_constraints,
.frames_init = cuda_frames_init,
.frames_get_buffer = cuda_get_buffer,
.transfer_get_formats = cuda_transfer_get_formats,
.transfer_data_to = cuda_transfer_data_to,
.transfer_data_from = cuda_transfer_data_from,
.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE },
};

View file

@ -0,0 +1,52 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_HWCONTEXT_CUDA_H
#define AVUTIL_HWCONTEXT_CUDA_H
#ifndef CUDA_VERSION
#include <cuda.h>
#endif
#include "pixfmt.h"
/**
* @file
* An API-specific header for AV_HWDEVICE_TYPE_CUDA.
*
* This API supports dynamic frame pools. AVHWFramesContext.pool must return
* AVBufferRefs whose data pointer is a CUdeviceptr.
*/
typedef struct AVCUDADeviceContextInternal AVCUDADeviceContextInternal;
/**
* This struct is allocated as AVHWDeviceContext.hwctx
*/
typedef struct AVCUDADeviceContext {
CUcontext cuda_ctx;
CUstream stream;
AVCUDADeviceContextInternal *internal;
} AVCUDADeviceContext;
/**
* AVHWFramesContext.hwctx is currently not used
*/
#endif /* AVUTIL_HWCONTEXT_CUDA_H */

View file

@ -0,0 +1,37 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_HWCONTEXT_CUDA_INTERNAL_H
#define AVUTIL_HWCONTEXT_CUDA_INTERNAL_H
#include "compat/cuda/dynlink_loader.h"
#include "hwcontext_cuda.h"
/**
* @file
* FFmpeg internal API for CUDA.
*/
struct AVCUDADeviceContextInternal {
CudaFunctions *cuda_dl;
int is_allocated;
};
#endif /* AVUTIL_HWCONTEXT_CUDA_INTERNAL_H */

View file

@ -0,0 +1,615 @@
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <windows.h>
#define COBJMACROS
#include <initguid.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#if HAVE_DXGIDEBUG_H
#include <dxgidebug.h>
#endif
#include "avassert.h"
#include "common.h"
#include "hwcontext.h"
#include "hwcontext_d3d11va.h"
#include "hwcontext_internal.h"
#include "imgutils.h"
#include "pixdesc.h"
#include "pixfmt.h"
#include "thread.h"
typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory);
static AVOnce functions_loaded = AV_ONCE_INIT;
static PFN_CREATE_DXGI_FACTORY mCreateDXGIFactory;
static PFN_D3D11_CREATE_DEVICE mD3D11CreateDevice;
static av_cold void load_functions(void)
{
#if !HAVE_UWP
// We let these "leak" - this is fine, as unloading has no great benefit, and
// Windows will mark a DLL as loaded forever if its internal refcount overflows
// from too many LoadLibrary calls.
HANDLE d3dlib, dxgilib;
d3dlib = LoadLibrary("d3d11.dll");
dxgilib = LoadLibrary("dxgi.dll");
if (!d3dlib || !dxgilib)
return;
mD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE) GetProcAddress(d3dlib, "D3D11CreateDevice");
mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) GetProcAddress(dxgilib, "CreateDXGIFactory");
#else
// In UWP (which lacks LoadLibrary), CreateDXGIFactory isn't available,
// only CreateDXGIFactory1
mD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE) D3D11CreateDevice;
mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) CreateDXGIFactory1;
#endif
}
typedef struct D3D11VAFramesContext {
int nb_surfaces_used;
DXGI_FORMAT format;
ID3D11Texture2D *staging_texture;
} D3D11VAFramesContext;
static const struct {
DXGI_FORMAT d3d_format;
enum AVPixelFormat pix_fmt;
} supported_formats[] = {
{ DXGI_FORMAT_NV12, AV_PIX_FMT_NV12 },
{ DXGI_FORMAT_P010, AV_PIX_FMT_P010 },
// Special opaque formats. The pix_fmt is merely a place holder, as the
// opaque format cannot be accessed directly.
{ DXGI_FORMAT_420_OPAQUE, AV_PIX_FMT_YUV420P },
};
static void d3d11va_default_lock(void *ctx)
{
WaitForSingleObjectEx(ctx, INFINITE, FALSE);
}
static void d3d11va_default_unlock(void *ctx)
{
ReleaseMutex(ctx);
}
static void d3d11va_frames_uninit(AVHWFramesContext *ctx)
{
AVD3D11VAFramesContext *frames_hwctx = ctx->hwctx;
D3D11VAFramesContext *s = ctx->internal->priv;
if (frames_hwctx->texture)
ID3D11Texture2D_Release(frames_hwctx->texture);
frames_hwctx->texture = NULL;
if (s->staging_texture)
ID3D11Texture2D_Release(s->staging_texture);
s->staging_texture = NULL;
}
static int d3d11va_frames_get_constraints(AVHWDeviceContext *ctx,
const void *hwconfig,
AVHWFramesConstraints *constraints)
{
AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
int nb_sw_formats = 0;
HRESULT hr;
int i;
constraints->valid_sw_formats = av_malloc_array(FF_ARRAY_ELEMS(supported_formats) + 1,
sizeof(*constraints->valid_sw_formats));
if (!constraints->valid_sw_formats)
return AVERROR(ENOMEM);
for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
UINT format_support = 0;
hr = ID3D11Device_CheckFormatSupport(device_hwctx->device, supported_formats[i].d3d_format, &format_support);
if (SUCCEEDED(hr) && (format_support & D3D11_FORMAT_SUPPORT_TEXTURE2D))
constraints->valid_sw_formats[nb_sw_formats++] = supported_formats[i].pix_fmt;
}
constraints->valid_sw_formats[nb_sw_formats] = AV_PIX_FMT_NONE;
constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
if (!constraints->valid_hw_formats)
return AVERROR(ENOMEM);
constraints->valid_hw_formats[0] = AV_PIX_FMT_D3D11;
constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
return 0;
}
static void free_texture(void *opaque, uint8_t *data)
{
ID3D11Texture2D_Release((ID3D11Texture2D *)opaque);
av_free(data);
}
static AVBufferRef *wrap_texture_buf(ID3D11Texture2D *tex, int index)
{
AVBufferRef *buf;
AVD3D11FrameDescriptor *desc = av_mallocz(sizeof(*desc));
if (!desc) {
ID3D11Texture2D_Release(tex);
return NULL;
}
desc->texture = tex;
desc->index = index;
buf = av_buffer_create((uint8_t *)desc, sizeof(desc), free_texture, tex, 0);
if (!buf) {
ID3D11Texture2D_Release(tex);
av_free(desc);
return NULL;
}
return buf;
}
static AVBufferRef *d3d11va_alloc_single(AVHWFramesContext *ctx)
{
D3D11VAFramesContext *s = ctx->internal->priv;
AVD3D11VAFramesContext *hwctx = ctx->hwctx;
AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
HRESULT hr;
ID3D11Texture2D *tex;
D3D11_TEXTURE2D_DESC texDesc = {
.Width = ctx->width,
.Height = ctx->height,
.MipLevels = 1,
.Format = s->format,
.SampleDesc = { .Count = 1 },
.ArraySize = 1,
.Usage = D3D11_USAGE_DEFAULT,
.BindFlags = hwctx->BindFlags,
.MiscFlags = hwctx->MiscFlags,
};
hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &tex);
if (FAILED(hr)) {
av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
return NULL;
}
return wrap_texture_buf(tex, 0);
}
static AVBufferRef *d3d11va_pool_alloc(void *opaque, int size)
{
AVHWFramesContext *ctx = (AVHWFramesContext*)opaque;
D3D11VAFramesContext *s = ctx->internal->priv;
AVD3D11VAFramesContext *hwctx = ctx->hwctx;
D3D11_TEXTURE2D_DESC texDesc;
if (!hwctx->texture)
return d3d11va_alloc_single(ctx);
ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc);
if (s->nb_surfaces_used >= texDesc.ArraySize) {
av_log(ctx, AV_LOG_ERROR, "Static surface pool size exceeded.\n");
return NULL;
}
ID3D11Texture2D_AddRef(hwctx->texture);
return wrap_texture_buf(hwctx->texture, s->nb_surfaces_used++);
}
static int d3d11va_frames_init(AVHWFramesContext *ctx)
{
AVD3D11VAFramesContext *hwctx = ctx->hwctx;
AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
D3D11VAFramesContext *s = ctx->internal->priv;
int i;
HRESULT hr;
D3D11_TEXTURE2D_DESC texDesc;
for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
if (ctx->sw_format == supported_formats[i].pix_fmt) {
s->format = supported_formats[i].d3d_format;
break;
}
}
if (i == FF_ARRAY_ELEMS(supported_formats)) {
av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n",
av_get_pix_fmt_name(ctx->sw_format));
return AVERROR(EINVAL);
}
texDesc = (D3D11_TEXTURE2D_DESC){
.Width = ctx->width,
.Height = ctx->height,
.MipLevels = 1,
.Format = s->format,
.SampleDesc = { .Count = 1 },
.ArraySize = ctx->initial_pool_size,
.Usage = D3D11_USAGE_DEFAULT,
.BindFlags = hwctx->BindFlags,
.MiscFlags = hwctx->MiscFlags,
};
if (hwctx->texture) {
D3D11_TEXTURE2D_DESC texDesc2;
ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc2);
if (texDesc.Width != texDesc2.Width ||
texDesc.Height != texDesc2.Height ||
texDesc.Format != texDesc2.Format) {
av_log(ctx, AV_LOG_ERROR, "User-provided texture has mismatching parameters\n");
return AVERROR(EINVAL);
}
} else if (texDesc.ArraySize > 0) {
hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &hwctx->texture);
if (FAILED(hr)) {
av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
return AVERROR_UNKNOWN;
}
}
ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(AVD3D11FrameDescriptor),
ctx, d3d11va_pool_alloc, NULL);
if (!ctx->internal->pool_internal)
return AVERROR(ENOMEM);
return 0;
}
static int d3d11va_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
{
AVD3D11FrameDescriptor *desc;
frame->buf[0] = av_buffer_pool_get(ctx->pool);
if (!frame->buf[0])
return AVERROR(ENOMEM);
desc = (AVD3D11FrameDescriptor *)frame->buf[0]->data;
frame->data[0] = (uint8_t *)desc->texture;
frame->data[1] = (uint8_t *)desc->index;
frame->format = AV_PIX_FMT_D3D11;
frame->width = ctx->width;
frame->height = ctx->height;
return 0;
}
static int d3d11va_transfer_get_formats(AVHWFramesContext *ctx,
enum AVHWFrameTransferDirection dir,
enum AVPixelFormat **formats)
{
D3D11VAFramesContext *s = ctx->internal->priv;
enum AVPixelFormat *fmts;
fmts = av_malloc_array(2, sizeof(*fmts));
if (!fmts)
return AVERROR(ENOMEM);
fmts[0] = ctx->sw_format;
fmts[1] = AV_PIX_FMT_NONE;
// Don't signal support for opaque formats. Actual access would fail.
if (s->format == DXGI_FORMAT_420_OPAQUE)
fmts[0] = AV_PIX_FMT_NONE;
*formats = fmts;
return 0;
}
static int d3d11va_create_staging_texture(AVHWFramesContext *ctx)
{
AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
D3D11VAFramesContext *s = ctx->internal->priv;
HRESULT hr;
D3D11_TEXTURE2D_DESC texDesc = {
.Width = ctx->width,
.Height = ctx->height,
.MipLevels = 1,
.Format = s->format,
.SampleDesc = { .Count = 1 },
.ArraySize = 1,
.Usage = D3D11_USAGE_STAGING,
.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE,
};
hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &s->staging_texture);
if (FAILED(hr)) {
av_log(ctx, AV_LOG_ERROR, "Could not create the staging texture (%lx)\n", (long)hr);
return AVERROR_UNKNOWN;
}
return 0;
}
static void fill_texture_ptrs(uint8_t *data[4], int linesize[4],
AVHWFramesContext *ctx,
D3D11_TEXTURE2D_DESC *desc,
D3D11_MAPPED_SUBRESOURCE *map)
{
int i;
for (i = 0; i < 4; i++)
linesize[i] = map->RowPitch;
av_image_fill_pointers(data, ctx->sw_format, desc->Height,
(uint8_t*)map->pData, linesize);
}
static int d3d11va_transfer_data(AVHWFramesContext *ctx, AVFrame *dst,
const AVFrame *src)
{
AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
D3D11VAFramesContext *s = ctx->internal->priv;
int download = src->format == AV_PIX_FMT_D3D11;
const AVFrame *frame = download ? src : dst;
const AVFrame *other = download ? dst : src;
// (The interface types are compatible.)
ID3D11Resource *texture = (ID3D11Resource *)(ID3D11Texture2D *)frame->data[0];
int index = (intptr_t)frame->data[1];
ID3D11Resource *staging;
int w = FFMIN(dst->width, src->width);
int h = FFMIN(dst->height, src->height);
uint8_t *map_data[4];
int map_linesize[4];
D3D11_TEXTURE2D_DESC desc;
D3D11_MAPPED_SUBRESOURCE map;
HRESULT hr;
if (frame->hw_frames_ctx->data != (uint8_t *)ctx || other->format != ctx->sw_format)
return AVERROR(EINVAL);
device_hwctx->lock(device_hwctx->lock_ctx);
if (!s->staging_texture) {
int res = d3d11va_create_staging_texture(ctx);
if (res < 0)
return res;
}
staging = (ID3D11Resource *)s->staging_texture;
ID3D11Texture2D_GetDesc(s->staging_texture, &desc);
if (download) {
ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
staging, 0, 0, 0, 0,
texture, index, NULL);
hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
staging, 0, D3D11_MAP_READ, 0, &map);
if (FAILED(hr))
goto map_failed;
fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
av_image_copy(dst->data, dst->linesize, (const uint8_t **)map_data, map_linesize,
ctx->sw_format, w, h);
ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0);
} else {
hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
staging, 0, D3D11_MAP_WRITE, 0, &map);
if (FAILED(hr))
goto map_failed;
fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
av_image_copy(map_data, map_linesize, (const uint8_t **)src->data, src->linesize,
ctx->sw_format, w, h);
ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0);
ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
texture, index, 0, 0, 0,
staging, 0, NULL);
}
device_hwctx->unlock(device_hwctx->lock_ctx);
return 0;
map_failed:
av_log(ctx, AV_LOG_ERROR, "Unable to lock D3D11VA surface (%lx)\n", (long)hr);
device_hwctx->unlock(device_hwctx->lock_ctx);
return AVERROR_UNKNOWN;
}
static int d3d11va_device_init(AVHWDeviceContext *hwdev)
{
AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx;
HRESULT hr;
if (!device_hwctx->lock) {
device_hwctx->lock_ctx = CreateMutex(NULL, 0, NULL);
if (device_hwctx->lock_ctx == INVALID_HANDLE_VALUE) {
av_log(NULL, AV_LOG_ERROR, "Failed to create a mutex\n");
return AVERROR(EINVAL);
}
device_hwctx->lock = d3d11va_default_lock;
device_hwctx->unlock = d3d11va_default_unlock;
}
if (!device_hwctx->device_context) {
ID3D11Device_GetImmediateContext(device_hwctx->device, &device_hwctx->device_context);
if (!device_hwctx->device_context)
return AVERROR_UNKNOWN;
}
if (!device_hwctx->video_device) {
hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device, &IID_ID3D11VideoDevice,
(void **)&device_hwctx->video_device);
if (FAILED(hr))
return AVERROR_UNKNOWN;
}
if (!device_hwctx->video_context) {
hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device_context, &IID_ID3D11VideoContext,
(void **)&device_hwctx->video_context);
if (FAILED(hr))
return AVERROR_UNKNOWN;
}
return 0;
}
static void d3d11va_device_uninit(AVHWDeviceContext *hwdev)
{
AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx;
if (device_hwctx->device) {
ID3D11Device_Release(device_hwctx->device);
device_hwctx->device = NULL;
}
if (device_hwctx->device_context) {
ID3D11DeviceContext_Release(device_hwctx->device_context);
device_hwctx->device_context = NULL;
}
if (device_hwctx->video_device) {
ID3D11VideoDevice_Release(device_hwctx->video_device);
device_hwctx->video_device = NULL;
}
if (device_hwctx->video_context) {
ID3D11VideoContext_Release(device_hwctx->video_context);
device_hwctx->video_context = NULL;
}
if (device_hwctx->lock == d3d11va_default_lock) {
CloseHandle(device_hwctx->lock_ctx);
device_hwctx->lock_ctx = INVALID_HANDLE_VALUE;
device_hwctx->lock = NULL;
}
}
static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
AVDictionary *opts, int flags)
{
AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
HRESULT hr;
IDXGIAdapter *pAdapter = NULL;
ID3D10Multithread *pMultithread;
UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
int is_debug = !!av_dict_get(opts, "debug", NULL, 0);
int ret;
// (On UWP we can't check this.)
#if !HAVE_UWP
if (!LoadLibrary("d3d11_1sdklayers.dll"))
is_debug = 0;
#endif
if (is_debug)
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
if ((ret = ff_thread_once(&functions_loaded, load_functions)) != 0)
return AVERROR_UNKNOWN;
if (!mD3D11CreateDevice || !mCreateDXGIFactory) {
av_log(ctx, AV_LOG_ERROR, "Failed to load D3D11 library or its functions\n");
return AVERROR_UNKNOWN;
}
if (device) {
IDXGIFactory2 *pDXGIFactory;
hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&pDXGIFactory);
if (SUCCEEDED(hr)) {
int adapter = atoi(device);
if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, &pAdapter)))
pAdapter = NULL;
IDXGIFactory2_Release(pDXGIFactory);
}
}
if (pAdapter) {
DXGI_ADAPTER_DESC desc;
hr = IDXGIAdapter2_GetDesc(pAdapter, &desc);
if (!FAILED(hr)) {
av_log(ctx, AV_LOG_INFO, "Using device %04x:%04x (%ls).\n",
desc.VendorId, desc.DeviceId, desc.Description);
}
}
hr = mD3D11CreateDevice(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0,
D3D11_SDK_VERSION, &device_hwctx->device, NULL, NULL);
if (pAdapter)
IDXGIAdapter_Release(pAdapter);
if (FAILED(hr)) {
av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device (%lx)\n", (long)hr);
return AVERROR_UNKNOWN;
}
hr = ID3D11Device_QueryInterface(device_hwctx->device, &IID_ID3D10Multithread, (void **)&pMultithread);
if (SUCCEEDED(hr)) {
ID3D10Multithread_SetMultithreadProtected(pMultithread, TRUE);
ID3D10Multithread_Release(pMultithread);
}
#if !HAVE_UWP && HAVE_DXGIDEBUG_H
if (is_debug) {
HANDLE dxgidebug_dll = LoadLibrary("dxgidebug.dll");
if (dxgidebug_dll) {
HRESULT (WINAPI * pf_DXGIGetDebugInterface)(const GUID *riid, void **ppDebug)
= (void *)GetProcAddress(dxgidebug_dll, "DXGIGetDebugInterface");
if (pf_DXGIGetDebugInterface) {
IDXGIDebug *dxgi_debug = NULL;
hr = pf_DXGIGetDebugInterface(&IID_IDXGIDebug, (void**)&dxgi_debug);
if (SUCCEEDED(hr) && dxgi_debug)
IDXGIDebug_ReportLiveObjects(dxgi_debug, DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL);
}
}
}
#endif
return 0;
}
const HWContextType ff_hwcontext_type_d3d11va = {
.type = AV_HWDEVICE_TYPE_D3D11VA,
.name = "D3D11VA",
.device_hwctx_size = sizeof(AVD3D11VADeviceContext),
.frames_hwctx_size = sizeof(AVD3D11VAFramesContext),
.frames_priv_size = sizeof(D3D11VAFramesContext),
.device_create = d3d11va_device_create,
.device_init = d3d11va_device_init,
.device_uninit = d3d11va_device_uninit,
.frames_get_constraints = d3d11va_frames_get_constraints,
.frames_init = d3d11va_frames_init,
.frames_uninit = d3d11va_frames_uninit,
.frames_get_buffer = d3d11va_get_buffer,
.transfer_get_formats = d3d11va_transfer_get_formats,
.transfer_data_to = d3d11va_transfer_data,
.transfer_data_from = d3d11va_transfer_data,
.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_D3D11, AV_PIX_FMT_NONE },
};

Some files were not shown because too many files have changed in this diff Show more