diff options
Diffstat (limited to 'libavutil')
206 files changed, 14344 insertions, 1783 deletions
diff --git a/libavutil/Makefile b/libavutil/Makefile index 0f8ed08d61..91751dc4c3 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -1,3 +1,5 @@ +include $(SUBDIR)../config.mak + NAME = avutil HEADERS = adler32.h \ @@ -10,6 +12,7 @@ HEADERS = adler32.h \ avutil.h \ base64.h \ blowfish.h \ + bprint.h \ bswap.h \ buffer.h \ channel_layout.h \ @@ -23,9 +26,11 @@ HEADERS = adler32.h \ fifo.h \ file.h \ frame.h \ + hash.h \ hmac.h \ imgutils.h \ intfloat.h \ + intfloat_readwrite.h \ intreadwrite.h \ lfg.h \ log.h \ @@ -33,6 +38,7 @@ HEADERS = adler32.h \ mathematics.h \ md5.h \ mem.h \ + murmur3.h \ dict.h \ old_pix_fmts.h \ opt.h \ @@ -42,21 +48,29 @@ HEADERS = adler32.h \ random_seed.h \ replaygain.h \ rational.h \ + ripemd.h \ samplefmt.h \ sha.h \ + sha512.h \ stereo3d.h \ + threadmessage.h \ time.h \ + timecode.h \ + timestamp.h \ version.h \ xtea.h \ HEADERS-$(CONFIG_LZO) += lzo.h +HEADERS-$(CONFIG_OPENCL) += opencl.h + ARCH_HEADERS = bswap.h \ intmath.h \ intreadwrite.h \ timer.h \ -BUILT_HEADERS = avconfig.h +BUILT_HEADERS = avconfig.h \ + ffversion.h OBJS = adler32.o \ aes.o \ @@ -65,6 +79,7 @@ OBJS = adler32.o \ avstring.o \ base64.o \ blowfish.o \ + bprint.o \ buffer.o \ channel_layout.o \ cpu.o \ @@ -78,17 +93,22 @@ OBJS = adler32.o \ file.o \ file_open.o \ float_dsp.o \ + fixed_dsp.o \ frame.o \ + hash.o \ hmac.o \ imgutils.o \ + intfloat_readwrite.o \ intmath.o \ lfg.o \ - lls.o \ + lls1.o \ + lls2.o \ log.o \ log2_tab.o \ mathematics.o \ md5.o \ mem.o \ + murmur3.o \ dict.o \ opt.o \ parseutils.o \ @@ -96,23 +116,33 @@ OBJS = adler32.o \ random_seed.o \ rational.o \ rc4.o \ + ripemd.o \ samplefmt.o \ sha.o \ + sha512.o \ stereo3d.o \ + threadmessage.o \ time.o \ + timecode.o \ tree.o \ utils.o \ + xga_font_data.o \ xtea.o \ OBJS-$(CONFIG_LZO) += lzo.o +OBJS-$(CONFIG_OPENCL) += opencl.o opencl_internal.o OBJS += $(COMPAT_OBJS:%=../compat/%) +# Windows resource file +SLIBOBJS-$(HAVE_GNU_WINDRES) += avutilres.o + SKIPHEADERS = old_pix_fmts.h SKIPHEADERS-$(HAVE_ATOMICS_GCC) += atomic_gcc.h SKIPHEADERS-$(HAVE_ATOMICS_SUNCC) += atomic_suncc.h SKIPHEADERS-$(HAVE_ATOMICS_WIN32) += atomic_win32.h +SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h TESTPROGS = adler32 \ aes \ @@ -120,18 +150,40 @@ TESTPROGS = adler32 \ avstring \ base64 \ blowfish \ + bprint \ cpu \ crc \ des \ + error \ eval \ + file \ fifo \ float_dsp \ hmac \ lfg \ - lls \ + lls1 \ + lls2 \ + log \ md5 \ + murmur3 \ opt \ + pca \ parseutils \ + pixdesc \ + random_seed \ + rational \ + ripemd \ sha \ + sha512 \ tree \ + utf8 \ xtea \ + +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)lzo-test$(EXESUF): ELIBS = -llzo2 diff --git a/libavutil/aarch64/asm.S b/libavutil/aarch64/asm.S index b766e67d43..c6adf6e112 100644 --- a/libavutil/aarch64/asm.S +++ b/libavutil/aarch64/asm.S @@ -1,20 +1,20 @@ /* * Copyright (c) 2008 Mans Rullgard <mans@mansr.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/aarch64/bswap.h b/libavutil/aarch64/bswap.h index 0c001cec19..1e735c52cf 100644 --- a/libavutil/aarch64/bswap.h +++ b/libavutil/aarch64/bswap.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/aarch64/cpu.c b/libavutil/aarch64/cpu.c index 37a7d8defa..8ef077aaea 100644 --- a/libavutil/aarch64/cpu.c +++ b/libavutil/aarch64/cpu.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/aarch64/cpu.h b/libavutil/aarch64/cpu.h index f5b1d89132..cf1b9cc516 100644 --- a/libavutil/aarch64/cpu.h +++ b/libavutil/aarch64/cpu.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/aarch64/float_dsp_init.c b/libavutil/aarch64/float_dsp_init.c index 37d34c96d0..4325071821 100644 --- a/libavutil/aarch64/float_dsp_init.c +++ b/libavutil/aarch64/float_dsp_init.c @@ -2,20 +2,20 @@ * ARM NEON optimised Float DSP functions * Copyright (c) 2008 Mans Rullgard <mans@mansr.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/aarch64/float_dsp_neon.S b/libavutil/aarch64/float_dsp_neon.S index 776542c4a9..02d790c0cc 100644 --- a/libavutil/aarch64/float_dsp_neon.S +++ b/libavutil/aarch64/float_dsp_neon.S @@ -3,20 +3,20 @@ * Copyright (c) 2008 Mans Rullgard <mans@mansr.com> * Copyright (c) 2014 Janne Grunau <janne-libav@jannau.net> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/aarch64/neontest.h b/libavutil/aarch64/neontest.h index de841bbbae..b9d4986072 100644 --- a/libavutil/aarch64/neontest.h +++ b/libavutil/aarch64/neontest.h @@ -3,20 +3,20 @@ * Copyright (c) 2008 Ramiro Polla <ramiro.polla@gmail.com> * Copyright (c) 2013 Martin Storsjo * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/adler32.c b/libavutil/adler32.c index 8a8065c4a3..579d022978 100644 --- a/libavutil/adler32.c +++ b/libavutil/adler32.c @@ -32,6 +32,8 @@ #include "config.h" #include "adler32.h" +#include "common.h" +#include "intreadwrite.h" #define BASE 65521L /* largest prime smaller than 65536 */ @@ -46,16 +48,46 @@ unsigned long av_adler32_update(unsigned long adler, const uint8_t * buf, unsigned long s2 = adler >> 16; while (len > 0) { -#if CONFIG_SMALL +#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; } -#else - while (len > 16 && s2 < (1U << 31)) { - DO16(buf); - len -= 16; - } #endif DO1(buf); len--; s1 %= BASE; @@ -65,6 +97,7 @@ unsigned long av_adler32_update(unsigned long adler, const uint8_t * buf, } #ifdef TEST +// LCOV_EXCL_START #include <string.h> #include "log.h" #include "timer.h" @@ -95,4 +128,5 @@ int main(int argc, char **argv) av_log(NULL, AV_LOG_DEBUG, "%X (expected 50E6E508)\n", checksum); return checksum == 0x50e6e508 ? 0 : 1; } +// LCOV_EXCL_STOP #endif diff --git a/libavutil/adler32.h b/libavutil/adler32.h index 53e3dbf51d..0dc69ec0a8 100644 --- a/libavutil/adler32.h +++ b/libavutil/adler32.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Mans Rullgard * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/aes.c b/libavutil/aes.c index 3ba5e9aef4..638fb81e8d 100644 --- a/libavutil/aes.c +++ b/libavutil/aes.c @@ -3,20 +3,20 @@ * * some optimization ideas from aes128.c by Reimar Doeffinger * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -40,9 +40,7 @@ typedef struct AVAES { int rounds; } AVAES; -#if FF_API_CONTEXT_SIZE const int av_aes_size= sizeof(AVAES); -#endif struct AVAES *av_aes_alloc(void) { @@ -267,6 +265,7 @@ int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt) } #ifdef TEST +// LCOV_EXCL_START #include <string.h> #include "lfg.h" #include "log.h" @@ -339,4 +338,5 @@ int main(int argc, char **argv) } return err; } +// LCOV_EXCL_STOP #endif diff --git a/libavutil/aes.h b/libavutil/aes.h index edff275b7a..09efbda107 100644 --- a/libavutil/aes.h +++ b/libavutil/aes.h @@ -1,20 +1,20 @@ /* * copyright (c) 2007 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -32,9 +32,7 @@ * @{ */ -#if FF_API_CONTEXT_SIZE -extern attribute_deprecated const int av_aes_size; -#endif +extern const int av_aes_size; struct AVAES; diff --git a/libavutil/arm/asm.S b/libavutil/arm/asm.S index 93d74b65e1..35559ce27a 100644 --- a/libavutil/arm/asm.S +++ b/libavutil/arm/asm.S @@ -1,20 +1,20 @@ /* * Copyright (c) 2008 Mans Rullgard <mans@mansr.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/arm/bswap.h b/libavutil/arm/bswap.h index 8bc7d9a8f7..ae5fdb7eb8 100644 --- a/libavutil/arm/bswap.h +++ b/libavutil/arm/bswap.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/arm/cpu.c b/libavutil/arm/cpu.c index 8bdaa88469..f6cf338591 100644 --- a/libavutil/arm/cpu.c +++ b/libavutil/arm/cpu.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/arm/cpu.h b/libavutil/arm/cpu.h index 224409afee..f056a91ca5 100644 --- a/libavutil/arm/cpu.h +++ b/libavutil/arm/cpu.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/arm/float_dsp_arm.h b/libavutil/arm/float_dsp_arm.h index ec925ecf5c..fe311cc0d2 100644 --- a/libavutil/arm/float_dsp_arm.h +++ b/libavutil/arm/float_dsp_arm.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2009 Mans Rullgard <mans@mansr.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/arm/float_dsp_init_arm.c b/libavutil/arm/float_dsp_init_arm.c index ff0105c5c9..678762862e 100644 --- a/libavutil/arm/float_dsp_init_arm.c +++ b/libavutil/arm/float_dsp_init_arm.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/arm/float_dsp_init_neon.c b/libavutil/arm/float_dsp_init_neon.c index 617bf5d576..689aa77c7b 100644 --- a/libavutil/arm/float_dsp_init_neon.c +++ b/libavutil/arm/float_dsp_init_neon.c @@ -2,20 +2,20 @@ * ARM NEON optimised Float DSP functions * Copyright (c) 2008 Mans Rullgard <mans@mansr.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/arm/float_dsp_init_vfp.c b/libavutil/arm/float_dsp_init_vfp.c index 61ff2ed38e..45508b8f81 100644 --- a/libavutil/arm/float_dsp_init_vfp.c +++ b/libavutil/arm/float_dsp_init_vfp.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2008 Siarhei Siamashka <ssvb@users.sourceforge.net> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/arm/float_dsp_neon.S b/libavutil/arm/float_dsp_neon.S index 559b565628..3823227608 100644 --- a/libavutil/arm/float_dsp_neon.S +++ b/libavutil/arm/float_dsp_neon.S @@ -2,20 +2,20 @@ * ARM NEON optimised Float DSP functions * Copyright (c) 2008 Mans Rullgard <mans@mansr.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/arm/float_dsp_vfp.S b/libavutil/arm/float_dsp_vfp.S index 9f920aae70..7db2452284 100644 --- a/libavutil/arm/float_dsp_vfp.S +++ b/libavutil/arm/float_dsp_vfp.S @@ -1,20 +1,20 @@ /* * Copyright (c) 2008 Siarhei Siamashka <ssvb@users.sourceforge.net> * - * This file is part of Libav. + * This file is part of FFmpeg * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/arm/intmath.h b/libavutil/arm/intmath.h index 56fcdb3ec0..fd52648f88 100644 --- a/libavutil/arm/intmath.h +++ b/libavutil/arm/intmath.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2010 Mans Rullgard <mans@mansr.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/arm/intreadwrite.h b/libavutil/arm/intreadwrite.h index 6eff7332fb..2340a9a935 100644 --- a/libavutil/arm/intreadwrite.h +++ b/libavutil/arm/intreadwrite.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/arm/neontest.h b/libavutil/arm/neontest.h index eb46df8e0b..f668c00733 100644 --- a/libavutil/arm/neontest.h +++ b/libavutil/arm/neontest.h @@ -3,20 +3,20 @@ * Copyright (c) 2008 Ramiro Polla <ramiro.polla@gmail.com> * Copyright (c) 2013 Martin Storsjo * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/arm/timer.h b/libavutil/arm/timer.h index 4bca877d00..5e8bc8edd0 100644 --- a/libavutil/arm/timer.h +++ b/libavutil/arm/timer.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2009 Mans Rullgard <mans@mansr.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/atomic.c b/libavutil/atomic.c index 83740396d4..1fa6308630 100644 --- a/libavutil/atomic.c +++ b/libavutil/atomic.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2012 Ronald S. Bultje <rsbultje@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -109,7 +109,7 @@ void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval) #endif /* !HAVE_ATOMICS_NATIVE */ #ifdef TEST -#include <assert.h> +#include "avassert.h" int main(void) { @@ -117,10 +117,10 @@ int main(void) int res; res = avpriv_atomic_int_add_and_fetch(&val, 1); - assert(res == 2); + av_assert0(res == 2); avpriv_atomic_int_set(&val, 3); res = avpriv_atomic_int_get(&val); - assert(res == 3); + av_assert0(res == 3); return 0; } diff --git a/libavutil/atomic.h b/libavutil/atomic.h index 57a0c19fcb..15906d24c9 100644 --- a/libavutil/atomic.h +++ b/libavutil/atomic.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2012 Ronald S. Bultje <rsbultje@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/atomic_gcc.h b/libavutil/atomic_gcc.h index 9470e8e50b..2bb43c3cea 100644 --- a/libavutil/atomic_gcc.h +++ b/libavutil/atomic_gcc.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2012 Ronald S. Bultje <rsbultje@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/atomic_suncc.h b/libavutil/atomic_suncc.h index 5c11b5704a..3cad24a051 100644 --- a/libavutil/atomic_suncc.h +++ b/libavutil/atomic_suncc.h @@ -1,19 +1,19 @@ /* * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/atomic_win32.h b/libavutil/atomic_win32.h index 84e8b7f0c1..f4ee07853f 100644 --- a/libavutil/atomic_win32.h +++ b/libavutil/atomic_win32.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2012 Ronald S. Bultje <rsbultje@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/attributes.h b/libavutil/attributes.h index d7f2bb5c6f..7d3f4a91cf 100644 --- a/libavutil/attributes.h +++ b/libavutil/attributes.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -32,6 +32,7 @@ # define AV_GCC_VERSION_AT_LEAST(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) @@ -39,6 +40,15 @@ #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,1) # define av_noinline __attribute__((noinline)) @@ -80,6 +90,30 @@ # 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__) # define av_unused __attribute__((unused)) #else @@ -103,7 +137,7 @@ # define av_alias #endif -#if defined(__GNUC__) && !defined(__ICC) +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) # define av_uninit(x) x=x #else # define av_uninit(x) x diff --git a/libavutil/audio_fifo.c b/libavutil/audio_fifo.c index b562537cf6..c3aadfdab7 100644 --- a/libavutil/audio_fifo.c +++ b/libavutil/audio_fifo.c @@ -2,20 +2,20 @@ * Audio FIFO * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -76,7 +76,7 @@ AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels, af->sample_size = buf_size / nb_samples; af->nb_buffers = av_sample_fmt_is_planar(sample_fmt) ? channels : 1; - af->buf = av_mallocz(af->nb_buffers * sizeof(*af->buf)); + af->buf = av_mallocz_array(af->nb_buffers, sizeof(*af->buf)); if (!af->buf) goto error; diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h index e73123d864..d21e6a1318 100644 --- a/libavutil/audio_fifo.h +++ b/libavutil/audio_fifo.h @@ -2,20 +2,20 @@ * Audio FIFO * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -88,7 +88,8 @@ int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples); * @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. + * 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); @@ -102,7 +103,9 @@ int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples); * @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. + * 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); diff --git a/libavutil/avassert.h b/libavutil/avassert.h index b223d26e8d..41f5e0eea7 100644 --- a/libavutil/avassert.h +++ b/libavutil/avassert.h @@ -1,20 +1,20 @@ /* * copyright (c) 2010 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -36,7 +36,7 @@ */ #define av_assert0(cond) do { \ if (!(cond)) { \ - av_log(NULL, AV_LOG_FATAL, "Assertion %s failed at %s:%d\n", \ + av_log(NULL, AV_LOG_PANIC, "Assertion %s failed at %s:%d\n", \ AV_STRINGIFY(cond), __FILE__, __LINE__); \ abort(); \ } \ diff --git a/libavutil/avr32/bswap.h b/libavutil/avr32/bswap.h index 857f024054..e79d53f369 100644 --- a/libavutil/avr32/bswap.h +++ b/libavutil/avr32/bswap.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/avr32/intreadwrite.h b/libavutil/avr32/intreadwrite.h index e0049feb09..c6fd3aa470 100644 --- a/libavutil/avr32/intreadwrite.h +++ b/libavutil/avr32/intreadwrite.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2009 Mans Rullgard <mans@mansr.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/avstring.c b/libavutil/avstring.c index eb5c95a01c..a63fb84bcf 100644 --- a/libavutil/avstring.c +++ b/libavutil/avstring.c @@ -2,20 +2,20 @@ * Copyright (c) 2000, 2001, 2002 Fabrice Bellard * Copyright (c) 2007 Mans Rullgard * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -28,6 +28,7 @@ #include "common.h" #include "mem.h" #include "avstring.h" +#include "bprint.h" int av_strstart(const char *str, const char *pfx, const char **ptr) { @@ -54,11 +55,11 @@ int av_stristart(const char *str, const char *pfx, const char **ptr) char *av_stristr(const char *s1, const char *s2) { if (!*s2) - return s1; + return (char*)(intptr_t)s1; do if (av_stristart(s1, s2, NULL)) - return s1; + return (char*)(intptr_t)s1; while (*s1++); return NULL; @@ -68,11 +69,11 @@ char *av_strnstr(const char *haystack, const char *needle, size_t hay_length) { size_t needle_len = strlen(needle); if (!needle_len) - return haystack; + return (char*)haystack; while (hay_length >= needle_len) { hay_length--; if (!memcmp(haystack, needle, needle_len)) - return haystack; + return (char*)haystack; haystack++; } return NULL; @@ -108,6 +109,32 @@ size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...) 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); @@ -153,6 +180,35 @@ char *av_get_token(const char **buf, const char *term) 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; @@ -212,6 +268,23 @@ const char *av_dirname(char *path) return path; } +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_isdigit(int c) { return c >= '0' && c <= '9'; @@ -252,14 +325,76 @@ int av_match_name(const char *name, const char *names) return !av_strcasecmp(name, names); } +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; + + 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; + + while (code & top) { + int tmp; + 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; + + if (code >= 1<<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; +} #ifdef TEST int main(void) { int i; - const char *strings[] = { + static const char * const strings[] = { "''", "", ":", diff --git a/libavutil/avstring.h b/libavutil/avstring.h index 9a18ddd893..616c0662fc 100644 --- a/libavutil/avstring.h +++ b/libavutil/avstring.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2007 Mans Rullgard * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -22,6 +22,7 @@ #define AVUTIL_AVSTRING_H #include <stddef.h> +#include <stdint.h> #include "attributes.h" /** @@ -131,6 +132,30 @@ size_t av_strlcat(char *dst, const char *src, size_t size); 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 a av_malloced string. */ char *av_d2str(double d); @@ -152,6 +177,30 @@ char *av_d2str(double d); 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. */ int av_isdigit(int c); @@ -191,7 +240,7 @@ static inline int av_tolower(int c) */ int av_isxdigit(int c); -/* +/** * Locale-independent case-insensitive compare. * @note This means only ASCII-range characters are case-insensitive */ @@ -219,7 +268,6 @@ const char *av_basename(const char *path); */ const char *av_dirname(char *path); - /** * Match instances of a name in a comma-separated list of names. * @param name Name to look for. @@ -228,6 +276,87 @@ const char *av_dirname(char *path); */ int av_match_name(const char *name, const char *names); +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 0x01 + +/** + * 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 0x02 + +/** + * 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() + */ +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 + */ +int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end, + unsigned int flags); + /** * @} */ diff --git a/libavutil/avutil.h b/libavutil/avutil.h index f056415f09..e6ebb6c43c 100644 --- a/libavutil/avutil.h +++ b/libavutil/avutil.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -29,22 +29,23 @@ /** * @mainpage * - * @section libav_intro Introduction + * @section ffmpeg_intro Introduction * * This document describes the usage of the different libraries - * provided by Libav. + * 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 lavr "libavresample" audio resampling, format conversion and mixing - * @li @ref libsws "libswscale" color conversion and scaling 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 libav_versioning Versioning and compatibility + * @section ffmpeg_versioning Versioning and compatibility * - * Each of the Libav libraries contains a version.h header, which defines a + * 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 @@ -55,22 +56,22 @@ * might still want to check for - e.g. changing behavior in a previously * unspecified situation. * - * Libav guarantees backward API and ABI compatibility for each library as long + * 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 Libav snapshot + * 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 - * Libav versions or to replacing the dynamic Libav libraries that a program + * 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 - * Libav). New macros and enum values may be added. Behavior in undocumented + * 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. @@ -80,7 +81,7 @@ * @defgroup lavu Common utility functions * * @brief - * libavutil contains the code shared across all the other Libav + * libavutil contains the code shared across all the other FFmpeg * libraries * * @note In order to use the functions provided by avutil you must include @@ -150,6 +151,12 @@ * @{ * * @} + * + * @defgroup version_utils Library Version Macros + * + * @{ + * + * @} */ @@ -193,6 +200,12 @@ enum AVMediaType { }; /** + * 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 * @{ * @@ -213,7 +226,7 @@ enum AVMediaType { * @} * @defgroup lavu_time Timestamp specific * - * Libav internal timebase and timestamp definitions + * FFmpeg internal timebase and timestamp definitions * * @{ */ @@ -225,7 +238,7 @@ enum AVMediaType { * either pts or dts. */ -#define AV_NOPTS_VALUE INT64_C(0x8000000000000000) +#define AV_NOPTS_VALUE ((int64_t)UINT64_C(0x8000000000000000)) /** * Internal time base represented as integer @@ -250,7 +263,8 @@ enum AVMediaType { */ enum AVPictureType { - AV_PICTURE_TYPE_I = 1, ///< Intra + 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 MPEG4 @@ -272,10 +286,50 @@ 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. diff --git a/libavutil/avutilres.rc b/libavutil/avutilres.rc new file mode 100644 index 0000000000..40a75eb377 --- /dev/null +++ b/libavutil/avutilres.rc @@ -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 + } +} diff --git a/libavutil/base64.c b/libavutil/base64.c index 725b03504d..03ebce8b80 100644 --- a/libavutil/base64.c +++ b/libavutil/base64.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com) * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -26,41 +26,107 @@ #include "common.h" #include "base64.h" +#include "intreadwrite.h" +#include "timer.h" /* ---------------- private code */ -static const uint8_t map2[] = +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, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, + 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 + 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, }; -int av_base64_decode(uint8_t *out, const char *in, int out_size) +#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) { - int i; - unsigned v = 0; uint8_t *dst = out; + uint8_t *end = out + out_size; + // no sign extension + const uint8_t *in = in_str; + unsigned bits = 0xff; + unsigned v; - for (i = 0; in[i] && in[i] != '='; i++) { - unsigned int index= in[i]-43; - if (index>=FF_ARRAY_ELEMS(map2) || map2[index] == 0xff) - return -1; - v = (v << 6) + map2[index]; - if (i & 3) { - if (dst - out < out_size) { - *dst++ = v >> (6 - 2 * (i & 3)); - } - } + 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++; } - return dst - out; +out3: + *dst++ = v >> 10; + v <<= 2; +out2: + *dst++ = v >> 4; +out1: +out0: + return bits & 1 ? AVERROR_INVALIDDATA : dst - out; } /***************************************************************************** @@ -82,15 +148,23 @@ char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size) 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; - - do { - *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f]; - i_shift -= 6; - } while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0)); + } + while (i_shift > 0) { + *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f]; + i_shift -= 6; } while ((dst - ret) & 3) *dst++ = '='; @@ -100,6 +174,7 @@ char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size) } #ifdef TEST +// LCOV_EXCL_START #define MAX_DATA_SIZE 1024 #define MAX_ENCODED_SIZE 2048 @@ -121,21 +196,40 @@ static int test_encode_decode(const uint8_t *data, unsigned int data_size, return 1; } - if ((data2_size = av_base64_decode(data2, encoded, max_data2_size)) < 0) { + if ((data2_size = av_base64_decode(data2, encoded, max_data2_size)) != data_size) { printf("Failed: cannot decode the encoded string\n" "Encoded:\n%s\n", encoded); return 1; } + if ((data2_size = av_base64_decode(data2, encoded, data_size)) != data_size) { + printf("Failed: cannot decode with minimal buffer\n" + "Encoded:\n%s\n", encoded); + return 1; + } if (memcmp(data2, data, data_size)) { printf("Failed: encoded/decoded data differs from original data\n"); return 1; } + if (av_base64_decode(NULL, encoded, 0) != 0) { + printf("Failed: decode to NULL buffer\n"); + return 1; + } + if (strlen(encoded)) { + char *end = strchr(encoded, '='); + if (!end) + end = encoded + strlen(encoded) - 1; + *end = '%'; + if (av_base64_decode(NULL, encoded, 0) >= 0) { + printf("Failed: error detection\n"); + return 1; + } + } printf("Passed!\n"); return 0; } -int main(void) +int main(int argc, char ** argv) { int i, error_count = 0; struct test { @@ -151,15 +245,37 @@ int main(void) { "666666", "NjY2NjY2"}, { "abc:def", "YWJjOmRlZg=="}, }; + char in[1024], out[2048]; printf("Encoding/decoding tests\n"); for (i = 0; i < FF_ARRAY_ELEMS(tests); i++) error_count += test_encode_decode(tests[i].data, strlen(tests[i].data), tests[i].encoded_ref); + if (argc>1 && !strcmp(argv[1], "-t")) { + memset(in, 123, sizeof(in)); + for(i=0; i<10000; i++){ + START_TIMER + av_base64_encode(out, sizeof(out), in, sizeof(in)); + STOP_TIMER("encode") + } + for(i=0; i<10000; i++){ + START_TIMER + av_base64_decode(in, out, sizeof(in)); + STOP_TIMER("decode") + } + + for(i=0; i<10000; i++){ + START_TIMER + av_base64_decode(NULL, out, 0); + STOP_TIMER("syntax check") + } + } + if (error_count) printf("Error Count: %d.\n", error_count); return !!error_count; } +// LCOV_EXCL_STOP #endif diff --git a/libavutil/base64.h b/libavutil/base64.h index 4750cf5c72..514498eac8 100644 --- a/libavutil/base64.h +++ b/libavutil/base64.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com) * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -46,15 +46,17 @@ int av_base64_decode(uint8_t *out, const char *in, int out_size); * Encode data to base64 and null-terminate. * * @param out buffer for encoded data - * @param out_size size in bytes of the output buffer, must be at - * least AV_BASE64_SIZE(in_size) - * @param in_size size in bytes of the 'in' buffer - * @return 'out' or NULL in case of error + * @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. + * 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) diff --git a/libavutil/bfin/bswap.h b/libavutil/bfin/bswap.h index 2837a2f7e1..363ed40bc5 100644 --- a/libavutil/bfin/bswap.h +++ b/libavutil/bfin/bswap.h @@ -1,20 +1,20 @@ /* * Copyright (C) 2007 Marc Hoffman * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/bfin/timer.h b/libavutil/bfin/timer.h index 49d32a8f6b..644573daec 100644 --- a/libavutil/bfin/timer.h +++ b/libavutil/bfin/timer.h @@ -1,20 +1,20 @@ /* * Copyright (C) 2007 Marc Hoffman * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/blowfish.c b/libavutil/blowfish.c index 8437dd6f94..3821427570 100644 --- a/libavutil/blowfish.c +++ b/libavutil/blowfish.c @@ -4,20 +4,20 @@ * * loosely based on Paul Kocher's implementation * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -293,24 +293,12 @@ static const uint32_t orig_s[4][256] = { 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 } }; -static void F(AVBlowfish *ctx, uint32_t *xl, uint32_t *xr, int i) -{ - uint32_t Xl, Xr; - uint32_t y; - - Xl = *xl; - Xr = *xr; - - Xl ^= ctx->p[i]; - y = ctx->s[0][(Xl >> 24) & 0xFF]; - y += ctx->s[1][(Xl >> 16) & 0xFF]; - y ^= ctx->s[2][(Xl >> 8) & 0xFF]; - y += ctx->s[3][ Xl & 0xFF]; - Xr ^= y; - - *xl = Xr; - *xr = Xl; -} +#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; av_cold void av_blowfish_init(AVBlowfish *ctx, const uint8_t *key, int key_len) { @@ -357,17 +345,21 @@ void av_blowfish_crypt_ecb(AVBlowfish *ctx, uint32_t *xl, uint32_t *xr, Xr = *xr; if (decrypt) { - for (i = AV_BF_ROUNDS + 1; i > 1; --i) - F(ctx, &Xl, &Xr, i); + 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]); + } - Xl = Xl ^ ctx->p[1]; - Xr = Xr ^ ctx->p[0]; + Xr ^= ctx->p[0]; } else { - for (i = 0; i < AV_BF_ROUNDS; ++i) - F(ctx, &Xl, &Xr, i); + 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]); + } - Xl = Xl ^ ctx->p[AV_BF_ROUNDS]; - Xr = Xr ^ ctx->p[AV_BF_ROUNDS + 1]; + Xr ^= ctx->p[AV_BF_ROUNDS + 1]; } *xl = Xr; diff --git a/libavutil/blowfish.h b/libavutil/blowfish.h index 8c29536cfe..0b004532de 100644 --- a/libavutil/blowfish.h +++ b/libavutil/blowfish.h @@ -1,20 +1,21 @@ /* * Blowfish algorithm + * Copyright (c) 2012 Samuel Pitoiset * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/bprint.c b/libavutil/bprint.c new file mode 100644 index 0000000000..0a0d07861b --- /dev/null +++ b/libavutil/bprint.c @@ -0,0 +1,381 @@ +/* + * 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" + +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; + } +} + +#ifdef TEST + +#undef printf + +static void bprint_pascal(AVBPrint *b, unsigned size) +{ + unsigned i, j; + unsigned p[42]; + + av_assert0(size < FF_ARRAY_ELEMS(p)); + + p[0] = 1; + av_bprintf(b, "%8d\n", 1); + for (i = 1; i <= size; i++) { + p[i] = 1; + for (j = i - 1; j > 0; j--) + p[j] = p[j] + p[j - 1]; + for (j = 0; j <= i; j++) + av_bprintf(b, "%8d", p[j]); + av_bprintf(b, "\n"); + } +} + +int main(void) +{ + AVBPrint b; + char buf[256]; + struct tm testtime = { .tm_year = 100, .tm_mon = 11, .tm_mday = 20 }; + + av_bprint_init(&b, 0, -1); + bprint_pascal(&b, 5); + printf("Short text in unlimited buffer: %u/%u\n", (unsigned)strlen(b.str), b.len); + printf("%s\n", b.str); + av_bprint_finalize(&b, NULL); + + av_bprint_init(&b, 0, -1); + bprint_pascal(&b, 25); + printf("Long text in unlimited buffer: %u/%u\n", (unsigned)strlen(b.str), b.len); + av_bprint_finalize(&b, NULL); + + av_bprint_init(&b, 0, 2048); + bprint_pascal(&b, 25); + printf("Long text in limited buffer: %u/%u\n", (unsigned)strlen(b.str), b.len); + av_bprint_finalize(&b, NULL); + + av_bprint_init(&b, 0, 1); + bprint_pascal(&b, 5); + printf("Short text in automatic buffer: %u/%u\n", (unsigned)strlen(b.str), b.len); + + av_bprint_init(&b, 0, 1); + bprint_pascal(&b, 25); + printf("Long text in automatic buffer: %u/%u\n", (unsigned)strlen(b.str)/8*8, b.len); + /* Note that the size of the automatic buffer is arch-dependent. */ + + av_bprint_init(&b, 0, 0); + bprint_pascal(&b, 25); + printf("Long text count only buffer: %u/%u\n", (unsigned)strlen(b.str), b.len); + + av_bprint_init_for_buffer(&b, buf, sizeof(buf)); + bprint_pascal(&b, 25); + printf("Long text count only buffer: %u/%u\n", (unsigned)strlen(buf), b.len); + + av_bprint_init(&b, 0, -1); + av_bprint_strftime(&b, "%Y-%m-%d", &testtime); + printf("strftime full: %u/%u \"%s\"\n", (unsigned)strlen(buf), b.len, b.str); + av_bprint_finalize(&b, NULL); + + av_bprint_init(&b, 0, 8); + av_bprint_strftime(&b, "%Y-%m-%d", &testtime); + printf("strftime truncated: %u/%u \"%s\"\n", (unsigned)strlen(buf), b.len, b.str); + + return 0; +} + +#endif diff --git a/libavutil/bprint.h b/libavutil/bprint.h new file mode 100644 index 0000000000..839ec1ec0d --- /dev/null +++ b/libavutil/bprint.h @@ -0,0 +1,216 @@ +/* + * 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(size, ...) \ + __VA_ARGS__ \ + char reserved_padding[size - sizeof(struct { __VA_ARGS__ })]; + +/** + * 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. + */ +typedef struct AVBPrint { + FF_PAD_STRUCTURE(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]; + ) +} AVBPrint; + +/** + * 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(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 */ diff --git a/libavutil/bswap.h b/libavutil/bswap.h index 93a6016b8c..f38e1dec83 100644 --- a/libavutil/bswap.h +++ b/libavutil/bswap.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/buffer.c b/libavutil/buffer.c index 2b38081e1d..e9bf54b96c 100644 --- a/libavutil/buffer.c +++ b/libavutil/buffer.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -122,7 +122,17 @@ int av_buffer_is_writable(const AVBufferRef *buf) if (buf->buffer->flags & AV_BUFFER_FLAG_READONLY) return 0; - return avpriv_atomic_int_add_and_fetch(&buf->buffer->refcount, 0) == 1; + return avpriv_atomic_int_get(&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 buf->buffer->refcount; } int av_buffer_make_writable(AVBufferRef **pbuf) @@ -239,14 +249,14 @@ void av_buffer_pool_uninit(AVBufferPool **ppool) /* remove the whole buffer list from the pool and return it */ static BufferPoolEntry *get_pool(AVBufferPool *pool) { - BufferPoolEntry *cur = NULL, *last = NULL; + BufferPoolEntry *cur = *(void * volatile *)&pool->pool, *last = NULL; - do { - FFSWAP(BufferPoolEntry*, cur, last); + while (cur != last) { + last = cur; cur = avpriv_atomic_ptr_cas((void * volatile *)&pool->pool, last, NULL); if (!cur) return NULL; - } while (cur != last); + } return cur; } @@ -263,7 +273,7 @@ static void add_to_pool(BufferPoolEntry *buf) while (end->next) end = end->next; - while ((cur = avpriv_atomic_ptr_cas((void * volatile *)&pool->pool, NULL, buf))) { + while (avpriv_atomic_ptr_cas((void * volatile *)&pool->pool, NULL, buf)) { /* pool is not empty, retrieve it and append it to our list */ cur = get_pool(pool); end->next = cur; @@ -276,6 +286,10 @@ 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); + add_to_pool(buf); if (!avpriv_atomic_int_add_and_fetch(&pool->refcount, -1)) buffer_pool_free(pool); @@ -307,6 +321,7 @@ static AVBufferRef *pool_alloc_buffer(AVBufferPool *pool) ret->buffer->free = pool_release_buffer; avpriv_atomic_int_add_and_fetch(&pool->refcount, 1); + avpriv_atomic_int_add_and_fetch(&pool->nb_allocated, 1); return ret; } @@ -318,6 +333,12 @@ AVBufferRef *av_buffer_pool_get(AVBufferPool *pool) /* check whether the pool is empty */ buf = get_pool(pool); + if (!buf && pool->refcount <= pool->nb_allocated) { + av_log(NULL, AV_LOG_DEBUG, "Pool race dectected, spining to avoid overallocation and eventual OOM\n"); + while (!buf && avpriv_atomic_int_get(&pool->refcount) <= avpriv_atomic_int_get(&pool->nb_allocated)) + buf = get_pool(pool); + } + if (!buf) return pool_alloc_buffer(pool); diff --git a/libavutil/buffer.h b/libavutil/buffer.h index 56b4d020e5..b4399fd39f 100644 --- a/libavutil/buffer.h +++ b/libavutil/buffer.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -49,7 +49,7 @@ * 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 Libav is such that the + * 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 @@ -122,7 +122,7 @@ AVBufferRef *av_buffer_allocz(int size); * @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 passed to free + * @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. @@ -163,6 +163,13 @@ void av_buffer_unref(AVBufferRef **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. * diff --git a/libavutil/buffer_internal.h b/libavutil/buffer_internal.h index cce83c3cd1..c29190839e 100644 --- a/libavutil/buffer_internal.h +++ b/libavutil/buffer_internal.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -85,6 +85,8 @@ struct AVBufferPool { */ volatile int refcount; + volatile int nb_allocated; + int size; AVBufferRef* (*alloc)(int size); }; diff --git a/libavutil/channel_layout.c b/libavutil/channel_layout.c index 253c495f4f..4c0677f794 100644 --- a/libavutil/channel_layout.c +++ b/libavutil/channel_layout.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -28,41 +28,47 @@ #include "avstring.h" #include "avutil.h" #include "channel_layout.h" +#include "bprint.h" #include "common.h" -static const char * const 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 */ +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]; + return channel_names[channel_id].name; } static const struct { @@ -72,19 +78,18 @@ static const struct { } channel_layout_map[] = { { "mono", 1, AV_CH_LAYOUT_MONO }, { "stereo", 2, AV_CH_LAYOUT_STEREO }, - { "stereo", 2, AV_CH_LAYOUT_STEREO_DOWNMIX }, { "2.1", 3, AV_CH_LAYOUT_2POINT1 }, { "3.0", 3, AV_CH_LAYOUT_SURROUND }, { "3.0(back)", 3, AV_CH_LAYOUT_2_1 }, - { "3.1", 4, AV_CH_LAYOUT_3POINT1 }, { "4.0", 4, AV_CH_LAYOUT_4POINT0 }, { "quad", 4, AV_CH_LAYOUT_QUAD }, { "quad(side)", 4, AV_CH_LAYOUT_2_2 }, - { "4.1", 5, AV_CH_LAYOUT_4POINT1 }, - { "5.0", 5, AV_CH_LAYOUT_5POINT0 }, + { "3.1", 4, AV_CH_LAYOUT_3POINT1 }, { "5.0", 5, AV_CH_LAYOUT_5POINT0_BACK }, - { "5.1", 6, AV_CH_LAYOUT_5POINT1 }, + { "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 }, @@ -94,40 +99,67 @@ static const struct { { "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 }, { "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 }, { "downmix", 2, AV_CH_LAYOUT_STEREO_DOWNMIX, }, - { 0 } }; +#if FF_API_GET_CHANNEL_LAYOUT_COMPAT +static uint64_t get_channel_layout_single(const char *name, int name_len, int compat) +#else static uint64_t get_channel_layout_single(const char *name, int name_len) +#endif { int i; char *end; int64_t layout; - for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map) - 1; i++) { + 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] && - strlen(channel_names[i]) == name_len && - !memcmp(channel_names[i], name, name_len)) + 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; i = strtol(name, &end, 10); - if (end - name == name_len || - (end + 1 - name == name_len && *end == 'c')) + +#if FF_API_GET_CHANNEL_LAYOUT_COMPAT + if (compat) { + if (end - name == name_len || + (end + 1 - name == name_len && *end == 'c')) { + layout = av_get_default_channel_layout(i); + if (end - name == name_len) { + av_log(NULL, AV_LOG_WARNING, + "Single channel layout '%.*s' is interpreted as a number of channels, " + "switch to the syntax '%.*sc' otherwise it will be interpreted as a " + "channel layout number in a later version\n", + name_len, name, name_len, name); + return layout; + } + } + } else { +#endif + if ((end + 1 - name == name_len && *end == 'c')) return av_get_default_channel_layout(i); +#if FF_API_GET_CHANNEL_LAYOUT_COMPAT + } +#endif + layout = strtoll(name, &end, 0); if (end - name == name_len) return FFMAX(layout, 0); return 0; } +#if FF_API_GET_CHANNEL_LAYOUT_COMPAT +uint64_t ff_get_channel_layout(const char *name, int compat) +#else uint64_t av_get_channel_layout(const char *name) +#endif { const char *n, *e; const char *name_end = name + strlen(name); @@ -135,7 +167,11 @@ uint64_t av_get_channel_layout(const char *name) for (n = name; n < name_end; n = e + 1) { for (e = n; e < name_end && *e != '+' && *e != '|'; e++); +#if FF_API_GET_CHANNEL_LAYOUT_COMPAT + layout_single = get_channel_layout_single(n, e - n, compat); +#else layout_single = get_channel_layout_single(n, e - n); +#endif if (!layout_single) return 0; layout |= layout_single; @@ -143,58 +179,67 @@ uint64_t av_get_channel_layout(const char *name) return layout; } -void av_get_channel_layout_string(char *buf, int buf_size, - int nb_channels, uint64_t channel_layout) +#if FF_API_GET_CHANNEL_LAYOUT_COMPAT +uint64_t av_get_channel_layout(const char *name) +{ + return ff_get_channel_layout(name, 1); +} +#endif + +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; channel_layout_map[i].name; i++) + 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_strlcpy(buf, channel_layout_map[i].name, buf_size); + av_bprintf(bp, "%s", channel_layout_map[i].name); return; } - snprintf(buf, buf_size, "%d channels", nb_channels); + av_bprintf(bp, "%d channels", nb_channels); if (channel_layout) { int i, ch; - av_strlcat(buf, " (", buf_size); + 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_strlcat(buf, "|", buf_size); - av_strlcat(buf, name, buf_size); + av_bprintf(bp, "+"); + av_bprintf(bp, "%s", name); } ch++; } } - av_strlcat(buf, ")", buf_size); + 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); } -uint64_t av_get_default_channel_layout(int nb_channels) -{ - switch(nb_channels) { - case 1: return AV_CH_LAYOUT_MONO; - case 2: return AV_CH_LAYOUT_STEREO; - case 3: return AV_CH_LAYOUT_SURROUND; - case 4: return AV_CH_LAYOUT_QUAD; - case 5: return AV_CH_LAYOUT_5POINT0; - case 6: return AV_CH_LAYOUT_5POINT1; - case 7: return AV_CH_LAYOUT_6POINT1; - case 8: return AV_CH_LAYOUT_7POINT1; - default: return 0; - } +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, @@ -218,6 +263,17 @@ const char *av_get_channel_name(uint64_t channel) 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; @@ -231,3 +287,13 @@ uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index) } 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; +} diff --git a/libavutil/channel_layout.h b/libavutil/channel_layout.h index 6a1f83005a..dea4d6093d 100644 --- a/libavutil/channel_layout.h +++ b/libavutil/channel_layout.h @@ -2,20 +2,20 @@ * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * Copyright (c) 2008 Peter Ross * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -36,6 +36,14 @@ /** * @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 @@ -71,7 +79,7 @@ /** * @} - * @defgroup channel_mask_c Audio channel convenience macros + * @defgroup channel_mask_c Audio channel layouts * @{ * */ #define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER) @@ -114,10 +122,6 @@ enum AVMatrixEncoding { }; /** - * @} - */ - -/** * 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, @@ -132,7 +136,12 @@ enum AVMatrixEncoding { * - a channel layout mask, in hexadecimal starting with "0x" (see the * AV_CH_* macros). * - * Example: "stereo+FC" = "2+FC" = "2c+1c" = "0x7" + * @warning Starting from the next major bump the trailing character + * 'c' to specify a number of channels will be required, while a + * channel layout mask could also be specified as a decimal number + * (if and only if not followed by "c"). + * + * Example: "stereo+FC" = "2c+FC" = "2c+1c" = "0x7" */ uint64_t av_get_channel_layout(const char *name); @@ -145,6 +154,12 @@ uint64_t av_get_channel_layout(const char *name); */ 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. */ @@ -153,7 +168,7 @@ int av_get_channel_layout_nb_channels(uint64_t channel_layout); /** * Return default channel layout for a given number of channels. */ -uint64_t av_get_default_channel_layout(int nb_channels); +int64_t av_get_default_channel_layout(int nb_channels); /** * Get the index of a channel in channel_layout. @@ -180,6 +195,27 @@ uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index); 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); + +/** + * @} * @} */ diff --git a/libavutil/colorspace.h b/libavutil/colorspace.h index 8757566c78..f438159811 100644 --- a/libavutil/colorspace.h +++ b/libavutil/colorspace.h @@ -2,20 +2,20 @@ * Colorspace conversion defines * Copyright (c) 2001, 2002, 2003 Fabrice Bellard * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/common.h b/libavutil/common.h index eb40e12990..c82a3a6240 100644 --- a/libavutil/common.h +++ b/libavutil/common.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -26,6 +26,10 @@ #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> @@ -49,6 +53,11 @@ #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)) +/* assume a>0 and b>0 */ +#define FF_CEIL_RSHIFT(a,b) (!av_builtin_constant_p(b) ? -((-(a)) >> (b)) \ + : ((a) + (1<<(b)) - 1) >> (b)) +#define FFUDIV(a,b) (((a)>0 ?(a):(a)-(b)+1) / (b)) +#define FFUMOD(a,b) ((a)-(b)*FFUDIV(a,b)) #define FFABS(a) ((a) >= 0 ? (a) : (-(a))) #define FFSIGN(a) ((a) > 0 ? 1 : -1) @@ -63,6 +72,9 @@ /* misc math functions */ +/** + * Reverse the order of the bits of an 8-bits unsigned integer. + */ #if FF_API_AV_REVERSE extern attribute_deprecated const uint8_t av_reverse[256]; #endif @@ -92,6 +104,26 @@ av_const int av_log2_16bit(unsigned v); */ 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; @@ -148,8 +180,8 @@ static av_always_inline av_const int16_t av_clip_int16_c(int a) */ static av_always_inline av_const int32_t av_clipl_int32_c(int64_t a) { - if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (a>>63) ^ 0x7FFFFFFF; - else return a; + if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (int32_t)((a>>63) ^ 0x7FFFFFFF); + else return (int32_t)a; } /** @@ -197,6 +229,26 @@ static av_always_inline int av_sat_dadd32_c(int a, int b) */ 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; @@ -232,7 +284,7 @@ static av_always_inline av_const int av_popcount_c(uint32_t x) */ static av_always_inline av_const int av_popcount64_c(uint64_t x) { - return av_popcount(x) + av_popcount(x >> 32); + return av_popcount((uint32_t)x) + av_popcount((uint32_t)(x >> 32)); } #define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24)) @@ -248,12 +300,17 @@ static av_always_inline av_const int av_popcount64_c(uint64_t x) * 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)\ + if ((val & 0xc0) == 0x80 || val >= 0xFE)\ ERROR\ while (val & top) {\ int tmp= GET_BYTE - 128;\ @@ -371,6 +428,9 @@ static av_always_inline av_const int av_popcount64_c(uint64_t x) #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 @@ -398,6 +458,9 @@ static av_always_inline av_const int av_popcount64_c(uint64_t x) #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 diff --git a/libavutil/cpu.c b/libavutil/cpu.c index a7e5f7f345..1192619b70 100644 --- a/libavutil/cpu.c +++ b/libavutil/cpu.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -25,7 +25,9 @@ #include "common.h" #if HAVE_SCHED_GETAFFINITY -#define _GNU_SOURCE +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif #include <sched.h> #endif #if HAVE_GETPROCESSAFFINITYMASK @@ -38,16 +40,39 @@ #include <sys/types.h> #include <sys/sysctl.h> #endif -#if HAVE_SYSCONF +#if HAVE_UNISTD_H #include <unistd.h> #endif -static int cpuflags_mask = -1, checked; +static int flags, checked; + +void av_force_cpu_flags(int arg){ + if ( (arg & ( AV_CPU_FLAG_3DNOW | + AV_CPU_FLAG_3DNOWEXT | + 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_XOP | + AV_CPU_FLAG_FMA3 | + AV_CPU_FLAG_FMA4 | + AV_CPU_FLAG_AVX2 )) + && !(arg & AV_CPU_FLAG_MMX)) { + av_log(NULL, AV_LOG_WARNING, "MMX implied by specified flags\n"); + arg |= AV_CPU_FLAG_MMX; + } + + flags = arg; + checked = arg != -1; +} int av_get_cpu_flags(void) { - static int flags; - if (checked) return flags; @@ -60,16 +85,15 @@ int av_get_cpu_flags(void) if (ARCH_X86) flags = ff_get_cpu_flags_x86(); - flags &= cpuflags_mask; checked = 1; - return flags; } void av_set_cpu_flags_mask(int mask) { - cpuflags_mask = mask; checked = 0; + flags = av_get_cpu_flags() & mask; + checked = 1; } int av_parse_cpu_flags(const char *s) @@ -148,8 +172,77 @@ int av_parse_cpu_flags(const char *s) 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" }, + { "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" }, + +#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" }, + { "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" }, +#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_SCHED_GETAFFINITY && defined(CPU_COUNT) cpu_set_t cpuset; @@ -174,6 +267,11 @@ int av_cpu_count(void) nb_cpus = sysconf(_SC_NPROCESSORS_ONLN); #endif + if (!printed) { + av_log(NULL, AV_LOG_DEBUG, "detected %d logical cores\n", nb_cpus); + printed = 1; + } + return nb_cpus; } diff --git a/libavutil/cpu.h b/libavutil/cpu.h index 7cecccc9c4..8ff14d3ada 100644 --- a/libavutil/cpu.h +++ b/libavutil/cpu.h @@ -1,36 +1,34 @@ /* * Copyright (c) 2000, 2001, 2002 Fabrice Bellard * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * 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 "version.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 -#if FF_API_CPU_FLAG_MMX2 #define AV_CPU_FLAG_MMX2 0x0002 ///< SSE integer functions or AMD MMX ext -#endif #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 @@ -47,7 +45,11 @@ #define AV_CPU_FLAG_AVX 0x4000 ///< AVX functions: requires OS support even if YMM registers aren't used #define AV_CPU_FLAG_XOP 0x0400 ///< Bulldozer XOP functions #define AV_CPU_FLAG_FMA4 0x0800 ///< Bulldozer FMA4 functions -#define AV_CPU_FLAG_CMOV 0x1000 ///< i686 cmov +// #if LIBAVUTIL_VERSION_MAJOR <52 +#define AV_CPU_FLAG_CMOV 0x1001000 ///< supports cmov instruction +// #else +// #define AV_CPU_FLAG_CMOV 0x1000 ///< supports cmov instruction +// #endif #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 @@ -65,25 +67,47 @@ /** * 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 a 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 * * @warning this function is not thread safe. */ -void av_set_cpu_flags_mask(int mask); +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); diff --git a/libavutil/cpu_internal.h b/libavutil/cpu_internal.h index 3bfe8a82d8..3c6ce6d079 100644 --- a/libavutil/cpu_internal.h +++ b/libavutil/cpu_internal.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/crc.c b/libavutil/crc.c index eb22e33ada..d8b1c99d1c 100644 --- a/libavutil/crc.c +++ b/libavutil/crc.c @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -119,6 +119,45 @@ static const AVCRC av_crc_table[AV_CRC_MAX][257] = { 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, @@ -246,6 +285,11 @@ static const AVCRC av_crc_table[AV_CRC_MAX][257] = { }, }; #else +#if CONFIG_SMALL +#define CRC_TABLE_SIZE 257 +#else +#define CRC_TABLE_SIZE 1024 +#endif static struct { uint8_t le; uint8_t bits; @@ -254,11 +298,12 @@ static struct { [AV_CRC_8_ATM] = { 0, 8, 0x07 }, [AV_CRC_16_ANSI] = { 0, 16, 0x8005 }, [AV_CRC_16_CCITT] = { 0, 16, 0x1021 }, + [AV_CRC_24_IEEE] = { 0, 24, 0x864CFB }, [AV_CRC_32_IEEE] = { 0, 32, 0x04C11DB7 }, [AV_CRC_32_IEEE_LE] = { 1, 32, 0xEDB88320 }, [AV_CRC_16_ANSI_LE] = { 1, 16, 0xA001 }, }; -static AVCRC av_crc_table[AV_CRC_MAX][257]; +static AVCRC av_crc_table[AV_CRC_MAX][CRC_TABLE_SIZE]; #endif int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size) @@ -338,8 +383,9 @@ int main(void) { uint8_t buf[1999]; int i; - int p[5][3] = { { AV_CRC_32_IEEE_LE, 0xEDB88320, 0x3D5CDD04 }, + int p[6][3] = { { AV_CRC_32_IEEE_LE, 0xEDB88320, 0x3D5CDD04 }, { AV_CRC_32_IEEE , 0x04C11DB7, 0xC0F5BAE0 }, + { AV_CRC_24_IEEE , 0x864CFB , 0xB704CE }, { AV_CRC_16_ANSI_LE, 0xA001 , 0xBFD8 }, { AV_CRC_16_ANSI , 0x8005 , 0x1FBB }, { AV_CRC_8_ATM , 0x07 , 0xE3 } @@ -349,7 +395,7 @@ int main(void) for (i = 0; i < sizeof(buf); i++) buf[i] = i + i * i; - for (i = 0; i < 5; i++) { + for (i = 0; i < 6; i++) { ctx = av_crc_get_table(p[i][0]); printf("crc %08X = %X\n", p[i][1], av_crc(ctx, 0, buf, sizeof(buf))); } diff --git a/libavutil/crc.h b/libavutil/crc.h index dcb7e2c7d7..e86bf1deba 100644 --- a/libavutil/crc.h +++ b/libavutil/crc.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -25,6 +25,12 @@ #include <stddef.h> #include "attributes.h" +/** + * @defgroup lavu_crc32 CRC32 + * @ingroup lavu_crypto + * @{ + */ + typedef uint32_t AVCRC; typedef enum { @@ -34,6 +40,7 @@ typedef enum { 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 = 12, AV_CRC_MAX, /*< Not part of public API! Do not use outside libavutil. */ }AVCRCId; @@ -72,4 +79,8 @@ const AVCRC *av_crc_get_table(AVCRCId crc_id); uint32_t av_crc(const AVCRC *ctx, uint32_t crc, const uint8_t *buffer, size_t length) av_pure; +/** + * @} + */ + #endif /* AVUTIL_CRC_H */ diff --git a/libavutil/des.c b/libavutil/des.c index ab0fc2f8bc..57ad0a4fff 100644 --- a/libavutil/des.c +++ b/libavutil/des.c @@ -2,20 +2,20 @@ * DES encryption/decryption * Copyright (c) 2007 Reimar Doeffinger * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <inttypes.h> @@ -286,7 +286,7 @@ static uint64_t des_encdec(uint64_t in, uint64_t K[16], int decrypt) { return in; } -int av_des_init(AVDES *d, const uint8_t *key, int key_bits, int decrypt) { +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 -1; d->triple_des = key_bits > 64; @@ -413,10 +413,10 @@ int main(void) { for (i = 0; i < 1000; i++) { key[0] = rand64(); key[1] = rand64(); key[2] = rand64(); data = rand64(); - av_des_init(&d, key, 192, 0); - av_des_crypt(&d, &ct, &data, 1, NULL, 0); - av_des_init(&d, key, 192, 1); - av_des_crypt(&d, &ct, &ct, 1, NULL, 1); + av_des_init(&d, (uint8_t*)key, 192, 0); + av_des_crypt(&d, (uint8_t*)&ct, (uint8_t*)&data, 1, NULL, 0); + av_des_init(&d, (uint8_t*)key, 192, 1); + av_des_crypt(&d, (uint8_t*)&ct, (uint8_t*)&ct, 1, NULL, 1); if (ct != data) { printf("Test 2 failed\n"); return 1; diff --git a/libavutil/des.h b/libavutil/des.h index cda98122d3..2feb0468db 100644 --- a/libavutil/des.h +++ b/libavutil/des.h @@ -2,20 +2,20 @@ * DES encryption/decryption * Copyright (c) 2007 Reimar Doeffinger * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/dict.c b/libavutil/dict.c index e4ea7769e0..aea8910541 100644 --- a/libavutil/dict.c +++ b/libavutil/dict.c @@ -1,20 +1,20 @@ /* * copyright (c) 2009 Michael Niedermayer * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -35,7 +35,7 @@ int av_dict_count(const AVDictionary *m) return m ? m->count : 0; } -AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key, +AVDictionaryEntry *av_dict_get(FF_CONST_AVUTIL53 AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags) { unsigned int i, j; @@ -90,24 +90,26 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value, } else { AVDictionaryEntry *tmp = av_realloc(m->elems, (m->count + 1) * sizeof(*m->elems)); - if (tmp) - m->elems = tmp; - else + if (!tmp) return AVERROR(ENOMEM); + m->elems = tmp; } if (value) { if (flags & AV_DICT_DONT_STRDUP_KEY) - m->elems[m->count].key = key; + m->elems[m->count].key = (char*)(intptr_t)key; else m->elems[m->count].key = av_strdup(key); if (flags & AV_DICT_DONT_STRDUP_VAL) { - m->elems[m->count].value = value; + m->elems[m->count].value = (char*)(intptr_t)value; } else if (oldval && flags & AV_DICT_APPEND) { int len = strlen(oldval) + strlen(value) + 1; - if (!(oldval = av_realloc(oldval, len))) + char *newval = av_mallocz(len); + if (!newval) return AVERROR(ENOMEM); - av_strlcat(oldval, value, len); - m->elems[m->count].value = oldval; + av_strlcat(newval, oldval, len); + av_freep(&oldval); + av_strlcat(newval, value, len); + m->elems[m->count].value = newval; } else m->elems[m->count].value = av_strdup(value); m->count++; @@ -181,7 +183,7 @@ void av_dict_free(AVDictionary **pm) av_freep(pm); } -void av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags) +void av_dict_copy(AVDictionary **dst, FF_CONST_AVUTIL53 AVDictionary *src, int flags) { AVDictionaryEntry *t = NULL; diff --git a/libavutil/dict.h b/libavutil/dict.h index e4aee27ca3..025d867993 100644 --- a/libavutil/dict.h +++ b/libavutil/dict.h @@ -1,30 +1,38 @@ /* * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * 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 "version.h" + /** * @addtogroup lavu_dict AVDictionary * @ingroup lavu_data @@ -58,12 +66,13 @@ * */ -#define AV_DICT_MATCH_CASE 1 -#define AV_DICT_IGNORE_SUFFIX 2 +#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() and children. */ + 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() and chilren. */ + 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. */ @@ -78,12 +87,19 @@ 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 flags Allows case as well as suffix-insensitive comparisons. - * @return Found entry or NULL, changing key or value leads to undefined behavior. + * @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, +AVDictionaryEntry *av_dict_get(FF_CONST_AVUTIL53 AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags); /** @@ -107,7 +123,10 @@ int av_dict_count(const AVDictionary *m); int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags); /** - * Parse the key/value pairs list and add to a dictionary. + * 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 @@ -131,7 +150,7 @@ int av_dict_parse_string(AVDictionary **pm, const char *str, * @param flags flags to use when setting entries in *dst * @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag */ -void av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags); +void av_dict_copy(AVDictionary **dst, FF_CONST_AVUTIL53 AVDictionary *src, int flags); /** * Free all the memory allocated for an AVDictionary struct diff --git a/libavutil/display.c b/libavutil/display.c index 74aceb2847..53e8aa255f 100644 --- a/libavutil/display.c +++ b/libavutil/display.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2014 Vittorio Giovara <vittorio.giovara@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -35,10 +35,8 @@ double av_display_rotation_get(const int32_t matrix[9]) { double rotation, scale[2]; - scale[0] = sqrt(CONV_FP(matrix[0]) * CONV_FP(matrix[0]) + - CONV_FP(matrix[3]) * CONV_FP(matrix[3])); - scale[1] = sqrt(CONV_FP(matrix[1]) * CONV_FP(matrix[1]) + - CONV_FP(matrix[4]) * CONV_FP(matrix[4])); + 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; diff --git a/libavutil/display.h b/libavutil/display.h index 7e37627637..2cb930dde1 100644 --- a/libavutil/display.h +++ b/libavutil/display.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2014 Vittorio Giovara <vittorio.giovara@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/downmix_info.c b/libavutil/downmix_info.c index 51505c8e04..c634c6a79f 100644 --- a/libavutil/downmix_info.c +++ b/libavutil/downmix_info.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2014 Tim Walker <tdskywalker@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/downmix_info.h b/libavutil/downmix_info.h index 69969f6fbd..221cf5bf9b 100644 --- a/libavutil/downmix_info.h +++ b/libavutil/downmix_info.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2014 Tim Walker <tdskywalker@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -95,11 +95,12 @@ typedef struct AVDownmixInfo { /** * Get a frame's AV_FRAME_DATA_DOWNMIX_INFO side data for editing. * - * The side data is created and added to the frame if it's absent. + * 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. + * @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. + * @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); diff --git a/libavutil/dynarray.h b/libavutil/dynarray.h new file mode 100644 index 0000000000..4947d93dc8 --- /dev/null +++ b/libavutil/dynarray.h @@ -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 of 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 AV_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 */ diff --git a/libavutil/error.c b/libavutil/error.c index 6803d2d4cd..bd66354df2 100644 --- a/libavutil/error.c +++ b/libavutil/error.c @@ -1,54 +1,71 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * 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 #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 +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(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(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" }, +}; + int av_strerror(int errnum, char *errbuf, size_t errbuf_size) { - int ret = 0; - const char *errstr = NULL; - - switch (errnum) { - case AVERROR_BSF_NOT_FOUND: errstr = "Bitstream filter not found" ; break; - case AVERROR_DECODER_NOT_FOUND: errstr = "Decoder not found" ; break; - case AVERROR_DEMUXER_NOT_FOUND: errstr = "Demuxer not found" ; break; - case AVERROR_ENCODER_NOT_FOUND: errstr = "Encoder not found" ; break; - case AVERROR_EOF: errstr = "End of file" ; break; - case AVERROR_EXIT: errstr = "Immediate exit requested" ; break; - case AVERROR_FILTER_NOT_FOUND: errstr = "Filter not found" ; break; - case AVERROR_INVALIDDATA: errstr = "Invalid data found when processing input" ; break; - case AVERROR_MUXER_NOT_FOUND: errstr = "Muxer not found" ; break; - case AVERROR_OPTION_NOT_FOUND: errstr = "Option not found" ; break; - case AVERROR_PATCHWELCOME: errstr = "Not yet implemented in Libav, patches welcome"; break; - case AVERROR_PROTOCOL_NOT_FOUND:errstr = "Protocol not found" ; break; - case AVERROR_STREAM_NOT_FOUND: errstr = "Stream not found" ; break; - case AVERROR_BUG: errstr = "Bug detected, please report the issue" ; break; - case AVERROR_UNKNOWN: errstr = "Unknown error occurred" ; break; - case AVERROR_EXPERIMENTAL: errstr = "Experimental feature" ; break; - } + int ret = 0, i; + const struct error_entry *entry = NULL; - if (errstr) { - av_strlcpy(errbuf, errstr, errbuf_size); + 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 = strerror_r(AVUNERROR(errnum), errbuf, errbuf_size); + ret = AVERROR(strerror_r(AVUNERROR(errnum), errbuf, errbuf_size)); #else ret = -1; #endif @@ -58,3 +75,25 @@ int av_strerror(int errnum, char *errbuf, size_t errbuf_size) return ret; } + +#ifdef TEST + +#undef printf + +int main(void) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(error_entries); i++) { + const struct error_entry *entry = &error_entries[i]; + printf("%d: %s [%s]\n", entry->num, av_err2str(entry->num), entry->tag); + } + + for (i = 0; i < 256; i++) { + printf("%d: %s\n", -i, av_err2str(-i)); + } + + return 0; +} + +#endif /* TEST */ diff --git a/libavutil/error.h b/libavutil/error.h index 268a0320a8..f3fd7bbff6 100644 --- a/libavutil/error.h +++ b/libavutil/error.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -44,23 +44,35 @@ #define AVUNERROR(e) (e) #endif -#define AVERROR_BSF_NOT_FOUND (-0x39acbd08) ///< Bitstream filter not found -#define AVERROR_DECODER_NOT_FOUND (-0x3cbabb08) ///< Decoder not found -#define AVERROR_DEMUXER_NOT_FOUND (-0x32babb08) ///< Demuxer not found -#define AVERROR_ENCODER_NOT_FOUND (-0x3cb1ba08) ///< Encoder not found -#define AVERROR_EOF (-0x5fb9b0bb) ///< End of file -#define AVERROR_EXIT (-0x2bb6a7bb) ///< Immediate exit was requested; the called function should not be restarted -#define AVERROR_FILTER_NOT_FOUND (-0x33b6b908) ///< Filter not found -#define AVERROR_INVALIDDATA (-0x3ebbb1b7) ///< Invalid data found when processing input -#define AVERROR_MUXER_NOT_FOUND (-0x27aab208) ///< Muxer not found -#define AVERROR_OPTION_NOT_FOUND (-0x2bafb008) ///< Option not found -#define AVERROR_PATCHWELCOME (-0x3aa8beb0) ///< Not yet implemented in Libav, patches welcome -#define AVERROR_PROTOCOL_NOT_FOUND (-0x30adaf08) ///< Protocol not found -#define AVERROR_STREAM_NOT_FOUND (-0x2dabac08) ///< Stream not found -#define AVERROR_BUG (-0x5fb8aabe) ///< Bug detected, please report the issue -#define AVERROR_UNKNOWN (-0x31b4b1ab) ///< Unknown error, typically from an external library +#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 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 @@ -76,6 +88,29 @@ 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) + +/** * @} */ diff --git a/libavutil/eval.c b/libavutil/eval.c index 72f976ca4b..99993b9d49 100644 --- a/libavutil/eval.c +++ b/libavutil/eval.c @@ -2,20 +2,20 @@ * Copyright (c) 2002-2006 Michael Niedermayer <michaelni@gmx.at> * Copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.org> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -26,12 +26,14 @@ * 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 "log.h" #include "mathematics.h" +#include "time.h" #include "avstring.h" #include "timer.h" @@ -49,10 +51,10 @@ typedef struct Parser { int log_offset; void *log_ctx; #define VARS 10 - double var[VARS]; + double *var; } Parser; -static const AVClass class = { "Eval", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, offsetof(Parser,log_offset), offsetof(Parser,log_ctx) }; +static const AVClass eval_class = { "Eval", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, offsetof(Parser,log_offset), offsetof(Parser,log_ctx) }; static const int8_t si_prefixes['z' - 'E' + 1] = { ['y'-'E']= -24, @@ -77,11 +79,24 @@ static const int8_t si_prefixes['z' - 'E' + 1] = { ['Y'-'E']= 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; - d = strtod(numstr, &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') { @@ -129,10 +144,11 @@ 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_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_floor, e_ceil, e_trunc, - e_sqrt, e_not, + e_last, e_st, e_while, e_taylor, e_root, e_floor, e_ceil, e_trunc, + e_sqrt, e_not, e_random, e_hypot, e_gcd, + e_if, e_ifnot, e_print, e_bitand, e_bitor, e_between, e_clip } type; double value; // is sign in other types union { @@ -141,9 +157,15 @@ struct AVExpr { double (*func1)(void *, double); double (*func2)(void *, double, double); } a; - struct AVExpr *param[2]; + 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) { @@ -161,29 +183,124 @@ static double eval_expr(Parser *p, AVExpr *e) 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_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_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_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] = av_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(d/d2)*d2); + 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 * (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 * (sqrt(d*d + d2*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); } } } @@ -197,6 +314,8 @@ 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); } @@ -229,6 +348,15 @@ static int parse_primary(AVExpr **e, Parser *p) 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==NULL) { @@ -259,6 +387,10 @@ static int parse_primary(AVExpr **e, Parser *p) 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); @@ -279,6 +411,7 @@ static int parse_primary(AVExpr **e, Parser *p) 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; @@ -287,18 +420,31 @@ static int parse_primary(AVExpr **e, Parser *p) 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" )) { AVExpr *tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gte; } - else if (strmatch(next, "lt" )) { AVExpr *tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; 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, "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 { for (i=0; p->func1_names && p->func1_names[i]; i++) { if (strmatch(next, p->func1_names[i])) { @@ -327,7 +473,7 @@ static int parse_primary(AVExpr **e, Parser *p) return 0; } -static AVExpr *new_eval_expr(int type, int value, AVExpr *p0, AVExpr *p1) +static AVExpr *make_eval_expr(int type, int value, AVExpr *p0, AVExpr *p1) { AVExpr *e = av_mallocz(sizeof(AVExpr)); if (!e) @@ -374,7 +520,7 @@ static int parse_factor(AVExpr **e, Parser *p) av_expr_free(e1); return ret; } - e0 = new_eval_expr(e_pow, 1, e1, e2); + e0 = make_eval_expr(e_pow, 1, e1, e2); if (!e0) { av_expr_free(e1); av_expr_free(e2); @@ -401,7 +547,7 @@ static int parse_term(AVExpr **e, Parser *p) av_expr_free(e1); return ret; } - e0 = new_eval_expr(c == '*' ? e_mul : e_div, 1, e1, e2); + e0 = make_eval_expr(c == '*' ? e_mul : e_div, 1, e1, e2); if (!e0) { av_expr_free(e1); av_expr_free(e2); @@ -424,7 +570,7 @@ static int parse_subexpr(AVExpr **e, Parser *p) av_expr_free(e1); return ret; } - e0 = new_eval_expr(e_add, 1, e1, e2); + e0 = make_eval_expr(e_add, 1, e1, e2); if (!e0) { av_expr_free(e1); av_expr_free(e2); @@ -453,7 +599,7 @@ static int parse_expr(AVExpr **e, Parser *p) av_expr_free(e1); return ret; } - e0 = new_eval_expr(e_last, 1, e1, e2); + e0 = make_eval_expr(e_last, 1, e1, e2); if (!e0) { av_expr_free(e1); av_expr_free(e2); @@ -484,8 +630,22 @@ static int verify_expr(AVExpr *e) case e_trunc: case e_sqrt: case e_not: - return verify_expr(e->param[0]); - default: return verify_expr(e->param[0]) && verify_expr(e->param[1]); + 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: + 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]; } } @@ -509,7 +669,7 @@ int av_expr_parse(AVExpr **expr, const char *s, if (!av_isspace(*s++)) *wp++ = s[-1]; *wp++ = 0; - p.class = &class; + p.class = &eval_class; p.stack_index=100; p.s= w; p.const_names = const_names; @@ -533,6 +693,7 @@ int av_expr_parse(AVExpr **expr, const char *s, ret = AVERROR(EINVAL); goto end; } + e->var= av_mallocz(sizeof(double) *VARS); *expr = e; end: av_free(w); @@ -542,6 +703,7 @@ end: 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; @@ -653,6 +815,35 @@ int main(int argc, char **argv) "not(0)", "6.0206dB", "-3.0103dB", + "pow(0,1.23)", + "pow(PI,1.23)", + "PI^1.23", + "pow(-1,1.23)", + "if(1, 2)", + "if(1, 1, 2)", + "if(0, 1, 2)", + "ifnot(0, 23)", + "ifnot(1, NaN) + if(0, 1)", + "ifnot(1, 1, 2)", + "ifnot(0, 1, 2)", + "taylor(1, 1)", + "taylor(eq(mod(ld(1),4),1)-eq(mod(ld(1),4),3), PI/2, 1)", + "root(sin(ld(0))-1, 2)", + "root(sin(ld(0))+6+sin(ld(0)/12)-log(ld(0)), 100)", + "7000000B*random(0)", + "squish(2)", + "gauss(0.1)", + "hypot(4,3)", + "gcd(30,55)*print(min(9,1))", + "bitor(42, 12)", + "bitand(42, 12)", + "bitand(NAN, 1)", + "between(10, -3, 10)", + "between(-4, -2, -1)", + "between(1,2)", + "clip(0, 2, 1)", + "clip(0/0, 1, 2)", + "clip(0, 0/0, 1)", NULL }; diff --git a/libavutil/eval.h b/libavutil/eval.h index ccb29e7a33..6159b0fe58 100644 --- a/libavutil/eval.h +++ b/libavutil/eval.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -45,7 +45,7 @@ typedef struct AVExpr AVExpr; * @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 + * @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, @@ -68,7 +68,7 @@ int av_expr_parse_and_eval(double *res, const char *s, * @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 + * @return >= 0 in case of success, a negative value corresponding to an * AVERROR code otherwise */ int av_expr_parse(AVExpr **expr, const char *s, diff --git a/libavutil/fifo.c b/libavutil/fifo.c index dffaf54533..77391ee7f2 100644 --- a/libavutil/fifo.c +++ b/libavutil/fifo.c @@ -3,58 +3,83 @@ * Copyright (c) 2000, 2001, 2002 Fabrice Bellard * Copyright (c) 2006 Roman Shaposhnik * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * 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" -AVFifoBuffer *av_fifo_alloc(unsigned int size) +static AVFifoBuffer *fifo_alloc_common(void *buffer, size_t size) { - AVFifoBuffer *f = av_mallocz(sizeof(AVFifoBuffer)); - if (!f) + AVFifoBuffer *f; + if (!buffer) return NULL; - f->buffer = av_malloc(size); + f = av_mallocz(sizeof(AVFifoBuffer)); + if (!f) { + av_free(buffer); + return NULL; + } + f->buffer = buffer; f->end = f->buffer + size; av_fifo_reset(f); - if (!f->buffer) - av_freep(&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_free(f->buffer); + 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(AVFifoBuffer *f) +int av_fifo_size(FF_CONST_AVUTIL53 AVFifoBuffer *f) { return (uint32_t)(f->wndx - f->rndx); } -int av_fifo_space(AVFifoBuffer *f) +int av_fifo_space(FF_CONST_AVUTIL53 AVFifoBuffer *f) { return f->end - f->buffer - av_fifo_size(f); } @@ -68,7 +93,7 @@ int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size) AVFifoBuffer *f2 = av_fifo_alloc(new_size); if (!f2) - return -1; + return AVERROR(ENOMEM); av_fifo_generic_read(f, f2->buffer, len, NULL); f2->wptr += len; f2->wndx += len; @@ -79,28 +104,46 @@ int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size) 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*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 - f->wptr, size); + int len = FFMIN(f->end - wptr, size); if (func) { - if (func(src, f->wptr, len) <= 0) + if (func(src, wptr, len) <= 0) break; } else { - memcpy(f->wptr, src, len); + memcpy(wptr, src, len); src = (uint8_t *)src + len; } // Write memory barrier needed for SMP here in theory - f->wptr += len; - if (f->wptr >= f->end) - f->wptr = f->buffer; - f->wndx += len; + 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; } @@ -126,6 +169,7 @@ int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, /** 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; diff --git a/libavutil/fifo.h b/libavutil/fifo.h index ea30f5d2bd..dda7dd2e96 100644 --- a/libavutil/fifo.h +++ b/libavutil/fifo.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -42,12 +42,26 @@ typedef struct AVFifoBuffer { 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 */ @@ -59,7 +73,7 @@ void av_fifo_reset(AVFifoBuffer *f); * @param f AVFifoBuffer to read from * @return size */ -int av_fifo_size(AVFifoBuffer *f); +int av_fifo_size(FF_CONST_AVUTIL53 AVFifoBuffer *f); /** * Return the amount of space in bytes in the AVFifoBuffer, that is the @@ -67,7 +81,7 @@ int av_fifo_size(AVFifoBuffer *f); * @param f AVFifoBuffer to write into * @return size */ -int av_fifo_space(AVFifoBuffer *f); +int av_fifo_space(FF_CONST_AVUTIL53 AVFifoBuffer *f); /** * Feed data from an AVFifoBuffer to a user-supplied callback. @@ -95,6 +109,8 @@ int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void /** * 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 @@ -102,6 +118,17 @@ int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void 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 diff --git a/libavutil/file.c b/libavutil/file.c index d2765b8490..45fe8538de 100644 --- a/libavutil/file.c +++ b/libavutil/file.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -136,3 +136,69 @@ void av_file_unmap(uint8_t *bufptr, size_t size) av_free(bufptr); #endif } + +int av_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 == NULL) { + 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); +#ifdef _WIN32 + 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 */ +} + +#ifdef TEST + +#undef printf + +int main(void) +{ + uint8_t *buf; + size_t size; + if (av_file_map("file.c", &buf, &size, 0, NULL) < 0) + return 1; + + buf[0] = 's'; + printf("%s", buf); + av_file_unmap(buf, size); + return 0; +} +#endif + diff --git a/libavutil/file.h b/libavutil/file.h index e3f02a8308..a7364fe8fe 100644 --- a/libavutil/file.h +++ b/libavutil/file.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -51,4 +51,16 @@ int av_file_map(const char *filename, uint8_t **bufptr, size_t *size, */ 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 -1 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. + */ +int av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx); + #endif /* AVUTIL_FILE_H */ diff --git a/libavutil/file_open.c b/libavutil/file_open.c index 765eb60ef3..f3164ebe68 100644 --- a/libavutil/file_open.c +++ b/libavutil/file_open.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -48,7 +48,7 @@ static int win32_open(const char *filename_utf8, int oflag, int pmode) num_chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename_utf8, -1, NULL, 0); if (num_chars <= 0) goto fallback; - filename_w = av_mallocz(sizeof(wchar_t) * num_chars); + filename_w = av_mallocz_array(num_chars, sizeof(wchar_t)); if (!filename_w) { errno = ENOMEM; return -1; @@ -62,7 +62,7 @@ static int win32_open(const char *filename_utf8, int oflag, int pmode) return fd; fallback: - /* filename may be be in CP_ACP */ + /* filename may be in CP_ACP */ return _sopen(filename_utf8, oflag, SH_DENYNO, pmode); } #define open win32_open @@ -85,9 +85,45 @@ int avpriv_open(const char *filename, int flags, ...) fd = open(filename, flags, mode); #if HAVE_FCNTL - if (fd != -1) - fcntl(fd, F_SETFD, FD_CLOEXEC); + 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; } + +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); +} diff --git a/libavutil/fixed_dsp.c b/libavutil/fixed_dsp.c new file mode 100644 index 0000000000..b99fea519e --- /dev/null +++ b/libavutil/fixed_dsp.c @@ -0,0 +1,98 @@ +/* + * 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 + */ + +#include "fixed_dsp.h" + +static void vector_fmul_window_fixed_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_c(((((int64_t)s0*wj - (int64_t)s1*wi + 0x40000000) >> 31) + round) >> bits); + dst[j] = av_clip_int16_c(((((int64_t)s0*wi + (int64_t)s1*wj + 0x40000000) >> 31) + round) >> bits); + } +} + +static void vector_fmul_window_fixed_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; + } +} + +AVFixedDSPContext * avpriv_alloc_fixed_dsp(int bit_exact) +{ + AVFixedDSPContext * fdsp = av_malloc(sizeof(AVFixedDSPContext)); + fdsp->vector_fmul_window_scaled = vector_fmul_window_fixed_scaled_c; + fdsp->vector_fmul_window = vector_fmul_window_fixed_c; + + return fdsp; +} diff --git a/libavutil/fixed_dsp.h b/libavutil/fixed_dsp.h new file mode 100644 index 0000000000..ff6f36599a --- /dev/null +++ b/libavutil/fixed_dsp.h @@ -0,0 +1,144 @@ +/* + * 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 { + /** + * 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 + * @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); + +} 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); + +/** + * 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 */ diff --git a/libavutil/float_dsp.c b/libavutil/float_dsp.c index aabc800db6..8ac74800ee 100644 --- a/libavutil/float_dsp.c +++ b/libavutil/float_dsp.c @@ -1,18 +1,21 @@ /* - * This file is part of Libav. + * Copyright 2005 Balatoni Denes + * Copyright 2006 Loren Merritt * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -89,7 +92,7 @@ static void vector_fmul_reverse_c(float *dst, const float *src0, dst[i] = src0[i] * src1[-i]; } -static void butterflies_float_c(float *restrict v1, float *restrict v2, +static void butterflies_float_c(float *av_restrict v1, float *av_restrict v2, int len) { int i; @@ -132,6 +135,8 @@ av_cold void avpriv_float_dsp_init(AVFloatDSPContext *fdsp, int bit_exact) 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); } #ifdef TEST diff --git a/libavutil/float_dsp.h b/libavutil/float_dsp.h index 3142df4fd3..7fc851b6e5 100644 --- a/libavutil/float_dsp.h +++ b/libavutil/float_dsp.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -145,7 +145,7 @@ typedef struct AVFloatDSPContext { * @param v2 second input vector, difference output, 16-byte aligned * @param len length of vectors, multiple of 4 */ - void (*butterflies_float)(float *restrict v1, float *restrict v2, int len); + void (*butterflies_float)(float *av_restrict v1, float *av_restrict v2, int len); /** * Calculate the scalar product of two vectors of floats. @@ -183,5 +183,6 @@ 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); #endif /* AVUTIL_FLOAT_DSP_H */ diff --git a/libavutil/frame.c b/libavutil/frame.c index 4b44075f44..2c62922db9 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -1,23 +1,24 @@ /* * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * 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" @@ -26,6 +27,65 @@ #include "mem.h" #include "samplefmt.h" +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) + +#define CHECK_CHANNELS_CONSISTENCY(frame) \ + av_assert2(!(frame)->channel_layout || \ + (frame)->channels == \ + av_get_channel_layout_nb_channels((frame)->channel_layout)) + +AVDictionary **avpriv_frame_get_metadatap(AVFrame *frame) {return &frame->metadata;}; + +int av_frame_set_qp_table(AVFrame *f, AVBufferRef *buf, int stride, int qp_type) +{ + 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; + + return 0; +} + +int8_t *av_frame_get_qp_table(AVFrame *f, int *stride, int *type) +{ + *stride = f->qstride; + *type = f->qscale_type; + + if (!f->qp_table_buf) + return NULL; + + return f->qp_table_buf->data; +} + +const char *av_get_colorspace_name(enum AVColorSpace val) +{ + static const char *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) @@ -33,7 +93,13 @@ static void get_frame_defaults(AVFrame *frame) memset(frame, 0, sizeof(*frame)); - frame->pts = AV_NOPTS_VALUE; + frame->pts = + frame->pkt_dts = + frame->pkt_pts = AV_NOPTS_VALUE; + av_frame_set_best_effort_timestamp(frame, AV_NOPTS_VALUE); + av_frame_set_pkt_duration (frame, 0); + av_frame_set_pkt_pos (frame, -1); + av_frame_set_pkt_size (frame, -1); frame->key_frame = 1; frame->sample_aspect_ratio = (AVRational){ 0, 1 }; frame->format = -1; /* unknown */ @@ -63,6 +129,7 @@ AVFrame *av_frame_alloc(void) if (!frame) return NULL; + frame->extended_data = NULL; get_frame_defaults(frame); return frame; @@ -89,21 +156,25 @@ static int get_video_buffer(AVFrame *frame, int align) return ret; if (!frame->linesize[0]) { - ret = av_image_fill_linesizes(frame->linesize, frame->format, - frame->width); - if (ret < 0) - return ret; + 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); } for (i = 0; i < 4 && frame->linesize[i]; i++) { - int h = frame->height; + int h = FFALIGN(frame->height, 32); if (i == 1 || i == 2) - h = -((-h) >> desc->log2_chroma_h); + h = FF_CEIL_RSHIFT(h, desc->log2_chroma_h); - frame->buf[i] = av_buffer_alloc(frame->linesize[i] * h); + frame->buf[i] = av_buffer_alloc(frame->linesize[i] * h + 16 + 16/*STRIDE_ALIGN*/ - 1); if (!frame->buf[i]) goto fail; @@ -127,11 +198,18 @@ fail: static int get_audio_buffer(AVFrame *frame, int align) { - int channels = av_get_channel_layout_nb_channels(frame->channel_layout); + int channels; int planar = av_sample_fmt_is_planar(frame->format); - int planes = planar ? channels : 1; + 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, @@ -141,9 +219,9 @@ static int get_audio_buffer(AVFrame *frame, int align) } if (planes > AV_NUM_DATA_POINTERS) { - frame->extended_data = av_mallocz(planes * + frame->extended_data = av_mallocz_array(planes, sizeof(*frame->extended_data)); - frame->extended_buf = av_mallocz((planes - AV_NUM_DATA_POINTERS) * + 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); @@ -181,7 +259,7 @@ int av_frame_get_buffer(AVFrame *frame, int align) if (frame->width > 0 && frame->height > 0) return get_video_buffer(frame, align); - else if (frame->nb_samples > 0 && frame->channel_layout) + else if (frame->nb_samples > 0 && (frame->channel_layout || frame->channels > 0)) return get_audio_buffer(frame, align); return AVERROR(EINVAL); @@ -194,6 +272,7 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src) 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; @@ -215,7 +294,9 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src) } /* ref the buffers */ - for (i = 0; i < FF_ARRAY_ELEMS(src->buf) && src->buf[i]; i++) { + 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); @@ -224,7 +305,7 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src) } if (src->extended_buf) { - dst->extended_buf = av_mallocz(sizeof(*dst->extended_buf) * + dst->extended_buf = av_mallocz_array(sizeof(*dst->extended_buf), src->nb_extended_buf); if (!dst->extended_buf) { ret = AVERROR(ENOMEM); @@ -243,14 +324,15 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src) /* duplicate extended data */ if (src->extended_data != src->data) { - int ch = av_get_channel_layout_nb_channels(src->channel_layout); + int ch = src->channels; if (!ch) { ret = AVERROR(EINVAL); goto fail; } + CHECK_CHANNELS_CONSISTENCY(src); - dst->extended_data = av_malloc(sizeof(*dst->extended_data) * ch); + dst->extended_data = av_malloc_array(sizeof(*dst->extended_data), ch); if (!dst->extended_data) { ret = AVERROR(ENOMEM); goto fail; @@ -296,6 +378,9 @@ void av_frame_unref(AVFrame *frame) 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); + av_buffer_unref(&frame->qp_table_buf); + get_frame_defaults(frame); } @@ -316,8 +401,9 @@ int av_frame_is_writable(AVFrame *frame) if (!frame->buf[0]) return 0; - for (i = 0; i < FF_ARRAY_ELEMS(frame->buf) && frame->buf[i]; i++) - ret &= !!av_buffer_is_writable(frame->buf[i]); + 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]); @@ -339,6 +425,7 @@ int av_frame_make_writable(AVFrame *frame) 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); @@ -380,13 +467,21 @@ int av_frame_copy_props(AVFrame *dst, const AVFrame *src) dst->palette_has_changed = src->palette_has_changed; dst->sample_rate = src->sample_rate; dst->opaque = src->opaque; +#if FF_API_AVFRAME_LAVC + dst->type = src->type; +#endif dst->pkt_pts = src->pkt_pts; 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; #if FF_API_AVFRAME_COLORSPACE dst->color_primaries = src->color_primaries; dst->color_trc = src->color_trc; @@ -395,6 +490,8 @@ int av_frame_copy_props(AVFrame *dst, const AVFrame *src) dst->chroma_location = src->chroma_location; #endif + av_dict_copy(&dst->metadata, src->metadata, 0); + memcpy(dst->error, src->error, sizeof(dst->error)); for (i = 0; i < src->nb_side_data; i++) { @@ -412,6 +509,18 @@ int av_frame_copy_props(AVFrame *dst, const AVFrame *src) av_dict_copy(&sd_dst->metadata, sd_src->metadata, 0); } + dst->qscale_table = NULL; + dst->qstride = 0; + dst->qscale_type = 0; + 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; + } + } + return 0; } @@ -421,9 +530,10 @@ AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane) int planes, i; if (frame->nb_samples) { - int channels = av_get_channel_layout_nb_channels(frame->channel_layout); + 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; @@ -495,8 +605,8 @@ 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) + if (dst->width < src->width || + dst->height < src->height) return AVERROR(EINVAL); planes = av_pix_fmt_count_planes(dst->format); @@ -507,7 +617,7 @@ static int frame_copy_video(AVFrame *dst, const AVFrame *src) memcpy(src_data, src->data, sizeof(src_data)); av_image_copy(dst->data, dst->linesize, src_data, src->linesize, - dst->format, dst->width, dst->height); + dst->format, src->width, src->height); return 0; } @@ -515,14 +625,17 @@ static int frame_copy_video(AVFrame *dst, const AVFrame *src) static int frame_copy_audio(AVFrame *dst, const AVFrame *src) { int planar = av_sample_fmt_is_planar(dst->format); - int channels = av_get_channel_layout_nb_channels(dst->channel_layout); + 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); @@ -559,3 +672,17 @@ void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type) } } } + +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 "Stereoscopic 3d metadata"; + 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"; + } + return NULL; +} diff --git a/libavutil/frame.h b/libavutil/frame.h index 8136fb570d..6ff372749a 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -1,19 +1,19 @@ /* * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -84,7 +84,7 @@ enum AVFrameSideDataType { AV_FRAME_DATA_DISPLAYMATRIX, /** * Active Format Description data consisting of a single byte as specified - * in ETSI TS 101 154 using enum AVActiveFormatDescription. + * in ETSI TS 101 154 using AVActiveFormatDescription enum. */ AV_FRAME_DATA_AFD, }; @@ -131,12 +131,20 @@ typedef struct AVFrameSideData { * * sizeof(AVFrame) is not a part of the public ABI, so new fields may be added * to the end with a minor bump. + * Similarly fields that are marked as to be only accessed by + * av_opt_ptr() can be reordered. This allows 2 forks to add fields + * without breaking compatibility with each other. */ 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. */ uint8_t *data[AV_NUM_DATA_POINTERS]; @@ -147,6 +155,11 @@ typedef struct AVFrame { * 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 multiplies 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. */ @@ -216,7 +229,9 @@ typedef struct AVFrame { int64_t pkt_pts; /** - * DTS copied from the AVPacket that triggered returning this frame. + * 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; @@ -269,7 +284,6 @@ typedef struct AVFrame { * motion_val[direction][x + y*mv_stride][0->mv_x, 1->mv_y]; * @endcode */ - attribute_deprecated int16_t (*motion_val[2])[2]; /** @@ -366,7 +380,6 @@ typedef struct AVFrame { * log2 of the size of the block which a single vector in motion_val represents: * (4->16x16, 3->8x8, 2-> 4x4, 1-> 2x2) */ - attribute_deprecated uint8_t motion_subsample_log2; #endif @@ -434,19 +447,144 @@ typedef struct AVFrame { int flags; #if FF_API_AVFRAME_COLORSPACE + /** + * MPEG vs JPEG YUV range. + * It must be accessed using av_frame_get_color_range() and + * av_frame_set_color_range(). + * - encoding: Set by user + * - decoding: Set by libavcodec + */ enum AVColorRange color_range; enum AVColorPrimaries color_primaries; enum AVColorTransferCharacteristic color_trc; + /** + * YUV colorspace type. + * It must be accessed using av_frame_get_colorspace() and + * av_frame_set_colorspace(). + * - encoding: Set by user + * - decoding: Set by libavcodec + */ enum AVColorSpace colorspace; enum AVChromaLocation chroma_location; #endif + + /** + * frame timestamp estimated using various heuristics, in stream time base + * Code outside libavcodec should access this field using: + * av_frame_get_best_effort_timestamp(frame) + * - 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 + * Code outside libavcodec should access this field using: + * av_frame_get_pkt_pos(frame) + * - encoding: unused + * - decoding: Read by user. + */ + int64_t pkt_pos; + + /** + * duration of the corresponding packet, expressed in + * AVStream->time_base units, 0 if unknown. + * Code outside libavcodec should access this field using: + * av_frame_get_pkt_duration(frame) + * - encoding: unused + * - decoding: Read by user. + */ + int64_t pkt_duration; + + /** + * metadata. + * Code outside libavcodec should access this field using: + * av_frame_get_metadata(frame) + * - 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. + * Code outside libavcodec should access this field using: + * av_frame_get_decode_error_flags(frame) + * - 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 + + /** + * number of audio channels, only used for audio. + * Code outside libavcodec should access this field using: + * av_frame_get_channels(frame) + * - encoding: unused + * - decoding: Read by user. + */ + int channels; + + /** + * size of the corresponding packet containing the compressed + * frame. It must be accessed using av_frame_get_pkt_size() and + * av_frame_set_pkt_size(). + * It is set to a negative value if unknown. + * - encoding: unused + * - decoding: set by libavcodec, read by user. + */ + int pkt_size; + + /** + * Not to be accessed directly from outside libavutil + */ + AVBufferRef *qp_table_buf; } AVFrame; /** + * Accessors for some AVFrame fields. + * The position of these field in the structure is not part of the ABI, + * they should not be accessed directly outside libavcodec. + */ +int64_t av_frame_get_best_effort_timestamp(const AVFrame *frame); +void av_frame_set_best_effort_timestamp(AVFrame *frame, int64_t val); +int64_t av_frame_get_pkt_duration (const AVFrame *frame); +void av_frame_set_pkt_duration (AVFrame *frame, int64_t val); +int64_t av_frame_get_pkt_pos (const AVFrame *frame); +void av_frame_set_pkt_pos (AVFrame *frame, int64_t val); +int64_t av_frame_get_channel_layout (const AVFrame *frame); +void av_frame_set_channel_layout (AVFrame *frame, int64_t val); +int av_frame_get_channels (const AVFrame *frame); +void av_frame_set_channels (AVFrame *frame, int val); +int av_frame_get_sample_rate (const AVFrame *frame); +void av_frame_set_sample_rate (AVFrame *frame, int val); +AVDictionary *av_frame_get_metadata (const AVFrame *frame); +void av_frame_set_metadata (AVFrame *frame, AVDictionary *val); +int av_frame_get_decode_error_flags (const AVFrame *frame); +void av_frame_set_decode_error_flags (AVFrame *frame, int val); +int av_frame_get_pkt_size(const AVFrame *frame); +void av_frame_set_pkt_size(AVFrame *frame, int val); +AVDictionary **avpriv_frame_get_metadatap(AVFrame *frame); +int8_t *av_frame_get_qp_table(AVFrame *f, int *stride, int *type); +int av_frame_set_qp_table(AVFrame *f, AVBufferRef *buf, int stride, int type); +enum AVColorSpace av_frame_get_colorspace(const AVFrame *frame); +void av_frame_set_colorspace(AVFrame *frame, enum AVColorSpace val); +enum AVColorRange av_frame_get_color_range(const AVFrame *frame); +void av_frame_set_color_range(AVFrame *frame, enum AVColorRange val); + +/** + * 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(). * @@ -605,6 +743,11 @@ AVFrameSideData *av_frame_get_side_data(const AVFrame *frame, void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type); /** + * @return a string identifying the side data type + */ +const char *av_frame_side_data_name(enum AVFrameSideDataType type); + +/** * @} */ diff --git a/libavutil/hash.c b/libavutil/hash.c new file mode 100644 index 0000000000..773f29e23b --- /dev/null +++ b/libavutil/hash.c @@ -0,0 +1,239 @@ +/* + * 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; + +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; + } +} + +void av_hash_update(AVHashContext *ctx, const uint8_t *src, int len) +{ + 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); +} diff --git a/libavutil/hash.h b/libavutil/hash.h new file mode 100644 index 0000000000..d4bcbf8cc8 --- /dev/null +++ b/libavutil/hash.h @@ -0,0 +1,112 @@ +/* + * 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 + */ + +#ifndef AVUTIL_HASH_H +#define AVUTIL_HASH_H + +#include <stdint.h> + +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, you must call av_hash_init(). + */ +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 i index of the hash algorithm, starting from 0 + * @return a 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 + * and are fine with not supporting hashes newly added to libavutil without + * recompilation. + * Note that you still need to check against av_hash_get_size, adding new hashes + * with larger sizes will not be considered an ABI change and should not cause + * your code to overflow a buffer. + */ +#define AV_HASH_MAX_SIZE 64 + +/** + * Get the size of the resulting hash value in bytes. + * + * The pointer passed to av_hash_final have space for at least this many bytes. + */ +int av_hash_get_size(const struct AVHashContext *ctx); + +/** + * Initialize or reset a hash context. + */ +void av_hash_init(struct AVHashContext *ctx); + +/** + * Update a hash context with additional data. + */ +void av_hash_update(struct AVHashContext *ctx, const uint8_t *src, int len); + +/** + * Finalize a hash context and compute the actual hash value. + */ +void av_hash_final(struct AVHashContext *ctx, uint8_t *dst); + +/** + * Finalize a hash context and compute the actual hash value. + * If size is smaller than the hash size, the hash is truncated; + * if size is larger, the buffer is padded with 0. + */ +void av_hash_final_bin(struct AVHashContext *ctx, uint8_t *dst, int size); + +/** + * Finalize a hash context and compute the actual hash value as a hex string. + * The string is always 0-terminated. + * If size is smaller than 2 * hash_size + 1, the hex string is truncated. + */ +void av_hash_final_hex(struct AVHashContext *ctx, uint8_t *dst, int size); + +/** + * Finalize a hash context and compute the actual hash value as a base64 string. + * The string is always 0-terminated. + * If size is smaller than AV_BASE64_SIZE(hash_size), the base64 string is + * truncated. + */ +void av_hash_final_b64(struct AVHashContext *ctx, uint8_t *dst, int size); + +/** + * Free hash context. + */ +void av_hash_freep(struct AVHashContext **ctx); + +#endif /* AVUTIL_HASH_H */ diff --git a/libavutil/hmac.c b/libavutil/hmac.c index f87728e181..02bdc182a1 100644 --- a/libavutil/hmac.c +++ b/libavutil/hmac.c @@ -1,20 +1,20 @@ /* * Copyright (C) 2012 Martin Storsjo * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -24,10 +24,11 @@ #include "hmac.h" #include "md5.h" #include "sha.h" +#include "sha512.h" #include "mem.h" -#define MAX_HASHLEN 20 -#define MAX_BLOCKLEN 64 +#define MAX_HASHLEN 64 +#define MAX_BLOCKLEN 128 struct AVHMAC { void *hash; @@ -39,11 +40,24 @@ struct AVHMAC { int keylen; }; -static av_cold void sha1_init(void *ctx) -{ - av_sha_init(ctx, 160); +#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)); @@ -53,19 +67,51 @@ AVHMAC *av_hmac_alloc(enum AVHMACType type) case AV_HMAC_MD5: c->blocklen = 64; c->hashlen = 16; - c->init = av_md5_init; - c->update = av_md5_update; - c->final = av_md5_final; + c->init = (void*)av_md5_init; + c->update = (void*)av_md5_update; + c->final = (void*)av_md5_final; c->hash = av_md5_alloc(); break; case AV_HMAC_SHA1: c->blocklen = 64; c->hashlen = 20; - c->init = sha1_init; - c->update = av_sha_update; - c->final = av_sha_final; + c->init = sha160_init; + c->update = (void*)av_sha_update; + c->final = (void*)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 = (void*)av_sha_update; + c->final = (void*)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 = (void*)av_sha_update; + c->final = (void*)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 = (void*)av_sha512_update; + c->final = (void*)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 = (void*)av_sha512_update; + c->final = (void*)av_sha512_final; + c->hash = av_sha512_alloc(); + break; default: av_free(c); return NULL; @@ -160,28 +206,54 @@ static void test(AVHMAC *hmac, const uint8_t *key, int keylen, int main(void) { - uint8_t key1[16], key3[16], data3[50], key4[63], key5[64], key6[65]; - const uint8_t key2[] = "Jefe"; - const uint8_t data1[] = "Hi There"; - const uint8_t data2[] = "what do ya want for nothing?"; + uint8_t key1[20], key3[131], data3[50]; + enum AVHMACType i = AV_HMAC_SHA224; + static const uint8_t key2[] = "Jefe"; + static const uint8_t data1[] = "Hi There"; + static const uint8_t data2[] = "what do ya want for nothing?"; + static const uint8_t data4[] = "Test Using Larger Than Block-Size Key - Hash Key First"; + static const uint8_t data5[] = "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"; + static const uint8_t data6[] = "This is a test using a larger than block-size key and a larger " + "than block-size data. The key needs to be hashed before being used" + " by the HMAC algorithm."; AVHMAC *hmac = av_hmac_alloc(AV_HMAC_MD5); if (!hmac) return 1; memset(key1, 0x0b, sizeof(key1)); memset(key3, 0xaa, sizeof(key3)); - memset(key4, 0x44, sizeof(key4)); - memset(key5, 0x55, sizeof(key5)); - memset(key6, 0x66, sizeof(key6)); memset(data3, 0xdd, sizeof(data3)); - // RFC 2104 test vectors + // RFC 2202 test vectors + test(hmac, key1, 16, data1, sizeof(data1)); + test(hmac, key2, sizeof(key2), data2, sizeof(data2)); + test(hmac, key3, 16, data3, sizeof(data3)); + test(hmac, key3, 80, data4, sizeof(data4)); + test(hmac, key3, 80, data5, sizeof(data5)); + av_hmac_free(hmac); + + /* SHA-1 */ + hmac = av_hmac_alloc(AV_HMAC_SHA1); + if (!hmac) + return 1; + // RFC 2202 test vectors test(hmac, key1, sizeof(key1), data1, sizeof(data1)); test(hmac, key2, sizeof(key2), data2, sizeof(data2)); - test(hmac, key3, sizeof(key3), data3, sizeof(data3)); - // Additional tests, to test cases where the key is too long - test(hmac, key4, sizeof(key4), data1, sizeof(data1)); - test(hmac, key5, sizeof(key5), data2, sizeof(data2)); - test(hmac, key6, sizeof(key6), data3, sizeof(data3)); + test(hmac, key3, 20, data3, sizeof(data3)); + test(hmac, key3, 80, data4, sizeof(data4)); + test(hmac, key3, 80, data5, sizeof(data5)); av_hmac_free(hmac); + + /* SHA-2 */ + while (i <= AV_HMAC_SHA512) { + hmac = av_hmac_alloc(i); + // RFC 4231 test vectors + test(hmac, key1, sizeof(key1), data1, sizeof(data1)); + test(hmac, key2, sizeof(key2), data2, sizeof(data2)); + test(hmac, key3, 20, data3, sizeof(data3)); + test(hmac, key3, sizeof(key3), data4, sizeof(data4)); + test(hmac, key3, sizeof(key3), data6, sizeof(data6)); + av_hmac_free(hmac); + i++; + } return 0; } #endif /* TEST */ diff --git a/libavutil/hmac.h b/libavutil/hmac.h index 28c2062b1b..d36d4de19e 100644 --- a/libavutil/hmac.h +++ b/libavutil/hmac.h @@ -1,20 +1,20 @@ /* * Copyright (C) 2012 Martin Storsjo * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -32,6 +32,10 @@ enum AVHMACType { AV_HMAC_MD5, AV_HMAC_SHA1, + AV_HMAC_SHA224 = 10, + AV_HMAC_SHA256, + AV_HMAC_SHA384, + AV_HMAC_SHA512, }; typedef struct AVHMAC AVHMAC; diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c index fc367d921b..00b203182b 100644 --- a/libavutil/imgutils.c +++ b/libavutil/imgutils.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -21,9 +21,11 @@ * misc image utilities */ +#include "avassert.h" #include "common.h" #include "imgutils.h" #include "internal.h" +#include "intreadwrite.h" #include "log.h" #include "mathematics.h" #include "pixdesc.h" @@ -47,27 +49,45 @@ void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], } } +static inline +int image_get_linesize(int width, int plane, + int max_step, int max_step_comp, + const AVPixFmtDescriptor *desc) +{ + int s, shifted_w, linesize; + + if (!desc) + return AVERROR(EINVAL); + + if (width < 0) + return AVERROR(EINVAL); + s = (max_step_comp == 1 || max_step_comp == 2) ? desc->log2_chroma_w : 0; + shifted_w = ((width + (1 << s) - 1)) >> s; + if (shifted_w && max_step > INT_MAX / shifted_w) + return AVERROR(EINVAL); + linesize = max_step * shifted_w; + + if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) + linesize = (linesize + 7) >> 3; + return linesize; +} + int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); int max_step [4]; /* max pixel step for each plane */ int max_step_comp[4]; /* the component for each plane which has the max pixel step */ - int s; - if (!desc) + if ((unsigned)pix_fmt >= AV_PIX_FMT_NB || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) return AVERROR(EINVAL); - if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) - return (width * (desc->comp[0].step_minus1+1) + 7) >> 3; - av_image_fill_max_pixsteps(max_step, max_step_comp, desc); - s = (max_step_comp[plane] == 1 || max_step_comp[plane] == 2) ? desc->log2_chroma_w : 0; - return max_step[plane] * (((width + (1 << s) - 1)) >> s); + return image_get_linesize(width, plane, max_step[plane], max_step_comp[plane], desc); } int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width) { - int i; + int i, ret; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); int max_step [4]; /* max pixel step for each plane */ int max_step_comp[4]; /* the component for each plane which has the max pixel step */ @@ -77,20 +97,11 @@ int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int wi if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) return AVERROR(EINVAL); - if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) { - if (width > (INT_MAX -7) / (desc->comp[0].step_minus1+1)) - return AVERROR(EINVAL); - linesizes[0] = (width * (desc->comp[0].step_minus1+1) + 7) >> 3; - return 0; - } - av_image_fill_max_pixsteps(max_step, max_step_comp, desc); for (i = 0; i < 4; i++) { - int s = (max_step_comp[i] == 1 || max_step_comp[i] == 2) ? desc->log2_chroma_w : 0; - int shifted_w = ((width + (1 << s) - 1)) >> s; - if (max_step[i] > INT_MAX / shifted_w) - return AVERROR(EINVAL); - linesizes[i] = max_step[i] * shifted_w; + if ((ret = image_get_linesize(width, i, max_step[i], max_step_comp[i], desc)) < 0) + return ret; + linesizes[i] = ret; } return 0; @@ -190,7 +201,7 @@ int av_image_alloc(uint8_t *pointers[4], int linesizes[4], if ((ret = av_image_check_size(w, h, 0, NULL)) < 0) return ret; - if ((ret = av_image_fill_linesizes(linesizes, pix_fmt, w)) < 0) + if ((ret = av_image_fill_linesizes(linesizes, pix_fmt, align>7 ? FFALIGN(w, 8) : w)) < 0) return ret; for (i = 0; i < 4; i++) @@ -257,6 +268,8 @@ void av_image_copy_plane(uint8_t *dst, int dst_linesize, { if (!dst || !src) return; + av_assert0(abs(src_linesize) >= bytewidth); + av_assert0(abs(dst_linesize) >= bytewidth); for (;height > 0; height--) { memcpy(dst, src, bytewidth); dst += dst_linesize; @@ -289,8 +302,12 @@ void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], for (i = 0; i < planes_nb; i++) { int h = height; int bwidth = av_image_get_linesize(pix_fmt, width, i); + if (bwidth < 0) { + av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n"); + return; + } if (i == 1 || i == 2) { - h= -((-height)>>desc->log2_chroma_h); + h = FF_CEIL_RSHIFT(height, desc->log2_chroma_h); } av_image_copy_plane(dst_data[i], dst_linesizes[i], src_data[i], src_linesizes[i], @@ -298,3 +315,77 @@ void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], } } } + +int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], + const uint8_t *src, + enum AVPixelFormat pix_fmt, int width, int height, int align) +{ + int ret, i; + + if ((ret = av_image_check_size(width, height, 0, NULL)) < 0) + return ret; + + if ((ret = av_image_fill_linesizes(dst_linesize, pix_fmt, width)) < 0) + return ret; + + for (i = 0; i < 4; i++) + dst_linesize[i] = FFALIGN(dst_linesize[i], align); + + if ((ret = av_image_fill_pointers(dst_data, pix_fmt, width, NULL, dst_linesize)) < 0) + return ret; + + return av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, dst_linesize); +} + +int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + uint8_t *data[4]; + int linesize[4]; + + if (!desc) + return AVERROR(EINVAL); + if (av_image_check_size(width, height, 0, NULL) < 0) + return AVERROR(EINVAL); + if (desc->flags & AV_PIX_FMT_FLAG_PSEUDOPAL) + // do not include palette for these pseudo-paletted formats + return width * height; + return av_image_fill_arrays(data, linesize, NULL, pix_fmt, width, height, align); +} + +int av_image_copy_to_buffer(uint8_t *dst, int dst_size, + const uint8_t * const src_data[4], const int src_linesize[4], + enum AVPixelFormat pix_fmt, int width, int height, int align) +{ + int i, j, nb_planes = 0, linesize[4]; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + int size = av_image_get_buffer_size(pix_fmt, width, height, align); + + if (size > dst_size || size < 0) + return AVERROR(EINVAL); + + for (i = 0; i < desc->nb_components; i++) + nb_planes = FFMAX(desc->comp[i].plane, nb_planes); + nb_planes++; + + av_image_fill_linesizes(linesize, pix_fmt, width); + for (i = 0; i < nb_planes; i++) { + int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; + const uint8_t *src = src_data[i]; + h = (height + (1 << shift) - 1) >> shift; + + for (j = 0; j < h; j++) { + memcpy(dst, src, linesize[i]); + dst += FFALIGN(linesize[i], align); + src += src_linesize[i]; + } + } + + if (desc->flags & AV_PIX_FMT_FLAG_PAL) { + uint32_t *d32 = (uint32_t *)(((size_t)dst + 3) & ~3); + for (i = 0; i<256; i++) + AV_WL32(d32 + i, AV_RN32(src_data[1] + 4*i)); + } + + return size; +} diff --git a/libavutil/imgutils.h b/libavutil/imgutils.h index 50fa8159e8..23282a38fa 100644 --- a/libavutil/imgutils.h +++ b/libavutil/imgutils.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -100,6 +100,9 @@ int av_image_alloc(uint8_t *pointers[4], int linesizes[4], * The first byte of each successive line is separated by *_linesize * bytes. * + * bytewidth must be contained by both absolute values of dst_linesize + * and src_linesize, otherwise the function behavior is undefined. + * * @param dst_linesize linesize for the image plane in dst * @param src_linesize linesize for the image plane in src */ @@ -118,6 +121,65 @@ void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height); /** + * Setup the data pointers and linesizes based on the specified image + * parameters and the provided array. + * + * The fields of the given image are filled in by using the src + * address which points to the image data buffer. Depending on the + * specified pixel format, one or multiple image data pointers and + * line sizes will be set. If a planar format is specified, several + * pointers will be set pointing to the different picture planes and + * the line sizes of the different planes will be stored in the + * lines_sizes array. Call with src == NULL to get the required + * size for the src buffer. + * + * To allocate the buffer and fill in the dst_data and dst_linesize in + * one call, use av_image_alloc(). + * + * @param dst_data data pointers to be filled in + * @param dst_linesizes linesizes for the image in dst_data to be filled in + * @param src buffer which will contain or contains the actual image data, can be NULL + * @param pix_fmt the pixel format of the image + * @param width the width of the image in pixels + * @param height the height of the image in pixels + * @param align the value used in src for linesize alignment + * @return the size in bytes required for src, a negative error code + * in case of failure + */ +int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4], + const uint8_t *src, + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Return the size in bytes of the amount of data required to store an + * image with the given parameters. + * + * @param[in] align the assumed linesize alignment + */ +int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** + * Copy image data from an image into a buffer. + * + * av_image_get_buffer_size() can be used to compute the required size + * for the buffer to fill. + * + * @param dst a buffer into which picture data will be copied + * @param dst_size the size in bytes of dst + * @param src_data pointers containing the source image data + * @param src_linesizes linesizes for the image in src_data + * @param pix_fmt the pixel format of the source image + * @param width the width of the source image in pixels + * @param height the height of the source image in pixels + * @param align the assumed linesize alignment for dst + * @return the number of bytes written to dst, or a negative value + * (error code) on error + */ +int av_image_copy_to_buffer(uint8_t *dst, int dst_size, + const uint8_t * const src_data[4], const int src_linesize[4], + enum AVPixelFormat pix_fmt, int width, int height, int align); + +/** * Check if the given dimension of an image is valid, meaning that all * bytes of the image can be addressed with a signed int. * diff --git a/libavutil/integer.c b/libavutil/integer.c new file mode 100644 index 0000000000..5bcde0dc6e --- /dev/null +++ b/libavutil/integer.c @@ -0,0 +1,196 @@ +/* + * arbitrary precision integers + * Copyright (c) 2004 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 + * arbitrary precision integers + * @author Michael Niedermayer <michaelni@gmx.at> + */ + +#include "common.h" +#include "integer.h" +#include "avassert.h" + +AVInteger av_add_i(AVInteger a, AVInteger b){ + int i, carry=0; + + for(i=0; i<AV_INTEGER_SIZE; i++){ + carry= (carry>>16) + a.v[i] + b.v[i]; + a.v[i]= carry; + } + return a; +} + +AVInteger av_sub_i(AVInteger a, AVInteger b){ + int i, carry=0; + + for(i=0; i<AV_INTEGER_SIZE; i++){ + carry= (carry>>16) + a.v[i] - b.v[i]; + a.v[i]= carry; + } + return a; +} + +int av_log2_i(AVInteger a){ + int i; + + for(i=AV_INTEGER_SIZE-1; i>=0; i--){ + if(a.v[i]) + return av_log2_16bit(a.v[i]) + 16*i; + } + return -1; +} + +AVInteger av_mul_i(AVInteger a, AVInteger b){ + AVInteger out; + int i, j; + int na= (av_log2_i(a)+16) >> 4; + int nb= (av_log2_i(b)+16) >> 4; + + memset(&out, 0, sizeof(out)); + + for(i=0; i<na; i++){ + unsigned int carry=0; + + if(a.v[i]) + for(j=i; j<AV_INTEGER_SIZE && j-i<=nb; j++){ + carry= (carry>>16) + out.v[j] + a.v[i]*b.v[j-i]; + out.v[j]= carry; + } + } + + return out; +} + +int av_cmp_i(AVInteger a, AVInteger b){ + int i; + int v= (int16_t)a.v[AV_INTEGER_SIZE-1] - (int16_t)b.v[AV_INTEGER_SIZE-1]; + if(v) return (v>>16)|1; + + for(i=AV_INTEGER_SIZE-2; i>=0; i--){ + int v= a.v[i] - b.v[i]; + if(v) return (v>>16)|1; + } + return 0; +} + +AVInteger av_shr_i(AVInteger a, int s){ + AVInteger out; + int i; + + for(i=0; i<AV_INTEGER_SIZE; i++){ + unsigned int index= i + (s>>4); + unsigned int v=0; + if(index+1<AV_INTEGER_SIZE) v = a.v[index+1]<<16; + if(index <AV_INTEGER_SIZE) v+= a.v[index ]; + out.v[i]= v >> (s&15); + } + return out; +} + +AVInteger av_mod_i(AVInteger *quot, AVInteger a, AVInteger b){ + int i= av_log2_i(a) - av_log2_i(b); + AVInteger quot_temp; + if(!quot) quot = "_temp; + + av_assert2((int16_t)a.v[AV_INTEGER_SIZE-1] >= 0 && (int16_t)b.v[AV_INTEGER_SIZE-1] >= 0); + av_assert2(av_log2_i(b)>=0); + + if(i > 0) + b= av_shr_i(b, -i); + + memset(quot, 0, sizeof(AVInteger)); + + while(i-- >= 0){ + *quot= av_shr_i(*quot, -1); + if(av_cmp_i(a, b) >= 0){ + a= av_sub_i(a, b); + quot->v[0] += 1; + } + b= av_shr_i(b, 1); + } + return a; +} + +AVInteger av_div_i(AVInteger a, AVInteger b){ + AVInteger quot; + av_mod_i(", a, b); + return quot; +} + +AVInteger av_int2i(int64_t a){ + AVInteger out; + int i; + + for(i=0; i<AV_INTEGER_SIZE; i++){ + out.v[i]= a; + a>>=16; + } + return out; +} + +int64_t av_i2int(AVInteger a){ + int i; + int64_t out=(int8_t)a.v[AV_INTEGER_SIZE-1]; + + for(i= AV_INTEGER_SIZE-2; i>=0; i--){ + out = (out<<16) + a.v[i]; + } + return out; +} + +#ifdef TEST + +const uint8_t ff_log2_tab[256]={ + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; + +int main(void){ + int64_t a,b; + + for(a=7; a<256*256*256; a+=13215){ + for(b=3; b<256*256*256; b+=27118){ + AVInteger ai= av_int2i(a); + AVInteger bi= av_int2i(b); + + av_assert0(av_i2int(ai) == a); + av_assert0(av_i2int(bi) == b); + av_assert0(av_i2int(av_add_i(ai,bi)) == a+b); + av_assert0(av_i2int(av_sub_i(ai,bi)) == a-b); + av_assert0(av_i2int(av_mul_i(ai,bi)) == a*b); + av_assert0(av_i2int(av_shr_i(ai, 9)) == a>>9); + av_assert0(av_i2int(av_shr_i(ai,-9)) == a<<9); + av_assert0(av_i2int(av_shr_i(ai, 17)) == a>>17); + av_assert0(av_i2int(av_shr_i(ai,-17)) == a<<17); + av_assert0(av_log2_i(ai) == av_log2(a)); + av_assert0(av_i2int(av_div_i(ai,bi)) == a/b); + } + } + return 0; +} +#endif diff --git a/libavutil/integer.h b/libavutil/integer.h new file mode 100644 index 0000000000..45f733c04c --- /dev/null +++ b/libavutil/integer.h @@ -0,0 +1,86 @@ +/* + * arbitrary precision integers + * Copyright (c) 2004 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 + * arbitrary precision integers + * @author Michael Niedermayer <michaelni@gmx.at> + */ + +#ifndef AVUTIL_INTEGER_H +#define AVUTIL_INTEGER_H + +#include <stdint.h> +#include "common.h" + +#define AV_INTEGER_SIZE 8 + +typedef struct AVInteger{ + uint16_t v[AV_INTEGER_SIZE]; +} AVInteger; + +AVInteger av_add_i(AVInteger a, AVInteger b) av_const; +AVInteger av_sub_i(AVInteger a, AVInteger b) av_const; + +/** + * Return the rounded-down value of the base 2 logarithm of the given + * AVInteger. This is simply the index of the most significant bit + * which is 1, or 0 if all bits are 0. + */ +int av_log2_i(AVInteger a) av_const; +AVInteger av_mul_i(AVInteger a, AVInteger b) av_const; + +/** + * Return 0 if a==b, 1 if a>b and -1 if a<b. + */ +int av_cmp_i(AVInteger a, AVInteger b) av_const; + +/** + * bitwise shift + * @param s the number of bits by which the value should be shifted right, + may be negative for shifting left + */ +AVInteger av_shr_i(AVInteger a, int s) av_const; + +/** + * Return a % b. + * @param quot a/b will be stored here. + */ +AVInteger av_mod_i(AVInteger *quot, AVInteger a, AVInteger b); + +/** + * Return a/b. + */ +AVInteger av_div_i(AVInteger a, AVInteger b) av_const; + +/** + * Convert the given int64_t to an AVInteger. + */ +AVInteger av_int2i(int64_t a) av_const; + +/** + * Convert the given AVInteger to an int64_t. + * If the AVInteger is too large to fit into an int64_t, + * then only the least significant 64 bits will be used. + */ +int64_t av_i2int(AVInteger a) av_const; + +#endif /* AVUTIL_INTEGER_H */ diff --git a/libavutil/internal.h b/libavutil/internal.h index 067c6ca303..2d1b37b719 100644 --- a/libavutil/internal.h +++ b/libavutil/internal.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -36,8 +36,11 @@ #include <assert.h> #include "config.h" #include "attributes.h" +#include "timer.h" +#include "cpu.h" #include "dict.h" #include "pixfmt.h" +#include "version.h" #if ARCH_X86 # include "x86/emms.h" @@ -62,7 +65,7 @@ #endif #if HAVE_PRAGMA_DEPRECATED -# if defined(__ICL) +# if defined(__ICL) || defined (__INTEL_COMPILER) # define FF_DISABLE_DEPRECATION_WARNINGS __pragma(warning(push)) __pragma(warning(disable:1478)) # define FF_ENABLE_DEPRECATION_WARNINGS __pragma(warning(pop)) # elif defined(_MSC_VER) @@ -81,6 +84,12 @@ # define INT_BIT (CHAR_BIT * sizeof(int)) #endif +#define FF_MEMORY_POISON 0x2a + +#define MAKE_ACCESSORS(str, name, type, field) \ + type av_##name##_get_##field(const str *s) { return s->field; } \ + void av_##name##_set_##field(str *s, type v) { s->field = v; } + // Some broken preprocessors need a second expansion // to be forced to tokenize __VA_ARGS__ #define E1(x) x @@ -114,6 +123,12 @@ # define LOCAL_ALIGNED_16(t, v, ...) LOCAL_ALIGNED(16, t, v, __VA_ARGS__) #endif +#if HAVE_LOCAL_ALIGNED_32 +# define LOCAL_ALIGNED_32(t, v, ...) E1(LOCAL_ALIGNED_D(32, t, v, __VA_ARGS__,,)) +#else +# define LOCAL_ALIGNED_32(t, v, ...) LOCAL_ALIGNED(32, t, v, __VA_ARGS__) +#endif + #define FF_ALLOC_OR_GOTO(ctx, p, size, label)\ {\ p = av_malloc(size);\ @@ -132,6 +147,24 @@ }\ } +#define FF_ALLOC_ARRAY_OR_GOTO(ctx, p, nelem, elsize, label)\ +{\ + p = av_malloc_array(nelem, elsize);\ + if (p == NULL) {\ + av_log(ctx, AV_LOG_ERROR, "Cannot allocate memory.\n");\ + goto label;\ + }\ +} + +#define FF_ALLOCZ_ARRAY_OR_GOTO(ctx, p, nelem, elsize, label)\ +{\ + p = av_mallocz_array(nelem, elsize);\ + if (p == NULL) {\ + av_log(ctx, AV_LOG_ERROR, "Cannot allocate memory.\n");\ + goto label;\ + }\ +} + #include "libm.h" #if defined(_MSC_VER) @@ -150,12 +183,11 @@ # define NULL_IF_CONFIG_SMALL(x) x #endif - /** * Define a function with only the non-default version specified. * * On systems with ELF shared libraries, all symbols exported from - * Libav libraries are tagged with the name and major version of the + * FFmpeg libraries are tagged with the name and major version of the * library to which they belong. If a function is moved from one * library to another, a wrapper must be retained in the original * location to preserve binary compatibility. @@ -213,6 +245,11 @@ void avpriv_request_sample(void *avc, #if HAVE_LIBC_MSVCRT #define avpriv_open ff_open +#define PTRDIFF_SPECIFIER "Id" +#define SIZE_SPECIFIER "Iu" +#else +#define PTRDIFF_SPECIFIER "td" +#define SIZE_SPECIFIER "zu" #endif /** @@ -222,4 +259,8 @@ int avpriv_open(const char *filename, int flags, ...); int avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt); +#if FF_API_GET_CHANNEL_LAYOUT_COMPAT +uint64_t ff_get_channel_layout(const char *name, int compat); +#endif + #endif /* AVUTIL_INTERNAL_H */ diff --git a/libavutil/intfloat.h b/libavutil/intfloat.h index 38d26ad87e..fe3d7ec4a5 100644 --- a/libavutil/intfloat.h +++ b/libavutil/intfloat.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2011 Mans Rullgard * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/intfloat_readwrite.c b/libavutil/intfloat_readwrite.c new file mode 100644 index 0000000000..af5da623cd --- /dev/null +++ b/libavutil/intfloat_readwrite.c @@ -0,0 +1,101 @@ +/* + * portable IEEE float/double read/write functions + * + * Copyright (c) 2005 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 + * portable IEEE float/double read/write functions + */ + +#include <stdint.h> +#include "common.h" +#include "mathematics.h" +#include "intfloat_readwrite.h" +#include "version.h" + +#if FF_API_INTFLOAT +double av_int2dbl(int64_t v){ + if((uint64_t)v+v > 0xFFEULL<<52) + return NAN; + return ldexp(((v&((1LL<<52)-1)) + (1LL<<52)) * (v>>63|1), (v>>52&0x7FF)-1075); +} + +float av_int2flt(int32_t v){ + if((uint32_t)v+v > 0xFF000000U) + return NAN; + return ldexp(((v&0x7FFFFF) + (1<<23)) * (v>>31|1), (v>>23&0xFF)-150); +} + +double av_ext2dbl(const AVExtFloat ext){ + uint64_t m = 0; + int e, i; + + for (i = 0; i < 8; i++) + m = (m<<8) + ext.mantissa[i]; + e = (((int)ext.exponent[0]&0x7f)<<8) | ext.exponent[1]; + if (e == 0x7fff && m) + return NAN; + e -= 16383 + 63; /* In IEEE 80 bits, the whole (i.e. 1.xxxx) + * mantissa bit is written as opposed to the + * single and double precision formats. */ + if (ext.exponent[0]&0x80) + m= -m; + return ldexp(m, e); +} + +int64_t av_dbl2int(double d){ + int e; + if ( !d) return 0; + else if(d-d) return 0x7FF0000000000000LL + ((int64_t)(d<0)<<63) + (d!=d); + d= frexp(d, &e); + return (int64_t)(d<0)<<63 | (e+1022LL)<<52 | (int64_t)((fabs(d)-0.5)*(1LL<<53)); +} + +int32_t av_flt2int(float d){ + int e; + if ( !d) return 0; + else if(d-d) return 0x7F800000 + ((d<0)<<31) + (d!=d); + d= frexp(d, &e); + return (d<0)<<31 | (e+126)<<23 | (int64_t)((fabs(d)-0.5)*(1<<24)); +} + +AVExtFloat av_dbl2ext(double d){ + struct AVExtFloat ext= {{0}}; + int e, i; double f; uint64_t m; + + f = fabs(frexp(d, &e)); + if (f >= 0.5 && f < 1) { + e += 16382; + ext.exponent[0] = e>>8; + ext.exponent[1] = e; + m = (uint64_t)ldexp(f, 64); + for (i=0; i < 8; i++) + ext.mantissa[i] = m>>(56-(i<<3)); + } else if (f != 0.0) { + ext.exponent[0] = 0x7f; ext.exponent[1] = 0xff; + if (!isinf(f)) + ext.mantissa[0] = ~0; + } + if (d < 0) + ext.exponent[0] |= 0x80; + return ext; +} +#endif /* FF_API_INTFLOAT */ diff --git a/libavutil/intfloat_readwrite.h b/libavutil/intfloat_readwrite.h new file mode 100644 index 0000000000..1d79e3e8af --- /dev/null +++ b/libavutil/intfloat_readwrite.h @@ -0,0 +1,44 @@ +/* + * copyright (c) 2005 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_INTFLOAT_READWRITE_H +#define AVUTIL_INTFLOAT_READWRITE_H + +#include <stdint.h> + +#include "attributes.h" +#include "version.h" + +#if FF_API_INTFLOAT +/* IEEE 80 bits extended float */ +typedef struct AVExtFloat { + uint8_t exponent[2]; + uint8_t mantissa[8]; +} AVExtFloat; + +attribute_deprecated double av_int2dbl(int64_t v) av_const; +attribute_deprecated float av_int2flt(int32_t v) av_const; +attribute_deprecated double av_ext2dbl(const AVExtFloat ext) av_const; +attribute_deprecated int64_t av_dbl2int(double d) av_const; +attribute_deprecated int32_t av_flt2int(float d) av_const; +attribute_deprecated AVExtFloat av_dbl2ext(double d) av_const; +#endif /* FF_API_INTFLOAT */ + +#endif /* AVUTIL_INTFLOAT_READWRITE_H */ diff --git a/libavutil/intmath.c b/libavutil/intmath.c index 8db425c6e9..1f725c741f 100644 --- a/libavutil/intmath.c +++ b/libavutil/intmath.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/intmath.h b/libavutil/intmath.h index a5ee6525ee..e140d822f3 100644 --- a/libavutil/intmath.h +++ b/libavutil/intmath.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2010 Mans Rullgard <mans@mansr.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -35,6 +35,10 @@ * @{ */ +#if ARCH_ARM +# include "arm/intmath.h" +#endif + #if HAVE_FAST_CLZ && AV_GCC_VERSION_AT_LEAST(3,4) #ifndef ff_log2 diff --git a/libavutil/intreadwrite.h b/libavutil/intreadwrite.h index f77fd60f38..51fbe30a23 100644 --- a/libavutil/intreadwrite.h +++ b/libavutil/intreadwrite.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -47,9 +47,17 @@ typedef union { /* * Arch-specific headers can provide any combination of - * AV_[RW][BLN](16|24|32|64) and AV_(COPY|SWAP|ZERO)(64|128) macros. + * AV_[RW][BLN](16|24|32|48|64) and AV_(COPY|SWAP|ZERO)(64|128) macros. * Preprocessor symbols must be defined, even if these are implemented * as inline functions. + * + * R/W means read/write, B/L/N means big/little/native endianness. + * The following macros require aligned access, compared to their + * unaligned variants: AV_(COPY|SWAP|ZERO)(64|128), AV_[RW]N[8-64]A. + * Incorrect usage may range from abysmal performance to crash + * depending on the platform. + * + * The unaligned variants are AV_[RW][BLN][8-64] and AV_COPY*U. */ #ifdef HAVE_AV_CONFIG_H @@ -114,6 +122,18 @@ typedef union { # define AV_WN32(p, v) AV_WB32(p, v) # endif +# if defined(AV_RN48) && !defined(AV_RB48) +# define AV_RB48(p) AV_RN48(p) +# elif !defined(AV_RN48) && defined(AV_RB48) +# define AV_RN48(p) AV_RB48(p) +# endif + +# if defined(AV_WN48) && !defined(AV_WB48) +# define AV_WB48(p, v) AV_WN48(p, v) +# elif !defined(AV_WN48) && defined(AV_WB48) +# define AV_WN48(p, v) AV_WB48(p, v) +# endif + # if defined(AV_RN64) && !defined(AV_RB64) # define AV_RB64(p) AV_RN64(p) # elif !defined(AV_RN64) && defined(AV_RB64) @@ -164,6 +184,18 @@ typedef union { # define AV_WN32(p, v) AV_WL32(p, v) # endif +# if defined(AV_RN48) && !defined(AV_RL48) +# define AV_RL48(p) AV_RN48(p) +# elif !defined(AV_RN48) && defined(AV_RL48) +# define AV_RN48(p) AV_RL48(p) +# endif + +# if defined(AV_WN48) && !defined(AV_WL48) +# define AV_WL48(p, v) AV_WN48(p, v) +# elif !defined(AV_WN48) && defined(AV_WL48) +# define AV_WN48(p, v) AV_WL48(p, v) +# endif + # if defined(AV_RN64) && !defined(AV_RL64) # define AV_RL64(p) AV_RN64(p) # elif !defined(AV_RN64) && defined(AV_RL64) @@ -210,7 +242,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; ((const uint8_t*)(x))[1]) #endif #ifndef AV_WB16 -# define AV_WB16(p, d) do { \ +# define AV_WB16(p, darg) do { \ + unsigned d = (darg); \ ((uint8_t*)(p))[1] = (d); \ ((uint8_t*)(p))[0] = (d)>>8; \ } while(0) @@ -222,7 +255,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; ((const uint8_t*)(x))[0]) #endif #ifndef AV_WL16 -# define AV_WL16(p, d) do { \ +# define AV_WL16(p, darg) do { \ + unsigned d = (darg); \ ((uint8_t*)(p))[0] = (d); \ ((uint8_t*)(p))[1] = (d)>>8; \ } while(0) @@ -236,7 +270,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; ((const uint8_t*)(x))[3]) #endif #ifndef AV_WB32 -# define AV_WB32(p, d) do { \ +# define AV_WB32(p, darg) do { \ + unsigned d = (darg); \ ((uint8_t*)(p))[3] = (d); \ ((uint8_t*)(p))[2] = (d)>>8; \ ((uint8_t*)(p))[1] = (d)>>16; \ @@ -252,7 +287,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; ((const uint8_t*)(x))[0]) #endif #ifndef AV_WL32 -# define AV_WL32(p, d) do { \ +# define AV_WL32(p, darg) do { \ + unsigned d = (darg); \ ((uint8_t*)(p))[0] = (d); \ ((uint8_t*)(p))[1] = (d)>>8; \ ((uint8_t*)(p))[2] = (d)>>16; \ @@ -272,7 +308,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; (uint64_t)((const uint8_t*)(x))[7]) #endif #ifndef AV_WB64 -# define AV_WB64(p, d) do { \ +# define AV_WB64(p, darg) do { \ + uint64_t d = (darg); \ ((uint8_t*)(p))[7] = (d); \ ((uint8_t*)(p))[6] = (d)>>8; \ ((uint8_t*)(p))[5] = (d)>>16; \ @@ -296,7 +333,8 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; (uint64_t)((const uint8_t*)(x))[0]) #endif #ifndef AV_WL64 -# define AV_WL64(p, d) do { \ +# define AV_WL64(p, darg) do { \ + uint64_t d = (darg); \ ((uint8_t*)(p))[0] = (d); \ ((uint8_t*)(p))[1] = (d)>>8; \ ((uint8_t*)(p))[2] = (d)>>16; \ @@ -430,6 +468,48 @@ union unaligned_16 { uint16_t l; } __attribute__((packed)) av_alias; } while(0) #endif +#ifndef AV_RB48 +# define AV_RB48(x) \ + (((uint64_t)((const uint8_t*)(x))[0] << 40) | \ + ((uint64_t)((const uint8_t*)(x))[1] << 32) | \ + ((uint64_t)((const uint8_t*)(x))[2] << 24) | \ + ((uint64_t)((const uint8_t*)(x))[3] << 16) | \ + ((uint64_t)((const uint8_t*)(x))[4] << 8) | \ + (uint64_t)((const uint8_t*)(x))[5]) +#endif +#ifndef AV_WB48 +# define AV_WB48(p, darg) do { \ + uint64_t d = (darg); \ + ((uint8_t*)(p))[5] = (d); \ + ((uint8_t*)(p))[4] = (d)>>8; \ + ((uint8_t*)(p))[3] = (d)>>16; \ + ((uint8_t*)(p))[2] = (d)>>24; \ + ((uint8_t*)(p))[1] = (d)>>32; \ + ((uint8_t*)(p))[0] = (d)>>40; \ + } while(0) +#endif + +#ifndef AV_RL48 +# define AV_RL48(x) \ + (((uint64_t)((const uint8_t*)(x))[5] << 40) | \ + ((uint64_t)((const uint8_t*)(x))[4] << 32) | \ + ((uint64_t)((const uint8_t*)(x))[3] << 24) | \ + ((uint64_t)((const uint8_t*)(x))[2] << 16) | \ + ((uint64_t)((const uint8_t*)(x))[1] << 8) | \ + (uint64_t)((const uint8_t*)(x))[0]) +#endif +#ifndef AV_WL48 +# define AV_WL48(p, darg) do { \ + uint64_t d = (darg); \ + ((uint8_t*)(p))[0] = (d); \ + ((uint8_t*)(p))[1] = (d)>>8; \ + ((uint8_t*)(p))[2] = (d)>>16; \ + ((uint8_t*)(p))[3] = (d)>>24; \ + ((uint8_t*)(p))[4] = (d)>>32; \ + ((uint8_t*)(p))[5] = (d)>>40; \ + } while(0) +#endif + /* * The AV_[RW]NA macros access naturally aligned data * in a type-safe way. diff --git a/libavutil/lfg.c b/libavutil/lfg.c index 4221e6228b..ffa2f1fd3d 100644 --- a/libavutil/lfg.c +++ b/libavutil/lfg.c @@ -2,20 +2,20 @@ * Lagged Fibonacci PRNG * Copyright (c) 2008 Michael Niedermayer * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -72,8 +72,10 @@ int main(void) av_lfg_init(&state, 0xdeadbeef); for (j = 0; j < 10000; j++) { START_TIMER - for (i = 0; i < 624; i++) + for (i = 0; i < 624; i++) { + //av_log(NULL, AV_LOG_ERROR, "%X\n", av_lfg_get(&state)); x += av_lfg_get(&state); + } STOP_TIMER("624 calls of av_lfg_get"); } av_log(NULL, AV_LOG_ERROR, "final value:%X\n", x); diff --git a/libavutil/lfg.h b/libavutil/lfg.h index 5e526c1dae..ec90562cf2 100644 --- a/libavutil/lfg.h +++ b/libavutil/lfg.h @@ -2,20 +2,20 @@ * Lagged Fibonacci PRNG * Copyright (c) 2008 Michael Niedermayer * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/libavutil.v b/libavutil/libavutil.v index e9f04cba65..eb16ae175e 100644 --- a/libavutil/libavutil.v +++ b/libavutil/libavutil.v @@ -1,4 +1,4 @@ LIBAVUTIL_$MAJOR { - global: av*; + global: av*; ff_*; local: *; }; diff --git a/libavutil/libm.h b/libavutil/libm.h index d6c2cf8623..28d5df871b 100644 --- a/libavutil/libm.h +++ b/libavutil/libm.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -29,6 +29,10 @@ #include "attributes.h" #include "intfloat.h" +#if HAVE_MIPSFPU && HAVE_INLINE_ASM +#include "libavutil/mips/libm_mips.h" +#endif /* HAVE_MIPSFPU && HAVE_INLINE_ASM*/ + #if !HAVE_ATANF #undef atanf #define atanf(x) ((float)atan(x)) @@ -44,6 +48,13 @@ #define powf(x, y) ((float)pow(x, y)) #endif +#if !HAVE_CBRT +static av_always_inline double cbrt(double x) +{ + return x < 0 ? -pow(-x, 1.0 / 3.0) : pow(x, 1.0 / 3.0); +} +#endif + #if !HAVE_CBRTF static av_always_inline float cbrtf(float x) { @@ -71,6 +82,16 @@ static av_always_inline float cbrtf(float x) #define exp2f(x) ((float)exp2(x)) #endif /* HAVE_EXP2F */ +#if !HAVE_FMINF +#undef fminf +static av_always_inline av_const float fminf(float x, float y) +{ + //Note, the NaN special case is needed for C spec compliance, it should be + //optimized away if the users compiler is configured to assume no NaN + return x > y ? y : (x == x ? x : y); +} +#endif + #if !HAVE_ISINF static av_always_inline av_const int isinf(float x) { diff --git a/libavutil/lls.c b/libavutil/lls1.c index f87c2cd153..c452d82334 100644 --- a/libavutil/lls.c +++ b/libavutil/lls1.c @@ -3,20 +3,20 @@ * * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -30,14 +30,23 @@ #include "attributes.h" #include "version.h" -#include "lls.h" +#include "lls1.h" -static void update_lls(LLSModel *m, double *var) +#if FF_API_LLS1 + +av_cold void avpriv_init_lls(LLSModel *m, int indep_count) +{ + memset(m, 0, sizeof(LLSModel)); + m->indep_count = indep_count; +} + +void avpriv_update_lls(LLSModel *m, double *var, double decay) { int i, j; for (i = 0; i <= m->indep_count; i++) { for (j = i; j <= m->indep_count; j++) { + m->covariance[i][j] *= decay; m->covariance[i][j] += var[i] * var[j]; } } @@ -46,8 +55,8 @@ static void update_lls(LLSModel *m, double *var) void avpriv_solve_lls(LLSModel *m, double threshold, unsigned short min_order) { int i, j, k; - double (*factor)[MAX_VARS_ALIGN] = (void *) &m->covariance[1][0]; - double (*covar) [MAX_VARS_ALIGN] = (void *) &m->covariance[1][1]; + double (*factor)[MAX_VARS + 1] = (void *) &m->covariance[1][0]; + double (*covar) [MAX_VARS + 1] = (void *) &m->covariance[1][1]; double *covar_y = m->covariance[0]; int count = m->indep_count; @@ -100,7 +109,7 @@ void avpriv_solve_lls(LLSModel *m, double threshold, unsigned short min_order) } } -static double evaluate_lls(LLSModel *m, double *param, int order) +double avpriv_evaluate_lls(LLSModel *m, double *param, int order) { int i; double out = 0; @@ -111,16 +120,6 @@ static double evaluate_lls(LLSModel *m, double *param, int order) return out; } -av_cold void avpriv_init_lls(LLSModel *m, int indep_count) -{ - memset(m, 0, sizeof(LLSModel)); - m->indep_count = indep_count; - m->update_lls = update_lls; - m->evaluate_lls = evaluate_lls; - if (ARCH_X86) - ff_init_lls_x86(m); -} - #if FF_API_LLS_PRIVATE av_cold void av_init_lls(LLSModel *m, int indep_count) { @@ -128,7 +127,7 @@ av_cold void av_init_lls(LLSModel *m, int indep_count) } void av_update_lls(LLSModel *m, double *param, double decay) { - m->update_lls(m, param); + avpriv_update_lls(m, param, decay); } void av_solve_lls(LLSModel *m, double threshold, int min_order) { @@ -136,10 +135,12 @@ void av_solve_lls(LLSModel *m, double threshold, int min_order) } double av_evaluate_lls(LLSModel *m, double *param, int order) { - return m->evaluate_lls(m, param, order); + return avpriv_evaluate_lls(m, param, order); } #endif /* FF_API_LLS_PRIVATE */ +#endif /* FF_API_LLS1 */ + #ifdef TEST #include <stdio.h> @@ -156,17 +157,17 @@ int main(void) avpriv_init_lls(&m, 3); for (i = 0; i < 100; i++) { - LOCAL_ALIGNED(32, double, var, [4]); + double var[4]; double eval; var[0] = (av_lfg_get(&lfg) / (double) UINT_MAX - 0.5) * 2; var[1] = var[0] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5; var[2] = var[1] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5; var[3] = var[2] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5; - m.update_lls(&m, var); + avpriv_update_lls(&m, var, 0.99); avpriv_solve_lls(&m, 0.001, 0); for (order = 0; order < 3; order++) { - eval = m.evaluate_lls(&m, var + 1, order); + eval = avpriv_evaluate_lls(&m, var + 1, order); printf("real:%9f order:%d pred:%9f var:%f coeffs:%f %9f %9f\n", var[0], order, eval, sqrt(m.variance[order] / (i + 1)), m.coeff[order][0], m.coeff[order][1], diff --git a/libavutil/lls1.h b/libavutil/lls1.h new file mode 100644 index 0000000000..c785d44421 --- /dev/null +++ b/libavutil/lls1.h @@ -0,0 +1,54 @@ +/* + * linear least squares model + * + * 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_LLS_H +#define AVUTIL_LLS_H + +#include "version.h" + +#define MAX_VARS 32 + +//FIXME avoid direct access to LLSModel from outside + +/** + * Linear least squares model. + */ +typedef struct LLSModel { + double covariance[MAX_VARS + 1][MAX_VARS + 1]; + double coeff[MAX_VARS][MAX_VARS]; + double variance[MAX_VARS]; + int indep_count; +} LLSModel; + +void avpriv_init_lls(LLSModel *m, int indep_count); +void avpriv_update_lls(LLSModel *m, double *param, double decay); +void avpriv_solve_lls(LLSModel *m, double threshold, unsigned short min_order); +double avpriv_evaluate_lls(LLSModel *m, double *param, int order); + +#if FF_API_LLS_PRIVATE +void av_init_lls(LLSModel *m, int indep_count); +void av_update_lls(LLSModel *m, double *param, double decay); +void av_solve_lls(LLSModel *m, double threshold, int min_order); +double av_evaluate_lls(LLSModel *m, double *param, int order); +#endif /* FF_API_LLS_PRIVATE */ + +#endif /* AVUTIL_LLS_H */ diff --git a/libavutil/lls2.c b/libavutil/lls2.c new file mode 100644 index 0000000000..8cadacb11d --- /dev/null +++ b/libavutil/lls2.c @@ -0,0 +1,160 @@ +/* + * linear least squares model + * + * 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 + * linear least squares model + */ + +#include <math.h> +#include <string.h> + +#include "attributes.h" +#include "version.h" +#include "lls2.h" + +static void update_lls(LLSModel2 *m, double *var) +{ + int i, j; + + for (i = 0; i <= m->indep_count; i++) { + for (j = i; j <= m->indep_count; j++) { + m->covariance[i][j] += var[i] * var[j]; + } + } +} + +void avpriv_solve_lls2(LLSModel2 *m, double threshold, unsigned short min_order) +{ + int i, j, k; + double (*factor)[MAX_VARS_ALIGN] = (void *) &m->covariance[1][0]; + double (*covar) [MAX_VARS_ALIGN] = (void *) &m->covariance[1][1]; + double *covar_y = m->covariance[0]; + int count = m->indep_count; + + for (i = 0; i < count; i++) { + for (j = i; j < count; j++) { + double sum = covar[i][j]; + + for (k = i - 1; k >= 0; k--) + sum -= factor[i][k] * factor[j][k]; + + if (i == j) { + if (sum < threshold) + sum = 1.0; + factor[i][i] = sqrt(sum); + } else { + factor[j][i] = sum / factor[i][i]; + } + } + } + + for (i = 0; i < count; i++) { + double sum = covar_y[i + 1]; + + for (k = i - 1; k >= 0; k--) + sum -= factor[i][k] * m->coeff[0][k]; + + m->coeff[0][i] = sum / factor[i][i]; + } + + for (j = count - 1; j >= min_order; j--) { + for (i = j; i >= 0; i--) { + double sum = m->coeff[0][i]; + + for (k = i + 1; k <= j; k++) + sum -= factor[k][i] * m->coeff[j][k]; + + m->coeff[j][i] = sum / factor[i][i]; + } + + m->variance[j] = covar_y[0]; + + for (i = 0; i <= j; i++) { + double sum = m->coeff[j][i] * covar[i][i] - 2 * covar_y[i + 1]; + + for (k = 0; k < i; k++) + sum += 2 * m->coeff[j][k] * covar[k][i]; + + m->variance[j] += m->coeff[j][i] * sum; + } + } +} + +static double evaluate_lls(LLSModel2 *m, double *param, int order) +{ + int i; + double out = 0; + + for (i = 0; i <= order; i++) + out += param[i] * m->coeff[order][i]; + + return out; +} + +av_cold void avpriv_init_lls2(LLSModel2 *m, int indep_count) +{ + memset(m, 0, sizeof(LLSModel2)); + m->indep_count = indep_count; + m->update_lls = update_lls; + m->evaluate_lls = evaluate_lls; + if (ARCH_X86) + ff_init_lls_x86(m); +} + +#ifdef TEST + +#include <stdio.h> +#include <limits.h> +#include "lfg.h" + +int main(void) +{ + LLSModel2 m; + int i, order; + AVLFG lfg; + + av_lfg_init(&lfg, 1); + avpriv_init_lls2(&m, 3); + + for (i = 0; i < 100; i++) { + LOCAL_ALIGNED(32, double, var, [4]); + double eval; + + var[0] = (av_lfg_get(&lfg) / (double) UINT_MAX - 0.5) * 2; + var[1] = var[0] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5; + var[2] = var[1] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5; + var[3] = var[2] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5; + m.update_lls(&m, var); + avpriv_solve_lls2(&m, 0.001, 0); + for (order = 0; order < 3; order++) { + eval = m.evaluate_lls(&m, var + 1, order); + printf("real:%9f order:%d pred:%9f var:%f coeffs:%f %9f %9f\n", + var[0], order, eval, sqrt(m.variance[order] / (i + 1)), + m.coeff[order][0], m.coeff[order][1], + m.coeff[order][2]); + } + } + return 0; +} + +#endif diff --git a/libavutil/lls.h b/libavutil/lls2.h index 27c0d5e3fe..35815d2704 100644 --- a/libavutil/lls.h +++ b/libavutil/lls2.h @@ -3,20 +3,20 @@ * * Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -30,12 +30,12 @@ #define MAX_VARS 32 #define MAX_VARS_ALIGN FFALIGN(MAX_VARS+1,4) -//FIXME avoid direct access to LLSModel from outside +//FIXME avoid direct access to LLSModel2 from outside /** * Linear least squares model. */ -typedef struct LLSModel { +typedef struct LLSModel2 { DECLARE_ALIGNED(32, double, covariance[MAX_VARS_ALIGN][MAX_VARS_ALIGN]); DECLARE_ALIGNED(32, double, coeff[MAX_VARS][MAX_VARS]); double variance[MAX_VARS]; @@ -47,25 +47,18 @@ typedef struct LLSModel { * 32-byte aligned, and any padding elements must be initialized * (i.e not denormal/nan). */ - void (*update_lls)(struct LLSModel *m, double *var); + void (*update_lls)(struct LLSModel2 *m, double *var); /** * Inner product of var[] and the LPC coefs. * @param m this context * @param var training samples, excluding the value to be predicted. unaligned. * @param order lpc order */ - double (*evaluate_lls)(struct LLSModel *m, double *var, int order); -} LLSModel; + double (*evaluate_lls)(struct LLSModel2 *m, double *var, int order); +} LLSModel2; -void avpriv_init_lls(LLSModel *m, int indep_count); -void ff_init_lls_x86(LLSModel *m); -void avpriv_solve_lls(LLSModel *m, double threshold, unsigned short min_order); - -#if FF_API_LLS_PRIVATE -void av_init_lls(LLSModel *m, int indep_count); -void av_update_lls(LLSModel *m, double *param, double decay); -void av_solve_lls(LLSModel *m, double threshold, int min_order); -double av_evaluate_lls(LLSModel *m, double *param, int order); -#endif /* FF_API_LLS_PRIVATE */ +void avpriv_init_lls2(LLSModel2 *m, int indep_count); +void ff_init_lls_x86(LLSModel2 *m); +void avpriv_solve_lls2(LLSModel2 *m, double threshold, unsigned short min_order); #endif /* AVUTIL_LLS_H */ diff --git a/libavutil/log.c b/libavutil/log.c index 5a8f293f20..2091316957 100644 --- a/libavutil/log.c +++ b/libavutil/log.c @@ -2,20 +2,20 @@ * log functions * Copyright (c) 2003 Michel Bardiaux * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -34,34 +34,88 @@ #endif #include <stdarg.h> #include <stdlib.h> -#include "avstring.h" #include "avutil.h" +#include "bprint.h" #include "common.h" #include "internal.h" #include "log.h" +#if HAVE_PTHREADS +#include <pthread.h> +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +#define LINE_SZ 1024 + static int av_log_level = AV_LOG_INFO; static int flags; -#if HAVE_SETCONSOLETEXTATTRIBUTE +#if defined(_WIN32) && !defined(__MINGW32CE__) && HAVE_SETCONSOLETEXTATTRIBUTE #include <windows.h> -static const uint8_t color[] = { 12, 12, 12, 14, 7, 10, 11 }; +static const uint8_t color[16 + AV_CLASS_CATEGORY_NB] = { + [AV_LOG_PANIC /8] = 12, + [AV_LOG_FATAL /8] = 12, + [AV_LOG_ERROR /8] = 12, + [AV_LOG_WARNING/8] = 14, + [AV_LOG_INFO /8] = 7, + [AV_LOG_VERBOSE/8] = 10, + [AV_LOG_DEBUG /8] = 10, + [16+AV_CLASS_CATEGORY_NA ] = 7, + [16+AV_CLASS_CATEGORY_INPUT ] = 13, + [16+AV_CLASS_CATEGORY_OUTPUT ] = 5, + [16+AV_CLASS_CATEGORY_MUXER ] = 13, + [16+AV_CLASS_CATEGORY_DEMUXER ] = 5, + [16+AV_CLASS_CATEGORY_ENCODER ] = 11, + [16+AV_CLASS_CATEGORY_DECODER ] = 3, + [16+AV_CLASS_CATEGORY_FILTER ] = 10, + [16+AV_CLASS_CATEGORY_BITSTREAM_FILTER] = 9, + [16+AV_CLASS_CATEGORY_SWSCALER ] = 7, + [16+AV_CLASS_CATEGORY_SWRESAMPLER ] = 7, + [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT ] = 13, + [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT ] = 5, + [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT ] = 13, + [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT ] = 5, + [16+AV_CLASS_CATEGORY_DEVICE_OUTPUT ] = 13, + [16+AV_CLASS_CATEGORY_DEVICE_INPUT ] = 5, +}; + static int16_t background, attr_orig; static HANDLE con; -#define set_color(x) SetConsoleTextAttribute(con, background | color[x]) -#define reset_color() SetConsoleTextAttribute(con, attr_orig) -#define print_256color(x) #else -static const uint8_t color[] = { 0x41, 0x41, 0x11, 0x03, 9, 0x02, 0x06 }; -#define set_color(x) fprintf(stderr, "\033[%d;3%dm", color[x] >> 4, color[x]&15) -#define print_256color(x) fprintf(stderr, "\033[38;5;%dm", x) -#define reset_color() fprintf(stderr, "\033[0m") + +static const uint32_t color[16 + AV_CLASS_CATEGORY_NB] = { + [AV_LOG_PANIC /8] = 52 << 16 | 196 << 8 | 0x41, + [AV_LOG_FATAL /8] = 208 << 8 | 0x41, + [AV_LOG_ERROR /8] = 196 << 8 | 0x11, + [AV_LOG_WARNING/8] = 226 << 8 | 0x03, + [AV_LOG_INFO /8] = 253 << 8 | 0x09, + [AV_LOG_VERBOSE/8] = 40 << 8 | 0x02, + [AV_LOG_DEBUG /8] = 34 << 8 | 0x02, + [16+AV_CLASS_CATEGORY_NA ] = 250 << 8 | 0x09, + [16+AV_CLASS_CATEGORY_INPUT ] = 219 << 8 | 0x15, + [16+AV_CLASS_CATEGORY_OUTPUT ] = 201 << 8 | 0x05, + [16+AV_CLASS_CATEGORY_MUXER ] = 213 << 8 | 0x15, + [16+AV_CLASS_CATEGORY_DEMUXER ] = 207 << 8 | 0x05, + [16+AV_CLASS_CATEGORY_ENCODER ] = 51 << 8 | 0x16, + [16+AV_CLASS_CATEGORY_DECODER ] = 39 << 8 | 0x06, + [16+AV_CLASS_CATEGORY_FILTER ] = 155 << 8 | 0x12, + [16+AV_CLASS_CATEGORY_BITSTREAM_FILTER] = 192 << 8 | 0x14, + [16+AV_CLASS_CATEGORY_SWSCALER ] = 153 << 8 | 0x14, + [16+AV_CLASS_CATEGORY_SWRESAMPLER ] = 147 << 8 | 0x14, + [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT ] = 213 << 8 | 0x15, + [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT ] = 207 << 8 | 0x05, + [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT ] = 213 << 8 | 0x15, + [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT ] = 207 << 8 | 0x05, + [16+AV_CLASS_CATEGORY_DEVICE_OUTPUT ] = 213 << 8 | 0x15, + [16+AV_CLASS_CATEGORY_DEVICE_INPUT ] = 207 << 8 | 0x05, +}; + #endif static int use_color = -1; static void check_color_terminal(void) { -#if HAVE_SETCONSOLETEXTATTRIBUTE +#if defined(_WIN32) && !defined(__MINGW32CE__) && HAVE_SETCONSOLETEXTATTRIBUTE CONSOLE_SCREEN_BUFFER_INFO con_info; con = GetStdHandle(STD_ERROR_HANDLE); use_color = (con != INVALID_HANDLE_VALUE) && !getenv("NO_COLOR") && @@ -75,7 +129,9 @@ static void check_color_terminal(void) char *term = getenv("TERM"); use_color = !getenv("NO_COLOR") && !getenv("AV_LOG_FORCE_NOCOLOR") && (getenv("TERM") && isatty(2) || getenv("AV_LOG_FORCE_COLOR")); - use_color += term && strstr(term, "256color"); + if ( getenv("AV_LOG_FORCE_256COLOR") + || (term && strstr(term, "256color"))) + use_color *= 256; #else use_color = getenv("AV_LOG_FORCE_COLOR") && !getenv("NO_COLOR") && !getenv("AV_LOG_FORCE_NOCOLOR"); @@ -84,25 +140,45 @@ static void check_color_terminal(void) static void colored_fputs(int level, int tint, const char *str) { + int local_use_color; + if (!*str) + return; + if (use_color < 0) check_color_terminal(); - switch (use_color) { - case 1: - set_color(level); - break; - case 2: - set_color(level); - if (tint) - print_256color(tint); - break; - default: - break; - } + if (level == AV_LOG_INFO/8) local_use_color = 0; + else local_use_color = use_color; + +#if defined(_WIN32) && !defined(__MINGW32CE__) && HAVE_SETCONSOLETEXTATTRIBUTE + if (local_use_color) + SetConsoleTextAttribute(con, background | color[level]); fputs(str, stderr); - if (use_color) { - reset_color(); - } + if (local_use_color) + SetConsoleTextAttribute(con, attr_orig); +#else + if (local_use_color == 1) { + fprintf(stderr, + "\033[%d;3%dm%s\033[0m", + (color[level] >> 4) & 15, + color[level] & 15, + str); + } else if (tint && use_color == 256) { + fprintf(stderr, + "\033[48;5;%dm\033[38;5;%dm%s\033[0m", + (color[level] >> 16) & 0xff, + tint, + str); + } else if (local_use_color == 256) { + fprintf(stderr, + "\033[48;5;%dm\033[38;5;%dm%s\033[0m", + (color[level] >> 16) & 0xff, + (color[level] >> 8) & 0xff, + str); + } else + fputs(str, stderr); +#endif + } const char *av_default_item_name(void *ptr) @@ -110,56 +186,156 @@ const char *av_default_item_name(void *ptr) return (*(AVClass **) ptr)->class_name; } -void av_log_default_callback(void *avcl, int level, const char *fmt, va_list vl) +AVClassCategory av_default_get_category(void *ptr) { - static int print_prefix = 1; - static int count; - static char prev[1024]; - char line[1024]; - static int is_atty; - AVClass* avc = avcl ? *(AVClass **) avcl : NULL; - unsigned tint = level & 0xff00; + return (*(AVClass **) ptr)->category; +} - level &= 0xff; +static void sanitize(uint8_t *line){ + while(*line){ + if(*line < 0x08 || (*line > 0x0D && *line < 0x20)) + *line='?'; + line++; + } +} - if (level > av_log_level) - return; - line[0] = 0; - if (print_prefix && avc) { +static int get_category(void *ptr){ + AVClass *avc = *(AVClass **) ptr; + if( !avc + || (avc->version&0xFF)<100 + || avc->version < (51 << 16 | 59 << 8) + || avc->category >= AV_CLASS_CATEGORY_NB) return AV_CLASS_CATEGORY_NA + 16; + + if(avc->get_category) + return avc->get_category(ptr) + 16; + + return avc->category + 16; +} + +static const char *get_level_str(int level) +{ + switch (level) { + case AV_LOG_QUIET: + return "quiet"; + case AV_LOG_DEBUG: + return "debug"; + case AV_LOG_VERBOSE: + return "verbose"; + case AV_LOG_INFO: + return "info"; + case AV_LOG_WARNING: + return "warning"; + case AV_LOG_ERROR: + return "error"; + case AV_LOG_FATAL: + return "fatal"; + case AV_LOG_PANIC: + return "panic"; + default: + return ""; + } +} + +static void format_line(void *avcl, int level, const char *fmt, va_list vl, + AVBPrint part[4], int *print_prefix, int type[2]) +{ + AVClass* avc = avcl ? *(AVClass **) avcl : NULL; + av_bprint_init(part+0, 0, 1); + av_bprint_init(part+1, 0, 1); + av_bprint_init(part+2, 0, 1); + av_bprint_init(part+3, 0, 65536); + + if(type) type[0] = type[1] = AV_CLASS_CATEGORY_NA + 16; + if (*print_prefix && avc) { if (avc->parent_log_context_offset) { AVClass** parent = *(AVClass ***) (((uint8_t *) avcl) + avc->parent_log_context_offset); if (parent && *parent) { - snprintf(line, sizeof(line), "[%s @ %p] ", + av_bprintf(part+0, "[%s @ %p] ", (*parent)->item_name(parent), parent); + if(type) type[0] = get_category(parent); } } - snprintf(line + strlen(line), sizeof(line) - strlen(line), "[%s @ %p] ", + av_bprintf(part+1, "[%s @ %p] ", avc->item_name(avcl), avcl); + if(type) type[1] = get_category(avcl); + + if (flags & AV_LOG_PRINT_LEVEL) + av_bprintf(part+2, "[%s] ", get_level_str(level)); } - vsnprintf(line + strlen(line), sizeof(line) - strlen(line), fmt, vl); + av_vbprintf(part+3, fmt, vl); - print_prefix = strlen(line) && line[strlen(line) - 1] == '\n'; + if(*part[0].str || *part[1].str || *part[2].str || *part[3].str) { + char lastc = part[3].len && part[3].len <= part[3].size ? part[3].str[part[3].len - 1] : 0; + *print_prefix = lastc == '\n' || lastc == '\r'; + } +} + +void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix) +{ + AVBPrint part[4]; + format_line(ptr, level, fmt, vl, part, print_prefix, NULL); + snprintf(line, line_size, "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str); + av_bprint_finalize(part+3, NULL); +} + +void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl) +{ + static int print_prefix = 1; + static int count; + static char prev[LINE_SZ]; + AVBPrint part[4]; + char line[LINE_SZ]; + static int is_atty; + int type[2]; + unsigned tint = 0; + + if (level >= 0) { + tint = level & 0xff00; + level &= 0xff; + } + + if (level > av_log_level) + return; +#if HAVE_PTHREADS + pthread_mutex_lock(&mutex); +#endif + + format_line(ptr, level, fmt, vl, part, &print_prefix, type); + snprintf(line, sizeof(line), "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str); #if HAVE_ISATTY if (!is_atty) is_atty = isatty(2) ? 1 : -1; #endif - if (print_prefix && (flags & AV_LOG_SKIP_REPEATED) && - !strncmp(line, prev, sizeof line)) { + if (print_prefix && (flags & AV_LOG_SKIP_REPEATED) && !strcmp(line, prev) && + *line && line[strlen(line) - 1] != '\r'){ count++; if (is_atty == 1) fprintf(stderr, " Last message repeated %d times\r", count); - return; + goto end; } if (count > 0) { fprintf(stderr, " Last message repeated %d times\n", count); count = 0; } - colored_fputs(av_clip(level >> 3, 0, 6), tint >> 8, line); - av_strlcpy(prev, line, sizeof line); + strcpy(prev, line); + sanitize(part[0].str); + colored_fputs(type[0], 0, part[0].str); + sanitize(part[1].str); + colored_fputs(type[1], 0, part[1].str); + sanitize(part[2].str); + colored_fputs(av_clip(level >> 3, 0, 6), tint >> 8, part[2].str); + sanitize(part[3].str); + colored_fputs(av_clip(level >> 3, 0, 6), tint >> 8, part[3].str); +end: + av_bprint_finalize(part+3, NULL); +#if HAVE_PTHREADS + pthread_mutex_unlock(&mutex); +#endif } static void (*av_log_callback)(void*, int, const char*, va_list) = @@ -179,7 +355,9 @@ void av_log(void* avcl, int level, const char *fmt, ...) void av_vlog(void* avcl, int level, const char *fmt, va_list vl) { - av_log_callback(avcl, level, fmt, vl); + void (*log_callback)(void*, int, const char*, va_list) = av_log_callback; + if (log_callback) + log_callback(avcl, level, fmt, vl); } int av_log_get_level(void) @@ -197,6 +375,11 @@ void av_log_set_flags(int arg) flags = arg; } +int av_log_get_flags(void) +{ + return flags; +} + void av_log_set_callback(void (*callback)(void*, int, const char*, va_list)) { av_log_callback = callback; @@ -206,14 +389,14 @@ static void missing_feature_sample(int sample, void *avc, const char *msg, va_list argument_list) { av_vlog(avc, AV_LOG_WARNING, msg, argument_list); - av_log(avc, AV_LOG_WARNING, " is not implemented. Update your Libav " + av_log(avc, AV_LOG_WARNING, " is not implemented. Update your FFmpeg " "version to the newest one from Git. If the problem still " "occurs, it means that your file has a feature which has not " "been implemented.\n"); if (sample) av_log(avc, AV_LOG_WARNING, "If you want to help, upload a sample " - "of this file to ftp://upload.libav.org/incoming/ " - "and contact the libav-devel mailing list.\n"); + "of this file to ftp://upload.ffmpeg.org/incoming/ " + "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)\n"); } void avpriv_request_sample(void *avc, const char *msg, ...) @@ -233,3 +416,26 @@ void avpriv_report_missing_feature(void *avc, const char *msg, ...) missing_feature_sample(0, avc, msg, argument_list); va_end(argument_list); } + +#ifdef TEST +// LCOV_EXCL_START +#include <string.h> + +int main(int argc, char **argv) +{ + int i; + av_log_set_level(AV_LOG_DEBUG); + for (use_color=0; use_color<=256; use_color = 255*use_color+1) { + av_log(NULL, AV_LOG_FATAL, "use_color: %d\n", use_color); + for (i = AV_LOG_DEBUG; i>=AV_LOG_QUIET; i-=8) { + av_log(NULL, i, " %d", i); + av_log(NULL, AV_LOG_INFO, "e "); + av_log(NULL, i + 256*123, "C%d", i); + av_log(NULL, AV_LOG_INFO, "e"); + } + av_log(NULL, AV_LOG_PANIC, "\n"); + } + return 0; +} +// LCOV_EXCL_STOP +#endif diff --git a/libavutil/log.h b/libavutil/log.h index 4e4424a553..a6a07e0653 100644 --- a/libavutil/log.h +++ b/libavutil/log.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -25,6 +25,29 @@ #include "avutil.h" #include "attributes.h" +typedef enum { + AV_CLASS_CATEGORY_NA = 0, + AV_CLASS_CATEGORY_INPUT, + AV_CLASS_CATEGORY_OUTPUT, + AV_CLASS_CATEGORY_MUXER, + AV_CLASS_CATEGORY_DEMUXER, + AV_CLASS_CATEGORY_ENCODER, + AV_CLASS_CATEGORY_DECODER, + AV_CLASS_CATEGORY_FILTER, + AV_CLASS_CATEGORY_BITSTREAM_FILTER, + AV_CLASS_CATEGORY_SWSCALER, + AV_CLASS_CATEGORY_SWRESAMPLER, + AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT = 40, + AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT, + AV_CLASS_CATEGORY_DEVICE_OUTPUT, + AV_CLASS_CATEGORY_DEVICE_INPUT, + AV_CLASS_CATEGORY_NB, ///< not part of ABI/API +}AVClassCategory; + +struct AVOptionRanges; + /** * Describe the class of an AVClass context structure. That is an * arbitrary struct of which the first field is a pointer to an @@ -87,6 +110,25 @@ typedef struct AVClass { * child_class_next iterates over _all possible_ children. */ const struct AVClass* (*child_class_next)(const struct AVClass *prev); + + /** + * Category used for visualization (like color) + * This is only set if the category is equal for all objects using this class. + * available since version (51 << 16 | 56 << 8 | 100) + */ + AVClassCategory category; + + /** + * Callback to return the category. + * available since version (51 << 16 | 59 << 8 | 100) + */ + AVClassCategory (*get_category)(void* ctx); + + /** + * Callback to return the supported/allowed ranges. + * available since version (52.12) + */ + int (*query_ranges)(struct AVOptionRanges **, void *obj, const char *key, int flags); } AVClass; /** @@ -143,6 +185,8 @@ typedef struct AVClass { */ #define AV_LOG_DEBUG 48 +#define AV_LOG_MAX_OFFSET (AV_LOG_DEBUG - AV_LOG_QUIET) + /** * @} */ @@ -212,6 +256,9 @@ void av_log_set_level(int level); /** * Set the logging callback * + * @note The callback must be thread safe, even if the application does not use + * threads itself as some codecs are multithreaded. + * * @see av_log_default_callback * * @param callback A logging function with a compatible signature. @@ -242,6 +289,17 @@ void av_log_default_callback(void *avcl, int level, const char *fmt, * @return The AVClass class_name */ const char* av_default_item_name(void* ctx); +AVClassCategory av_default_get_category(void *ptr); + +/** + * Format a line of log the same way as the default callback. + * @param line buffer to receive the formated line + * @param line_size size of the buffer + * @param print_prefix used to store whether the prefix must be printed; + * must point to a persistent integer initially set to 1 + */ +void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, + char *line, int line_size, int *print_prefix); /** * av_dlog macros @@ -251,7 +309,7 @@ const char* av_default_item_name(void* ctx); #ifdef DEBUG # define av_dlog(pctx, ...) av_log(pctx, AV_LOG_DEBUG, __VA_ARGS__) #else -# define av_dlog(pctx, ...) +# define av_dlog(pctx, ...) do { if (0) av_log(pctx, AV_LOG_DEBUG, __VA_ARGS__); } while (0) #endif /** @@ -260,10 +318,20 @@ const char* av_default_item_name(void* ctx); * "Last message repeated x times" messages below (f)printf messages with some * bad luck. * Also to receive the last, "last repeated" line if any, the user app must - * call av_log(NULL, AV_LOG_QUIET, ""); at the end + * call av_log(NULL, AV_LOG_QUIET, "%s", ""); at the end */ #define AV_LOG_SKIP_REPEATED 1 + +/** + * Include the log severity in messages originating from codecs. + * + * Results in messages such as: + * [rawvideo @ 0xDEADBEEF] [error] encode did not produce valid pts + */ +#define AV_LOG_PRINT_LEVEL 2 + void av_log_set_flags(int arg); +int av_log_get_flags(void); /** * @} diff --git a/libavutil/log2_tab.c b/libavutil/log2_tab.c index f6cbe79063..0dbf07d74c 100644 --- a/libavutil/log2_tab.c +++ b/libavutil/log2_tab.c @@ -1,18 +1,20 @@ /* - * This file is part of Libav. + * Copyright (c) 2003-2012 Michael Niedermayer <michaelni@gmx.at> * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/lzo.c b/libavutil/lzo.c index e458165261..7b027eeb33 100644 --- a/libavutil/lzo.c +++ b/libavutil/lzo.c @@ -2,26 +2,27 @@ * LZO 1x decompression * Copyright (c) 2006 Reimar Doeffinger * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * 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 "avutil.h" +#include "avassert.h" #include "common.h" #include "intreadwrite.h" #include "lzo.h" @@ -65,8 +66,13 @@ static inline int get_len(LZOContext *c, int x, int mask) { int cnt = x & mask; if (!cnt) { - while (!(x = get_byte(c))) + while (!(x = get_byte(c))) { + if (cnt >= INT_MAX - 1000) { + c->error |= AV_LZO_ERROR; + break; + } cnt += 255; + } cnt += mask + x; } return cnt; @@ -80,10 +86,7 @@ static inline void copy(LZOContext *c, int cnt) { register const uint8_t *src = c->in; register uint8_t *dst = c->out; - if (cnt < 0) { - c->error |= AV_LZO_ERROR; - return; - } + av_assert0(cnt >= 0); if (cnt > c->in_end - src) { cnt = FFMAX(c->in_end - src, 0); c->error |= AV_LZO_INPUT_DEPLETED; @@ -106,7 +109,7 @@ static inline void copy(LZOContext *c, int cnt) /** * @brief Copies previously decoded bytes to current position. - * @param back how many bytes back we start + * @param back how many bytes back we start, must be > 0 * @param cnt number of bytes to copy, must be > 0 * * cnt > back is valid, this will copy the bytes we just copied, @@ -115,10 +118,7 @@ static inline void copy(LZOContext *c, int cnt) static inline void copy_backptr(LZOContext *c, int back, int cnt) { register uint8_t *dst = c->out; - if (cnt <= 0) { - c->error |= AV_LZO_ERROR; - return; - } + av_assert0(cnt > 0); if (dst - c->out_start < back) { c->error |= AV_LZO_INVALID_BACKPTR; return; @@ -136,11 +136,11 @@ int av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen) int state = 0; int x; LZOContext c; - if (!*outlen || !*inlen) { + if (*outlen <= 0 || *inlen <= 0) { int res = 0; - if (!*outlen) + if (*outlen <= 0) res |= AV_LZO_OUTPUT_FULL; - if (!*inlen) + if (*inlen <= 0) res |= AV_LZO_INPUT_DEPLETED; return res; } @@ -203,3 +203,57 @@ int av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen) *outlen = c.out_end - c.out; return c.error; } + +#ifdef TEST +#include <stdio.h> +#include <lzo/lzo1x.h> +#include "log.h" +#define MAXSZ (10*1024*1024) + +/* Define one of these to 1 if you wish to benchmark liblzo + * instead of our native implementation. */ +#define BENCHMARK_LIBLZO_SAFE 0 +#define BENCHMARK_LIBLZO_UNSAFE 0 + +int main(int argc, char *argv[]) { + FILE *in = fopen(argv[1], "rb"); + int comp_level = argc > 2 ? atoi(argv[2]) : 0; + uint8_t *orig = av_malloc(MAXSZ + 16); + uint8_t *comp = av_malloc(2*MAXSZ + 16); + uint8_t *decomp = av_malloc(MAXSZ + 16); + size_t s = fread(orig, 1, MAXSZ, in); + lzo_uint clen = 0; + long tmp[LZO1X_MEM_COMPRESS]; + int inlen, outlen; + int i; + av_log_set_level(AV_LOG_DEBUG); + if (comp_level == 0) { + lzo1x_1_compress(orig, s, comp, &clen, tmp); + } else if (comp_level == 11) { + lzo1x_1_11_compress(orig, s, comp, &clen, tmp); + } else if (comp_level == 12) { + lzo1x_1_12_compress(orig, s, comp, &clen, tmp); + } else if (comp_level == 15) { + lzo1x_1_15_compress(orig, s, comp, &clen, tmp); + } else + lzo1x_999_compress(orig, s, comp, &clen, tmp); + for (i = 0; i < 300; i++) { +START_TIMER + inlen = clen; outlen = MAXSZ; +#if BENCHMARK_LIBLZO_SAFE + if (lzo1x_decompress_safe(comp, inlen, decomp, &outlen, NULL)) +#elif BENCHMARK_LIBLZO_UNSAFE + if (lzo1x_decompress(comp, inlen, decomp, &outlen, NULL)) +#else + if (av_lzo1x_decode(decomp, &outlen, comp, &inlen)) +#endif + av_log(NULL, AV_LOG_ERROR, "decompression error\n"); +STOP_TIMER("lzod") + } + if (memcmp(orig, decomp, s)) + av_log(NULL, AV_LOG_ERROR, "decompression incorrect\n"); + else + av_log(NULL, AV_LOG_ERROR, "decompression OK\n"); + return 0; +} +#endif diff --git a/libavutil/lzo.h b/libavutil/lzo.h index 9d7e8f1dc1..c03403992d 100644 --- a/libavutil/lzo.h +++ b/libavutil/lzo.h @@ -2,20 +2,20 @@ * LZO 1x decompression * copyright (c) 2006 Reimar Doeffinger * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/macros.h b/libavutil/macros.h index bf3eb9b9a4..446532377a 100644 --- a/libavutil/macros.h +++ b/libavutil/macros.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/mathematics.c b/libavutil/mathematics.c index f36623a0b9..126cffc3f0 100644 --- a/libavutil/mathematics.c +++ b/libavutil/mathematics.c @@ -1,20 +1,20 @@ /* - * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at> + * Copyright (c) 2005-2012 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -27,6 +27,8 @@ #include <limits.h> #include "mathematics.h" +#include "libavutil/common.h" +#include "avassert.h" #include "version.h" #if FF_API_AV_REVERSE @@ -61,10 +63,19 @@ int64_t av_gcd(int64_t a, int64_t b) int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd) { int64_t r = 0; + av_assert2(c > 0); + av_assert2(b >=0); + av_assert2((unsigned)(rnd&~AV_ROUND_PASS_MINMAX)<=5 && (rnd&~AV_ROUND_PASS_MINMAX)!=4); - if (c <= 0 || b < 0 || rnd == 4 || rnd > 5) + if (c <= 0 || b < 0 || !((unsigned)(rnd&~AV_ROUND_PASS_MINMAX)<=5 && (rnd&~AV_ROUND_PASS_MINMAX)!=4)) return INT64_MIN; + if (rnd & AV_ROUND_PASS_MINMAX) { + if (a == INT64_MIN || a == INT64_MAX) + return a; + rnd -= AV_ROUND_PASS_MINMAX; + } + if (a < 0 && a != INT64_MIN) return -av_rescale_rnd(-a, b, c, rnd ^ ((rnd >> 1) & 1)); @@ -135,6 +146,8 @@ int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b) { int64_t a = tb_a.num * (int64_t)tb_b.den; int64_t b = tb_b.num * (int64_t)tb_a.den; + if ((FFABS(ts_a)|a|FFABS(ts_b)|b) <= INT_MAX) + return (ts_a*a > ts_b*b) - (ts_a*a < ts_b*b); if (av_rescale_rnd(ts_a, a, b, AV_ROUND_DOWN) < ts_b) return -1; if (av_rescale_rnd(ts_b, b, a, AV_ROUND_DOWN) < ts_a) @@ -149,3 +162,48 @@ int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod) c -= mod; return c; } + +int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb){ + int64_t a, b, this; + + av_assert0(in_ts != AV_NOPTS_VALUE); + av_assert0(duration >= 0); + + if (*last == AV_NOPTS_VALUE || !duration || in_tb.num*(int64_t)out_tb.den <= out_tb.num*(int64_t)in_tb.den) { +simple_round: + *last = av_rescale_q(in_ts, in_tb, fs_tb) + duration; + return av_rescale_q(in_ts, in_tb, out_tb); + } + + a = av_rescale_q_rnd(2*in_ts-1, in_tb, fs_tb, AV_ROUND_DOWN) >>1; + b = (av_rescale_q_rnd(2*in_ts+1, in_tb, fs_tb, AV_ROUND_UP )+1)>>1; + if (*last < 2*a - b || *last > 2*b - a) + goto simple_round; + + this = av_clip64(*last, a, b); + *last = this + duration; + + return av_rescale_q(this, fs_tb, out_tb); +} + +int64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc) +{ + int64_t m, d; + + if (inc != 1) + inc_tb = av_mul_q(inc_tb, (AVRational) {inc, 1}); + + m = inc_tb.num * (int64_t)ts_tb.den; + d = inc_tb.den * (int64_t)ts_tb.num; + + if (m % d == 0) + return ts + m / d; + if (m < d) + return ts; + + { + int64_t old = av_rescale_q(ts, ts_tb, inc_tb); + int64_t old_ts = av_rescale_q(old, inc_tb, ts_tb); + return av_rescale_q(old + 1, inc_tb, ts_tb) + (ts - old_ts); + } +} diff --git a/libavutil/mathematics.h b/libavutil/mathematics.h index 043dd0fafe..ac94488729 100644 --- a/libavutil/mathematics.h +++ b/libavutil/mathematics.h @@ -1,20 +1,20 @@ /* - * copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at> + * copyright (c) 2005-2012 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -27,12 +27,33 @@ #include "rational.h" #include "intfloat.h" +#ifndef M_E +#define M_E 2.7182818284590452354 /* e */ +#endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#endif +#ifndef M_LN10 +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#endif #ifndef M_LOG2_10 #define M_LOG2_10 3.32192809488736234787 /* log_2 10 */ #endif #ifndef M_PHI #define M_PHI 1.61803398874989484820 /* phi / golden ratio */ #endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#endif +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#endif #ifndef NAN #define NAN av_int2float(0x7fc00000) #endif @@ -52,6 +73,7 @@ enum AVRounding { AV_ROUND_DOWN = 2, ///< Round toward -infinity. AV_ROUND_UP = 3, ///< Round toward +infinity. AV_ROUND_NEAR_INF = 5, ///< Round to nearest and halfway cases away from zero. + AV_ROUND_PASS_MINMAX = 8192, ///< Flag to pass INT64_MIN/MAX through instead of rescaling, this avoids special cases for AV_NOPTS_VALUE }; /** @@ -70,6 +92,9 @@ int64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const; /** * Rescale a 64-bit integer with specified rounding. * A simple a*b/c isn't possible as it can overflow. + * + * @return rescaled value a, or if AV_ROUND_PASS_MINMAX is set and a is + * INT64_MIN or INT64_MAX then a is passed through unchanged. */ int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding) av_const; @@ -80,6 +105,9 @@ int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const; /** * Rescale a 64-bit integer by 2 rational numbers with specified rounding. + * + * @return rescaled value a, or if AV_ROUND_PASS_MINMAX is set and a is + * INT64_MIN or INT64_MAX then a is passed through unchanged. */ int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, enum AVRounding) av_const; @@ -105,6 +133,31 @@ int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b); int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod); /** + * Rescale a timestamp while preserving known durations. + * + * @param in_ts Input timestamp + * @param in_tb Input timebase + * @param fs_tb Duration and *last timebase + * @param duration duration till the next call + * @param out_tb Output timebase + */ +int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb); + +/** + * Add a value to a timestamp. + * + * This function guarantees that when the same value is repeatly added that + * no accumulation of rounding errors occurs. + * + * @param ts Input timestamp + * @param ts_tb Input timestamp timebase + * @param inc value to add to ts + * @param inc_tb inc timebase + */ +int64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc); + + + /** * @} */ diff --git a/libavutil/md5.c b/libavutil/md5.c index efb993e605..63fc37dafc 100644 --- a/libavutil/md5.c +++ b/libavutil/md5.c @@ -13,20 +13,20 @@ * If you use gcc, then version 4.1 or later and -fomit-frame-pointer is * strongly recommended. * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -42,9 +42,7 @@ typedef struct AVMD5{ uint32_t ABCD[4]; } AVMD5; -#if FF_API_CONTEXT_SIZE const int av_md5_size = sizeof(AVMD5); -#endif struct AVMD5 *av_md5_alloc(void) { @@ -85,50 +83,56 @@ static const uint32_t T[64] = { // T[i]= fabs(sin(i+1)<<32) a += T[i]; \ \ if (i < 32) { \ - if (i < 16) a += (d ^ (b & (c ^ d))) + X[ i & 15]; \ - else a += (c ^ (d & (c ^ b))) + X[(1 + 5*i) & 15]; \ + if (i < 16) a += (d ^ (b & (c ^ d))) + X[ i & 15]; \ + else a += ((d & b) | (~d & c)) + X[(1 + 5*i) & 15]; \ } else { \ - if (i < 48) a += (b ^ c ^ d) + X[(5 + 3*i) & 15]; \ - else a += (c ^ (b | ~d)) + X[( 7*i) & 15]; \ + if (i < 48) a += (b ^ c ^ d) + X[(5 + 3*i) & 15]; \ + else a += (c ^ (b | ~d)) + X[( 7*i) & 15]; \ } \ a = b + (a << t | a >> (32 - t)); \ } while (0) -static void body(uint32_t ABCD[4], uint32_t X[16]) +static void body(uint32_t ABCD[4], uint32_t *src, int nblocks) { - int t; int i av_unused; - unsigned int a = ABCD[3]; - unsigned int b = ABCD[2]; - unsigned int c = ABCD[1]; - unsigned int d = ABCD[0]; + int n; + uint32_t a, b, c, d, t, *X; + + for (n = 0; n < nblocks; n++) { + a = ABCD[3]; + b = ABCD[2]; + c = ABCD[1]; + d = ABCD[0]; + + X = src + n * 16; #if HAVE_BIGENDIAN - for (i = 0; i < 16; i++) - X[i] = av_bswap32(X[i]); + for (i = 0; i < 16; i++) + X[i] = av_bswap32(X[i]); #endif #if CONFIG_SMALL - for (i = 0; i < 64; i++) { - CORE(i, a, b, c, d); - t = d; - d = c; - c = b; - b = a; - a = t; - } + for (i = 0; i < 64; i++) { + CORE(i, a, b, c, d); + t = d; + d = c; + c = b; + b = a; + a = t; + } #else #define CORE2(i) \ - CORE( i, a,b,c,d); CORE((i+1),d,a,b,c); \ - CORE((i+2),c,d,a,b); CORE((i+3),b,c,d,a) + CORE( i, a,b,c,d); CORE((i+1),d,a,b,c); \ + CORE((i+2),c,d,a,b); CORE((i+3),b,c,d,a) #define CORE4(i) CORE2(i); CORE2((i+4)); CORE2((i+8)); CORE2((i+12)) - CORE4(0); CORE4(16); CORE4(32); CORE4(48); + CORE4(0); CORE4(16); CORE4(32); CORE4(48); #endif - ABCD[0] += d; - ABCD[1] += c; - ABCD[2] += b; - ABCD[3] += a; + ABCD[0] += d; + ABCD[1] += c; + ABCD[2] += b; + ABCD[3] += a; + } } void av_md5_init(AVMD5 *ctx) @@ -141,20 +145,39 @@ void av_md5_init(AVMD5 *ctx) ctx->ABCD[3] = 0x67452301; } -void av_md5_update(AVMD5 *ctx, const uint8_t *src, const int len) +void av_md5_update(AVMD5 *ctx, const uint8_t *src, int len) { - int i, j; + const uint8_t *end; + int j; j = ctx->len & 63; ctx->len += len; - for (i = 0; i < len; i++) { - ctx->block[j++] = src[i]; - if (j == 64) { - body(ctx->ABCD, (uint32_t *) ctx->block); - j = 0; + if (j) { + int cnt = FFMIN(len, 64 - j); + memcpy(ctx->block + j, src, cnt); + src += cnt; + len -= cnt; + if (j + cnt < 64) + return; + body(ctx->ABCD, (uint32_t *)ctx->block, 1); + } + + end = src + (len & ~63); + if (HAVE_BIGENDIAN || (!HAVE_FAST_UNALIGNED && ((intptr_t)src & 3))) { + while (src < end) { + memcpy(ctx->block, src, 64); + body(ctx->ABCD, (uint32_t *) ctx->block, 1); + src += 64; } + } else { + int nblocks = len / 64; + body(ctx->ABCD, (uint32_t *)src, nblocks); + src = end; } + len &= 63; + if (len > 0) + memcpy(ctx->block, src, len); } void av_md5_final(AVMD5 *ctx, uint8_t *dst) diff --git a/libavutil/md5.h b/libavutil/md5.h index 29e4e7c2ba..79702c88c2 100644 --- a/libavutil/md5.h +++ b/libavutil/md5.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -32,16 +32,46 @@ * @{ */ -#if FF_API_CONTEXT_SIZE -extern attribute_deprecated const int av_md5_size; -#endif +extern const int av_md5_size; struct AVMD5; +/** + * Allocate an AVMD5 context. + */ struct AVMD5 *av_md5_alloc(void); + +/** + * Initialize MD5 hashing. + * + * @param ctx pointer to the function context (of size av_md5_size) + */ void av_md5_init(struct AVMD5 *ctx); -void av_md5_update(struct AVMD5 *ctx, const uint8_t *src, const int len); + +/** + * Update hash value. + * + * @param ctx hash function context + * @param src input data to update hash with + * @param len input data length + */ +void av_md5_update(struct AVMD5 *ctx, const uint8_t *src, int len); + +/** + * Finish hashing and output digest value. + * + * @param ctx hash function context + * @param dst buffer where output digest value is stored + */ void av_md5_final(struct AVMD5 *ctx, uint8_t *dst); + +/** + * Hash an array of data. + * + * @param dst The output buffer to write the digest into + * @param src The data to hash + * @param len The length of the data, in bytes + */ void av_md5_sum(uint8_t *dst, const uint8_t *src, const int len); /** diff --git a/libavutil/mem.c b/libavutil/mem.c index be42342de2..8226168eed 100644 --- a/libavutil/mem.c +++ b/libavutil/mem.c @@ -2,20 +2,20 @@ * default memory allocator for libavutil * Copyright (c) 2002 Fabrice Bellard * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -24,6 +24,8 @@ * default memory allocator for libavutil */ +#define _XOPEN_SOURCE 600 + #include "config.h" #include <limits.h> @@ -34,8 +36,10 @@ #include <malloc.h> #endif +#include "avassert.h" #include "avutil.h" #include "common.h" +#include "dynarray.h" #include "intreadwrite.h" #include "mem.h" @@ -55,9 +59,18 @@ void free(void *ptr); #endif /* MALLOC_PREFIX */ -/* You can redefine av_malloc and av_free in your project to use your - * memory allocator. You do not need to suppress this file because the - * linker will do it automatically. */ +#define ALIGN (HAVE_AVX ? 32 : 16) + +/* NOTE: if you want to override these functions with your own + * implementations (not recommended) you have to link libav* as + * dynamic libraries and remove -Wl,-Bsymbolic from the linker flags. + * Note that this will cost performance. */ + +static size_t max_alloc_size= INT_MAX; + +void av_max_alloc(size_t max){ + max_alloc_size = max; +} void *av_malloc(size_t size) { @@ -67,23 +80,28 @@ void *av_malloc(size_t size) #endif /* let's disallow possibly ambiguous cases */ - if (size > (INT_MAX - 32) || !size) + if (size > (max_alloc_size - 32)) return NULL; #if CONFIG_MEMALIGN_HACK - ptr = malloc(size + 32); + ptr = malloc(size + ALIGN); if (!ptr) return ptr; - diff = ((-(long)ptr - 1) & 31) + 1; + diff = ((~(long)ptr)&(ALIGN - 1)) + 1; ptr = (char *)ptr + diff; ((char *)ptr)[-1] = diff; #elif HAVE_POSIX_MEMALIGN - if (posix_memalign(&ptr, 32, size)) + if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation + if (posix_memalign(&ptr, ALIGN, size)) ptr = NULL; #elif HAVE_ALIGNED_MALLOC - ptr = _aligned_malloc(size, 32); + ptr = _aligned_malloc(size, ALIGN); #elif HAVE_MEMALIGN - ptr = memalign(32, size); +#ifndef __DJGPP__ + ptr = memalign(ALIGN, size); +#else + ptr = memalign(size, ALIGN); +#endif /* Why 64? * Indeed, we should align it: * on 4 for 386 @@ -111,6 +129,14 @@ void *av_malloc(size_t size) #else ptr = malloc(size); #endif + if(!ptr && !size) { + size = 1; + ptr= av_malloc(1); + } +#if CONFIG_MEMORY_POISONING + if (ptr) + memset(ptr, FF_MEMORY_POISON, size); +#endif return ptr; } @@ -121,7 +147,7 @@ void *av_realloc(void *ptr, size_t size) #endif /* let's disallow possibly ambiguous cases */ - if (size > (INT_MAX - 16)) + if (size > (max_alloc_size - 32)) return NULL; #if CONFIG_MEMALIGN_HACK @@ -129,14 +155,33 @@ void *av_realloc(void *ptr, size_t size) if (!ptr) return av_malloc(size); diff = ((char *)ptr)[-1]; - return (char *)realloc((char *)ptr - diff, size + diff) + diff; + av_assert0(diff>0 && diff<=ALIGN); + ptr = realloc((char *)ptr - diff, size + diff); + if (ptr) + ptr = (char *)ptr + diff; + return ptr; #elif HAVE_ALIGNED_MALLOC - return _aligned_realloc(ptr, size, 32); + return _aligned_realloc(ptr, size + !size, ALIGN); #else - return realloc(ptr, size); + return realloc(ptr, size + !size); #endif } +void *av_realloc_f(void *ptr, size_t nelem, size_t elsize) +{ + size_t size; + void *r; + + if (av_size_mult(elsize, nelem, &size)) { + av_free(ptr); + return NULL; + } + r = av_realloc(ptr, size); + if (!r && size) + av_free(ptr); + return r; +} + int av_reallocp(void *ptr, size_t size) { void **ptrptr = ptr; @@ -167,27 +212,20 @@ void *av_realloc_array(void *ptr, size_t nmemb, size_t size) int av_reallocp_array(void *ptr, size_t nmemb, size_t size) { void **ptrptr = ptr; - void *ret; - if (!size || nmemb >= INT_MAX / size) + *ptrptr = av_realloc_f(*ptrptr, nmemb, size); + if (!*ptrptr && nmemb && size) return AVERROR(ENOMEM); - if (!nmemb) { - av_freep(ptr); - return 0; - } - ret = av_realloc(*ptrptr, nmemb * size); - if (!ret) { - av_freep(ptr); - return AVERROR(ENOMEM); - } - *ptrptr = ret; return 0; } void av_free(void *ptr) { #if CONFIG_MEMALIGN_HACK - if (ptr) - free((char *)ptr - ((char *)ptr)[-1]); + if (ptr) { + int v= ((char *)ptr)[-1]; + av_assert0(v>0 && v<=ALIGN); + free((char *)ptr - v); + } #elif HAVE_ALIGNED_MALLOC _aligned_free(ptr); #else @@ -210,6 +248,13 @@ void *av_mallocz(size_t size) return ptr; } +void *av_calloc(size_t nmemb, size_t size) +{ + if (size <= 0 || nmemb >= INT_MAX / size) + return NULL; + return av_mallocz(nmemb * size); +} + char *av_strdup(const char *s) { char *ptr = NULL; @@ -222,6 +267,61 @@ char *av_strdup(const char *s) return ptr; } +void *av_memdup(const void *p, size_t size) +{ + void *ptr = NULL; + if (p) { + ptr = av_malloc(size); + if (ptr) + memcpy(ptr, p, size); + } + return ptr; +} + +int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem) +{ + void **tab = *(void ***)tab_ptr; + + AV_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, { + tab[*nb_ptr] = elem; + *(void ***)tab_ptr = tab; + }, { + return AVERROR(ENOMEM); + }); + return 0; +} + +void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem) +{ + void **tab = *(void ***)tab_ptr; + + AV_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, { + tab[*nb_ptr] = elem; + *(void ***)tab_ptr = tab; + }, { + *nb_ptr = 0; + av_freep(tab_ptr); + }); +} + +void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, + const uint8_t *elem_data) +{ + uint8_t *tab_elem_data = NULL; + + AV_DYNARRAY_ADD(INT_MAX, elem_size, *tab_ptr, *nb_ptr, { + tab_elem_data = (uint8_t *)*tab_ptr + (*nb_ptr) * elem_size; + if (elem_data) + memcpy(tab_elem_data, elem_data, elem_size); + else if (CONFIG_MEMORY_POISONING) + memset(tab_elem_data, FF_MEMORY_POISON, elem_size); + }, { + av_freep(tab_ptr); + *nb_ptr = 0; + }); + return tab_elem_data; +} + static void fill16(uint8_t *dst, int len) { uint32_t v = AV_RN16(dst - 2); @@ -365,15 +465,22 @@ void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size) return ptr; } -void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size) +static inline int ff_fast_malloc(void *ptr, unsigned int *size, size_t min_size, int zero_realloc) { void **p = ptr; if (min_size < *size) - return; + return 0; min_size = FFMAX(17 * min_size / 16 + 32, min_size); av_free(*p); - *p = av_malloc(min_size); + *p = zero_realloc ? av_mallocz(min_size) : av_malloc(min_size); if (!*p) min_size = 0; *size = min_size; + return 1; } + +void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size) +{ + ff_fast_malloc(ptr, size, min_size, 0); +} + diff --git a/libavutil/mem.h b/libavutil/mem.h index 4a5e362cec..0be2127071 100644 --- a/libavutil/mem.h +++ b/libavutil/mem.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -30,6 +30,7 @@ #include <stdint.h> #include "attributes.h" +#include "error.h" #include "avutil.h" /** @@ -38,7 +39,7 @@ */ -#if defined(__ICC) && __ICC < 1200 || defined(__SUNPRO_C) +#if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1110 || defined(__SUNPRO_C) #define DECLARE_ALIGNED(n,t,v) t __attribute__ ((aligned (n))) v #define DECLARE_ASM_CONST(n,t,v) const t __attribute__ ((aligned (n))) v #elif defined(__TI_COMPILER_VERSION__) @@ -118,6 +119,16 @@ void *av_realloc(void *ptr, size_t size) av_alloc_size(2); /** * Allocate or reallocate a block of memory. + * This function does the same thing as av_realloc, except: + * - It takes two arguments and checks the result of the multiplication for + * integer overflow. + * - It frees the input block in case of failure, thus avoiding the memory + * leak with the classic "buf = realloc(buf); if (!buf) return -1;". + */ +void *av_realloc_f(void *ptr, size_t nelem, size_t elsize); + +/** + * Allocate or reallocate a block of memory. * If *ptr is NULL and size > 0, allocate a new block. If * size is zero, free the memory block pointed to by ptr. * @param ptr Pointer to a pointer to a memory block already allocated @@ -194,6 +205,18 @@ void av_free(void *ptr); void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1); /** + * Allocate a block of nmemb * size bytes with alignment suitable for all + * memory accesses (including vectors if available on the CPU) and + * zero all the bytes of the block. + * The allocation will fail if nmemb * size is greater than or equal + * to INT_MAX. + * @param nmemb + * @param size + * @return Pointer to the allocated block, NULL if it cannot be allocated. + */ +void *av_calloc(size_t nmemb, size_t size) av_malloc_attrib; + +/** * Allocate a block of size * nmemb bytes with av_mallocz(). * @param nmemb Number of elements * @param size Size of the single element @@ -218,18 +241,109 @@ av_alloc_size(1, 2) static inline void *av_mallocz_array(size_t nmemb, size_t si char *av_strdup(const char *s) av_malloc_attrib; /** + * Duplicate the buffer p. + * @param p buffer to be duplicated + * @return Pointer to a newly allocated buffer containing a + * copy of p or NULL if the buffer cannot be allocated. + */ +void *av_memdup(const void *p, size_t size); + +/** * Free a memory block which has been allocated with av_malloc(z)() or * av_realloc() and set the pointer pointing to it to NULL. * @param ptr Pointer to the pointer to the memory block which should * be freed. + * @note passing a pointer to a NULL pointer is safe and leads to no action. * @see av_free() */ void av_freep(void *ptr); /** + * Add an element to a dynamic array. + * + * The array to grow is supposed to be an array of pointers to + * structures, and the element to add must be a pointer to an already + * allocated structure. + * + * The array is reallocated when its size 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 number pointed to by nb_ptr + * is incremented. + * In case of failure, the array is freed, *tab_ptr is set to NULL and + * *nb_ptr is set to 0. + * + * @param tab_ptr pointer to the array to grow + * @param nb_ptr pointer to the number of elements in the array + * @param elem element to add + * @see av_dynarray_add_nofree(), av_dynarray2_add() + */ +void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element to a dynamic array. + * + * Function has the same functionality as av_dynarray_add(), + * but it doesn't free memory on fails. It returns error code + * instead and leave current buffer untouched. + * + * @param tab_ptr pointer to the array to grow + * @param nb_ptr pointer to the number of elements in the array + * @param elem element to add + * @return >=0 on success, negative otherwise. + * @see av_dynarray_add(), av_dynarray2_add() + */ +int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem); + +/** + * Add an element of size elem_size 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 number pointed to by nb_ptr + * is incremented. + * In case of failure, the array is freed, *tab_ptr is set to NULL and + * *nb_ptr is set to 0. + * + * @param tab_ptr pointer to the array to grow + * @param nb_ptr pointer to the number of elements in the array + * @param elem_size size in bytes of the elements in the array + * @param elem_data pointer to the data of the element to add. If NULL, the space of + * the new added element is not filled. + * @return pointer to the data of the element to copy in the new allocated space. + * If NULL, the new allocated space is left uninitialized." + * @see av_dynarray_add(), av_dynarray_add_nofree() + */ +void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, + const uint8_t *elem_data); + +/** + * Multiply two size_t values checking for overflow. + * @return 0 if success, AVERROR(EINVAL) if overflow. + */ +static inline int av_size_mult(size_t a, size_t b, size_t *r) +{ + size_t t = a * b; + /* Hack inspired from glibc: only try the division if nelem and elsize + * are both greater than sqrt(SIZE_MAX). */ + if ((a | b) >= ((size_t)1 << (sizeof(size_t) * 4)) && a && t / a != b) + return AVERROR(EINVAL); + *r = t; + return 0; +} + +/** + * Set the maximum size that may me allocated in one block. + */ +void av_max_alloc(size_t max); + +/** * deliberately overlapping memcpy implementation * @param dst destination buffer - * @param back how many bytes back we start (the initial size of the overlapping window) + * @param back how many bytes back we start (the initial size of the overlapping window), must be > 0 * @param cnt number of bytes to copy, must be >= 0 * * cnt > back is valid, this will copy the bytes we just copied, diff --git a/libavutil/mips/Makefile b/libavutil/mips/Makefile new file mode 100644 index 0000000000..dbfa5aa341 --- /dev/null +++ b/libavutil/mips/Makefile @@ -0,0 +1 @@ +OBJS += mips/float_dsp_mips.o diff --git a/libavutil/mips/float_dsp_mips.c b/libavutil/mips/float_dsp_mips.c new file mode 100644 index 0000000000..06d52dc258 --- /dev/null +++ b/libavutil/mips/float_dsp_mips.c @@ -0,0 +1,383 @@ +/* + * 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: Branimir Vasic (bvasic@mips.com) + * Author: Zoran Lukic (zoranl@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 + */ + +/** + * @file + * Reference: libavutil/float_dsp.c + */ + +#include "config.h" +#include "libavutil/float_dsp.h" + +#if HAVE_INLINE_ASM && HAVE_MIPSFPU +static void vector_fmul_mips(float *dst, const float *src0, const float *src1, + int len) +{ + int i; + + if (len & 3) { + for (i = 0; i < len; i++) + dst[i] = src0[i] * src1[i]; + } else { + float *d = (float *)dst; + float *d_end = d + len; + float *s0 = (float *)src0; + float *s1 = (float *)src1; + + float src0_0, src0_1, src0_2, src0_3; + float src1_0, src1_1, src1_2, src1_3; + + __asm__ volatile ( + "1: \n\t" + "lwc1 %[src0_0], 0(%[s0]) \n\t" + "lwc1 %[src1_0], 0(%[s1]) \n\t" + "lwc1 %[src0_1], 4(%[s0]) \n\t" + "lwc1 %[src1_1], 4(%[s1]) \n\t" + "lwc1 %[src0_2], 8(%[s0]) \n\t" + "lwc1 %[src1_2], 8(%[s1]) \n\t" + "lwc1 %[src0_3], 12(%[s0]) \n\t" + "lwc1 %[src1_3], 12(%[s1]) \n\t" + "mul.s %[src0_0], %[src0_0], %[src1_0] \n\t" + "mul.s %[src0_1], %[src0_1], %[src1_1] \n\t" + "mul.s %[src0_2], %[src0_2], %[src1_2] \n\t" + "mul.s %[src0_3], %[src0_3], %[src1_3] \n\t" + "swc1 %[src0_0], 0(%[d]) \n\t" + "swc1 %[src0_1], 4(%[d]) \n\t" + "swc1 %[src0_2], 8(%[d]) \n\t" + "swc1 %[src0_3], 12(%[d]) \n\t" + "addiu %[s0], %[s0], 16 \n\t" + "addiu %[s1], %[s1], 16 \n\t" + "addiu %[d], %[d], 16 \n\t" + "bne %[d], %[d_end], 1b \n\t" + + : [src0_0]"=&f"(src0_0), [src0_1]"=&f"(src0_1), + [src0_2]"=&f"(src0_2), [src0_3]"=&f"(src0_3), + [src1_0]"=&f"(src1_0), [src1_1]"=&f"(src1_1), + [src1_2]"=&f"(src1_2), [src1_3]"=&f"(src1_3), + [d]"+r"(d), [s0]"+r"(s0), [s1]"+r"(s1) + : [d_end]"r"(d_end) + : "memory" + ); + } +} + +static void vector_fmul_scalar_mips(float *dst, const float *src, float mul, + int len) +{ + float temp0, temp1, temp2, temp3; + float *local_src = (float*)src; + float *end = local_src + len; + + /* loop unrolled 4 times */ + __asm__ volatile( + ".set push \n\t" + ".set noreorder \n\t" + "1: \n\t" + "lwc1 %[temp0], 0(%[src]) \n\t" + "lwc1 %[temp1], 4(%[src]) \n\t" + "lwc1 %[temp2], 8(%[src]) \n\t" + "lwc1 %[temp3], 12(%[src]) \n\t" + "addiu %[dst], %[dst], 16 \n\t" + "mul.s %[temp0], %[temp0], %[mul] \n\t" + "mul.s %[temp1], %[temp1], %[mul] \n\t" + "mul.s %[temp2], %[temp2], %[mul] \n\t" + "mul.s %[temp3], %[temp3], %[mul] \n\t" + "addiu %[src], %[src], 16 \n\t" + "swc1 %[temp0], -16(%[dst]) \n\t" + "swc1 %[temp1], -12(%[dst]) \n\t" + "swc1 %[temp2], -8(%[dst]) \n\t" + "bne %[src], %[end], 1b \n\t" + " swc1 %[temp3], -4(%[dst]) \n\t" + ".set pop \n\t" + + : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), + [temp2]"=&f"(temp2), [temp3]"=&f"(temp3), + [dst]"+r"(dst), [src]"+r"(local_src) + : [end]"r"(end), [mul]"f"(mul) + : "memory" + ); +} + +static void vector_fmul_window_mips(float *dst, const float *src0, + const float *src1, const float *win, int len) +{ + int i, j; + /* + * variables used in inline assembler + */ + float * dst_i, * dst_j, * dst_i2, * dst_j2; + float temp, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + dst += len; + win += len; + src0 += len; + + for (i = -len, j = len - 1; i < 0; i += 8, j -= 8) { + + dst_i = dst + i; + dst_j = dst + j; + + dst_i2 = dst + i + 4; + dst_j2 = dst + j - 4; + + __asm__ volatile ( + "mul.s %[temp], %[s1], %[wi] \n\t" + "mul.s %[temp1], %[s1], %[wj] \n\t" + "mul.s %[temp2], %[s11], %[wi1] \n\t" + "mul.s %[temp3], %[s11], %[wj1] \n\t" + + "msub.s %[temp], %[temp], %[s0], %[wj] \n\t" + "madd.s %[temp1], %[temp1], %[s0], %[wi] \n\t" + "msub.s %[temp2], %[temp2], %[s01], %[wj1] \n\t" + "madd.s %[temp3], %[temp3], %[s01], %[wi1] \n\t" + + "swc1 %[temp], 0(%[dst_i]) \n\t" /* dst[i] = s0*wj - s1*wi; */ + "swc1 %[temp1], 0(%[dst_j]) \n\t" /* dst[j] = s0*wi + s1*wj; */ + "swc1 %[temp2], 4(%[dst_i]) \n\t" /* dst[i+1] = s01*wj1 - s11*wi1; */ + "swc1 %[temp3], -4(%[dst_j]) \n\t" /* dst[j-1] = s01*wi1 + s11*wj1; */ + + "mul.s %[temp4], %[s12], %[wi2] \n\t" + "mul.s %[temp5], %[s12], %[wj2] \n\t" + "mul.s %[temp6], %[s13], %[wi3] \n\t" + "mul.s %[temp7], %[s13], %[wj3] \n\t" + + "msub.s %[temp4], %[temp4], %[s02], %[wj2] \n\t" + "madd.s %[temp5], %[temp5], %[s02], %[wi2] \n\t" + "msub.s %[temp6], %[temp6], %[s03], %[wj3] \n\t" + "madd.s %[temp7], %[temp7], %[s03], %[wi3] \n\t" + + "swc1 %[temp4], 8(%[dst_i]) \n\t" /* dst[i+2] = s02*wj2 - s12*wi2; */ + "swc1 %[temp5], -8(%[dst_j]) \n\t" /* dst[j-2] = s02*wi2 + s12*wj2; */ + "swc1 %[temp6], 12(%[dst_i]) \n\t" /* dst[i+2] = s03*wj3 - s13*wi3; */ + "swc1 %[temp7], -12(%[dst_j]) \n\t" /* dst[j-3] = s03*wi3 + s13*wj3; */ + : [temp]"=&f"(temp), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7) + : [dst_j]"r"(dst_j), [dst_i]"r" (dst_i), + [s0] "f"(src0[i]), [wj] "f"(win[j]), [s1] "f"(src1[j]), + [wi] "f"(win[i]), [s01]"f"(src0[i + 1]),[wj1]"f"(win[j - 1]), + [s11]"f"(src1[j - 1]), [wi1]"f"(win[i + 1]), [s02]"f"(src0[i + 2]), + [wj2]"f"(win[j - 2]), [s12]"f"(src1[j - 2]),[wi2]"f"(win[i + 2]), + [s03]"f"(src0[i + 3]), [wj3]"f"(win[j - 3]), [s13]"f"(src1[j - 3]), + [wi3]"f"(win[i + 3]) + : "memory" + ); + + __asm__ volatile ( + "mul.s %[temp], %[s1], %[wi] \n\t" + "mul.s %[temp1], %[s1], %[wj] \n\t" + "mul.s %[temp2], %[s11], %[wi1] \n\t" + "mul.s %[temp3], %[s11], %[wj1] \n\t" + + "msub.s %[temp], %[temp], %[s0], %[wj] \n\t" + "madd.s %[temp1], %[temp1], %[s0], %[wi] \n\t" + "msub.s %[temp2], %[temp2], %[s01], %[wj1] \n\t" + "madd.s %[temp3], %[temp3], %[s01], %[wi1] \n\t" + + "swc1 %[temp], 0(%[dst_i2]) \n\t" /* dst[i] = s0*wj - s1*wi; */ + "swc1 %[temp1], 0(%[dst_j2]) \n\t" /* dst[j] = s0*wi + s1*wj; */ + "swc1 %[temp2], 4(%[dst_i2]) \n\t" /* dst[i+1] = s01*wj1 - s11*wi1; */ + "swc1 %[temp3], -4(%[dst_j2]) \n\t" /* dst[j-1] = s01*wi1 + s11*wj1; */ + + "mul.s %[temp4], %[s12], %[wi2] \n\t" + "mul.s %[temp5], %[s12], %[wj2] \n\t" + "mul.s %[temp6], %[s13], %[wi3] \n\t" + "mul.s %[temp7], %[s13], %[wj3] \n\t" + + "msub.s %[temp4], %[temp4], %[s02], %[wj2] \n\t" + "madd.s %[temp5], %[temp5], %[s02], %[wi2] \n\t" + "msub.s %[temp6], %[temp6], %[s03], %[wj3] \n\t" + "madd.s %[temp7], %[temp7], %[s03], %[wi3] \n\t" + + "swc1 %[temp4], 8(%[dst_i2]) \n\t" /* dst[i+2] = s02*wj2 - s12*wi2; */ + "swc1 %[temp5], -8(%[dst_j2]) \n\t" /* dst[j-2] = s02*wi2 + s12*wj2; */ + "swc1 %[temp6], 12(%[dst_i2]) \n\t" /* dst[i+2] = s03*wj3 - s13*wi3; */ + "swc1 %[temp7], -12(%[dst_j2]) \n\t" /* dst[j-3] = s03*wi3 + s13*wj3; */ + : [temp]"=&f"(temp), + [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), [temp3]"=&f"(temp3), + [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), [temp6]"=&f"(temp6), + [temp7] "=&f" (temp7) + : [dst_j2]"r"(dst_j2), [dst_i2]"r"(dst_i2), + [s0] "f"(src0[i + 4]), [wj] "f"(win[j - 4]), [s1] "f"(src1[j - 4]), + [wi] "f"(win[i + 4]), [s01]"f"(src0[i + 5]),[wj1]"f"(win[j - 5]), + [s11]"f"(src1[j - 5]), [wi1]"f"(win[i + 5]), [s02]"f"(src0[i + 6]), + [wj2]"f"(win[j - 6]), [s12]"f"(src1[j - 6]),[wi2]"f"(win[i + 6]), + [s03]"f"(src0[i + 7]), [wj3]"f"(win[j - 7]), [s13]"f"(src1[j - 7]), + [wi3]"f"(win[i + 7]) + : "memory" + ); + } +} + +static void butterflies_float_mips(float *av_restrict v1, float *av_restrict v2, + int len) +{ + float temp0, temp1, temp2, temp3, temp4; + float temp5, temp6, temp7, temp8, temp9; + float temp10, temp11, temp12, temp13, temp14, temp15; + int pom; + pom = (len >> 2)-1; + + /* loop unrolled 4 times */ + __asm__ volatile ( + "lwc1 %[temp0], 0(%[v1]) \n\t" + "lwc1 %[temp1], 4(%[v1]) \n\t" + "lwc1 %[temp2], 8(%[v1]) \n\t" + "lwc1 %[temp3], 12(%[v1]) \n\t" + "lwc1 %[temp4], 0(%[v2]) \n\t" + "lwc1 %[temp5], 4(%[v2]) \n\t" + "lwc1 %[temp6], 8(%[v2]) \n\t" + "lwc1 %[temp7], 12(%[v2]) \n\t" + "beq %[pom], $zero, 2f \n\t" + "1: \n\t" + "sub.s %[temp8], %[temp0], %[temp4] \n\t" + "add.s %[temp9], %[temp0], %[temp4] \n\t" + "sub.s %[temp10], %[temp1], %[temp5] \n\t" + "add.s %[temp11], %[temp1], %[temp5] \n\t" + "sub.s %[temp12], %[temp2], %[temp6] \n\t" + "add.s %[temp13], %[temp2], %[temp6] \n\t" + "sub.s %[temp14], %[temp3], %[temp7] \n\t" + "add.s %[temp15], %[temp3], %[temp7] \n\t" + "addiu %[v1], %[v1], 16 \n\t" + "addiu %[v2], %[v2], 16 \n\t" + "addiu %[pom], %[pom], -1 \n\t" + "lwc1 %[temp0], 0(%[v1]) \n\t" + "lwc1 %[temp1], 4(%[v1]) \n\t" + "lwc1 %[temp2], 8(%[v1]) \n\t" + "lwc1 %[temp3], 12(%[v1]) \n\t" + "lwc1 %[temp4], 0(%[v2]) \n\t" + "lwc1 %[temp5], 4(%[v2]) \n\t" + "lwc1 %[temp6], 8(%[v2]) \n\t" + "lwc1 %[temp7], 12(%[v2]) \n\t" + "swc1 %[temp9], -16(%[v1]) \n\t" + "swc1 %[temp8], -16(%[v2]) \n\t" + "swc1 %[temp11], -12(%[v1]) \n\t" + "swc1 %[temp10], -12(%[v2]) \n\t" + "swc1 %[temp13], -8(%[v1]) \n\t" + "swc1 %[temp12], -8(%[v2]) \n\t" + "swc1 %[temp15], -4(%[v1]) \n\t" + "swc1 %[temp14], -4(%[v2]) \n\t" + "bgtz %[pom], 1b \n\t" + "2: \n\t" + "sub.s %[temp8], %[temp0], %[temp4] \n\t" + "add.s %[temp9], %[temp0], %[temp4] \n\t" + "sub.s %[temp10], %[temp1], %[temp5] \n\t" + "add.s %[temp11], %[temp1], %[temp5] \n\t" + "sub.s %[temp12], %[temp2], %[temp6] \n\t" + "add.s %[temp13], %[temp2], %[temp6] \n\t" + "sub.s %[temp14], %[temp3], %[temp7] \n\t" + "add.s %[temp15], %[temp3], %[temp7] \n\t" + "swc1 %[temp9], 0(%[v1]) \n\t" + "swc1 %[temp8], 0(%[v2]) \n\t" + "swc1 %[temp11], 4(%[v1]) \n\t" + "swc1 %[temp10], 4(%[v2]) \n\t" + "swc1 %[temp13], 8(%[v1]) \n\t" + "swc1 %[temp12], 8(%[v2]) \n\t" + "swc1 %[temp15], 12(%[v1]) \n\t" + "swc1 %[temp14], 12(%[v2]) \n\t" + + : [v1]"+r"(v1), [v2]"+r"(v2), [pom]"+r"(pom), [temp0] "=&f" (temp0), + [temp1]"=&f"(temp1), [temp2]"=&f"(temp2), [temp3]"=&f"(temp3), + [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), [temp6]"=&f"(temp6), + [temp7]"=&f"(temp7), [temp8]"=&f"(temp8), [temp9]"=&f"(temp9), + [temp10]"=&f"(temp10), [temp11]"=&f"(temp11), [temp12]"=&f"(temp12), + [temp13]"=&f"(temp13), [temp14]"=&f"(temp14), [temp15]"=&f"(temp15) + : + : "memory" + ); +} + +static void vector_fmul_reverse_mips(float *dst, const float *src0, const float *src1, int len){ + int i; + float temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + src1 += len-1; + + for(i=0; i<(len>>2); i++) + { + /* loop unrolled 4 times */ + __asm__ volatile( + "lwc1 %[temp0], 0(%[src0]) \n\t" + "lwc1 %[temp1], 0(%[src1]) \n\t" + "lwc1 %[temp2], 4(%[src0]) \n\t" + "lwc1 %[temp3], -4(%[src1]) \n\t" + "lwc1 %[temp4], 8(%[src0]) \n\t" + "lwc1 %[temp5], -8(%[src1]) \n\t" + "lwc1 %[temp6], 12(%[src0]) \n\t" + "lwc1 %[temp7], -12(%[src1]) \n\t" + "mul.s %[temp0], %[temp1], %[temp0] \n\t" + "mul.s %[temp2], %[temp3], %[temp2] \n\t" + "mul.s %[temp4], %[temp5], %[temp4] \n\t" + "mul.s %[temp6], %[temp7], %[temp6] \n\t" + "addiu %[src0], %[src0], 16 \n\t" + "addiu %[src1], %[src1], -16 \n\t" + "addiu %[dst], %[dst], 16 \n\t" + "swc1 %[temp0], -16(%[dst]) \n\t" + "swc1 %[temp2], -12(%[dst]) \n\t" + "swc1 %[temp4], -8(%[dst]) \n\t" + "swc1 %[temp6], -4(%[dst]) \n\t" + + : [dst]"+r"(dst), [src0]"+r"(src0), [src1]"+r"(src1), + [temp0]"=&f"(temp0), [temp1]"=&f"(temp1),[temp2]"=&f"(temp2), + [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5), + [temp6]"=&f"(temp6), [temp7]"=&f"(temp7) + : + : "memory" + ); + } +} +#endif /* HAVE_INLINE_ASM && HAVE_MIPSFPU */ + +void ff_float_dsp_init_mips(AVFloatDSPContext *fdsp) { +#if HAVE_INLINE_ASM && HAVE_MIPSFPU + fdsp->vector_fmul = vector_fmul_mips; + fdsp->vector_fmul_scalar = vector_fmul_scalar_mips; + fdsp->vector_fmul_window = vector_fmul_window_mips; + fdsp->butterflies_float = butterflies_float_mips; + fdsp->vector_fmul_reverse = vector_fmul_reverse_mips; +#endif /* HAVE_INLINE_ASM && HAVE_MIPSFPU */ +} diff --git a/libavutil/mips/intreadwrite.h b/libavutil/mips/intreadwrite.h index 4dabbe6819..9ba0491372 100644 --- a/libavutil/mips/intreadwrite.h +++ b/libavutil/mips/intreadwrite.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2009 Mans Rullgard <mans@mansr.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/mips/libm_mips.h b/libavutil/mips/libm_mips.h new file mode 100644 index 0000000000..8853bbc751 --- /dev/null +++ b/libavutil/mips/libm_mips.h @@ -0,0 +1,73 @@ +/* + * 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 + */ + +/** + * @file + * MIPS optimization for some libm functions + */ + +#ifndef AVUTIL_LIBM_MIPS_H +#define AVUTIL_LIBM_MIPS_H + +static av_always_inline av_const long int lrintf_mips(float x) +{ + register int ret_int; + + __asm__ volatile ( + "cvt.w.s %[x], %[x] \n\t" + "mfc1 %[ret_int], %[x] \n\t" + + :[x]"+f"(x), [ret_int]"=r"(ret_int) + ); + return ret_int; +} + +#undef lrintf +#define lrintf(x) lrintf_mips(x) + +#define HAVE_LRINTF 1 +#endif /* AVUTIL_LIBM_MIPS_H */ diff --git a/libavutil/murmur3.c b/libavutil/murmur3.c new file mode 100644 index 0000000000..701fa6a0ff --- /dev/null +++ b/libavutil/murmur3.c @@ -0,0 +1,192 @@ +/* + * 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 "mem.h" +#include "intreadwrite.h" +#include "murmur3.h" + +typedef struct AVMurMur3 { + uint64_t h1, h2; + uint8_t state[16]; + int state_pos; + uint64_t len; +} AVMurMur3; + +AVMurMur3 *av_murmur3_alloc(void) +{ + return av_mallocz(sizeof(AVMurMur3)); +} + +void av_murmur3_init_seeded(AVMurMur3 *c, uint64_t seed) +{ + memset(c, 0, sizeof(*c)); + c->h1 = c->h2 = seed; +} + +void av_murmur3_init(AVMurMur3 *c) +{ + // arbitrary random number as seed + av_murmur3_init_seeded(c, 0x725acc55daddca55); +} + +static const uint64_t c1 = UINT64_C(0x87c37b91114253d5); +static const uint64_t c2 = UINT64_C(0x4cf5ad432745937f); + +#define ROT(a, b) ((a << b) | (a >> (64 - b))) + +static uint64_t inline get_k1(const uint8_t *src) +{ + uint64_t k = AV_RL64(src); + k *= c1; + k = ROT(k, 31); + k *= c2; + return k; +} + +static uint64_t inline get_k2(const uint8_t *src) +{ + uint64_t k = AV_RL64(src + 8); + k *= c2; + k = ROT(k, 33); + k *= c1; + return k; +} + +static uint64_t inline update_h1(uint64_t k, uint64_t h1, uint64_t h2) +{ + k ^= h1; + k = ROT(k, 27); + k += h2; + k *= 5; + k += 0x52dce729; + return k; +} + +static uint64_t inline update_h2(uint64_t k, uint64_t h1, uint64_t h2) +{ + k ^= h2; + k = ROT(k, 31); + k += h1; + k *= 5; + k += 0x38495ab5; + return k; +} + +void av_murmur3_update(AVMurMur3 *c, const uint8_t *src, int len) +{ + const uint8_t *end; + uint64_t h1 = c->h1, h2 = c->h2; + uint64_t k1, k2; + if (len <= 0) return; + c->len += len; + if (c->state_pos > 0) { + while (c->state_pos < 16) { + c->state[c->state_pos++] = *src++; + if (--len <= 0) return; + } + c->state_pos = 0; + k1 = get_k1(c->state); + k2 = get_k2(c->state); + h1 = update_h1(k1, h1, h2); + h2 = update_h2(k2, h1, h2); + } + + end = src + (len & ~15); + while (src < end) { + // These could be done sequentially instead + // of interleaved, but like this is over 10% faster + k1 = get_k1(src); + k2 = get_k2(src); + h1 = update_h1(k1, h1, h2); + h2 = update_h2(k2, h1, h2); + src += 16; + } + c->h1 = h1; + c->h2 = h2; + + len &= 15; + if (len > 0) { + memcpy(c->state, src, len); + c->state_pos = len; + } +} + +static inline uint64_t fmix(uint64_t k) +{ + k ^= k >> 33; + k *= UINT64_C(0xff51afd7ed558ccd); + k ^= k >> 33; + k *= UINT64_C(0xc4ceb9fe1a85ec53); + k ^= k >> 33; + return k; +} + +void av_murmur3_final(AVMurMur3 *c, uint8_t dst[16]) +{ + uint64_t h1 = c->h1, h2 = c->h2; + memset(c->state + c->state_pos, 0, sizeof(c->state) - c->state_pos); + h1 ^= get_k1(c->state) ^ c->len; + h2 ^= get_k2(c->state) ^ c->len; + h1 += h2; + h2 += h1; + h1 = fmix(h1); + h2 = fmix(h2); + h1 += h2; + h2 += h1; + AV_WL64(dst, h1); + AV_WL64(dst + 8, h2); +} + +#ifdef TEST +int main(void) +{ + int i; + uint8_t hash_result[16] = {0}; + AVMurMur3 *ctx = av_murmur3_alloc(); +#if 1 + uint8_t in[256] = {0}; + uint8_t *hashes = av_mallocz(256 * 16); + for (i = 0; i < 256; i++) + { + in[i] = i; + av_murmur3_init_seeded(ctx, 256 - i); + // Note: this actually tests hashing 0 bytes + av_murmur3_update(ctx, in, i); + av_murmur3_final(ctx, hashes + 16 * i); + } + av_murmur3_init_seeded(ctx, 0); + av_murmur3_update(ctx, hashes, 256 * 16); + av_murmur3_final(ctx, hash_result); + av_free(hashes); + av_freep(&ctx); + printf("result: 0x%"PRIx64" 0x%"PRIx64"\n", AV_RL64(hash_result), AV_RL64(hash_result + 8)); + // official reference value is 32 bit + return AV_RL32(hash_result) != 0x6384ba69; +#else + uint8_t *in = av_mallocz(512*1024); + av_murmur3_init(ctx); + for (i = 0; i < 40*1024; i++) + av_murmur3_update(ctx, in, 512*1024); + av_murmur3_final(ctx, hash_result); + av_free(in); + return hash_result[0]; +#endif +} +#endif diff --git a/libavutil/murmur3.h b/libavutil/murmur3.h new file mode 100644 index 0000000000..f29ed973e9 --- /dev/null +++ b/libavutil/murmur3.h @@ -0,0 +1,32 @@ +/* + * 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 + */ + +#ifndef AVUTIL_MURMUR3_H +#define AVUTIL_MURMUR3_H + +#include <stdint.h> + +struct AVMurMur3 *av_murmur3_alloc(void); +void av_murmur3_init_seeded(struct AVMurMur3 *c, uint64_t seed); +void av_murmur3_init(struct AVMurMur3 *c); +void av_murmur3_update(struct AVMurMur3 *c, const uint8_t *src, int len); +void av_murmur3_final(struct AVMurMur3 *c, uint8_t dst[16]); + +#endif /* AVUTIL_MURMUR3_H */ diff --git a/libavutil/old_pix_fmts.h b/libavutil/old_pix_fmts.h index d3e1e5b24d..cd1ed7c19f 100644 --- a/libavutil/old_pix_fmts.h +++ b/libavutil/old_pix_fmts.h @@ -1,18 +1,20 @@ /* - * This file is part of Libav. + * copyright (c) 2006-2012 Michael Niedermayer <michaelni@gmx.at> * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -106,9 +108,13 @@ PIX_FMT_RGB444BE, ///< packed RGB 4:4:4, 16bpp, (msb)4A 4R 4G 4B(lsb), big-endian, most significant bits to 0 PIX_FMT_BGR444LE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), little-endian, most significant bits to 1 PIX_FMT_BGR444BE, ///< packed BGR 4:4:4, 16bpp, (msb)4A 4B 4G 4R(lsb), big-endian, most significant bits to 1 - PIX_FMT_Y400A, ///< 8bit gray, 8bit alpha + PIX_FMT_GRAY8A, ///< 8bit gray, 8bit alpha PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian + + //the following 10 formats have the disadvantage of needing 1 format for each bit depth, thus + //If you want to support multiple bit depths, then using PIX_FMT_YUV420P16* with the bpp stored separately + //is better PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian @@ -122,6 +128,13 @@ PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian PIX_FMT_VDA_VLD, ///< hardware decoding through VDA + +#ifdef AV_PIX_FMT_ABI_GIT_MASTER + PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian +#endif PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big endian PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little endian @@ -129,6 +142,36 @@ PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little endian PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big endian PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, little endian - PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions +#ifndef AV_PIX_FMT_ABI_GIT_MASTER + PIX_FMT_RGBA64BE=0x123, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian +#endif + PIX_FMT_0RGB=0x123+4, ///< packed RGB 8:8:8, 32bpp, 0RGB0RGB... + PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGB0RGB0... + PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, 0BGR0BGR... + PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGR0BGR0... + PIX_FMT_YUVA444P, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + PIX_FMT_YUVA422P, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) + + PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + PIX_FMT_GBRP12BE, ///< planar GBR 4:4:4 36bpp, big endian + PIX_FMT_GBRP12LE, ///< planar GBR 4:4:4 36bpp, little endian + PIX_FMT_GBRP14BE, ///< planar GBR 4:4:4 42bpp, big endian + PIX_FMT_GBRP14LE, ///< planar GBR 4:4:4 42bpp, little endian + + PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions #endif /* AVUTIL_OLD_PIX_FMTS_H */ diff --git a/libavutil/opencl.c b/libavutil/opencl.c new file mode 100644 index 0000000000..a92bce76b4 --- /dev/null +++ b/libavutil/opencl.c @@ -0,0 +1,837 @@ +/* + * Copyright (C) 2012 Peng Gao <peng@multicorewareinc.com> + * Copyright (C) 2012 Li Cao <li@multicorewareinc.com> + * Copyright (C) 2012 Wei Gao <weigao@multicorewareinc.com> + * Copyright (C) 2013 Lenny Wang <lwanghpc@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 "opencl.h" +#include "avstring.h" +#include "log.h" +#include "avassert.h" +#include "opt.h" + +#if HAVE_THREADS +#if HAVE_PTHREADS +#include <pthread.h> +#elif HAVE_W32THREADS +#include "compat/w32pthreads.h" +#elif HAVE_OS2THREADS +#include "compat/os2threads.h" +#endif +#include "atomic.h" + +static volatile pthread_mutex_t *atomic_opencl_lock = NULL; +#define LOCK_OPENCL pthread_mutex_lock(atomic_opencl_lock) +#define UNLOCK_OPENCL pthread_mutex_unlock(atomic_opencl_lock) +#else +#define LOCK_OPENCL +#define UNLOCK_OPENCL +#endif + +#define MAX_KERNEL_CODE_NUM 200 + +typedef struct { + int is_compiled; + const char *kernel_string; +} KernelCode; + +typedef struct { + const AVClass *class; + int log_offset; + void *log_ctx; + int init_count; + int opt_init_flag; + /** + * if set to 1, the OpenCL environment was created by the user and + * passed as AVOpenCLExternalEnv when initing ,0:created by opencl wrapper. + */ + int is_user_created; + int platform_idx; + int device_idx; + cl_platform_id platform_id; + cl_device_type device_type; + cl_context context; + cl_device_id device_id; + cl_command_queue command_queue; +#if FF_API_OLD_OPENCL + char *build_options; + int program_count; + cl_program programs[MAX_KERNEL_CODE_NUM]; + int kernel_count; +#endif + int kernel_code_count; + KernelCode kernel_code[MAX_KERNEL_CODE_NUM]; + AVOpenCLDeviceList device_list; +} OpenclContext; + +#define OFFSET(x) offsetof(OpenclContext, x) + +static const AVOption opencl_options[] = { + { "platform_idx", "set platform index value", OFFSET(platform_idx), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX}, + { "device_idx", "set device index value", OFFSET(device_idx), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX}, +#if FF_API_OLD_OPENCL + { "build_options", "build options of opencl", OFFSET(build_options), AV_OPT_TYPE_STRING, {.str="-I."}, CHAR_MIN, CHAR_MAX}, +#endif + { NULL } +}; + +static const AVClass openclutils_class = { + .class_name = "OPENCLUTILS", + .option = opencl_options, + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, + .log_level_offset_offset = offsetof(OpenclContext, log_offset), + .parent_log_context_offset = offsetof(OpenclContext, log_ctx), +}; + +static OpenclContext opencl_ctx = {&openclutils_class}; + +static const cl_device_type device_type[] = {CL_DEVICE_TYPE_GPU, CL_DEVICE_TYPE_CPU}; + +typedef struct { + int err_code; + const char *err_str; +} OpenclErrorMsg; + +static const OpenclErrorMsg opencl_err_msg[] = { + {CL_DEVICE_NOT_FOUND, "DEVICE NOT FOUND"}, + {CL_DEVICE_NOT_AVAILABLE, "DEVICE NOT AVAILABLE"}, + {CL_COMPILER_NOT_AVAILABLE, "COMPILER NOT AVAILABLE"}, + {CL_MEM_OBJECT_ALLOCATION_FAILURE, "MEM OBJECT ALLOCATION FAILURE"}, + {CL_OUT_OF_RESOURCES, "OUT OF RESOURCES"}, + {CL_OUT_OF_HOST_MEMORY, "OUT OF HOST MEMORY"}, + {CL_PROFILING_INFO_NOT_AVAILABLE, "PROFILING INFO NOT AVAILABLE"}, + {CL_MEM_COPY_OVERLAP, "MEM COPY OVERLAP"}, + {CL_IMAGE_FORMAT_MISMATCH, "IMAGE FORMAT MISMATCH"}, + {CL_IMAGE_FORMAT_NOT_SUPPORTED, "IMAGE FORMAT NOT_SUPPORTED"}, + {CL_BUILD_PROGRAM_FAILURE, "BUILD PROGRAM FAILURE"}, + {CL_MAP_FAILURE, "MAP FAILURE"}, + {CL_MISALIGNED_SUB_BUFFER_OFFSET, "MISALIGNED SUB BUFFER OFFSET"}, + {CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST, "EXEC STATUS ERROR FOR EVENTS IN WAIT LIST"}, + {CL_COMPILE_PROGRAM_FAILURE, "COMPILE PROGRAM FAILURE"}, + {CL_LINKER_NOT_AVAILABLE, "LINKER NOT AVAILABLE"}, + {CL_LINK_PROGRAM_FAILURE, "LINK PROGRAM FAILURE"}, + {CL_DEVICE_PARTITION_FAILED, "DEVICE PARTITION FAILED"}, + {CL_KERNEL_ARG_INFO_NOT_AVAILABLE, "KERNEL ARG INFO NOT AVAILABLE"}, + {CL_INVALID_VALUE, "INVALID VALUE"}, + {CL_INVALID_DEVICE_TYPE, "INVALID DEVICE TYPE"}, + {CL_INVALID_PLATFORM, "INVALID PLATFORM"}, + {CL_INVALID_DEVICE, "INVALID DEVICE"}, + {CL_INVALID_CONTEXT, "INVALID CONTEXT"}, + {CL_INVALID_QUEUE_PROPERTIES, "INVALID QUEUE PROPERTIES"}, + {CL_INVALID_COMMAND_QUEUE, "INVALID COMMAND QUEUE"}, + {CL_INVALID_HOST_PTR, "INVALID HOST PTR"}, + {CL_INVALID_MEM_OBJECT, "INVALID MEM OBJECT"}, + {CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, "INVALID IMAGE FORMAT DESCRIPTOR"}, + {CL_INVALID_IMAGE_SIZE, "INVALID IMAGE SIZE"}, + {CL_INVALID_SAMPLER, "INVALID SAMPLER"}, + {CL_INVALID_BINARY, "INVALID BINARY"}, + {CL_INVALID_BUILD_OPTIONS, "INVALID BUILD OPTIONS"}, + {CL_INVALID_PROGRAM, "INVALID PROGRAM"}, + {CL_INVALID_PROGRAM_EXECUTABLE, "INVALID PROGRAM EXECUTABLE"}, + {CL_INVALID_KERNEL_NAME, "INVALID KERNEL NAME"}, + {CL_INVALID_KERNEL_DEFINITION, "INVALID KERNEL DEFINITION"}, + {CL_INVALID_KERNEL, "INVALID KERNEL"}, + {CL_INVALID_ARG_INDEX, "INVALID ARG INDEX"}, + {CL_INVALID_ARG_VALUE, "INVALID ARG VALUE"}, + {CL_INVALID_ARG_SIZE, "INVALID ARG_SIZE"}, + {CL_INVALID_KERNEL_ARGS, "INVALID KERNEL ARGS"}, + {CL_INVALID_WORK_DIMENSION, "INVALID WORK DIMENSION"}, + {CL_INVALID_WORK_GROUP_SIZE, "INVALID WORK GROUP SIZE"}, + {CL_INVALID_WORK_ITEM_SIZE, "INVALID WORK ITEM SIZE"}, + {CL_INVALID_GLOBAL_OFFSET, "INVALID GLOBAL OFFSET"}, + {CL_INVALID_EVENT_WAIT_LIST, "INVALID EVENT WAIT LIST"}, + {CL_INVALID_EVENT, "INVALID EVENT"}, + {CL_INVALID_OPERATION, "INVALID OPERATION"}, + {CL_INVALID_GL_OBJECT, "INVALID GL OBJECT"}, + {CL_INVALID_BUFFER_SIZE, "INVALID BUFFER SIZE"}, + {CL_INVALID_MIP_LEVEL, "INVALID MIP LEVEL"}, + {CL_INVALID_GLOBAL_WORK_SIZE, "INVALID GLOBAL WORK SIZE"}, + {CL_INVALID_PROPERTY, "INVALID PROPERTY"}, + {CL_INVALID_IMAGE_DESCRIPTOR, "INVALID IMAGE DESCRIPTOR"}, + {CL_INVALID_COMPILER_OPTIONS, "INVALID COMPILER OPTIONS"}, + {CL_INVALID_LINKER_OPTIONS, "INVALID LINKER OPTIONS"}, + {CL_INVALID_DEVICE_PARTITION_COUNT, "INVALID DEVICE PARTITION COUNT"}, +}; + +const char *av_opencl_errstr(cl_int status) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(opencl_err_msg); i++) { + if (opencl_err_msg[i].err_code == status) + return opencl_err_msg[i].err_str; + } + return "unknown error"; +} + +static void free_device_list(AVOpenCLDeviceList *device_list) +{ + int i, j; + if (!device_list) + return; + for (i = 0; i < device_list->platform_num; i++) { + if (!device_list->platform_node[i]) + continue; + for (j = 0; j < device_list->platform_node[i]->device_num; j++) { + av_freep(&(device_list->platform_node[i]->device_node[j])); + } + av_freep(&device_list->platform_node[i]->device_node); + av_freep(&device_list->platform_node[i]); + } + av_freep(&device_list->platform_node); + device_list->platform_num = 0; +} + +static int get_device_list(AVOpenCLDeviceList *device_list) +{ + cl_int status; + int i, j, k, device_num, total_devices_num, ret = 0; + int *devices_num; + cl_platform_id *platform_ids = NULL; + cl_device_id *device_ids = NULL; + AVOpenCLDeviceNode *device_node = NULL; + status = clGetPlatformIDs(0, NULL, &device_list->platform_num); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not get OpenCL platform ids: %s\n", av_opencl_errstr(status)); + return AVERROR_EXTERNAL; + } + platform_ids = av_mallocz(device_list->platform_num * sizeof(cl_platform_id)); + if (!platform_ids) + return AVERROR(ENOMEM); + status = clGetPlatformIDs(device_list->platform_num, platform_ids, NULL); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not get OpenCL platform ids: %s\n", av_opencl_errstr(status)); + ret = AVERROR_EXTERNAL; + goto end; + } + device_list->platform_node = av_mallocz(device_list->platform_num * sizeof(AVOpenCLPlatformNode *)); + if (!device_list->platform_node) { + ret = AVERROR(ENOMEM); + goto end; + } + devices_num = av_mallocz(sizeof(int) * FF_ARRAY_ELEMS(device_type)); + if (!devices_num) { + ret = AVERROR(ENOMEM); + goto end; + } + for (i = 0; i < device_list->platform_num; i++) { + device_list->platform_node[i] = av_mallocz(sizeof(AVOpenCLPlatformNode)); + if (!device_list->platform_node[i]) { + ret = AVERROR(ENOMEM); + goto end; + } + device_list->platform_node[i]->platform_id = platform_ids[i]; + status = clGetPlatformInfo(platform_ids[i], CL_PLATFORM_VENDOR, + sizeof(device_list->platform_node[i]->platform_name), + device_list->platform_node[i]->platform_name, NULL); + total_devices_num = 0; + for (j = 0; j < FF_ARRAY_ELEMS(device_type); j++) { + status = clGetDeviceIDs(device_list->platform_node[i]->platform_id, + device_type[j], 0, NULL, &devices_num[j]); + total_devices_num += devices_num[j]; + } + device_list->platform_node[i]->device_node = av_mallocz(total_devices_num * sizeof(AVOpenCLDeviceNode *)); + if (!device_list->platform_node[i]->device_node) { + ret = AVERROR(ENOMEM); + goto end; + } + for (j = 0; j < FF_ARRAY_ELEMS(device_type); j++) { + if (devices_num[j]) { + device_ids = av_mallocz(devices_num[j] * sizeof(cl_device_id)); + if (!device_ids) { + ret = AVERROR(ENOMEM); + goto end; + } + status = clGetDeviceIDs(device_list->platform_node[i]->platform_id, device_type[j], + devices_num[j], device_ids, NULL); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_WARNING, + "Could not get device ID: %s:\n", av_opencl_errstr(status)); + av_freep(&device_ids); + continue; + } + for (k = 0; k < devices_num[j]; k++) { + device_num = device_list->platform_node[i]->device_num; + device_list->platform_node[i]->device_node[device_num] = av_mallocz(sizeof(AVOpenCLDeviceNode)); + if (!device_list->platform_node[i]->device_node[device_num]) { + ret = AVERROR(ENOMEM); + goto end; + } + device_node = device_list->platform_node[i]->device_node[device_num]; + device_node->device_id = device_ids[k]; + device_node->device_type = device_type[j]; + status = clGetDeviceInfo(device_node->device_id, CL_DEVICE_NAME, + sizeof(device_node->device_name), device_node->device_name, + NULL); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_WARNING, + "Could not get device name: %s\n", av_opencl_errstr(status)); + continue; + } + device_list->platform_node[i]->device_num++; + } + av_freep(&device_ids); + } + } + } +end: + av_freep(&platform_ids); + av_freep(&devices_num); + av_freep(&device_ids); + if (ret < 0) + free_device_list(device_list); + return ret; +} + +int av_opencl_get_device_list(AVOpenCLDeviceList **device_list) +{ + int ret = 0; + *device_list = av_mallocz(sizeof(AVOpenCLDeviceList)); + if (!(*device_list)) { + av_log(&opencl_ctx, AV_LOG_ERROR, "Could not allocate opencl device list\n"); + return AVERROR(ENOMEM); + } + ret = get_device_list(*device_list); + if (ret < 0) { + av_log(&opencl_ctx, AV_LOG_ERROR, "Could not get device list from environment\n"); + free_device_list(*device_list); + av_freep(device_list); + return ret; + } + return ret; +} + +void av_opencl_free_device_list(AVOpenCLDeviceList **device_list) +{ + free_device_list(*device_list); + av_freep(device_list); +} + +static inline int init_opencl_mtx(void) +{ +#if HAVE_THREADS + if (!atomic_opencl_lock) { + int err; + pthread_mutex_t *tmp = av_malloc(sizeof(pthread_mutex_t)); + if (!tmp) + return AVERROR(ENOMEM); + if ((err = pthread_mutex_init(tmp, NULL))) { + av_free(tmp); + return AVERROR(err); + } + if (avpriv_atomic_ptr_cas(&atomic_opencl_lock, NULL, tmp)) { + pthread_mutex_destroy(tmp); + av_free(tmp); + } + } +#endif + return 0; +} + +int av_opencl_set_option(const char *key, const char *val) +{ + int ret = init_opencl_mtx( ); + if (ret < 0) + return ret; + LOCK_OPENCL; + if (!opencl_ctx.opt_init_flag) { + av_opt_set_defaults(&opencl_ctx); + opencl_ctx.opt_init_flag = 1; + } + ret = av_opt_set(&opencl_ctx, key, val, 0); + UNLOCK_OPENCL; + return ret; +} + +int av_opencl_get_option(const char *key, uint8_t **out_val) +{ + int ret = 0; + LOCK_OPENCL; + ret = av_opt_get(&opencl_ctx, key, 0, out_val); + UNLOCK_OPENCL; + return ret; +} + +void av_opencl_free_option(void) +{ + /*FIXME: free openclutils context*/ + LOCK_OPENCL; + av_opt_free(&opencl_ctx); + UNLOCK_OPENCL; +} + +AVOpenCLExternalEnv *av_opencl_alloc_external_env(void) +{ + AVOpenCLExternalEnv *ext = av_mallocz(sizeof(AVOpenCLExternalEnv)); + if (!ext) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not malloc external opencl environment data space\n"); + } + return ext; +} + +void av_opencl_free_external_env(AVOpenCLExternalEnv **ext_opencl_env) +{ + av_freep(ext_opencl_env); +} + +int av_opencl_register_kernel_code(const char *kernel_code) +{ + int i, ret = init_opencl_mtx( ); + if (ret < 0) + return ret; + LOCK_OPENCL; + if (opencl_ctx.kernel_code_count >= MAX_KERNEL_CODE_NUM) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not register kernel code, maximum number of registered kernel code %d already reached\n", + MAX_KERNEL_CODE_NUM); + ret = AVERROR(EINVAL); + goto end; + } + for (i = 0; i < opencl_ctx.kernel_code_count; i++) { + if (opencl_ctx.kernel_code[i].kernel_string == kernel_code) { + av_log(&opencl_ctx, AV_LOG_WARNING, "Same kernel code has been registered\n"); + goto end; + } + } + opencl_ctx.kernel_code[opencl_ctx.kernel_code_count].kernel_string = kernel_code; + opencl_ctx.kernel_code[opencl_ctx.kernel_code_count].is_compiled = 0; + opencl_ctx.kernel_code_count++; +end: + UNLOCK_OPENCL; + return ret; +} + +cl_program av_opencl_compile(const char *program_name, const char *build_opts) +{ + int i; + cl_int status; + int kernel_code_idx = 0; + const char *kernel_source; + size_t kernel_code_len; + char* ptr = NULL; + cl_program program = NULL; + + LOCK_OPENCL; + for (i = 0; i < opencl_ctx.kernel_code_count; i++) { + // identify a program using a unique name within the kernel source + ptr = av_stristr(opencl_ctx.kernel_code[i].kernel_string, program_name); + if (ptr && !opencl_ctx.kernel_code[i].is_compiled) { + kernel_source = opencl_ctx.kernel_code[i].kernel_string; + kernel_code_len = strlen(opencl_ctx.kernel_code[i].kernel_string); + kernel_code_idx = i; + break; + } + } + if (!kernel_source) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Unable to find OpenCL kernel source '%s'\n", program_name); + goto end; + } + + /* create a CL program from kernel source */ + program = clCreateProgramWithSource(opencl_ctx.context, 1, &kernel_source, &kernel_code_len, &status); + if(status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Unable to create OpenCL program '%s': %s\n", program_name, av_opencl_errstr(status)); + program = NULL; + goto end; + } + status = clBuildProgram(program, 1, &(opencl_ctx.device_id), build_opts, NULL, NULL); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Compilation failed with OpenCL program: %s\n", program_name); + program = NULL; + goto end; + } + + opencl_ctx.kernel_code[kernel_code_idx].is_compiled = 1; +end: + UNLOCK_OPENCL; + return program; +} + +cl_command_queue av_opencl_get_command_queue(void) +{ + return opencl_ctx.command_queue; +} + +#if FF_API_OLD_OPENCL +int av_opencl_create_kernel(AVOpenCLKernelEnv *env, const char *kernel_name) +{ + av_log(&opencl_ctx, AV_LOG_ERROR, "Could not create OpenCL kernel %s, please update libavfilter.\n", kernel_name); + return AVERROR(EINVAL); +} + +void av_opencl_release_kernel(AVOpenCLKernelEnv *env) +{ + av_log(&opencl_ctx, AV_LOG_ERROR, "Could not release OpenCL kernel, please update libavfilter.\n"); +} +#endif + +static int init_opencl_env(OpenclContext *opencl_ctx, AVOpenCLExternalEnv *ext_opencl_env) +{ + cl_int status; + cl_context_properties cps[3]; + int i, ret = 0; + AVOpenCLDeviceNode *device_node = NULL; + + if (ext_opencl_env) { + if (opencl_ctx->is_user_created) + return 0; + opencl_ctx->platform_id = ext_opencl_env->platform_id; + opencl_ctx->is_user_created = 1; + opencl_ctx->command_queue = ext_opencl_env->command_queue; + opencl_ctx->context = ext_opencl_env->context; + opencl_ctx->device_id = ext_opencl_env->device_id; + opencl_ctx->device_type = ext_opencl_env->device_type; + } else { + if (!opencl_ctx->is_user_created) { + if (!opencl_ctx->device_list.platform_num) { + ret = get_device_list(&opencl_ctx->device_list); + if (ret < 0) { + return ret; + } + } + if (opencl_ctx->platform_idx >= 0) { + if (opencl_ctx->device_list.platform_num < opencl_ctx->platform_idx + 1) { + av_log(opencl_ctx, AV_LOG_ERROR, "User set platform index not exist\n"); + return AVERROR(EINVAL); + } + if (!opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->device_num) { + av_log(opencl_ctx, AV_LOG_ERROR, "No devices in user specific platform with index %d\n", + opencl_ctx->platform_idx); + return AVERROR(EINVAL); + } + opencl_ctx->platform_id = opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->platform_id; + } else { + /* get a usable platform by default*/ + for (i = 0; i < opencl_ctx->device_list.platform_num; i++) { + if (opencl_ctx->device_list.platform_node[i]->device_num) { + opencl_ctx->platform_id = opencl_ctx->device_list.platform_node[i]->platform_id; + opencl_ctx->platform_idx = i; + break; + } + } + } + if (!opencl_ctx->platform_id) { + av_log(opencl_ctx, AV_LOG_ERROR, "Could not get OpenCL platforms\n"); + return AVERROR_EXTERNAL; + } + /* get a usable device*/ + if (opencl_ctx->device_idx >= 0) { + if (opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->device_num < opencl_ctx->device_idx + 1) { + av_log(opencl_ctx, AV_LOG_ERROR, + "Could not get OpenCL device idx %d in the user set platform\n", opencl_ctx->platform_idx); + return AVERROR(EINVAL); + } + } else { + opencl_ctx->device_idx = 0; + } + + device_node = opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->device_node[opencl_ctx->device_idx]; + opencl_ctx->device_id = device_node->device_id; + opencl_ctx->device_type = device_node->device_type; + + /* + * Use available platform. + */ + av_log(opencl_ctx, AV_LOG_VERBOSE, "Platform Name: %s, Device Name: %s\n", + opencl_ctx->device_list.platform_node[opencl_ctx->platform_idx]->platform_name, + device_node->device_name); + cps[0] = CL_CONTEXT_PLATFORM; + cps[1] = (cl_context_properties)opencl_ctx->platform_id; + cps[2] = 0; + + opencl_ctx->context = clCreateContextFromType(cps, opencl_ctx->device_type, + NULL, NULL, &status); + if (status != CL_SUCCESS) { + av_log(opencl_ctx, AV_LOG_ERROR, + "Could not get OpenCL context from device type: %s\n", av_opencl_errstr(status)); + return AVERROR_EXTERNAL; + } + opencl_ctx->command_queue = clCreateCommandQueue(opencl_ctx->context, opencl_ctx->device_id, + 0, &status); + if (status != CL_SUCCESS) { + av_log(opencl_ctx, AV_LOG_ERROR, + "Could not create OpenCL command queue: %s\n", av_opencl_errstr(status)); + return AVERROR_EXTERNAL; + } + } + } + return ret; +} + +int av_opencl_init(AVOpenCLExternalEnv *ext_opencl_env) +{ + int ret = init_opencl_mtx( ); + if (ret < 0) + return ret; + LOCK_OPENCL; + if (!opencl_ctx.init_count) { + if (!opencl_ctx.opt_init_flag) { + av_opt_set_defaults(&opencl_ctx); + opencl_ctx.opt_init_flag = 1; + } + ret = init_opencl_env(&opencl_ctx, ext_opencl_env); + if (ret < 0) + goto end; + if (opencl_ctx.kernel_code_count <= 0) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "No kernel code is registered, compile kernel file failed\n"); + ret = AVERROR(EINVAL); + goto end; + } + } + opencl_ctx.init_count++; +end: + UNLOCK_OPENCL; + return ret; +} + +void av_opencl_uninit(void) +{ + cl_int status; + LOCK_OPENCL; + opencl_ctx.init_count--; + if (opencl_ctx.is_user_created) + goto end; + if (opencl_ctx.init_count > 0) + goto end; + if (opencl_ctx.command_queue) { + status = clReleaseCommandQueue(opencl_ctx.command_queue); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not release OpenCL command queue: %s\n", av_opencl_errstr(status)); + } + opencl_ctx.command_queue = NULL; + } + if (opencl_ctx.context) { + status = clReleaseContext(opencl_ctx.context); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not release OpenCL context: %s\n", av_opencl_errstr(status)); + } + opencl_ctx.context = NULL; + } + free_device_list(&opencl_ctx.device_list); +end: + if (opencl_ctx.init_count <= 0) + av_opt_free(&opencl_ctx); //FIXME: free openclutils context + UNLOCK_OPENCL; +} + +int av_opencl_buffer_create(cl_mem *cl_buf, size_t cl_buf_size, int flags, void *host_ptr) +{ + cl_int status; + *cl_buf = clCreateBuffer(opencl_ctx.context, flags, cl_buf_size, host_ptr, &status); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, "Could not create OpenCL buffer: %s\n", av_opencl_errstr(status)); + return AVERROR_EXTERNAL; + } + return 0; +} + +void av_opencl_buffer_release(cl_mem *cl_buf) +{ + cl_int status = 0; + if (!cl_buf) + return; + status = clReleaseMemObject(*cl_buf); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not release OpenCL buffer: %s\n", av_opencl_errstr(status)); + } + memset(cl_buf, 0, sizeof(*cl_buf)); +} + +int av_opencl_buffer_write(cl_mem dst_cl_buf, uint8_t *src_buf, size_t buf_size) +{ + cl_int status; + void *mapped = clEnqueueMapBuffer(opencl_ctx.command_queue, dst_cl_buf, + CL_TRUE, CL_MAP_WRITE, 0, sizeof(uint8_t) * buf_size, + 0, NULL, NULL, &status); + + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not map OpenCL buffer: %s\n", av_opencl_errstr(status)); + return AVERROR_EXTERNAL; + } + memcpy(mapped, src_buf, buf_size); + + status = clEnqueueUnmapMemObject(opencl_ctx.command_queue, dst_cl_buf, mapped, 0, NULL, NULL); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not unmap OpenCL buffer: %s\n", av_opencl_errstr(status)); + return AVERROR_EXTERNAL; + } + return 0; +} + +int av_opencl_buffer_read(uint8_t *dst_buf, cl_mem src_cl_buf, size_t buf_size) +{ + cl_int status; + void *mapped = clEnqueueMapBuffer(opencl_ctx.command_queue, src_cl_buf, + CL_TRUE, CL_MAP_READ, 0, buf_size, + 0, NULL, NULL, &status); + + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not map OpenCL buffer: %s\n", av_opencl_errstr(status)); + return AVERROR_EXTERNAL; + } + memcpy(dst_buf, mapped, buf_size); + + status = clEnqueueUnmapMemObject(opencl_ctx.command_queue, src_cl_buf, mapped, 0, NULL, NULL); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not unmap OpenCL buffer: %s\n", av_opencl_errstr(status)); + return AVERROR_EXTERNAL; + } + return 0; +} + +int av_opencl_buffer_write_image(cl_mem dst_cl_buf, size_t cl_buffer_size, int dst_cl_offset, + uint8_t **src_data, int *plane_size, int plane_num) +{ + int i, buffer_size = 0; + uint8_t *temp; + cl_int status; + void *mapped; + if ((unsigned int)plane_num > 8) { + return AVERROR(EINVAL); + } + for (i = 0;i < plane_num;i++) { + buffer_size += plane_size[i]; + } + if (buffer_size > cl_buffer_size) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Cannot write image to OpenCL buffer: buffer too small\n"); + return AVERROR(EINVAL); + } + mapped = clEnqueueMapBuffer(opencl_ctx.command_queue, dst_cl_buf, + CL_TRUE, CL_MAP_WRITE, 0, buffer_size + dst_cl_offset, + 0, NULL, NULL, &status); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not map OpenCL buffer: %s\n", av_opencl_errstr(status)); + return AVERROR_EXTERNAL; + } + temp = mapped; + temp += dst_cl_offset; + for (i = 0; i < plane_num; i++) { + memcpy(temp, src_data[i], plane_size[i]); + temp += plane_size[i]; + } + status = clEnqueueUnmapMemObject(opencl_ctx.command_queue, dst_cl_buf, mapped, 0, NULL, NULL); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not unmap OpenCL buffer: %s\n", av_opencl_errstr(status)); + return AVERROR_EXTERNAL; + } + return 0; +} + +int av_opencl_buffer_read_image(uint8_t **dst_data, int *plane_size, int plane_num, + cl_mem src_cl_buf, size_t cl_buffer_size) +{ + int i,buffer_size = 0,ret = 0; + uint8_t *temp; + void *mapped; + cl_int status; + if ((unsigned int)plane_num > 8) { + return AVERROR(EINVAL); + } + for (i = 0; i < plane_num; i++) { + buffer_size += plane_size[i]; + } + if (buffer_size > cl_buffer_size) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Cannot write image to CPU buffer: OpenCL buffer too small\n"); + return AVERROR(EINVAL); + } + mapped = clEnqueueMapBuffer(opencl_ctx.command_queue, src_cl_buf, + CL_TRUE, CL_MAP_READ, 0, buffer_size, + 0, NULL, NULL, &status); + + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not map OpenCL buffer: %s\n", av_opencl_errstr(status)); + return AVERROR_EXTERNAL; + } + temp = mapped; + if (ret >= 0) { + for (i = 0; i < plane_num; i++) { + memcpy(dst_data[i], temp, plane_size[i]); + temp += plane_size[i]; + } + } + status = clEnqueueUnmapMemObject(opencl_ctx.command_queue, src_cl_buf, mapped, 0, NULL, NULL); + if (status != CL_SUCCESS) { + av_log(&opencl_ctx, AV_LOG_ERROR, + "Could not unmap OpenCL buffer: %s\n", av_opencl_errstr(status)); + return AVERROR_EXTERNAL; + } + return 0; +} + +int64_t av_opencl_benchmark(AVOpenCLDeviceNode *device_node, cl_platform_id platform, + int64_t (*benchmark)(AVOpenCLExternalEnv *ext_opencl_env)) +{ + int64_t ret = 0; + cl_int status; + cl_context_properties cps[3]; + AVOpenCLExternalEnv *ext_opencl_env = NULL; + + ext_opencl_env = av_opencl_alloc_external_env(); + ext_opencl_env->device_id = device_node->device_id; + ext_opencl_env->device_type = device_node->device_type; + av_log(&opencl_ctx, AV_LOG_VERBOSE, "Performing test on OpenCL device %s\n", + device_node->device_name); + + cps[0] = CL_CONTEXT_PLATFORM; + cps[1] = (cl_context_properties)platform; + cps[2] = 0; + ext_opencl_env->context = clCreateContextFromType(cps, ext_opencl_env->device_type, + NULL, NULL, &status); + if (status != CL_SUCCESS || !ext_opencl_env->context) { + ret = AVERROR_EXTERNAL; + goto end; + } + ext_opencl_env->command_queue = clCreateCommandQueue(ext_opencl_env->context, + ext_opencl_env->device_id, 0, &status); + if (status != CL_SUCCESS || !ext_opencl_env->command_queue) { + ret = AVERROR_EXTERNAL; + goto end; + } + ret = benchmark(ext_opencl_env); + if (ret < 0) + av_log(&opencl_ctx, AV_LOG_ERROR, "Benchmark failed with OpenCL device %s\n", + device_node->device_name); +end: + if (ext_opencl_env->command_queue) + clReleaseCommandQueue(ext_opencl_env->command_queue); + if (ext_opencl_env->context) + clReleaseContext(ext_opencl_env->context); + av_opencl_free_external_env(&ext_opencl_env); + return ret; +} diff --git a/libavutil/opencl.h b/libavutil/opencl.h new file mode 100644 index 0000000000..9e6dc55ee8 --- /dev/null +++ b/libavutil/opencl.h @@ -0,0 +1,330 @@ +/* + * Copyright (C) 2012 Peng Gao <peng@multicorewareinc.com> + * Copyright (C) 2012 Li Cao <li@multicorewareinc.com> + * Copyright (C) 2012 Wei Gao <weigao@multicorewareinc.com> + * Copyright (C) 2013 Lenny Wang <lwanghpc@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 + * OpenCL wrapper + * + * This interface is considered still experimental and its API and ABI may + * change without prior notice. + */ + +#ifndef LIBAVUTIL_OPENCL_H +#define LIBAVUTIL_OPENCL_H + +#include "config.h" +#if HAVE_CL_CL_H +#include <CL/cl.h> +#else +#include <OpenCL/cl.h> +#endif +#include <stdint.h> +#include "dict.h" + +#include "libavutil/version.h" + +#define AV_OPENCL_KERNEL( ... )# __VA_ARGS__ + +#define AV_OPENCL_MAX_KERNEL_NAME_SIZE 150 + +#define AV_OPENCL_MAX_DEVICE_NAME_SIZE 100 + +#define AV_OPENCL_MAX_PLATFORM_NAME_SIZE 100 + +typedef struct { + int device_type; + char device_name[AV_OPENCL_MAX_DEVICE_NAME_SIZE]; + cl_device_id device_id; +} AVOpenCLDeviceNode; + +typedef struct { + cl_platform_id platform_id; + char platform_name[AV_OPENCL_MAX_PLATFORM_NAME_SIZE]; + int device_num; + AVOpenCLDeviceNode **device_node; +} AVOpenCLPlatformNode; + +typedef struct { + int platform_num; + AVOpenCLPlatformNode **platform_node; +} AVOpenCLDeviceList; + +#if FF_API_OLD_OPENCL +typedef struct { + cl_command_queue command_queue; + cl_kernel kernel; + char kernel_name[AV_OPENCL_MAX_KERNEL_NAME_SIZE]; +} AVOpenCLKernelEnv; +#endif + +typedef struct { + cl_platform_id platform_id; + cl_device_type device_type; + cl_context context; + cl_device_id device_id; + cl_command_queue command_queue; + char *platform_name; +} AVOpenCLExternalEnv; + +/** + * Get OpenCL device list. + * + * It must be freed with av_opencl_free_device_list(). + * + * @param device_list pointer to OpenCL environment device list, + * should be released by av_opencl_free_device_list() + * + * @return >=0 on success, a negative error code in case of failure + */ +int av_opencl_get_device_list(AVOpenCLDeviceList **device_list); + +/** + * Free OpenCL device list. + * + * @param device_list pointer to OpenCL environment device list + * created by av_opencl_get_device_list() + */ +void av_opencl_free_device_list(AVOpenCLDeviceList **device_list); + +/** + * Set option in the global OpenCL context. + * + * This options affect the operation performed by the next + * av_opencl_init() operation. + * + * The currently accepted options are: + * - platform: set index of platform in device list + * - device: set index of device in device list + * + * See reference "OpenCL Specification Version: 1.2 chapter 5.6.4". + * + * @param key option key + * @param val option value + * @return >=0 on success, a negative error code in case of failure + * @see av_opencl_get_option() + */ +int av_opencl_set_option(const char *key, const char *val); + +/** + * Get option value from the global OpenCL context. + * + * @param key option key + * @param out_val pointer to location where option value will be + * written, must be freed with av_freep() + * @return >=0 on success, a negative error code in case of failure + * @see av_opencl_set_option() + */ +int av_opencl_get_option(const char *key, uint8_t **out_val); + +/** + * Free option values of the global OpenCL context. + * + */ +void av_opencl_free_option(void); + +/** + * Allocate OpenCL external environment. + * + * It must be freed with av_opencl_free_external_env(). + * + * @return pointer to allocated OpenCL external environment + */ +AVOpenCLExternalEnv *av_opencl_alloc_external_env(void); + +/** + * Free OpenCL external environment. + * + * @param ext_opencl_env pointer to OpenCL external environment + * created by av_opencl_alloc_external_env() + */ +void av_opencl_free_external_env(AVOpenCLExternalEnv **ext_opencl_env); + +/** + * Get OpenCL error string. + * + * @param status OpenCL error code + * @return OpenCL error string + */ +const char *av_opencl_errstr(cl_int status); + +/** + * Register kernel code. + * + * The registered kernel code is stored in a global context, and compiled + * in the runtime environment when av_opencl_init() is called. + * + * @param kernel_code kernel code to be compiled in the OpenCL runtime environment + * @return >=0 on success, a negative error code in case of failure + */ +int av_opencl_register_kernel_code(const char *kernel_code); + +/** + * Initialize the run time OpenCL environment + * + * @param ext_opencl_env external OpenCL environment, created by an + * application program, ignored if set to NULL + * @return >=0 on success, a negative error code in case of failure + */ +int av_opencl_init(AVOpenCLExternalEnv *ext_opencl_env); + +#if FF_API_OLD_OPENCL +/** + * Create kernel object in the specified kernel environment. + * + * @param env pointer to kernel environment which is filled with + * the environment used to run the kernel + * @param kernel_name kernel function name + * @return >=0 on success, a negative error code in case of failure + * @deprecated, use clCreateKernel + */ +int av_opencl_create_kernel(AVOpenCLKernelEnv *env, const char *kernel_name); +#endif + +/** + * compile specific OpenCL kernel source + * + * @param program_name pointer to a program name used for identification + * @param build_opts pointer to a string that describes the preprocessor + * build options to be used for building the program + * @return a cl_program object + */ +cl_program av_opencl_compile(const char *program_name, const char* build_opts); + +/** + * get OpenCL command queue + * + * @return a cl_command_queue object + */ +cl_command_queue av_opencl_get_command_queue(void); + +/** + * Create OpenCL buffer. + * + * The buffer is used to save the data used or created by an OpenCL + * kernel. + * The created buffer must be released with av_opencl_buffer_release(). + * + * See clCreateBuffer() function reference for more information about + * the parameters. + * + * @param cl_buf pointer to OpenCL buffer + * @param cl_buf_size size in bytes of the OpenCL buffer to create + * @param flags flags used to control buffer attributes + * @param host_ptr host pointer of the OpenCL buffer + * @return >=0 on success, a negative error code in case of failure + */ +int av_opencl_buffer_create(cl_mem *cl_buf, size_t cl_buf_size, int flags, void *host_ptr); + +/** + * Write OpenCL buffer with data from src_buf. + * + * @param dst_cl_buf pointer to OpenCL destination buffer + * @param src_buf pointer to source buffer + * @param buf_size size in bytes of the source and destination buffers + * @return >=0 on success, a negative error code in case of failure + */ +int av_opencl_buffer_write(cl_mem dst_cl_buf, uint8_t *src_buf, size_t buf_size); + +/** + * Read data from OpenCL buffer to memory buffer. + * + * @param dst_buf pointer to destination buffer (CPU memory) + * @param src_cl_buf pointer to source OpenCL buffer + * @param buf_size size in bytes of the source and destination buffers + * @return >=0 on success, a negative error code in case of failure + */ +int av_opencl_buffer_read(uint8_t *dst_buf, cl_mem src_cl_buf, size_t buf_size); + +/** + * Write image data from memory to OpenCL buffer. + * + * The source must be an array of pointers to image plane buffers. + * + * @param dst_cl_buf pointer to destination OpenCL buffer + * @param dst_cl_buf_size size in bytes of OpenCL buffer + * @param dst_cl_buf_offset the offset of the OpenCL buffer start position + * @param src_data array of pointers to source plane buffers + * @param src_plane_sizes array of sizes in bytes of the source plane buffers + * @param src_plane_num number of source image planes + * @return >=0 on success, a negative error code in case of failure + */ +int av_opencl_buffer_write_image(cl_mem dst_cl_buf, size_t cl_buffer_size, int dst_cl_offset, + uint8_t **src_data, int *plane_size, int plane_num); + +/** + * Read image data from OpenCL buffer. + * + * @param dst_data array of pointers to destination plane buffers + * @param dst_plane_sizes array of pointers to destination plane buffers + * @param dst_plane_num number of destination image planes + * @param src_cl_buf pointer to source OpenCL buffer + * @param src_cl_buf_size size in bytes of OpenCL buffer + * @return >=0 on success, a negative error code in case of failure + */ +int av_opencl_buffer_read_image(uint8_t **dst_data, int *plane_size, int plane_num, + cl_mem src_cl_buf, size_t cl_buffer_size); + +/** + * Release OpenCL buffer. + * + * @param cl_buf pointer to OpenCL buffer to release, which was + * previously filled with av_opencl_buffer_create() + */ +void av_opencl_buffer_release(cl_mem *cl_buf); + +#if FF_API_OLD_OPENCL +/** + * Release kernel object. + * + * @param env kernel environment where the kernel object was created + * with av_opencl_create_kernel() + * @deprecated, use clReleaseKernel + */ +void av_opencl_release_kernel(AVOpenCLKernelEnv *env); +#endif + +/** + * Release OpenCL environment. + * + * The OpenCL environment is effectively released only if all the created + * kernels had been released with av_opencl_release_kernel(). + */ +void av_opencl_uninit(void); + +/** + * Benchmark an OpenCL device with a user defined callback function. This function + * sets up an external OpenCL environment including context and command queue on + * the device then tears it down in the end. The callback function should perform + * the rest of the work. + * + * @param device pointer to the OpenCL device to be used + * @param platform cl_platform_id handle to which the device belongs to + * @param benchmark callback function to perform the benchmark, return a + * negative value in case of failure + * @return the score passed from the callback function, a negative error code in case + * of failure + */ +int64_t av_opencl_benchmark(AVOpenCLDeviceNode *device, cl_platform_id platform, + int64_t (*benchmark)(AVOpenCLExternalEnv *ext_opencl_env)); + +#endif /* LIBAVUTIL_OPENCL_H */ diff --git a/libavutil/opencl_internal.c b/libavutil/opencl_internal.c new file mode 100644 index 0000000000..3d996ab006 --- /dev/null +++ b/libavutil/opencl_internal.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2012 Peng Gao <peng@multicorewareinc.com> + * Copyright (C) 2012 Li Cao <li@multicorewareinc.com> + * Copyright (C) 2012 Wei Gao <weigao@multicorewareinc.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 "opencl_internal.h" +#include "libavutil/log.h" + +int ff_opencl_set_parameter(FFOpenclParam *opencl_param, ...) +{ + int ret = 0; + va_list arg_ptr; + void *param; + size_t param_size; + cl_int status; + if (!opencl_param->kernel) { + av_log(opencl_param->ctx, AV_LOG_ERROR, "OpenCL kernel must be set\n"); + return AVERROR(EINVAL); + } + va_start(arg_ptr, opencl_param); + do { + param = va_arg(arg_ptr, void *); + if (!param) + break; + param_size = va_arg(arg_ptr, size_t); + if (!param_size) { + av_log(opencl_param->ctx, AV_LOG_ERROR, "Parameter size must not be 0\n"); + ret = AVERROR(EINVAL); + goto end; + } + status = clSetKernelArg(opencl_param->kernel, opencl_param->param_num, param_size, param); + if (status != CL_SUCCESS) { + av_log(opencl_param->ctx, AV_LOG_ERROR, "Cannot set kernel argument: %s\n", av_opencl_errstr(status)); + ret = AVERROR_EXTERNAL; + goto end; + } + opencl_param->param_num++; + } while (param && param_size); +end: + va_end(arg_ptr); + return ret; +} diff --git a/libavutil/opencl_internal.h b/libavutil/opencl_internal.h new file mode 100644 index 0000000000..34b39a0d6b --- /dev/null +++ b/libavutil/opencl_internal.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012 Peng Gao <peng@multicorewareinc.com> + * Copyright (C) 2012 Li Cao <li@multicorewareinc.com> + * Copyright (C) 2012 Wei Gao <weigao@multicorewareinc.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 "opencl.h" + +#define FF_OPENCL_PARAM_INFO(a) ((void*)(&(a))), (sizeof(a)) + +typedef struct { + cl_kernel kernel; + int param_num; + void *ctx; +} FFOpenclParam; + +int ff_opencl_set_parameter(FFOpenclParam *opencl_param, ...); diff --git a/libavutil/opt.c b/libavutil/opt.c index 9f9f1f2fe1..2a06eb6f39 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -2,20 +2,20 @@ * AVOptions * Copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -27,17 +27,44 @@ #include "avutil.h" #include "avstring.h" +#include "channel_layout.h" #include "common.h" #include "opt.h" #include "eval.h" #include "dict.h" #include "log.h" +#include "parseutils.h" +#include "pixdesc.h" #include "mathematics.h" +#include "samplefmt.h" + +#include <float.h> + +#if FF_API_FIND_OPT +//FIXME order them and do a bin search +const AVOption *av_find_opt(void *v, const char *name, const char *unit, int mask, int flags) +{ + const AVOption *o = NULL; + + while ((o = av_next_option(v, o))) { + if (!strcmp(o->name, name) && (!unit || (o->unit && !strcmp(o->unit, unit))) && (o->flags & mask) == flags) + return o; + } + return NULL; +} +#endif + +#if FF_API_OLD_AVOPTIONS +const AVOption *av_next_option(void *obj, const AVOption *last) +{ + return av_opt_next(obj, last); +} +#endif const AVOption *av_opt_next(void *obj, const AVOption *last) { AVClass *class = *(AVClass**)obj; - if (!last && class->option && class->option[0].name) + if (!last && class && class->option && class->option[0].name) return class->option; if (last && last[1].name) return ++last; @@ -48,13 +75,18 @@ static int read_number(const AVOption *o, void *dst, double *num, int *den, int6 { switch (o->type) { case AV_OPT_TYPE_FLAGS: *intnum = *(unsigned int*)dst;return 0; + case AV_OPT_TYPE_PIXEL_FMT: + case AV_OPT_TYPE_SAMPLE_FMT: case AV_OPT_TYPE_INT: *intnum = *(int *)dst;return 0; + case AV_OPT_TYPE_CHANNEL_LAYOUT: + case AV_OPT_TYPE_DURATION: case AV_OPT_TYPE_INT64: *intnum = *(int64_t *)dst;return 0; case AV_OPT_TYPE_FLOAT: *num = *(float *)dst;return 0; case AV_OPT_TYPE_DOUBLE: *num = *(double *)dst;return 0; case AV_OPT_TYPE_RATIONAL: *intnum = ((AVRational*)dst)->num; *den = ((AVRational*)dst)->den; return 0; + case AV_OPT_TYPE_CONST: *num = o->default_val.dbl; return 0; } return AVERROR(EINVAL); } @@ -63,14 +95,27 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int { if (o->type != AV_OPT_TYPE_FLAGS && (o->max * den < num * intnum || o->min * den > num * intnum)) { - av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range\n", - num*intnum/den, o->name); + av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range [%g - %g]\n", + num*intnum/den, o->name, o->min, o->max); return AVERROR(ERANGE); } + if (o->type == AV_OPT_TYPE_FLAGS) { + double d = num*intnum/den; + if (d < -1.5 || d > 0xFFFFFFFF+0.5 || (llrint(d*256) & 255)) { + av_log(obj, AV_LOG_ERROR, + "Value %f for parameter '%s' is not a valid set of 32bit integer flags\n", + num*intnum/den, o->name); + return AVERROR(ERANGE); + } + } switch (o->type) { case AV_OPT_TYPE_FLAGS: + case AV_OPT_TYPE_PIXEL_FMT: + case AV_OPT_TYPE_SAMPLE_FMT: case AV_OPT_TYPE_INT: *(int *)dst= llrint(num/den)*intnum; break; + case AV_OPT_TYPE_DURATION: + case AV_OPT_TYPE_CHANNEL_LAYOUT: case AV_OPT_TYPE_INT64: *(int64_t *)dst= llrint(num/den)*intnum; break; case AV_OPT_TYPE_FLOAT: *(float *)dst= num*intnum/den; break; case AV_OPT_TYPE_DOUBLE:*(double *)dst= num*intnum/den; break; @@ -84,20 +129,6 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int return 0; } -static const double const_values[] = { - M_PI, - M_E, - FF_QP2LAMBDA, - 0 -}; - -static const char * const const_names[] = { - "PI", - "E", - "QP2LAMBDA", - 0 -}; - static int hexchar2int(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; @@ -149,37 +180,69 @@ static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **d static int set_string_number(void *obj, void *target_obj, const AVOption *o, const char *val, void *dst) { - int ret = 0, notfirst = 0; + int ret = 0; + int num, den; + char c; + + if (sscanf(val, "%d%*1[:/]%d%c", &num, &den, &c) == 2) { + if ((ret = write_number(obj, o, dst, 1, den, num)) >= 0) + return ret; + ret = 0; + } + for (;;) { - int i, den = 1; + int i = 0; char buf[256]; int cmd = 0; - double d, num = 1; + double d; int64_t intnum = 1; - i = 0; - if (*val == '+' || *val == '-') { - if (o->type == AV_OPT_TYPE_FLAGS) + if (o->type == AV_OPT_TYPE_FLAGS) { + if (*val == '+' || *val == '-') cmd = *(val++); - else if (!notfirst) - buf[i++] = *val; + for (; i < sizeof(buf) - 1 && val[i] && val[i] != '+' && val[i] != '-'; i++) + buf[i] = val[i]; + buf[i] = 0; } - for (; i < sizeof(buf) - 1 && val[i] && val[i] != '+' && val[i] != '-'; i++) - buf[i] = val[i]; - buf[i] = 0; - { - const AVOption *o_named = av_opt_find(target_obj, buf, o->unit, 0, 0); + const AVOption *o_named = av_opt_find(target_obj, i ? buf : val, o->unit, 0, 0); + int res; + int ci = 0; + double const_values[64]; + const char * const_names[64]; if (o_named && o_named->type == AV_OPT_TYPE_CONST) d = DEFAULT_NUMVAL(o_named); - else if (!strcmp(buf, "default")) d = DEFAULT_NUMVAL(o); - else if (!strcmp(buf, "max" )) d = o->max; - else if (!strcmp(buf, "min" )) d = o->min; - else if (!strcmp(buf, "none" )) d = 0; - else if (!strcmp(buf, "all" )) d = ~0; else { - int res = av_expr_parse_and_eval(&d, buf, const_names, const_values, NULL, NULL, NULL, NULL, NULL, 0, obj); + if (o->unit) { + for (o_named = NULL; o_named = av_opt_next(target_obj, o_named); ) { + if (o_named->type == AV_OPT_TYPE_CONST && + o_named->unit && + !strcmp(o_named->unit, o->unit)) { + if (ci + 6 >= FF_ARRAY_ELEMS(const_values)) { + av_log(obj, AV_LOG_ERROR, "const_values array too small for %s\n", o->unit); + return AVERROR_PATCHWELCOME; + } + const_names [ci ] = o_named->name; + const_values[ci++] = DEFAULT_NUMVAL(o_named); + } + } + } + const_names [ci ] = "default"; + const_values[ci++] = DEFAULT_NUMVAL(o); + const_names [ci ] = "max"; + const_values[ci++] = o->max; + const_names [ci ] = "min"; + const_values[ci++] = o->min; + const_names [ci ] = "none"; + const_values[ci++] = 0; + const_names [ci ] = "all"; + const_values[ci++] = ~0; + const_names [ci] = NULL; + const_values[ci] = 0; + + res = av_expr_parse_and_eval(&d, i ? buf : val, const_names, + const_values, NULL, NULL, NULL, NULL, NULL, 0, obj); if (res < 0) { av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\"\n", val); return res; @@ -190,30 +253,138 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con read_number(o, dst, NULL, NULL, &intnum); if (cmd == '+') d = intnum | (int64_t)d; else if (cmd == '-') d = intnum &~(int64_t)d; - } else { - read_number(o, dst, &num, &den, &intnum); - if (cmd == '+') d = notfirst*num*intnum/den + d; - else if (cmd == '-') d = notfirst*num*intnum/den - d; } if ((ret = write_number(obj, o, dst, d, 1, 1)) < 0) return ret; val += i; - if (!*val) + if (!i || !*val) return 0; - notfirst = 1; } return 0; } +static int set_string_image_size(void *obj, const AVOption *o, const char *val, int *dst) +{ + int ret; + + if (!val || !strcmp(val, "none")) { + dst[0] = + dst[1] = 0; + return 0; + } + ret = av_parse_video_size(dst, dst + 1, val); + if (ret < 0) + av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as image size\n", val); + return ret; +} + +static int set_string_video_rate(void *obj, const AVOption *o, const char *val, AVRational *dst) +{ + int ret; + if (!val) { + ret = AVERROR(EINVAL); + } else { + ret = av_parse_video_rate(dst, val); + } + if (ret < 0) + av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as video rate\n", val); + return ret; +} + +static int set_string_color(void *obj, const AVOption *o, const char *val, uint8_t *dst) +{ + int ret; + + if (!val) { + return 0; + } else { + ret = av_parse_color(dst, val, -1, obj); + if (ret < 0) + av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as color\n", val); + return ret; + } + return 0; +} + +static int set_string_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst, + int fmt_nb, int ((*get_fmt)(const char *)), const char *desc) +{ + int fmt, min, max; + + if (!val || !strcmp(val, "none")) { + fmt = -1; + } else { + fmt = get_fmt(val); + if (fmt == -1) { + char *tail; + fmt = strtol(val, &tail, 0); + if (*tail || (unsigned)fmt >= fmt_nb) { + av_log(obj, AV_LOG_ERROR, + "Unable to parse option value \"%s\" as %s\n", val, desc); + return AVERROR(EINVAL); + } + } + } + + min = FFMAX(o->min, -1); + max = FFMIN(o->max, fmt_nb-1); + + // hack for compatibility with old ffmpeg + if(min == 0 && max == 0) { + min = -1; + max = fmt_nb-1; + } + + if (fmt < min || fmt > max) { + av_log(obj, AV_LOG_ERROR, + "Value %d for parameter '%s' out of %s format range [%d - %d]\n", + fmt, o->name, desc, min, max); + return AVERROR(ERANGE); + } + + *(int *)dst = fmt; + return 0; +} + +static int set_string_pixel_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst) +{ + return set_string_fmt(obj, o, val, dst, + AV_PIX_FMT_NB, av_get_pix_fmt, "pixel format"); +} + +static int set_string_sample_fmt(void *obj, const AVOption *o, const char *val, uint8_t *dst) +{ + return set_string_fmt(obj, o, val, dst, + AV_SAMPLE_FMT_NB, av_get_sample_fmt, "sample format"); +} + +#if FF_API_OLD_AVOPTIONS +int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out) +{ + const AVOption *o = av_opt_find(obj, name, NULL, 0, 0); + if (o_out) + *o_out = o; + return av_opt_set(obj, name, val, 0); +} +#endif + int av_opt_set(void *obj, const char *name, const char *val, int search_flags) { + int ret = 0; void *dst, *target_obj; const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); if (!o || !target_obj) return AVERROR_OPTION_NOT_FOUND; - if (!val || o->flags & AV_OPT_FLAG_READONLY) + if (!val && (o->type != AV_OPT_TYPE_STRING && + o->type != AV_OPT_TYPE_PIXEL_FMT && o->type != AV_OPT_TYPE_SAMPLE_FMT && + o->type != AV_OPT_TYPE_IMAGE_SIZE && o->type != AV_OPT_TYPE_VIDEO_RATE && + o->type != AV_OPT_TYPE_DURATION && o->type != AV_OPT_TYPE_COLOR && + o->type != AV_OPT_TYPE_CHANNEL_LAYOUT)) + return AVERROR(EINVAL); + + if (o->flags & AV_OPT_FLAG_READONLY) return AVERROR(EINVAL); dst = ((uint8_t*)target_obj) + o->offset; @@ -226,6 +397,38 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags) case AV_OPT_TYPE_FLOAT: case AV_OPT_TYPE_DOUBLE: case AV_OPT_TYPE_RATIONAL: return set_string_number(obj, target_obj, o, val, dst); + case AV_OPT_TYPE_IMAGE_SIZE: return set_string_image_size(obj, o, val, dst); + case AV_OPT_TYPE_VIDEO_RATE: return set_string_video_rate(obj, o, val, dst); + case AV_OPT_TYPE_PIXEL_FMT: return set_string_pixel_fmt(obj, o, val, dst); + case AV_OPT_TYPE_SAMPLE_FMT: return set_string_sample_fmt(obj, o, val, dst); + case AV_OPT_TYPE_DURATION: + if (!val) { + *(int64_t *)dst = 0; + return 0; + } else { + if ((ret = av_parse_time(dst, val, 1)) < 0) + av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as duration\n", val); + return ret; + } + break; + case AV_OPT_TYPE_COLOR: return set_string_color(obj, o, val, dst); + case AV_OPT_TYPE_CHANNEL_LAYOUT: + if (!val || !strcmp(val, "none")) { + *(int64_t *)dst = 0; + } else { +#if FF_API_GET_CHANNEL_LAYOUT_COMPAT + int64_t cl = ff_get_channel_layout(val, 0); +#else + int64_t cl = av_get_channel_layout(val); +#endif + if (!cl) { + av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as channel layout\n", val); + ret = AVERROR(EINVAL); + } + *(int64_t *)dst = cl; + return ret; + } + break; } av_log(obj, AV_LOG_ERROR, "Invalid option type.\n"); @@ -263,6 +466,32 @@ static int set_number(void *obj, const char *name, double num, int den, int64_t return write_number(obj, o, dst, num, den, intnum); } +#if FF_API_OLD_AVOPTIONS +const AVOption *av_set_double(void *obj, const char *name, double n) +{ + const AVOption *o = av_opt_find(obj, name, NULL, 0, 0); + if (set_number(obj, name, n, 1, 1, 0) < 0) + return NULL; + return o; +} + +const AVOption *av_set_q(void *obj, const char *name, AVRational n) +{ + const AVOption *o = av_opt_find(obj, name, NULL, 0, 0); + if (set_number(obj, name, n.num, n.den, 1, 0) < 0) + return NULL; + return o; +} + +const AVOption *av_set_int(void *obj, const char *name, int64_t n) +{ + const AVOption *o = av_opt_find(obj, name, NULL, 0, 0); + if (set_number(obj, name, 1, 1, n, 0) < 0) + return NULL; + return o; +} +#endif + int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags) { return set_number(obj, name, 1, 1, val, search_flags); @@ -292,8 +521,8 @@ int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int if (o->type != AV_OPT_TYPE_BINARY || o->flags & AV_OPT_FLAG_READONLY) return AVERROR(EINVAL); - ptr = av_malloc(len); - if (!ptr) + ptr = len ? av_malloc(len) : NULL; + if (len && !ptr) return AVERROR(ENOMEM); dst = (uint8_t **)(((uint8_t *)target_obj) + o->offset); @@ -302,19 +531,164 @@ int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int av_free(*dst); *dst = ptr; *lendst = len; - memcpy(ptr, val, len); + if (len) + memcpy(ptr, val, len); + + return 0; +} + +int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags) +{ + void *target_obj; + const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); + + if (!o || !target_obj) + return AVERROR_OPTION_NOT_FOUND; + if (o->type != AV_OPT_TYPE_IMAGE_SIZE) { + av_log(obj, AV_LOG_ERROR, + "The value set by option '%s' is not an image size.\n", o->name); + return AVERROR(EINVAL); + } + if (w<0 || h<0) { + av_log(obj, AV_LOG_ERROR, + "Invalid negative size value %dx%d for size '%s'\n", w, h, o->name); + return AVERROR(EINVAL); + } + *(int *)(((uint8_t *)target_obj) + o->offset) = w; + *(int *)(((uint8_t *)target_obj+sizeof(int)) + o->offset) = h; + return 0; +} + +int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags) +{ + void *target_obj; + const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); + + if (!o || !target_obj) + return AVERROR_OPTION_NOT_FOUND; + if (o->type != AV_OPT_TYPE_VIDEO_RATE) { + av_log(obj, AV_LOG_ERROR, + "The value set by option '%s' is not a video rate.\n", o->name); + return AVERROR(EINVAL); + } + if (val.num <= 0 || val.den <= 0) + return AVERROR(EINVAL); + return set_number(obj, name, val.num, val.den, 1, search_flags); +} + +static int set_format(void *obj, const char *name, int fmt, int search_flags, + enum AVOptionType type, const char *desc, int nb_fmts) +{ + void *target_obj; + const AVOption *o = av_opt_find2(obj, name, NULL, 0, + search_flags, &target_obj); + int min, max; + const AVClass *class = *(AVClass **)obj; + + if (!o || !target_obj) + return AVERROR_OPTION_NOT_FOUND; + if (o->type != type) { + av_log(obj, AV_LOG_ERROR, + "The value set by option '%s' is not a %s format", name, desc); + return AVERROR(EINVAL); + } +#if LIBAVUTIL_VERSION_MAJOR < 54 + if (class->version && class->version < AV_VERSION_INT(52, 11, 100)) { + min = -1; + max = nb_fmts-1; + } else +#endif + { + min = FFMAX(o->min, -1); + max = FFMIN(o->max, nb_fmts-1); + } + if (fmt < min || fmt > max) { + av_log(obj, AV_LOG_ERROR, + "Value %d for parameter '%s' out of %s format range [%d - %d]\n", + fmt, name, desc, min, max); + return AVERROR(ERANGE); + } + *(int *)(((uint8_t *)target_obj) + o->offset) = fmt; return 0; } +int av_opt_set_pixel_fmt(void *obj, const char *name, enum AVPixelFormat fmt, int search_flags) +{ + return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_PIXEL_FMT, "pixel", AV_PIX_FMT_NB); +} + +int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags) +{ + return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_SAMPLE_FMT, "sample", AV_SAMPLE_FMT_NB); +} + +int av_opt_set_channel_layout(void *obj, const char *name, int64_t cl, int search_flags) +{ + void *target_obj; + const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); + + if (!o || !target_obj) + return AVERROR_OPTION_NOT_FOUND; + if (o->type != AV_OPT_TYPE_CHANNEL_LAYOUT) { + av_log(obj, AV_LOG_ERROR, + "The value set by option '%s' is not a channel layout.\n", o->name); + return AVERROR(EINVAL); + } + *(int *)(((int64_t *)target_obj) + o->offset) = cl; + return 0; +} + +#if FF_API_OLD_AVOPTIONS +/** + * + * @param buf a buffer which is used for returning non string values as strings, can be NULL + * @param buf_len allocated length in bytes of buf + */ +const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len) +{ + const AVOption *o = av_opt_find(obj, name, NULL, 0, AV_OPT_SEARCH_CHILDREN); + void *dst; + uint8_t *bin; + int len, i; + if (!o) + return NULL; + if (o->type != AV_OPT_TYPE_STRING && (!buf || !buf_len)) + return NULL; + + dst= ((uint8_t*)obj) + o->offset; + if (o_out) *o_out= o; + + switch (o->type) { + case AV_OPT_TYPE_FLAGS: snprintf(buf, buf_len, "0x%08X",*(int *)dst);break; + case AV_OPT_TYPE_INT: snprintf(buf, buf_len, "%d" , *(int *)dst);break; + case AV_OPT_TYPE_INT64: snprintf(buf, buf_len, "%"PRId64, *(int64_t*)dst);break; + case AV_OPT_TYPE_FLOAT: snprintf(buf, buf_len, "%f" , *(float *)dst);break; + case AV_OPT_TYPE_DOUBLE: snprintf(buf, buf_len, "%f" , *(double *)dst);break; + case AV_OPT_TYPE_RATIONAL: snprintf(buf, buf_len, "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break; + case AV_OPT_TYPE_CONST: snprintf(buf, buf_len, "%f" , o->default_val.dbl);break; + case AV_OPT_TYPE_STRING: return *(void**)dst; + case AV_OPT_TYPE_BINARY: + len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *)); + if (len >= (buf_len + 1)/2) return NULL; + bin = *(uint8_t**)dst; + for (i = 0; i < len; i++) snprintf(buf + i*2, 3, "%02X", bin[i]); + break; + default: return NULL; + } + return buf; +} +#endif + int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val) { void *dst, *target_obj; const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); uint8_t *bin, buf[128]; int len, i, ret; + int64_t i64; - if (!o || !target_obj) + if (!o || !target_obj || (o->offset<=0 && o->type != AV_OPT_TYPE_CONST)) return AVERROR_OPTION_NOT_FOUND; dst = (uint8_t*)target_obj + o->offset; @@ -326,7 +700,9 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val) case AV_OPT_TYPE_INT64: ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t*)dst);break; case AV_OPT_TYPE_FLOAT: ret = snprintf(buf, sizeof(buf), "%f" , *(float *)dst);break; case AV_OPT_TYPE_DOUBLE: ret = snprintf(buf, sizeof(buf), "%f" , *(double *)dst);break; + case AV_OPT_TYPE_VIDEO_RATE: case AV_OPT_TYPE_RATIONAL: ret = snprintf(buf, sizeof(buf), "%d/%d", ((AVRational*)dst)->num, ((AVRational*)dst)->den);break; + case AV_OPT_TYPE_CONST: ret = snprintf(buf, sizeof(buf), "%f" , o->default_val.dbl);break; case AV_OPT_TYPE_STRING: if (*(uint8_t**)dst) *out_val = av_strdup(*(uint8_t**)dst); @@ -343,6 +719,28 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val) for (i = 0; i < len; i++) snprintf(*out_val + i*2, 3, "%02X", bin[i]); return 0; + case AV_OPT_TYPE_IMAGE_SIZE: + ret = snprintf(buf, sizeof(buf), "%dx%d", ((int *)dst)[0], ((int *)dst)[1]); + break; + case AV_OPT_TYPE_PIXEL_FMT: + ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_pix_fmt_name(*(enum AVPixelFormat *)dst), "none")); + break; + case AV_OPT_TYPE_SAMPLE_FMT: + ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(av_get_sample_fmt_name(*(enum AVSampleFormat *)dst), "none")); + break; + case AV_OPT_TYPE_DURATION: + i64 = *(int64_t *)dst; + ret = snprintf(buf, sizeof(buf), "%"PRIi64"d:%02d:%02d.%06d", + i64 / 3600000000, (int)((i64 / 60000000) % 60), + (int)((i64 / 1000000) % 60), (int)(i64 % 1000000)); + break; + case AV_OPT_TYPE_COLOR: + ret = snprintf(buf, sizeof(buf), "0x%02x%02x%02x%02x", ((int *)dst)[0], ((int *)dst)[1], ((int *)dst)[2], ((int *)dst)[3]); + break; + case AV_OPT_TYPE_CHANNEL_LAYOUT: + i64 = *(int64_t *)dst; + ret = snprintf(buf, sizeof(buf), "0x%"PRIx64, i64); + break; default: return AVERROR(EINVAL); } @@ -353,7 +751,7 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val) return 0; } -static int get_number(void *obj, const char *name, double *num, int *den, int64_t *intnum, +static int get_number(void *obj, const char *name, const AVOption **o_out, double *num, int *den, int64_t *intnum, int search_flags) { void *dst, *target_obj; @@ -363,6 +761,8 @@ static int get_number(void *obj, const char *name, double *num, int *den, int64_ dst = ((uint8_t*)target_obj) + o->offset; + if (o_out) *o_out= o; + return read_number(o, dst, num, den, intnum); error: @@ -370,13 +770,51 @@ error: return -1; } +#if FF_API_OLD_AVOPTIONS +double av_get_double(void *obj, const char *name, const AVOption **o_out) +{ + int64_t intnum=1; + double num=1; + int den=1; + + if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0) + return NAN; + return num*intnum/den; +} + +AVRational av_get_q(void *obj, const char *name, const AVOption **o_out) +{ + int64_t intnum=1; + double num=1; + int den=1; + + if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0) + return (AVRational){0, 0}; + if (num == 1.0 && (int)intnum == intnum) + return (AVRational){intnum, den}; + else + return av_d2q(num*intnum/den, 1<<24); +} + +int64_t av_get_int(void *obj, const char *name, const AVOption **o_out) +{ + int64_t intnum=1; + double num=1; + int den=1; + + if (get_number(obj, name, o_out, &num, &den, &intnum, 0) < 0) + return -1; + return num*intnum/den; +} +#endif + int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_val) { int64_t intnum = 1; double num = 1; int ret, den = 1; - if ((ret = get_number(obj, name, &num, &den, &intnum, search_flags)) < 0) + if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) return ret; *out_val = num*intnum/den; return 0; @@ -388,7 +826,7 @@ int av_opt_get_double(void *obj, const char *name, int search_flags, double *out double num = 1; int ret, den = 1; - if ((ret = get_number(obj, name, &num, &den, &intnum, search_flags)) < 0) + if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) return ret; *out_val = num*intnum/den; return 0; @@ -400,7 +838,41 @@ int av_opt_get_q(void *obj, const char *name, int search_flags, AVRational *out_ double num = 1; int ret, den = 1; - if ((ret = get_number(obj, name, &num, &den, &intnum, search_flags)) < 0) + if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) + return ret; + + if (num == 1.0 && (int)intnum == intnum) + *out_val = (AVRational){intnum, den}; + else + *out_val = av_d2q(num*intnum/den, 1<<24); + return 0; +} + +int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out) +{ + void *dst, *target_obj; + const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); + if (!o || !target_obj) + return AVERROR_OPTION_NOT_FOUND; + if (o->type != AV_OPT_TYPE_IMAGE_SIZE) { + av_log(obj, AV_LOG_ERROR, + "The value for option '%s' is not an image size.\n", name); + return AVERROR(EINVAL); + } + + dst = ((uint8_t*)target_obj) + o->offset; + if (w_out) *w_out = *(int *)dst; + if (h_out) *h_out = *((int *)dst+1); + return 0; +} + +int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val) +{ + int64_t intnum = 1; + double num = 1; + int ret, den = 1; + + if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) return ret; if (num == 1.0 && (int)intnum == intnum) @@ -410,6 +882,51 @@ int av_opt_get_q(void *obj, const char *name, int search_flags, AVRational *out_ return 0; } +static int get_format(void *obj, const char *name, int search_flags, int *out_fmt, + enum AVOptionType type, const char *desc) +{ + void *dst, *target_obj; + const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); + if (!o || !target_obj) + return AVERROR_OPTION_NOT_FOUND; + if (o->type != type) { + av_log(obj, AV_LOG_ERROR, + "The value for option '%s' is not a %s format.\n", desc, name); + return AVERROR(EINVAL); + } + + dst = ((uint8_t*)target_obj) + o->offset; + *out_fmt = *(int *)dst; + return 0; +} + +int av_opt_get_pixel_fmt(void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt) +{ + return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_PIXEL_FMT, "pixel"); +} + +int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt) +{ + return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_SAMPLE_FMT, "sample"); +} + +int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *cl) +{ + void *dst, *target_obj; + const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); + if (!o || !target_obj) + return AVERROR_OPTION_NOT_FOUND; + if (o->type != AV_OPT_TYPE_CHANNEL_LAYOUT) { + av_log(obj, AV_LOG_ERROR, + "The value for option '%s' is not a channel layout.\n", name); + return AVERROR(EINVAL); + } + + dst = ((uint8_t*)target_obj) + o->offset; + *cl = *(int64_t *)dst; + return 0; +} + int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name) { const AVOption *field = av_opt_find(obj, field_name, NULL, 0, 0); @@ -423,10 +940,45 @@ int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name) return res & flag->default_val.i64; } +static void log_value(void *av_log_obj, int level, double d) +{ + if (d == INT_MAX) { + av_log(av_log_obj, level, "INT_MAX"); + } else if (d == INT_MIN) { + av_log(av_log_obj, level, "INT_MIN"); + } else if (d == UINT32_MAX) { + av_log(av_log_obj, level, "UINT32_MAX"); + } else if (d == (double)INT64_MAX) { + av_log(av_log_obj, level, "I64_MAX"); + } else if (d == INT64_MIN) { + av_log(av_log_obj, level, "I64_MIN"); + } else if (d == FLT_MAX) { + av_log(av_log_obj, level, "FLT_MAX"); + } else if (d == FLT_MIN) { + av_log(av_log_obj, level, "FLT_MIN"); + } else if (d == -FLT_MAX) { + av_log(av_log_obj, level, "-FLT_MAX"); + } else if (d == -FLT_MIN) { + av_log(av_log_obj, level, "-FLT_MIN"); + } else if (d == DBL_MAX) { + av_log(av_log_obj, level, "DBL_MAX"); + } else if (d == DBL_MIN) { + av_log(av_log_obj, level, "DBL_MIN"); + } else if (d == -DBL_MAX) { + av_log(av_log_obj, level, "-DBL_MAX"); + } else if (d == -DBL_MIN) { + av_log(av_log_obj, level, "-DBL_MIN"); + } else { + av_log(av_log_obj, level, "%g", d); + } +} + static void opt_list(void *obj, void *av_log_obj, const char *unit, int req_flags, int rej_flags) { const AVOption *opt=NULL; + AVOptionRanges *r; + int i; while ((opt = av_opt_next(obj, opt))) { if (!(opt->flags & req_flags) || (opt->flags & rej_flags)) @@ -443,42 +995,66 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit, else if (unit && opt->type==AV_OPT_TYPE_CONST && strcmp(unit, opt->unit)) continue; else if (unit && opt->type == AV_OPT_TYPE_CONST) - av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name); + av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name); else - av_log(av_log_obj, AV_LOG_INFO, "-%-17s ", opt->name); + av_log(av_log_obj, AV_LOG_INFO, " %s%-17s ", + (opt->flags & AV_OPT_FLAG_FILTERING_PARAM) ? "" : "-", + opt->name); switch (opt->type) { case AV_OPT_TYPE_FLAGS: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<flags>"); + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<flags>"); break; case AV_OPT_TYPE_INT: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<int>"); + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<int>"); break; case AV_OPT_TYPE_INT64: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<int64>"); + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<int64>"); break; case AV_OPT_TYPE_DOUBLE: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<double>"); + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<double>"); break; case AV_OPT_TYPE_FLOAT: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<float>"); + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<float>"); break; case AV_OPT_TYPE_STRING: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<string>"); + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<string>"); break; case AV_OPT_TYPE_RATIONAL: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<rational>"); + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<rational>"); break; case AV_OPT_TYPE_BINARY: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", "<binary>"); + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<binary>"); + break; + case AV_OPT_TYPE_IMAGE_SIZE: + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<image_size>"); + break; + case AV_OPT_TYPE_VIDEO_RATE: + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<video_rate>"); + break; + case AV_OPT_TYPE_PIXEL_FMT: + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<pix_fmt>"); + break; + case AV_OPT_TYPE_SAMPLE_FMT: + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<sample_fmt>"); + break; + case AV_OPT_TYPE_DURATION: + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<duration>"); + break; + case AV_OPT_TYPE_COLOR: + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<color>"); + break; + case AV_OPT_TYPE_CHANNEL_LAYOUT: + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", "<channel_layout>"); break; case AV_OPT_TYPE_CONST: default: - av_log(av_log_obj, AV_LOG_INFO, "%-7s ", ""); + av_log(av_log_obj, AV_LOG_INFO, "%-12s ", ""); break; } av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_ENCODING_PARAM) ? 'E' : '.'); av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_DECODING_PARAM) ? 'D' : '.'); + av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_FILTERING_PARAM)? 'F' : '.'); av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_VIDEO_PARAM ) ? 'V' : '.'); av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_AUDIO_PARAM ) ? 'A' : '.'); av_log(av_log_obj, AV_LOG_INFO, "%c", (opt->flags & AV_OPT_FLAG_SUBTITLE_PARAM) ? 'S' : '.'); @@ -487,6 +1063,70 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit, if (opt->help) av_log(av_log_obj, AV_LOG_INFO, " %s", opt->help); + + if (av_opt_query_ranges(&r, obj, opt->name, AV_OPT_SEARCH_FAKE_OBJ) >= 0) { + switch (opt->type) { + case AV_OPT_TYPE_INT: + case AV_OPT_TYPE_INT64: + case AV_OPT_TYPE_DOUBLE: + case AV_OPT_TYPE_FLOAT: + case AV_OPT_TYPE_RATIONAL: + for (i = 0; i < r->nb_ranges; i++) { + av_log(av_log_obj, AV_LOG_INFO, " (from "); + log_value(av_log_obj, AV_LOG_INFO, r->range[i]->value_min); + av_log(av_log_obj, AV_LOG_INFO, " to "); + log_value(av_log_obj, AV_LOG_INFO, r->range[i]->value_max); + av_log(av_log_obj, AV_LOG_INFO, ")"); + } + break; + } + av_opt_freep_ranges(&r); + } + + if (opt->type != AV_OPT_TYPE_CONST && + opt->type != AV_OPT_TYPE_BINARY && + !((opt->type == AV_OPT_TYPE_COLOR || + opt->type == AV_OPT_TYPE_IMAGE_SIZE || + opt->type == AV_OPT_TYPE_STRING || + opt->type == AV_OPT_TYPE_VIDEO_RATE) && + !opt->default_val.str)) { + av_log(av_log_obj, AV_LOG_INFO, " (default "); + switch (opt->type) { + case AV_OPT_TYPE_FLAGS: + av_log(av_log_obj, AV_LOG_INFO, "%"PRIX64, opt->default_val.i64); + break; + case AV_OPT_TYPE_DURATION: + case AV_OPT_TYPE_INT: + case AV_OPT_TYPE_INT64: + log_value(av_log_obj, AV_LOG_INFO, opt->default_val.i64); + break; + case AV_OPT_TYPE_DOUBLE: + case AV_OPT_TYPE_FLOAT: + log_value(av_log_obj, AV_LOG_INFO, opt->default_val.dbl); + break; + case AV_OPT_TYPE_RATIONAL: { + AVRational q = av_d2q(opt->default_val.dbl, INT_MAX); + av_log(av_log_obj, AV_LOG_INFO, "%d/%d", q.num, q.den); } + break; + case AV_OPT_TYPE_PIXEL_FMT: + av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_pix_fmt_name(opt->default_val.i64), "none")); + break; + case AV_OPT_TYPE_SAMPLE_FMT: + av_log(av_log_obj, AV_LOG_INFO, "%s", (char *)av_x_if_null(av_get_sample_fmt_name(opt->default_val.i64), "none")); + break; + case AV_OPT_TYPE_COLOR: + case AV_OPT_TYPE_IMAGE_SIZE: + case AV_OPT_TYPE_STRING: + case AV_OPT_TYPE_VIDEO_RATE: + av_log(av_log_obj, AV_LOG_INFO, "\"%s\"", opt->default_val.str); + break; + case AV_OPT_TYPE_CHANNEL_LAYOUT: + av_log(av_log_obj, AV_LOG_INFO, "0x%"PRIx64, opt->default_val.i64); + break; + } + av_log(av_log_obj, AV_LOG_INFO, ")"); + } + av_log(av_log_obj, AV_LOG_INFO, "\n"); if (opt->unit && opt->type != AV_OPT_TYPE_CONST) { opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags); @@ -508,8 +1148,22 @@ int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags) void av_opt_set_defaults(void *s) { +#if FF_API_OLD_AVOPTIONS + av_opt_set_defaults2(s, 0, 0); +} + +void av_opt_set_defaults2(void *s, int mask, int flags) +{ +#endif + const AVClass *class = *(AVClass **)s; const AVOption *opt = NULL; while ((opt = av_opt_next(s, opt)) != NULL) { + void *dst = ((uint8_t*)s) + opt->offset; +#if FF_API_OLD_AVOPTIONS + if ((opt->flags & mask) != flags) + continue; +#endif + if (opt->flags & AV_OPT_FLAG_READONLY) continue; @@ -520,23 +1174,50 @@ void av_opt_set_defaults(void *s) case AV_OPT_TYPE_FLAGS: case AV_OPT_TYPE_INT: case AV_OPT_TYPE_INT64: - av_opt_set_int(s, opt->name, opt->default_val.i64, 0); + case AV_OPT_TYPE_DURATION: + case AV_OPT_TYPE_CHANNEL_LAYOUT: + write_number(s, opt, dst, 1, 1, opt->default_val.i64); break; case AV_OPT_TYPE_DOUBLE: case AV_OPT_TYPE_FLOAT: { double val; val = opt->default_val.dbl; - av_opt_set_double(s, opt->name, val, 0); + write_number(s, opt, dst, val, 1, 1); } break; case AV_OPT_TYPE_RATIONAL: { AVRational val; val = av_d2q(opt->default_val.dbl, INT_MAX); - av_opt_set_q(s, opt->name, val, 0); + write_number(s, opt, dst, 1, val.den, val.num); } break; + case AV_OPT_TYPE_COLOR: + set_string_color(s, opt, opt->default_val.str, dst); + break; case AV_OPT_TYPE_STRING: - av_opt_set(s, opt->name, opt->default_val.str, 0); + set_string(s, opt, opt->default_val.str, dst); + break; + case AV_OPT_TYPE_IMAGE_SIZE: + set_string_image_size(s, opt, opt->default_val.str, dst); + break; + case AV_OPT_TYPE_VIDEO_RATE: + set_string_video_rate(s, opt, opt->default_val.str, dst); + break; + case AV_OPT_TYPE_PIXEL_FMT: +#if LIBAVUTIL_VERSION_MAJOR < 54 + if (class->version && class->version < AV_VERSION_INT(52, 10, 100)) + av_opt_set(s, opt->name, opt->default_val.str, 0); + else +#endif + write_number(s, opt, dst, 1, 1, opt->default_val.i64); + break; + case AV_OPT_TYPE_SAMPLE_FMT: +#if LIBAVUTIL_VERSION_MAJOR < 54 + if (class->version && class->version < AV_VERSION_INT(52, 10, 100)) + av_opt_set(s, opt->name, opt->default_val.str, 0); + else +#endif + write_number(s, opt, dst, 1, 1, opt->default_val.i64); break; case AV_OPT_TYPE_BINARY: /* Cannot set default for binary */ @@ -587,7 +1268,7 @@ static int parse_key_value_pair(void *ctx, const char **buf, return AVERROR(EINVAL); } - av_log(ctx, AV_LOG_DEBUG, "Setting value '%s' for key '%s'\n", val, key); + av_log(ctx, AV_LOG_DEBUG, "Setting entry with key '%s' to value '%s'\n", key, val); ret = av_opt_set(ctx, key, val, AV_OPT_SEARCH_CHILDREN); if (ret == AVERROR_OPTION_NOT_FOUND) @@ -618,6 +1299,118 @@ int av_set_options_string(void *ctx, const char *opts, return count; } +#define WHITESPACES " \n\t" + +static int is_key_char(char c) +{ + return (unsigned)((c | 32) - 'a') < 26 || + (unsigned)(c - '0') < 10 || + c == '-' || c == '_' || c == '/' || c == '.'; +} + +/** + * Read a key from a string. + * + * The key consists of is_key_char characters and must be terminated by a + * character from the delim string; spaces are ignored. + * + * @return 0 for success (even with ellipsis), <0 for failure + */ +static int get_key(const char **ropts, const char *delim, char **rkey) +{ + const char *opts = *ropts; + const char *key_start, *key_end; + + key_start = opts += strspn(opts, WHITESPACES); + while (is_key_char(*opts)) + opts++; + key_end = opts; + opts += strspn(opts, WHITESPACES); + if (!*opts || !strchr(delim, *opts)) + return AVERROR(EINVAL); + opts++; + if (!(*rkey = av_malloc(key_end - key_start + 1))) + return AVERROR(ENOMEM); + memcpy(*rkey, key_start, key_end - key_start); + (*rkey)[key_end - key_start] = 0; + *ropts = opts; + return 0; +} + +int av_opt_get_key_value(const char **ropts, + const char *key_val_sep, const char *pairs_sep, + unsigned flags, + char **rkey, char **rval) +{ + int ret; + char *key = NULL, *val; + const char *opts = *ropts; + + if ((ret = get_key(&opts, key_val_sep, &key)) < 0 && + !(flags & AV_OPT_FLAG_IMPLICIT_KEY)) + return AVERROR(EINVAL); + if (!(val = av_get_token(&opts, pairs_sep))) { + av_free(key); + return AVERROR(ENOMEM); + } + *ropts = opts; + *rkey = key; + *rval = val; + return 0; +} + +int av_opt_set_from_string(void *ctx, const char *opts, + const char *const *shorthand, + const char *key_val_sep, const char *pairs_sep) +{ + int ret, count = 0; + const char *dummy_shorthand = NULL; + char *av_uninit(parsed_key), *av_uninit(value); + const char *key; + + if (!opts) + return 0; + if (!shorthand) + shorthand = &dummy_shorthand; + + while (*opts) { + ret = av_opt_get_key_value(&opts, key_val_sep, pairs_sep, + *shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0, + &parsed_key, &value); + if (ret < 0) { + if (ret == AVERROR(EINVAL)) + av_log(ctx, AV_LOG_ERROR, "No option name near '%s'\n", opts); + else + av_log(ctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", opts, + av_err2str(ret)); + return ret; + } + if (*opts) + opts++; + if (parsed_key) { + key = parsed_key; + while (*shorthand) /* discard all remaining shorthand */ + shorthand++; + } else { + key = *(shorthand++); + } + + av_log(ctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value); + if ((ret = av_opt_set(ctx, key, value, 0)) < 0) { + if (ret == AVERROR_OPTION_NOT_FOUND) + av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key); + av_free(value); + av_free(parsed_key); + return ret; + } + + av_free(value); + av_free(parsed_key); + count++; + } + return count; +} + void av_opt_free(void *obj) { const AVOption *o = NULL; @@ -626,14 +1419,17 @@ void av_opt_free(void *obj) av_freep((uint8_t *)obj + o->offset); } -int av_opt_set_dict(void *obj, AVDictionary **options) +int av_opt_set_dict2(void *obj, AVDictionary **options, int search_flags) { AVDictionaryEntry *t = NULL; AVDictionary *tmp = NULL; int ret = 0; + if (!options) + return 0; + while ((t = av_dict_get(*options, "", t, AV_DICT_IGNORE_SUFFIX))) { - ret = av_opt_set(obj, t->key, t->value, 0); + ret = av_opt_set(obj, t->key, t->value, search_flags); if (ret == AVERROR_OPTION_NOT_FOUND) av_dict_set(&tmp, t->key, t->value, 0); else if (ret < 0) { @@ -647,6 +1443,11 @@ int av_opt_set_dict(void *obj, AVDictionary **options) return ret; } +int av_opt_set_dict(void *obj, AVDictionary **options) +{ + return av_opt_set_dict2(obj, options, 0); +} + const AVOption *av_opt_find(void *obj, const char *name, const char *unit, int opt_flags, int search_flags) { @@ -656,9 +1457,14 @@ const AVOption *av_opt_find(void *obj, const char *name, const char *unit, const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, int opt_flags, int search_flags, void **target_obj) { - const AVClass *c = *(AVClass**)obj; + const AVClass *c; const AVOption *o = NULL; + if(!obj) + return NULL; + + c= *(AVClass**)obj; + if (!c) return NULL; @@ -679,7 +1485,7 @@ const AVOption *av_opt_find2(void *obj, const char *name, const char *unit, while (o = av_opt_next(obj, o)) { if (!strcmp(o->name, name) && (o->flags & opt_flags) == opt_flags && ((!unit && o->type != AV_OPT_TYPE_CONST) || - (unit && o->unit && !strcmp(o->unit, unit)))) { + (unit && o->type == AV_OPT_TYPE_CONST && o->unit && !strcmp(o->unit, unit)))) { if (target_obj) { if (!(search_flags & AV_OPT_SEARCH_FAKE_OBJ)) *target_obj = obj; @@ -707,6 +1513,190 @@ const AVClass *av_opt_child_class_next(const AVClass *parent, const AVClass *pre return NULL; } +void *av_opt_ptr(const AVClass *class, void *obj, const char *name) +{ + const AVOption *opt= av_opt_find2(&class, name, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ, NULL); + if(!opt) + return NULL; + return (uint8_t*)obj + opt->offset; +} + +static int opt_size(enum AVOptionType type) +{ + switch(type) { + case AV_OPT_TYPE_INT: + case AV_OPT_TYPE_FLAGS: return sizeof(int); + case AV_OPT_TYPE_DURATION: + case AV_OPT_TYPE_CHANNEL_LAYOUT: + case AV_OPT_TYPE_INT64: return sizeof(int64_t); + case AV_OPT_TYPE_DOUBLE: return sizeof(double); + case AV_OPT_TYPE_FLOAT: return sizeof(float); + case AV_OPT_TYPE_STRING: return sizeof(uint8_t*); + case AV_OPT_TYPE_VIDEO_RATE: + case AV_OPT_TYPE_RATIONAL: return sizeof(AVRational); + case AV_OPT_TYPE_BINARY: return sizeof(uint8_t*) + sizeof(int); + case AV_OPT_TYPE_IMAGE_SIZE:return sizeof(int[2]); + case AV_OPT_TYPE_PIXEL_FMT: return sizeof(enum AVPixelFormat); + case AV_OPT_TYPE_SAMPLE_FMT:return sizeof(enum AVSampleFormat); + case AV_OPT_TYPE_COLOR: return 4; + } + return 0; +} + +int av_opt_copy(void *dst, void *src) +{ + const AVOption *o = NULL; + const AVClass *c; + int ret = 0; + + if (!src) + return 0; + + c = *(AVClass**)src; + if (*(AVClass**)dst && c != *(AVClass**)dst) + return AVERROR(EINVAL); + + while ((o = av_opt_next(src, o))) { + void *field_dst = ((uint8_t*)dst) + o->offset; + void *field_src = ((uint8_t*)src) + o->offset; + uint8_t **field_dst8 = (uint8_t**)field_dst; + uint8_t **field_src8 = (uint8_t**)field_src; + + if (o->type == AV_OPT_TYPE_STRING) { + if (*field_dst8 != *field_src8) + av_freep(field_dst8); + *field_dst8 = av_strdup(*field_src8); + if (*field_src8 && !*field_dst8) + ret = AVERROR(ENOMEM); + } else if (o->type == AV_OPT_TYPE_BINARY) { + int len = *(int*)(field_src8 + 1); + if (*field_dst8 != *field_src8) + av_freep(field_dst8); + *field_dst8 = av_memdup(*field_src8, len); + if (len && !*field_dst8) { + ret = AVERROR(ENOMEM); + len = 0; + } + *(int*)(field_dst8 + 1) = len; + } else if (o->type == AV_OPT_TYPE_CONST) { + // do nothing + } else { + memcpy(field_dst, field_src, opt_size(o->type)); + } + } + return ret; +} + +int av_opt_query_ranges(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags) +{ + int ret; + const AVClass *c = *(AVClass**)obj; + int (*callback)(AVOptionRanges **, void *obj, const char *key, int flags) = NULL; + + if (c->version > (52 << 16 | 11 << 8)) + callback = c->query_ranges; + + if (!callback) + callback = av_opt_query_ranges_default; + + ret = callback(ranges_arg, obj, key, flags); + if (ret >= 0) { + if (!(flags & AV_OPT_MULTI_COMPONENT_RANGE)) + ret = 1; + (*ranges_arg)->nb_components = ret; + } + return ret; +} + +int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const char *key, int flags) +{ + AVOptionRanges *ranges = av_mallocz(sizeof(*ranges)); + AVOptionRange **range_array = av_mallocz(sizeof(void*)); + AVOptionRange *range = av_mallocz(sizeof(*range)); + const AVOption *field = av_opt_find(obj, key, NULL, 0, flags); + int ret; + + *ranges_arg = NULL; + + if (!ranges || !range || !range_array || !field) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ranges->range = range_array; + ranges->range[0] = range; + ranges->nb_ranges = 1; + ranges->nb_components = 1; + range->is_range = 1; + range->value_min = field->min; + range->value_max = field->max; + + switch (field->type) { + case AV_OPT_TYPE_INT: + case AV_OPT_TYPE_INT64: + case AV_OPT_TYPE_PIXEL_FMT: + case AV_OPT_TYPE_SAMPLE_FMT: + case AV_OPT_TYPE_FLOAT: + case AV_OPT_TYPE_DOUBLE: + case AV_OPT_TYPE_DURATION: + case AV_OPT_TYPE_COLOR: + case AV_OPT_TYPE_CHANNEL_LAYOUT: + break; + case AV_OPT_TYPE_STRING: + range->component_min = 0; + range->component_max = 0x10FFFF; // max unicode value + range->value_min = -1; + range->value_max = INT_MAX; + break; + case AV_OPT_TYPE_RATIONAL: + range->component_min = INT_MIN; + range->component_max = INT_MAX; + break; + case AV_OPT_TYPE_IMAGE_SIZE: + range->component_min = 0; + range->component_max = INT_MAX/128/8; + range->value_min = 0; + range->value_max = INT_MAX/8; + break; + case AV_OPT_TYPE_VIDEO_RATE: + range->component_min = 1; + range->component_max = INT_MAX; + range->value_min = 1; + range->value_max = INT_MAX; + break; + default: + ret = AVERROR(ENOSYS); + goto fail; + } + + *ranges_arg = ranges; + return 1; +fail: + av_free(ranges); + av_free(range); + av_free(range_array); + return ret; +} + +void av_opt_freep_ranges(AVOptionRanges **rangesp) +{ + int i; + AVOptionRanges *ranges = *rangesp; + + if (!ranges) + return; + + for (i = 0; i < ranges->nb_ranges * ranges->nb_components; i++) { + AVOptionRange *range = ranges->range[i]; + if (range) { + av_freep(&range->str); + av_freep(&ranges->range[i]); + } + } + av_freep(&ranges->range); + av_freep(rangesp); +} + #ifdef TEST typedef struct TestContext @@ -717,6 +1707,13 @@ typedef struct TestContext char *string; int flags; AVRational rational; + AVRational video_rate; + int w, h; + enum AVPixelFormat pix_fmt; + enum AVSampleFormat sample_fmt; + int64_t duration; + uint8_t color[4]; + int64_t channel_layout; } TestContext; #define OFFSET(x) offsetof(TestContext, x) @@ -728,12 +1725,19 @@ typedef struct TestContext static const AVOption test_options[]= { {"num", "set num", OFFSET(num), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 100 }, {"toggle", "set toggle", OFFSET(toggle), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1 }, -{"rational", "set rational", OFFSET(rational), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, 10 }, -{"string", "set string", OFFSET(string), AV_OPT_TYPE_STRING, {0}, CHAR_MIN, CHAR_MAX }, +{"rational", "set rational", OFFSET(rational), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, 10 }, +{"string", "set string", OFFSET(string), AV_OPT_TYPE_STRING, {.str = "default"}, CHAR_MIN, CHAR_MAX }, {"flags", "set flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, INT_MAX, 0, "flags" }, {"cool", "set cool flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_COOL}, INT_MIN, INT_MAX, 0, "flags" }, {"lame", "set lame flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_LAME}, INT_MIN, INT_MAX, 0, "flags" }, {"mu", "set mu flag ", 0, AV_OPT_TYPE_CONST, {.i64 = TEST_FLAG_MU}, INT_MIN, INT_MAX, 0, "flags" }, +{"size", "set size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE,{0}, 0, 0 }, +{"pix_fmt", "set pixfmt", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, -1, INT_MAX}, +{"sample_fmt", "set samplefmt", OFFSET(sample_fmt), AV_OPT_TYPE_SAMPLE_FMT, {.i64 = AV_SAMPLE_FMT_NONE}, -1, INT_MAX}, +{"video_rate", "set videorate", OFFSET(video_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0 }, +{"duration", "set duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX}, +{"color", "set color", OFFSET(color), AV_OPT_TYPE_COLOR, {.str = "pink"}, 0, 0}, +{"cl", "set channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64 = AV_CH_LAYOUT_HEXAGONAL}, 0, INT64_MAX}, {NULL}, }; @@ -754,8 +1758,8 @@ int main(void) printf("\nTesting av_set_options_string()\n"); { - TestContext test_ctx; - const char *options[] = { + TestContext test_ctx = { 0 }; + static const char * const options[] = { "", ":", "=", @@ -775,11 +1779,32 @@ int main(void) "num=42 : string=blahblah", "rational=0 : rational=1/2 : rational=1/-1", "rational=-1/0", + "size=1024x768", + "size=pal", + "size=bogus", + "pix_fmt=yuv420p", + "pix_fmt=2", + "pix_fmt=bogus", + "sample_fmt=s16", + "sample_fmt=2", + "sample_fmt=bogus", + "video_rate=pal", + "video_rate=25", + "video_rate=30000/1001", + "video_rate=30/1.001", + "video_rate=bogus", + "duration=bogus", + "duration=123.45", + "duration=1\\:23\\:45.67", + "color=blue", + "color=0x223300", + "color=0x42FF07AA", + "cl=stereo+downmix", + "cl=foo", }; test_ctx.class = &test_class; av_opt_set_defaults(&test_ctx); - test_ctx.string = av_strdup("default"); av_log_set_level(AV_LOG_DEBUG); @@ -789,6 +1814,37 @@ int main(void) av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]); printf("\n"); } + av_opt_free(&test_ctx); + } + + printf("\nTesting av_opt_set_from_string()\n"); + { + TestContext test_ctx = { 0 }; + static const char * const options[] = { + "", + "5", + "5:hello", + "5:hello:size=pal", + "5:size=pal:hello", + ":", + "=", + " 5 : hello : size = pal ", + "a_very_long_option_name_that_will_need_to_be_ellipsized_around_here=42" + }; + static const char * const shorthand[] = { "num", "string", NULL }; + + test_ctx.class = &test_class; + av_opt_set_defaults(&test_ctx); + + av_log_set_level(AV_LOG_DEBUG); + + for (i=0; i < FF_ARRAY_ELEMS(options); i++) { + av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]); + if (av_opt_set_from_string(&test_ctx, options[i], shorthand, "=", ":") < 0) + av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]); + printf("\n"); + } + av_opt_free(&test_ctx); } return 0; diff --git a/libavutil/opt.h b/libavutil/opt.h index b90feaad8f..7705990210 100644 --- a/libavutil/opt.h +++ b/libavutil/opt.h @@ -2,20 +2,20 @@ * AVOptions * copyright (c) 2005 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -31,6 +31,8 @@ #include "avutil.h" #include "dict.h" #include "log.h" +#include "pixfmt.h" +#include "samplefmt.h" /** * @defgroup avoptions AVOptions @@ -44,7 +46,7 @@ * This section describes how to add AVOptions capabilities to a struct. * * All AVOptions-related information is stored in an AVClass. Therefore - * the first member of the struct must be a pointer to an AVClass describing it. + * the first member of the struct should be a pointer to an AVClass describing it. * The option field of the AVClass must be set to a NULL-terminated static array * of AVOptions. Each AVOption must have a non-empty name, a type, a default * value and for number-type AVOptions also a range of allowed values. It must @@ -81,7 +83,7 @@ * @endcode * * Next, when allocating your struct, you must ensure that the AVClass pointer - * is set to the correct value. Then, av_opt_set_defaults() must be called to + * is set to the correct value. Then, av_opt_set_defaults() can be called to * initialize defaults. After that the struct is ready to be used with the * AVOptions API. * @@ -161,7 +163,7 @@ * * @subsection avoptions_implement_named_constants Named constants * It is possible to create named constants for options. Simply set the unit - * field of the option the constants should apply to to a string and + * field of the option the constants should apply to a string and * create the constants themselves as options of type AV_OPT_TYPE_CONST * with their unit field set to the same string. * Their default_val field should contain the value of the named @@ -176,7 +178,7 @@ * * @section avoptions_use Using AVOptions * This section deals with accessing options in an AVOptions-enabled struct. - * Such structs in Libav are e.g. AVCodecContext in libavcodec or + * Such structs in FFmpeg are e.g. AVCodecContext in libavcodec or * AVFormatContext in libavformat. * * @subsection avoptions_use_examine Examining AVOptions @@ -225,6 +227,24 @@ enum AVOptionType{ AV_OPT_TYPE_RATIONAL, AV_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length AV_OPT_TYPE_CONST = 128, + AV_OPT_TYPE_IMAGE_SIZE = MKBETAG('S','I','Z','E'), ///< offset must point to two consecutive integers + AV_OPT_TYPE_PIXEL_FMT = MKBETAG('P','F','M','T'), + AV_OPT_TYPE_SAMPLE_FMT = MKBETAG('S','F','M','T'), + AV_OPT_TYPE_VIDEO_RATE = MKBETAG('V','R','A','T'), ///< offset must point to AVRational + AV_OPT_TYPE_DURATION = MKBETAG('D','U','R',' '), + AV_OPT_TYPE_COLOR = MKBETAG('C','O','L','R'), + AV_OPT_TYPE_CHANNEL_LAYOUT = MKBETAG('C','H','L','A'), +#if FF_API_OLD_AVOPTIONS + FF_OPT_TYPE_FLAGS = 0, + FF_OPT_TYPE_INT, + FF_OPT_TYPE_INT64, + FF_OPT_TYPE_DOUBLE, + FF_OPT_TYPE_FLOAT, + FF_OPT_TYPE_STRING, + FF_OPT_TYPE_RATIONAL, + FF_OPT_TYPE_BINARY, ///< offset must point to a pointer immediately followed by an int for the length + FF_OPT_TYPE_CONST=128, +#endif }; /** @@ -277,6 +297,7 @@ typedef struct AVOption { * This flag only makes sense when AV_OPT_FLAG_EXPORT is also set. */ #define AV_OPT_FLAG_READONLY 128 +#define AV_OPT_FLAG_FILTERING_PARAM (1<<16) ///< a generic parameter which can be set by the user for filtering //FIXME think about enc-audio, ... style flags /** @@ -288,6 +309,135 @@ typedef struct AVOption { } AVOption; /** + * A single allowed range of values, or a single allowed value. + */ +typedef struct AVOptionRange { + const char *str; + /** + * Value range. + * For string ranges this represents the min/max length. + * For dimensions this represents the min/max pixel count or width/height in multi-component case. + */ + double value_min, value_max; + /** + * Value's component range. + * For string this represents the unicode range for chars, 0-127 limits to ASCII. + */ + double component_min, component_max; + /** + * Range flag. + * If set to 1 the struct encodes a range, if set to 0 a single value. + */ + int is_range; +} AVOptionRange; + +/** + * List of AVOptionRange structs. + */ +typedef struct AVOptionRanges { + /** + * Array of option ranges. + * + * Most of option types use just one component. + * Following describes multi-component option types: + * + * AV_OPT_TYPE_IMAGE_SIZE: + * component index 0: range of pixel count (width * height). + * component index 1: range of width. + * component index 2: range of height. + * + * @note To obtain multi-component version of this structure, user must + * provide AV_OPT_MULTI_COMPONENT_RANGE to av_opt_query_ranges or + * av_opt_query_ranges_default function. + * + * Multi-component range can be read as in following example: + * + * @code + * int range_index, component_index; + * AVOptionRanges *ranges; + * AVOptionRange *range[3]; //may require more than 3 in the future. + * av_opt_query_ranges(&ranges, obj, key, AV_OPT_MULTI_COMPONENT_RANGE); + * for (range_index = 0; range_index < ranges->nb_ranges; range_index++) { + * for (component_index = 0; component_index < ranges->nb_components; component_index++) + * range[component_index] = ranges->range[ranges->nb_ranges * component_index + range_index]; + * //do something with range here. + * } + * av_opt_freep_ranges(&ranges); + * @endcode + */ + AVOptionRange **range; + /** + * Number of ranges per component. + */ + int nb_ranges; + /** + * Number of componentes. + */ + int nb_components; +} AVOptionRanges; + + +#if FF_API_FIND_OPT +/** + * Look for an option in obj. Look only for the options which + * have the flags set as specified in mask and flags (that is, + * for which it is the case that (opt->flags & mask) == flags). + * + * @param[in] obj a pointer to a struct whose first element is a + * pointer to an AVClass + * @param[in] name the name of the option to look for + * @param[in] unit the unit of the option to look for, or any if NULL + * @return a pointer to the option found, or NULL if no option + * has been found + * + * @deprecated use av_opt_find. + */ +attribute_deprecated +const AVOption *av_find_opt(void *obj, const char *name, const char *unit, int mask, int flags); +#endif + +#if FF_API_OLD_AVOPTIONS +/** + * Set the field of obj with the given name to value. + * + * @param[in] obj A struct whose first element is a pointer to an + * AVClass. + * @param[in] name the name of the field to set + * @param[in] val The value to set. If the field is not of a string + * type, then the given string is parsed. + * SI postfixes and some named scalars are supported. + * If the field is of a numeric type, it has to be a numeric or named + * scalar. Behavior with more than one scalar and +- infix operators + * is undefined. + * If the field is of a flags type, it has to be a sequence of numeric + * scalars or named flags separated by '+' or '-'. Prefixing a flag + * with '+' causes it to be set without affecting the other flags; + * similarly, '-' unsets a flag. + * @param[out] o_out if non-NULL put here a pointer to the AVOption + * found + * @param alloc this parameter is currently ignored + * @return 0 if the value has been set, or an AVERROR code in case of + * error: + * AVERROR_OPTION_NOT_FOUND if no matching option exists + * AVERROR(ERANGE) if the value is out of range + * AVERROR(EINVAL) if the value is not valid + * @deprecated use av_opt_set() + */ +attribute_deprecated +int av_set_string3(void *obj, const char *name, const char *val, int alloc, const AVOption **o_out); + +attribute_deprecated const AVOption *av_set_double(void *obj, const char *name, double n); +attribute_deprecated const AVOption *av_set_q(void *obj, const char *name, AVRational n); +attribute_deprecated const AVOption *av_set_int(void *obj, const char *name, int64_t n); + +double av_get_double(void *obj, const char *name, const AVOption **o_out); +AVRational av_get_q(void *obj, const char *name, const AVOption **o_out); +int64_t av_get_int(void *obj, const char *name, const AVOption **o_out); +attribute_deprecated const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len); +attribute_deprecated const AVOption *av_next_option(void *obj, const AVOption *last); +#endif + +/** * Show the obj options. * * @param req_flags requested flags for the options to show. Show only the @@ -305,12 +455,18 @@ int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags); */ void av_opt_set_defaults(void *s); +#if FF_API_OLD_AVOPTIONS +attribute_deprecated +void av_opt_set_defaults2(void *s, int mask, int flags); +#endif + /** * Parse the key/value pairs list in opts. For each key/value pair * found, stores the value in the field in ctx that is named like the * key. ctx must be an AVClass context, storing is done using * AVOptions. * + * @param opts options string to parse, may be NULL * @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 @@ -325,6 +481,36 @@ int av_set_options_string(void *ctx, const char *opts, const char *key_val_sep, const char *pairs_sep); /** + * Parse the key-value pairs list in opts. For each key=value pair found, + * set the value of the corresponding option in ctx. + * + * @param ctx the AVClass object to set options on + * @param opts the options string, key-value pairs separated by a + * delimiter + * @param shorthand a NULL-terminated array of options names for shorthand + * notation: if the first field in opts has no key part, + * the key is taken from the first element of shorthand; + * then again for the second, etc., until either opts is + * finished, shorthand is finished or a named option is + * found; after that, all options must be named + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @return the number of successfully set key=value pairs, or a negative + * value corresponding to an AVERROR code in case of error: + * AVERROR(EINVAL) if opts cannot be parsed, + * the error code issued by av_set_string3() if a key/value pair + * cannot be set + * + * Options names must use only the following characters: a-z A-Z 0-9 - . / _ + * Separators must use characters distinct from option names and from each + * other. + */ +int av_opt_set_from_string(void *ctx, const char *opts, + const char *const *shorthand, + const char *key_val_sep, const char *pairs_sep); +/** * Free all string and binary options in obj. */ void av_opt_free(void *obj); @@ -339,7 +525,7 @@ void av_opt_free(void *obj); */ int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name); -/* +/** * Set all the options from a given dictionary on an object. * * @param obj a struct whose first element is a pointer to AVClass @@ -355,6 +541,57 @@ int av_opt_flag_is_set(void *obj, const char *field_name, const char *flag_name) */ int av_opt_set_dict(void *obj, struct AVDictionary **options); + +/** + * Set all the options from a given dictionary on an object. + * + * @param obj a struct whose first element is a pointer to AVClass + * @param options options to process. This dictionary will be freed and replaced + * by a new one containing all options not found in obj. + * Of course this new dictionary needs to be freed by caller + * with av_dict_free(). + * @param search_flags A combination of AV_OPT_SEARCH_*. + * + * @return 0 on success, a negative AVERROR if some option was found in obj, + * but could not be set. + * + * @see av_dict_copy() + */ +int av_opt_set_dict2(void *obj, struct AVDictionary **options, int search_flags); + +/** + * Extract a key-value pair from the beginning of a string. + * + * @param ropts pointer to the options string, will be updated to + * point to the rest of the string (one of the pairs_sep + * or the final NUL) + * @param key_val_sep a 0-terminated list of characters used to separate + * key from value, for example '=' + * @param pairs_sep a 0-terminated list of characters used to separate + * two pairs from each other, for example ':' or ',' + * @param flags flags; see the AV_OPT_FLAG_* values below + * @param rkey parsed key; must be freed using av_free() + * @param rval parsed value; must be freed using av_free() + * + * @return >=0 for success, or a negative value corresponding to an + * AVERROR code in case of error; in particular: + * AVERROR(EINVAL) if no key is present + * + */ +int av_opt_get_key_value(const char **ropts, + const char *key_val_sep, const char *pairs_sep, + unsigned flags, + char **rkey, char **rval); + +enum { + + /** + * Accept to parse a value without a key; the key will then be returned + * as NULL. + */ + AV_OPT_FLAG_IMPLICIT_KEY = 1, +}; + /** * @defgroup opt_eval_funcs Evaluating option strings * @{ @@ -390,6 +627,13 @@ int av_opt_eval_q (void *obj, const AVOption *o, const char *val, AVRational #define AV_OPT_SEARCH_FAKE_OBJ 0x0002 /** + * Allows av_opt_query_ranges and av_opt_query_ranges_default to return more than + * one component for certain option types. + * @see AVOptionRanges for details. + */ +#define AV_OPT_MULTI_COMPONENT_RANGE 0x1000 + +/** * Look for an option in an object. Consider only options which * have all the specified flags set. * @@ -496,6 +740,27 @@ int av_opt_set_int (void *obj, const char *name, int64_t val, int search_f int av_opt_set_double(void *obj, const char *name, double val, int search_flags); int av_opt_set_q (void *obj, const char *name, AVRational val, int search_flags); int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int size, int search_flags); +int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_flags); +int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags); +int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags); +int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags); +int av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags); + +/** + * Set a binary option to an integer list. + * + * @param obj AVClass object to set options on + * @param name name of the binary option + * @param val pointer to an integer list (must have the correct type with + * regard to the contents of the list) + * @param term list terminator (usually 0 or -1) + * @param flags search flags + */ +#define av_opt_set_int_list(obj, name, val, term, flags) \ + (av_int_list_length(val, term) > INT_MAX / sizeof(*(val)) ? \ + AVERROR(EINVAL) : \ + av_opt_set_bin(obj, name, (const uint8_t *)(val), \ + av_int_list_length(val, term) * sizeof(*(val)), flags)) /** * @} */ @@ -510,17 +775,72 @@ int av_opt_set_bin (void *obj, const char *name, const uint8_t *val, int size, * @param[in] search_flags flags passed to av_opt_find2. I.e. if AV_OPT_SEARCH_CHILDREN * is passed here, then the option may be found in a child of obj. * @param[out] out_val value of the option will be written here - * @return 0 on success, a negative error code otherwise + * @return >=0 on success, a negative error code otherwise */ /** - * @note the returned string will av_malloc()ed and must be av_free()ed by the caller + * @note the returned string will be av_malloc()ed and must be av_free()ed by the caller */ int av_opt_get (void *obj, const char *name, int search_flags, uint8_t **out_val); int av_opt_get_int (void *obj, const char *name, int search_flags, int64_t *out_val); int av_opt_get_double(void *obj, const char *name, int search_flags, double *out_val); int av_opt_get_q (void *obj, const char *name, int search_flags, AVRational *out_val); +int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_out, int *h_out); +int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt); +int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt); +int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val); +int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *ch_layout); /** * @} + */ +/** + * Gets a pointer to the requested field in a struct. + * This function allows accessing a struct even when its fields are moved or + * renamed since the application making the access has been compiled, + * + * @returns a pointer to the field, it can be cast to the correct type and read + * or written to. + */ +void *av_opt_ptr(const AVClass *avclass, void *obj, const char *name); + +/** + * Free an AVOptionRanges struct and set it to NULL. + */ +void av_opt_freep_ranges(AVOptionRanges **ranges); + +/** + * Get a list of allowed ranges for the given option. + * + * The returned list may depend on other fields in obj like for example profile. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_freep_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges(AVOptionRanges **, void *obj, const char *key, int flags); + +int av_opt_copy(void *dest, void *src); + +/** + * Get a default list of allowed ranges for the given option. + * + * This list is constructed without using the AVClass.query_ranges() callback + * and can be used as fallback from within the callback. + * + * @param flags is a bitmask of flags, undefined flags should not be set and should be ignored + * AV_OPT_SEARCH_FAKE_OBJ indicates that the obj is a double pointer to a AVClass instead of a full instance + * AV_OPT_MULTI_COMPONENT_RANGE indicates that function may return more than one component, @see AVOptionRanges + * + * The result must be freed with av_opt_free_ranges. + * + * @return number of compontents returned on success, a negative errro code otherwise + */ +int av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags); + +/** * @} */ diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c index 414cd47e66..ba4b4e1b72 100644 --- a/libavutil/parseutils.c +++ b/libavutil/parseutils.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -31,6 +31,36 @@ #include "random_seed.h" #include "parseutils.h" +#ifdef TEST + +#define av_get_random_seed av_get_random_seed_deterministic +static uint32_t av_get_random_seed_deterministic(void); + +#define time(t) 1331972053 + +#endif + +int av_parse_ratio(AVRational *q, const char *str, int max, + int log_offset, void *log_ctx) +{ + char c; + int ret; + + if (sscanf(str, "%d:%d%c", &q->num, &q->den, &c) != 2) { + double d; + ret = av_expr_parse_and_eval(&d, str, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, log_offset, log_ctx); + if (ret < 0) + return ret; + *q = av_d2q(d, max); + } else { + av_reduce(&q->num, &q->den, q->num, q->den, max); + } + + return 0; +} + typedef struct { const char *abbr; int width, height; @@ -79,6 +109,18 @@ static const VideoSizeAbbr video_size_abbrs[] = { { "hd480", 852, 480 }, { "hd720", 1280, 720 }, { "hd1080", 1920,1080 }, + { "2k", 2048,1080 }, /* Digital Cinema System Specification */ + { "2kflat", 1998,1080 }, + { "2kscope", 2048, 858 }, + { "4k", 4096,2160 }, /* Digital Cinema System Specification */ + { "4kflat", 3996,2160 }, + { "4kscope", 4096,1716 }, + { "nhd", 640,360 }, + { "hqvga", 240,160 }, + { "wqvga", 400,240 }, + { "fwqvga", 432,240 }, + { "hvga", 480,320 }, + { "qhd", 960,540 }, }; static const VideoRateAbbr video_rate_abbrs[]= { @@ -96,7 +138,7 @@ int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str) { int i; int n = FF_ARRAY_ELEMS(video_size_abbrs); - char *p; + const char *p; int width = 0, height = 0; for (i = 0; i < n; i++) { @@ -107,10 +149,14 @@ int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str) } } if (i == n) { - width = strtol(str, &p, 10); + width = strtol(str, (void*)&p, 10); if (*p) p++; - height = strtol(p, &p, 10); + height = strtol(p, (void*)&p, 10); + + /* trailing extraneous data detected, like in 123x345foobar */ + if (*p) + return AVERROR(EINVAL); } if (width <= 0 || height <= 0) return AVERROR(EINVAL); @@ -123,7 +169,6 @@ int av_parse_video_rate(AVRational *rate, const char *arg) { int i, ret; int n = FF_ARRAY_ELEMS(video_rate_abbrs); - double res; /* First, we check our abbreviation table */ for (i = 0; i < n; ++i) @@ -133,10 +178,8 @@ int av_parse_video_rate(AVRational *rate, const char *arg) } /* Then, we try to parse it as fraction */ - if ((ret = av_expr_parse_and_eval(&res, arg, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, 0, NULL)) < 0) + if ((ret = av_parse_ratio_quiet(rate, arg, 1001000)) < 0) return ret; - *rate = av_d2q(res, 1001000); if (rate->num <= 0 || rate->den <= 0) return AVERROR(EINVAL); return 0; @@ -147,7 +190,7 @@ typedef struct { uint8_t rgb_color[3]; ///< RGB values for the color } ColorEntry; -static ColorEntry color_table[] = { +static const ColorEntry color_table[] = { { "AliceBlue", { 0xF0, 0xF8, 0xFF } }, { "AntiqueWhite", { 0xFA, 0xEB, 0xD7 } }, { "Aqua", { 0x00, 0xFF, 0xFF } }, @@ -215,8 +258,8 @@ static ColorEntry color_table[] = { { "LightCoral", { 0xF0, 0x80, 0x80 } }, { "LightCyan", { 0xE0, 0xFF, 0xFF } }, { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } }, - { "LightGrey", { 0xD3, 0xD3, 0xD3 } }, { "LightGreen", { 0x90, 0xEE, 0x90 } }, + { "LightGrey", { 0xD3, 0xD3, 0xD3 } }, { "LightPink", { 0xFF, 0xB6, 0xC1 } }, { "LightSalmon", { 0xFF, 0xA0, 0x7A } }, { "LightSeaGreen", { 0x20, 0xB2, 0xAA } }, @@ -359,7 +402,11 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, if (!strncmp(alpha_string, "0x", 2)) { alpha = strtoul(alpha_string, &tail, 16); } else { - alpha = 255 * strtod(alpha_string, &tail); + double norm_alpha = strtod(alpha_string, &tail); + if (norm_alpha < 0.0 || norm_alpha > 1.0) + alpha = 256; + else + alpha = 255 * norm_alpha; } if (tail == alpha_string || *tail || alpha > 255 || alpha < 0) { @@ -373,6 +420,20 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, return 0; } +const char *av_get_known_color_name(int color_idx, const uint8_t **rgbp) +{ + const ColorEntry *color; + + if ((unsigned)color_idx >= FF_ARRAY_ELEMS(color_table)) + return NULL; + + color = &color_table[color_idx]; + if (rgbp) + *rgbp = color->rgb_color; + + return color->name; +} + /* get a positive number between n_min and n_max, for a maximum length of len_max. Return -1 if error. */ static int date_get_num(const char **pp, @@ -399,19 +460,26 @@ static int date_get_num(const char **pp, return val; } -static const char *small_strptime(const char *p, const char *fmt, struct tm *dt) +char *av_small_strptime(const char *p, const char *fmt, struct tm *dt) { int c, val; for(;;) { + /* consume time string until a non whitespace char is found */ + while (av_isspace(*fmt)) { + while (av_isspace(*p)) + p++; + fmt++; + } c = *fmt++; if (c == '\0') { - return p; + return (char *)p; } else if (c == '%') { c = *fmt++; switch(c) { case 'H': - val = date_get_num(&p, 0, 23, 2); + case 'J': + val = date_get_num(&p, 0, c == 'H' ? 23 : INT_MAX, 2); if (val == -1) return NULL; dt->tm_hour = val; @@ -471,7 +539,7 @@ time_t av_timegm(struct tm *tm) y--; } - t = 86400 * + t = 86400LL * (d + (153 * m - 457) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 719469); t += 3600 * tm->tm_hour + 60 * tm->tm_min + tm->tm_sec; @@ -481,9 +549,11 @@ time_t av_timegm(struct tm *tm) int av_parse_time(int64_t *timeval, const char *timestr, int duration) { - const char *p; + const char *p, *q; int64_t t; + time_t now; struct tm dt = { 0 }; + int today = 0, negative = 0, microseconds = 0; int i; static const char * const date_fmt[] = { "%Y-%m-%d", @@ -493,58 +563,41 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) "%H:%M:%S", "%H%M%S", }; - const char *q; - int is_utc, len; - char lastch; - int negative = 0; - - time_t now = time(0); - - len = strlen(timestr); - if (len > 0) - lastch = timestr[len - 1]; - else - lastch = '\0'; - is_utc = (lastch == 'z' || lastch == 'Z'); p = timestr; q = NULL; + *timeval = INT64_MIN; if (!duration) { - if (!av_strncasecmp(timestr, "now", len)) { + now = time(0); + + if (!av_strcasecmp(timestr, "now")) { *timeval = (int64_t) now * 1000000; return 0; } /* parse the year-month-day part */ for (i = 0; i < FF_ARRAY_ELEMS(date_fmt); i++) { - q = small_strptime(p, date_fmt[i], &dt); - if (q) { + q = av_small_strptime(p, date_fmt[i], &dt); + if (q) break; - } } /* if the year-month-day part is missing, then take the * current year-month-day time */ if (!q) { - if (is_utc) { - dt = *gmtime(&now); - } else { - dt = *localtime(&now); - } - dt.tm_hour = dt.tm_min = dt.tm_sec = 0; - } else { - p = q; + today = 1; + q = p; } + p = q; if (*p == 'T' || *p == 't' || *p == ' ') p++; /* parse the hour-minute-second part */ for (i = 0; i < FF_ARRAY_ELEMS(time_fmt); i++) { - q = small_strptime(p, time_fmt[i], &dt); - if (q) { + q = av_small_strptime(p, time_fmt[i], &dt); + if (q) break; - } } } else { /* parse timestr as a duration */ @@ -553,16 +606,18 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) ++p; } /* parse timestr as HH:MM:SS */ - q = small_strptime(p, time_fmt[0], &dt); + q = av_small_strptime(p, "%J:%M:%S", &dt); + if (!q) { + /* parse timestr as MM:SS */ + q = av_small_strptime(p, "%M:%S", &dt); + dt.tm_hour = 0; + } if (!q) { char *o; /* parse timestr as S+ */ dt.tm_sec = strtol(p, &o, 10); - if (o == p) { - /* the parsing didn't succeed */ - *timeval = INT64_MIN; + if (o == p) /* the parsing didn't succeed */ return AVERROR(EINVAL); - } dt.tm_min = 0; dt.tm_hour = 0; q = o; @@ -570,35 +625,43 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration) } /* Now we have all the fields that we can get */ - if (!q) { - *timeval = INT64_MIN; + if (!q) return AVERROR(EINVAL); + + /* parse the .m... part */ + if (*q == '.') { + int n; + q++; + for (n = 100000; n >= 1; n /= 10, q++) { + if (!av_isdigit(*q)) + break; + microseconds += n * (*q - '0'); + } + while (av_isdigit(*q)) + q++; } if (duration) { t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec; } else { - dt.tm_isdst = -1; /* unknown */ - if (is_utc) { - t = av_timegm(&dt); - } else { - t = mktime(&dt); + int is_utc = *q == 'Z' || *q == 'z'; + q += is_utc; + if (today) { /* fill in today's date */ + struct tm dt2 = is_utc ? *gmtime(&now) : *localtime(&now); + dt2.tm_hour = dt.tm_hour; + dt2.tm_min = dt.tm_min; + dt2.tm_sec = dt.tm_sec; + dt = dt2; } + t = is_utc ? av_timegm(&dt) : mktime(&dt); } - t *= 1000000; + /* Check that we are at the end of the string */ + if (*q) + return AVERROR(EINVAL); - /* parse the .m... part */ - if (*q == '.') { - int val, n; - q++; - for (val = 0, n = 100000; n >= 1; n /= 10, q++) { - if (!av_isdigit(*q)) - break; - val += n * (*q - '0'); - } - t += val; - } + t *= 1000000; + t += microseconds; *timeval = negative ? -t : t; return 0; } @@ -644,6 +707,13 @@ int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info #ifdef TEST +static uint32_t randomv = MKTAG('L','A','V','U'); + +static uint32_t av_get_random_seed_deterministic(void) +{ + return randomv = randomv * 1664525 + 1013904223; +} + int main(void) { printf("Testing av_parse_video_rate()\n"); @@ -691,6 +761,8 @@ int main(void) int i; uint8_t rgba[4]; static const char *const color_names[] = { + "bikeshed", + "RaNdOm", "foo", "red", "Red ", @@ -733,6 +805,84 @@ int main(void) if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0) printf("%s -> R(%d) G(%d) B(%d) A(%d)\n", color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]); + else + printf("%s -> error\n", color_names[i]); + } + } + + printf("\nTesting av_small_strptime()\n"); + { + int i; + struct tm tm = { 0 }; + struct fmt_timespec_entry { + const char *fmt, *timespec; + } fmt_timespec_entries[] = { + { "%Y-%m-%d", "2012-12-21" }, + { "%Y - %m - %d", "2012-12-21" }, + { "%Y-%m-%d %H:%M:%S", "2012-12-21 20:12:21" }, + { " %Y - %m - %d %H : %M : %S", " 2012 - 12 - 21 20 : 12 : 21" }, + }; + + av_log_set_level(AV_LOG_DEBUG); + for (i = 0; i < FF_ARRAY_ELEMS(fmt_timespec_entries); i++) { + char *p; + struct fmt_timespec_entry *e = &fmt_timespec_entries[i]; + printf("fmt:'%s' spec:'%s' -> ", e->fmt, e->timespec); + p = av_small_strptime(e->timespec, e->fmt, &tm); + if (p) { + printf("%04d-%02d-%2d %02d:%02d:%02d\n", + 1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + } else { + printf("error\n"); + } + } + } + + printf("\nTesting av_parse_time()\n"); + { + int i; + int64_t tv; + time_t tvi; + struct tm *tm; + static char tzstr[] = "TZ=CET-1"; + static const char * const time_string[] = { + "now", + "12:35:46", + "2000-12-20 0:02:47.5z", + "2000-12-20T010247.6", + }; + static const char * const duration_string[] = { + "2:34:56.79", + "-1:23:45.67", + "42.1729", + "-1729.42", + "12:34", + }; + + av_log_set_level(AV_LOG_DEBUG); + putenv(tzstr); + printf("(now is 2012-03-17 09:14:13 +0100, local time is UTC+1)\n"); + for (i = 0; i < FF_ARRAY_ELEMS(time_string); i++) { + printf("%-24s -> ", time_string[i]); + if (av_parse_time(&tv, time_string[i], 0)) { + printf("error\n"); + } else { + tvi = tv / 1000000; + tm = gmtime(&tvi); + printf("%14"PRIi64".%06d = %04d-%02d-%02dT%02d:%02d:%02dZ\n", + tv / 1000000, (int)(tv % 1000000), + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + } + } + for (i = 0; i < FF_ARRAY_ELEMS(duration_string); i++) { + printf("%-24s -> ", duration_string[i]); + if (av_parse_time(&tv, duration_string[i], 1)) { + printf("error\n"); + } else { + printf("%+21"PRIi64"\n", tv); + } } } diff --git a/libavutil/parseutils.h b/libavutil/parseutils.h index 0844abb2f0..c80f0de3de 100644 --- a/libavutil/parseutils.h +++ b/libavutil/parseutils.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -29,6 +29,30 @@ */ /** + * Parse str and store the parsed ratio in q. + * + * Note that a ratio with infinite (1/0) or negative value is + * considered valid, so you should check on the returned value if you + * want to exclude those values. + * + * The undefined value can be expressed using the "0:0" string. + * + * @param[in,out] q pointer to the AVRational which will contain the ratio + * @param[in] str the string to parse: it has to be a string in the format + * num:den, a float number or an expression + * @param[in] max the maximum allowed numerator and denominator + * @param[in] log_offset log level offset which is applied to the log + * level of log_ctx + * @param[in] log_ctx parent logging context + * @return >= 0 on success, a negative error code otherwise + */ +int av_parse_ratio(AVRational *q, const char *str, int max, + int log_offset, void *log_ctx); + +#define av_parse_ratio_quiet(rate, str, max) \ + av_parse_ratio(rate, str, max, AV_LOG_MAX_OFFSET, NULL) + +/** * Parse str and put in width_ptr and height_ptr the detected values. * * @param[in,out] width_ptr pointer to the variable which will contain the detected @@ -75,6 +99,19 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, void *log_ctx); /** + * Get the name of a color from the internal table of hard-coded named + * colors. + * + * This function is meant to enumerate the color names recognized by + * av_parse_color(). + * + * @param color_idx index of the requested color, starting from 0 + * @param rgbp if not NULL, will point to a 3-elements array with the color value in RGB + * @return the color name string or NULL if color_idx is not in the array + */ +const char *av_get_known_color_name(int color_idx, const uint8_t **rgb); + +/** * Parse timestr and return in *time a corresponding number of * microseconds. * @@ -88,7 +125,7 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, * @param timestr a string representing a date or a duration. * - If a date the syntax is: * @code - * [{YYYY-MM-DD|YYYYMMDD}[T|t| ]]{{HH[:MM[:SS[.m...]]]}|{HH[MM[SS[.m...]]]}}[Z] + * [{YYYY-MM-DD|YYYYMMDD}[T|t| ]]{{HH:MM:SS[.m...]]]}|{HHMMSS[.m...]]]}}[Z] * now * @endcode * If the value is "now" it takes the current time. @@ -98,17 +135,43 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, * year-month-day. * - If a duration the syntax is: * @code - * [-]HH[:MM[:SS[.m...]]] + * [-][HH:]MM:SS[.m...] * [-]S+[.m...] * @endcode * @param duration flag which tells how to interpret timestr, if not * zero timestr is interpreted as a duration, otherwise as a date - * @return 0 in case of success, a negative value corresponding to an + * @return >= 0 in case of success, a negative value corresponding to an * AVERROR code otherwise */ int av_parse_time(int64_t *timeval, const char *timestr, int duration); /** + * Parse the input string p according to the format string fmt and + * store its results in the structure dt. + * This implementation supports only a subset of the formats supported + * by the standard strptime(). + * + * In particular it actually supports the parameters: + * - %H: the hour as a decimal number, using a 24-hour clock, in the + * range '00' through '23' + * - %J: hours as a decimal number, in the range '0' through INT_MAX + * - %M: the minute as a decimal number, using a 24-hour clock, in the + * range '00' through '59' + * - %S: the second as a decimal number, using a 24-hour clock, in the + * range '00' through '59' + * - %Y: the year as a decimal number, using the Gregorian calendar + * - %m: the month as a decimal number, in the range '1' through '12' + * - %d: the day of the month as a decimal number, in the range '1' + * through '31' + * - %%: a literal '%' + * + * @return a pointer to the first character not processed in this + * function call, or NULL in case the function fails to match all of + * the fmt string and therefore an error occurred + */ +char *av_small_strptime(const char *p, const char *fmt, struct tm *dt); + +/** * Attempt to find a specific tag in a URL. * * syntax: '?tag1=val1&tag2=val2...'. Little URL decoding is done. diff --git a/libavutil/pca.c b/libavutil/pca.c new file mode 100644 index 0000000000..26d5bbb157 --- /dev/null +++ b/libavutil/pca.c @@ -0,0 +1,248 @@ +/* + * principal component analysis (PCA) + * Copyright (c) 2004 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 + * principal component analysis (PCA) + */ + +#include "common.h" +#include "pca.h" + +typedef struct PCA{ + int count; + int n; + double *covariance; + double *mean; + double *z; +}PCA; + +PCA *ff_pca_init(int n){ + PCA *pca; + if(n<=0) + return NULL; + + pca= av_mallocz(sizeof(*pca)); + pca->n= n; + pca->z = av_malloc_array(n, sizeof(*pca->z)); + pca->count=0; + pca->covariance= av_calloc(n*n, sizeof(double)); + pca->mean= av_calloc(n, sizeof(double)); + + return pca; +} + +void ff_pca_free(PCA *pca){ + av_freep(&pca->covariance); + av_freep(&pca->mean); + av_freep(&pca->z); + av_free(pca); +} + +void ff_pca_add(PCA *pca, double *v){ + int i, j; + const int n= pca->n; + + for(i=0; i<n; i++){ + pca->mean[i] += v[i]; + for(j=i; j<n; j++) + pca->covariance[j + i*n] += v[i]*v[j]; + } + pca->count++; +} + +int ff_pca(PCA *pca, double *eigenvector, double *eigenvalue){ + int i, j, pass; + int k=0; + const int n= pca->n; + double *z = pca->z; + + memset(eigenvector, 0, sizeof(double)*n*n); + + for(j=0; j<n; j++){ + pca->mean[j] /= pca->count; + eigenvector[j + j*n] = 1.0; + for(i=0; i<=j; i++){ + pca->covariance[j + i*n] /= pca->count; + pca->covariance[j + i*n] -= pca->mean[i] * pca->mean[j]; + pca->covariance[i + j*n] = pca->covariance[j + i*n]; + } + eigenvalue[j]= pca->covariance[j + j*n]; + z[j]= 0; + } + + for(pass=0; pass < 50; pass++){ + double sum=0; + + for(i=0; i<n; i++) + for(j=i+1; j<n; j++) + sum += fabs(pca->covariance[j + i*n]); + + if(sum == 0){ + for(i=0; i<n; i++){ + double maxvalue= -1; + for(j=i; j<n; j++){ + if(eigenvalue[j] > maxvalue){ + maxvalue= eigenvalue[j]; + k= j; + } + } + eigenvalue[k]= eigenvalue[i]; + eigenvalue[i]= maxvalue; + for(j=0; j<n; j++){ + double tmp= eigenvector[k + j*n]; + eigenvector[k + j*n]= eigenvector[i + j*n]; + eigenvector[i + j*n]= tmp; + } + } + return pass; + } + + for(i=0; i<n; i++){ + for(j=i+1; j<n; j++){ + double covar= pca->covariance[j + i*n]; + double t,c,s,tau,theta, h; + + if(pass < 3 && fabs(covar) < sum / (5*n*n)) //FIXME why pass < 3 + continue; + if(fabs(covar) == 0.0) //FIXME should not be needed + continue; + if(pass >=3 && fabs((eigenvalue[j]+z[j])/covar) > (1LL<<32) && fabs((eigenvalue[i]+z[i])/covar) > (1LL<<32)){ + pca->covariance[j + i*n]=0.0; + continue; + } + + h= (eigenvalue[j]+z[j]) - (eigenvalue[i]+z[i]); + theta=0.5*h/covar; + t=1.0/(fabs(theta)+sqrt(1.0+theta*theta)); + if(theta < 0.0) t = -t; + + c=1.0/sqrt(1+t*t); + s=t*c; + tau=s/(1.0+c); + z[i] -= t*covar; + z[j] += t*covar; + +#define ROTATE(a,i,j,k,l) {\ + double g=a[j + i*n];\ + double h=a[l + k*n];\ + a[j + i*n]=g-s*(h+g*tau);\ + a[l + k*n]=h+s*(g-h*tau); } + for(k=0; k<n; k++) { + if(k!=i && k!=j){ + ROTATE(pca->covariance,FFMIN(k,i),FFMAX(k,i),FFMIN(k,j),FFMAX(k,j)) + } + ROTATE(eigenvector,k,i,k,j) + } + pca->covariance[j + i*n]=0.0; + } + } + for (i=0; i<n; i++) { + eigenvalue[i] += z[i]; + z[i]=0.0; + } + } + + return -1; +} + +#ifdef TEST + +#undef printf +#include <stdio.h> +#include <stdlib.h> +#include "lfg.h" + +int main(void){ + PCA *pca; + int i, j, k; +#define LEN 8 + double eigenvector[LEN*LEN]; + double eigenvalue[LEN]; + AVLFG prng; + + av_lfg_init(&prng, 1); + + pca= ff_pca_init(LEN); + + for(i=0; i<9000000; i++){ + double v[2*LEN+100]; + double sum=0; + int pos = av_lfg_get(&prng) % LEN; + int v2 = av_lfg_get(&prng) % 101 - 50; + v[0] = av_lfg_get(&prng) % 101 - 50; + for(j=1; j<8; j++){ + if(j<=pos) v[j]= v[0]; + else v[j]= v2; + sum += v[j]; + } +/* for(j=0; j<LEN; j++){ + v[j] -= v[pos]; + }*/ +// sum += av_lfg_get(&prng) % 10; +/* for(j=0; j<LEN; j++){ + v[j] -= sum/LEN; + }*/ +// lbt1(v+100,v+100,LEN); + ff_pca_add(pca, v); + } + + + ff_pca(pca, eigenvector, eigenvalue); + for(i=0; i<LEN; i++){ + pca->count= 1; + pca->mean[i]= 0; + +// (0.5^|x|)^2 = 0.5^2|x| = 0.25^|x| + + +// pca.covariance[i + i*LEN]= pow(0.5, fabs + for(j=i; j<LEN; j++){ + printf("%f ", pca->covariance[i + j*LEN]); + } + printf("\n"); + } + + for(i=0; i<LEN; i++){ + double v[LEN]; + double error=0; + memset(v, 0, sizeof(v)); + for(j=0; j<LEN; j++){ + for(k=0; k<LEN; k++){ + v[j] += pca->covariance[FFMIN(k,j) + FFMAX(k,j)*LEN] * eigenvector[i + k*LEN]; + } + v[j] /= eigenvalue[i]; + error += fabs(v[j] - eigenvector[i + j*LEN]); + } + printf("%f ", error); + } + printf("\n"); + + for(i=0; i<LEN; i++){ + for(j=0; j<LEN; j++){ + printf("%9.6f ", eigenvector[i + j*LEN]); + } + printf(" %9.1f %f\n", eigenvalue[i], eigenvalue[i]/eigenvalue[0]); + } + + return 0; +} +#endif diff --git a/libavutil/pca.h b/libavutil/pca.h new file mode 100644 index 0000000000..00ddd60c7e --- /dev/null +++ b/libavutil/pca.h @@ -0,0 +1,35 @@ +/* + * principal component analysis (PCA) + * Copyright (c) 2004 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 + * principal component analysis (PCA) + */ + +#ifndef AVUTIL_PCA_H +#define AVUTIL_PCA_H + +struct PCA *ff_pca_init(int n); +void ff_pca_free(struct PCA *pca); +void ff_pca_add(struct PCA *pca, double *v); +int ff_pca(struct PCA *pca, double *eigenvector, double *eigenvalue); + +#endif /* AVUTIL_PCA_H */ diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 526e0010d4..5deafb5115 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -2,26 +2,27 @@ * pixel format descriptor * Copyright (c) 2009 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <stdio.h> #include <string.h> +#include "avassert.h" #include "avstring.h" #include "common.h" #include "pixfmt.h" @@ -182,9 +183,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 2, 1, 0, 7 }, /* B */ - { 0, 2, 2, 0, 7 }, /* G */ { 0, 2, 3, 0, 7 }, /* R */ + { 0, 2, 2, 0, 7 }, /* G */ + { 0, 2, 1, 0, 7 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -236,6 +237,18 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, + [AV_PIX_FMT_YUVJ411P] = { + .name = "yuvj411p", + .nb_components = 3, + .log2_chroma_w = 2, + .log2_chroma_h = 0, + .comp = { + { 0, 0, 1, 0, 7 }, /* Y */ + { 1, 0, 1, 0, 7 }, /* U */ + { 2, 0, 1, 0, 7 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, [AV_PIX_FMT_GRAY8] = { .name = "gray", .nb_components = 1, @@ -307,9 +320,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - {0, 0, 1, 0, 7}, /* Y */ - {1, 0, 1, 0, 7}, /* U */ - {2, 0, 1, 0, 7}, /* V */ + { 0, 0, 1, 0, 7 }, /* Y */ + { 1, 0, 1, 0, 7 }, /* U */ + { 2, 0, 1, 0, 7 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -323,6 +336,12 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .flags = AV_PIX_FMT_FLAG_HWACCEL, }, #endif /* FF_API_XVMC */ +#if !FF_API_XVMC + [AV_PIX_FMT_XVMC] = { + .name = "xvmc", + .flags = AV_PIX_FMT_FLAG_HWACCEL, + }, +#endif /* !FF_API_XVMC */ [AV_PIX_FMT_UYVY422] = { .name = "uyvy422", .nb_components = 3, @@ -351,9 +370,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 6, 1 }, /* B */ - { 0, 0, 1, 3, 2 }, /* G */ { 0, 0, 1, 0, 2 }, /* R */ + { 0, 0, 1, 3, 2 }, /* G */ + { 0, 0, 1, 6, 1 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PSEUDOPAL, }, @@ -363,9 +382,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 3, 1, 0, 0 }, /* B */ - { 0, 3, 2, 0, 1 }, /* G */ { 0, 3, 4, 0, 0 }, /* R */ + { 0, 3, 2, 0, 1 }, /* G */ + { 0, 3, 1, 0, 0 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_RGB, }, @@ -375,9 +394,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 0, 1, 3, 0 }, /* B */ - { 0, 0, 1, 1, 1 }, /* G */ { 0, 0, 1, 0, 0 }, /* R */ + { 0, 0, 1, 1, 1 }, /* G */ + { 0, 0, 1, 3, 0 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_PSEUDOPAL, }, @@ -436,8 +455,8 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_h = 1, .comp = { { 0, 0, 1, 0, 7 }, /* Y */ - { 1, 1, 1, 0, 7 }, /* V */ { 1, 1, 2, 0, 7 }, /* U */ + { 1, 1, 1, 0, 7 }, /* V */ }, .flags = AV_PIX_FMT_FLAG_PLANAR, }, @@ -447,10 +466,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 3, 1, 0, 7 }, /* A */ { 0, 3, 2, 0, 7 }, /* R */ { 0, 3, 3, 0, 7 }, /* G */ { 0, 3, 4, 0, 7 }, /* B */ + { 0, 3, 1, 0, 7 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, @@ -473,10 +492,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 3, 1, 0, 7 }, /* A */ - { 0, 3, 2, 0, 7 }, /* B */ - { 0, 3, 3, 0, 7 }, /* G */ { 0, 3, 4, 0, 7 }, /* R */ + { 0, 3, 3, 0, 7 }, /* G */ + { 0, 3, 2, 0, 7 }, /* B */ + { 0, 3, 1, 0, 7 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, @@ -486,13 +505,61 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 3, 1, 0, 7 }, /* B */ - { 0, 3, 2, 0, 7 }, /* G */ { 0, 3, 3, 0, 7 }, /* R */ + { 0, 3, 2, 0, 7 }, /* G */ + { 0, 3, 1, 0, 7 }, /* B */ { 0, 3, 4, 0, 7 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, + [AV_PIX_FMT_0RGB] = { + .name = "0rgb", + .nb_components= 3, + .log2_chroma_w= 0, + .log2_chroma_h= 0, + .comp = { + { 0, 3, 2, 0, 7 }, /* R */ + { 0, 3, 3, 0, 7 }, /* G */ + { 0, 3, 4, 0, 7 }, /* B */ + }, + .flags = AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_RGB0] = { + .name = "rgb0", + .nb_components= 3, + .log2_chroma_w= 0, + .log2_chroma_h= 0, + .comp = { + { 0, 3, 1, 0, 7 }, /* R */ + { 0, 3, 2, 0, 7 }, /* G */ + { 0, 3, 3, 0, 7 }, /* B */ + }, + .flags = AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_0BGR] = { + .name = "0bgr", + .nb_components= 3, + .log2_chroma_w= 0, + .log2_chroma_h= 0, + .comp = { + { 0, 3, 4, 0, 7 }, /* R */ + { 0, 3, 3, 0, 7 }, /* G */ + { 0, 3, 2, 0, 7 }, /* B */ + }, + .flags = AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_BGR0] = { + .name = "bgr0", + .nb_components= 3, + .log2_chroma_w= 0, + .log2_chroma_h= 0, + .comp = { + { 0, 3, 3, 0, 7 }, /* R */ + { 0, 3, 2, 0, 7 }, /* G */ + { 0, 3, 1, 0, 7 }, /* B */ + }, + .flags = AV_PIX_FMT_FLAG_RGB, + }, [AV_PIX_FMT_GRAY16BE] = { .name = "gray16be", .nb_components = 1, @@ -551,7 +618,7 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, - [AV_PIX_FMT_YUVA422P] = { + [AV_PIX_FMT_YUVA422P] = { .name = "yuva422p", .nb_components = 4, .log2_chroma_w = 1, @@ -588,7 +655,7 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { { 2, 1, 1, 0, 8 }, /* V */ { 3, 1, 1, 0, 8 }, /* A */ }, - .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_ALPHA, }, [AV_PIX_FMT_YUVA420P9LE] = { .name = "yuva420p9le", @@ -977,9 +1044,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 5, 1, 0, 15 }, /* B */ - { 0, 5, 3, 0, 15 }, /* G */ { 0, 5, 5, 0, 15 }, /* R */ + { 0, 5, 3, 0, 15 }, /* G */ + { 0, 5, 1, 0, 15 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, }, @@ -989,9 +1056,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 5, 1, 0, 15 }, /* B */ - { 0, 5, 3, 0, 15 }, /* G */ { 0, 5, 5, 0, 15 }, /* R */ + { 0, 5, 3, 0, 15 }, /* G */ + { 0, 5, 1, 0, 15 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -1001,10 +1068,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 5, 1, 0, 15 }, /* B */ - { 0, 5, 3, 0, 15 }, /* G */ - { 0, 5, 5, 0, 15 }, /* R */ - { 0, 5, 7, 0, 15 }, /* A */ + { 0, 7, 5, 0, 15 }, /* R */ + { 0, 7, 3, 0, 15 }, /* G */ + { 0, 7, 1, 0, 15 }, /* B */ + { 0, 7, 7, 0, 15 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, @@ -1014,10 +1081,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 5, 1, 0, 15 }, /* B */ - { 0, 5, 3, 0, 15 }, /* G */ - { 0, 5, 5, 0, 15 }, /* R */ - { 0, 5, 7, 0, 15 }, /* A */ + { 0, 7, 5, 0, 15 }, /* R */ + { 0, 7, 3, 0, 15 }, /* G */ + { 0, 7, 1, 0, 15 }, /* B */ + { 0, 7, 7, 0, 15 }, /* A */ }, .flags = AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, }, @@ -1027,9 +1094,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 0, 3, 4 }, /* B */ - { 0, 1, 1, 5, 5 }, /* G */ { 0, 1, 1, 0, 4 }, /* R */ + { 0, 1, 1, 5, 5 }, /* G */ + { 0, 1, 0, 3, 4 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, }, @@ -1039,9 +1106,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 2, 3, 4 }, /* B */ - { 0, 1, 1, 5, 5 }, /* G */ { 0, 1, 1, 0, 4 }, /* R */ + { 0, 1, 1, 5, 5 }, /* G */ + { 0, 1, 2, 3, 4 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -1051,9 +1118,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 0, 2, 4 }, /* B */ - { 0, 1, 1, 5, 4 }, /* G */ { 0, 1, 1, 0, 4 }, /* R */ + { 0, 1, 1, 5, 4 }, /* G */ + { 0, 1, 0, 2, 4 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, }, @@ -1063,9 +1130,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 2, 2, 4 }, /* B */ - { 0, 1, 1, 5, 4 }, /* G */ { 0, 1, 1, 0, 4 }, /* R */ + { 0, 1, 1, 5, 4 }, /* G */ + { 0, 1, 2, 2, 4 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -1075,9 +1142,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 0, 0, 3 }, /* B */ - { 0, 1, 1, 4, 3 }, /* G */ { 0, 1, 1, 0, 3 }, /* R */ + { 0, 1, 1, 4, 3 }, /* G */ + { 0, 1, 0, 0, 3 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, }, @@ -1087,9 +1154,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { - { 0, 1, 2, 0, 3 }, /* B */ - { 0, 1, 1, 4, 3 }, /* G */ { 0, 1, 1, 0, 3 }, /* R */ + { 0, 1, 1, 4, 3 }, /* G */ + { 0, 1, 2, 0, 3 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_RGB, }, @@ -1111,12 +1178,6 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_h = 1, .flags = AV_PIX_FMT_FLAG_HWACCEL, }, - [AV_PIX_FMT_VDA_VLD] = { - .name = "vda_vld", - .log2_chroma_w = 1, - .log2_chroma_h = 1, - .flags = AV_PIX_FMT_FLAG_HWACCEL, - }, [AV_PIX_FMT_YUV420P9LE] = { .name = "yuv420p9le", .nb_components = 3, @@ -1165,6 +1226,54 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, }, + [AV_PIX_FMT_YUV420P12LE] = { + .name = "yuv420p12le", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 1, + .comp = { + { 0, 1, 1, 0, 11 }, /* Y */ + { 1, 1, 1, 0, 11 }, /* U */ + { 2, 1, 1, 0, 11 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_YUV420P12BE] = { + .name = "yuv420p12be", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 1, + .comp = { + { 0, 1, 1, 0, 11 }, /* Y */ + { 1, 1, 1, 0, 11 }, /* U */ + { 2, 1, 1, 0, 11 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_YUV420P14LE] = { + .name = "yuv420p14le", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 1, + .comp = { + { 0, 1, 1, 0, 13 }, /* Y */ + { 1, 1, 1, 0, 13 }, /* U */ + { 2, 1, 1, 0, 13 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_YUV420P14BE] = { + .name = "yuv420p14be", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 1, + .comp = { + { 0, 1, 1, 0, 13 }, /* Y */ + { 1, 1, 1, 0, 13 }, /* U */ + { 2, 1, 1, 0, 13 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, + }, [AV_PIX_FMT_YUV420P16LE] = { .name = "yuv420p16le", .nb_components = 3, @@ -1237,6 +1346,54 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, }, + [AV_PIX_FMT_YUV422P12LE] = { + .name = "yuv422p12le", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 1, 1, 0, 11 }, /* Y */ + { 1, 1, 1, 0, 11 }, /* U */ + { 2, 1, 1, 0, 11 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_YUV422P12BE] = { + .name = "yuv422p12be", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 1, 1, 0, 11 }, /* Y */ + { 1, 1, 1, 0, 11 }, /* U */ + { 2, 1, 1, 0, 11 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_YUV422P14LE] = { + .name = "yuv422p14le", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 1, 1, 0, 13 }, /* Y */ + { 1, 1, 1, 0, 13 }, /* U */ + { 2, 1, 1, 0, 13 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_YUV422P14BE] = { + .name = "yuv422p14be", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 1, 1, 0, 13 }, /* Y */ + { 1, 1, 1, 0, 13 }, /* U */ + { 2, 1, 1, 0, 13 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, + }, [AV_PIX_FMT_YUV422P16LE] = { .name = "yuv422p16le", .nb_components = 3, @@ -1333,12 +1490,66 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, }, + [AV_PIX_FMT_YUV444P12LE] = { + .name = "yuv444p12le", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 1, 1, 0, 11 }, /* Y */ + { 1, 1, 1, 0, 11 }, /* U */ + { 2, 1, 1, 0, 11 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_YUV444P12BE] = { + .name = "yuv444p12be", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 1, 1, 0, 11 }, /* Y */ + { 1, 1, 1, 0, 11 }, /* U */ + { 2, 1, 1, 0, 11 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_YUV444P14LE] = { + .name = "yuv444p14le", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 1, 1, 0, 13 }, /* Y */ + { 1, 1, 1, 0, 13 }, /* U */ + { 2, 1, 1, 0, 13 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_YUV444P14BE] = { + .name = "yuv444p14be", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 1, 1, 0, 13 }, /* Y */ + { 1, 1, 1, 0, 13 }, /* U */ + { 2, 1, 1, 0, 13 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR, + }, [AV_PIX_FMT_DXVA2_VLD] = { .name = "dxva2_vld", .log2_chroma_w = 1, .log2_chroma_h = 1, .flags = AV_PIX_FMT_FLAG_HWACCEL, }, + [AV_PIX_FMT_VDA_VLD] = { + .name = "vda_vld", + .log2_chroma_w = 1, + .log2_chroma_h = 1, + .flags = AV_PIX_FMT_FLAG_HWACCEL, + }, [AV_PIX_FMT_YA8] = { .name = "ya8", .nb_components = 2, @@ -1355,9 +1566,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { + { 2, 0, 1, 0, 7 }, /* R */ { 0, 0, 1, 0, 7 }, /* G */ { 1, 0, 1, 0, 7 }, /* B */ - { 2, 0, 1, 0, 7 }, /* R */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, @@ -1367,9 +1578,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { + { 2, 1, 1, 0, 8 }, /* R */ { 0, 1, 1, 0, 8 }, /* G */ { 1, 1, 1, 0, 8 }, /* B */ - { 2, 1, 1, 0, 8 }, /* R */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, @@ -1379,9 +1590,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { + { 2, 1, 1, 0, 8 }, /* R */ { 0, 1, 1, 0, 8 }, /* G */ { 1, 1, 1, 0, 8 }, /* B */ - { 2, 1, 1, 0, 8 }, /* R */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, @@ -1391,9 +1602,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { + { 2, 1, 1, 0, 9 }, /* R */ { 0, 1, 1, 0, 9 }, /* G */ { 1, 1, 1, 0, 9 }, /* B */ - { 2, 1, 1, 0, 9 }, /* R */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, @@ -1403,9 +1614,57 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { + { 2, 1, 1, 0, 9 }, /* R */ { 0, 1, 1, 0, 9 }, /* G */ { 1, 1, 1, 0, 9 }, /* B */ - { 2, 1, 1, 0, 9 }, /* R */ + }, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_GBRP12LE] = { + .name = "gbrp12le", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 2, 1, 1, 0, 11 }, /* R */ + { 0, 1, 1, 0, 11 }, /* G */ + { 1, 1, 1, 0, 11 }, /* B */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_GBRP12BE] = { + .name = "gbrp12be", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 2, 1, 1, 0, 11 }, /* R */ + { 0, 1, 1, 0, 11 }, /* G */ + { 1, 1, 1, 0, 11 }, /* B */ + }, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_GBRP14LE] = { + .name = "gbrp14le", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 2, 1, 1, 0, 13 }, /* R */ + { 0, 1, 1, 0, 13 }, /* G */ + { 1, 1, 1, 0, 13 }, /* B */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_GBRP14BE] = { + .name = "gbrp14be", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 2, 1, 1, 0, 13 }, /* R */ + { 0, 1, 1, 0, 13 }, /* G */ + { 1, 1, 1, 0, 13 }, /* B */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, @@ -1415,9 +1674,9 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { + { 2, 1, 1, 0, 15 }, /* R */ { 0, 1, 1, 0, 15 }, /* G */ { 1, 1, 1, 0, 15 }, /* B */ - { 2, 1, 1, 0, 15 }, /* R */ }, .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, @@ -1427,12 +1686,51 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .log2_chroma_w = 0, .log2_chroma_h = 0, .comp = { + { 2, 1, 1, 0, 15 }, /* R */ { 0, 1, 1, 0, 15 }, /* G */ { 1, 1, 1, 0, 15 }, /* B */ - { 2, 1, 1, 0, 15 }, /* R */ }, .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB, }, + [AV_PIX_FMT_GBRAP] = { + .name = "gbrap", + .nb_components = 4, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 2, 0, 1, 0, 7 }, /* R */ + { 0, 0, 1, 0, 7 }, /* G */ + { 1, 0, 1, 0, 7 }, /* B */ + { 3, 0, 1, 0, 7 }, /* A */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, + }, + [AV_PIX_FMT_GBRAP16LE] = { + .name = "gbrap16le", + .nb_components = 4, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 2, 1, 1, 0, 15 }, /* R */ + { 0, 1, 1, 0, 15 }, /* G */ + { 1, 1, 1, 0, 15 }, /* B */ + { 3, 1, 1, 0, 15 }, /* A */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, + }, + [AV_PIX_FMT_GBRAP16BE] = { + .name = "gbrap16be", + .nb_components = 4, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 2, 1, 1, 0, 15 }, /* R */ + { 0, 1, 1, 0, 15 }, /* G */ + { 1, 1, 1, 0, 15 }, /* B */ + { 3, 1, 1, 0, 15 }, /* A */ + }, + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA, + }, [AV_PIX_FMT_VDPAU] = { .name = "vdpau", .log2_chroma_w = 1, @@ -1463,6 +1761,87 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { }, .flags = AV_PIX_FMT_FLAG_BE, }, + +#define BAYER8_DESC_COMMON \ + .nb_components= 3, \ + .log2_chroma_w= 0, \ + .log2_chroma_h= 0, \ + .comp = { \ + {0,0,0,0,1}, \ + {0,0,0,0,3}, \ + {0,0,0,0,1}, \ + }, \ + +#define BAYER16_DESC_COMMON \ + .nb_components= 3, \ + .log2_chroma_w= 0, \ + .log2_chroma_h= 0, \ + .comp = { \ + {0,1,0,0, 3}, \ + {0,1,0,0, 7}, \ + {0,1,0,0, 3}, \ + }, \ + + [AV_PIX_FMT_BAYER_BGGR8] = { + .name = "bayer_bggr8", + BAYER8_DESC_COMMON + .flags = AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_BAYER_BGGR16LE] = { + .name = "bayer_bggr16le", + BAYER16_DESC_COMMON + .flags = AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_BAYER_BGGR16BE] = { + .name = "bayer_bggr16be", + BAYER16_DESC_COMMON + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_BAYER_RGGB8] = { + .name = "bayer_rggb8", + BAYER8_DESC_COMMON + .flags = AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_BAYER_RGGB16LE] = { + .name = "bayer_rggb16le", + BAYER16_DESC_COMMON + .flags = AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_BAYER_RGGB16BE] = { + .name = "bayer_rggb16be", + BAYER16_DESC_COMMON + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_BAYER_GBRG8] = { + .name = "bayer_gbrg8", + BAYER8_DESC_COMMON + .flags = AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_BAYER_GBRG16LE] = { + .name = "bayer_gbrg16le", + BAYER16_DESC_COMMON + .flags = AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_BAYER_GBRG16BE] = { + .name = "bayer_gbrg16be", + BAYER16_DESC_COMMON + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_BAYER_GRBG8] = { + .name = "bayer_grbg8", + BAYER8_DESC_COMMON + .flags = AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_BAYER_GRBG16LE] = { + .name = "bayer_grbg16le", + BAYER16_DESC_COMMON + .flags = AV_PIX_FMT_FLAG_RGB, + }, + [AV_PIX_FMT_BAYER_GRBG16BE] = { + .name = "bayer_grbg16be", + BAYER16_DESC_COMMON + .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_RGB, + }, [AV_PIX_FMT_NV16] = { .name = "nv16", .nb_components = 3, @@ -1563,6 +1942,26 @@ int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc) return bits >> log2_pixels; } +int av_get_padded_bits_per_pixel(const AVPixFmtDescriptor *pixdesc) +{ + int c, bits = 0; + int log2_pixels = pixdesc->log2_chroma_w + pixdesc->log2_chroma_h; + int steps[4] = {0}; + + for (c = 0; c < pixdesc->nb_components; c++) { + const AVComponentDescriptor *comp = &pixdesc->comp[c]; + int s = c == 1 || c == 2 ? 0 : log2_pixels; + steps[comp->plane] = (comp->step_minus1 + 1) << s; + } + for (c = 0; c < 4; c++) + bits += steps[c]; + + if(!(pixdesc->flags & AV_PIX_FMT_FLAG_BITSTREAM)) + bits *= 8; + + return bits >> log2_pixels; +} + char *av_get_pix_fmt_string(char *buf, int buf_size, enum AVPixelFormat pix_fmt) { @@ -1589,8 +1988,11 @@ const AVPixFmtDescriptor *av_pix_fmt_desc_next(const AVPixFmtDescriptor *prev) { if (!prev) return &av_pix_fmt_descriptors[0]; - if (prev - av_pix_fmt_descriptors < FF_ARRAY_ELEMS(av_pix_fmt_descriptors) - 1) - return prev + 1; + while (prev - av_pix_fmt_descriptors < FF_ARRAY_ELEMS(av_pix_fmt_descriptors) - 1) { + prev++; + if (prev->name) + return prev; + } return NULL; } @@ -1631,53 +2033,284 @@ int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt) return ret; } +void ff_check_pixfmt_descriptors(void){ + int i, j; + + for (i=0; i<FF_ARRAY_ELEMS(av_pix_fmt_descriptors); i++) { + const AVPixFmtDescriptor *d = &av_pix_fmt_descriptors[i]; + uint8_t fill[4][8+6+3] = {{0}}; + uint8_t *data[4] = {fill[0], fill[1], fill[2], fill[3]}; + int linesize[4] = {0,0,0,0}; + uint16_t tmp[2]; + + if (!d->name && !d->nb_components && !d->log2_chroma_w && !d->log2_chroma_h && !d->flags) + continue; +// av_log(NULL, AV_LOG_DEBUG, "Checking: %s\n", d->name); + av_assert0(d->log2_chroma_w <= 3); + av_assert0(d->log2_chroma_h <= 3); + av_assert0(d->nb_components <= 4); + av_assert0(d->name && d->name[0]); + av_assert0((d->nb_components==4 || d->nb_components==2) == !!(d->flags & AV_PIX_FMT_FLAG_ALPHA)); + av_assert2(av_get_pix_fmt(d->name) == i); + + for (j=0; j<FF_ARRAY_ELEMS(d->comp); j++) { + const AVComponentDescriptor *c = &d->comp[j]; + if(j>=d->nb_components) { + av_assert0(!c->plane && !c->step_minus1 && !c->offset_plus1 && !c->shift && !c->depth_minus1); + continue; + } + if (d->flags & AV_PIX_FMT_FLAG_BITSTREAM) { + av_assert0(c->step_minus1 >= c->depth_minus1); + } else { + av_assert0(8*(c->step_minus1+1) >= c->depth_minus1+1); + } + if (!strncmp(d->name, "bayer_", 6)) + continue; + av_read_image_line(tmp, (void*)data, linesize, d, 0, 0, j, 2, 0); + av_assert0(tmp[0] == 0 && tmp[1] == 0); + tmp[0] = tmp[1] = (1<<(c->depth_minus1 + 1)) - 1; + av_write_image_line(tmp, data, linesize, d, 0, 0, j, 2); + } + } +} + enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt) { -#define PIX_FMT_SWAP_ENDIANNESS(fmt) \ - case AV_PIX_FMT_ ## fmt ## BE: return AV_PIX_FMT_ ## fmt ## LE; \ - case AV_PIX_FMT_ ## fmt ## LE: return AV_PIX_FMT_ ## fmt ## BE - - switch (pix_fmt) { - PIX_FMT_SWAP_ENDIANNESS(GRAY16); - PIX_FMT_SWAP_ENDIANNESS(RGB48); - PIX_FMT_SWAP_ENDIANNESS(RGB565); - PIX_FMT_SWAP_ENDIANNESS(RGB555); - PIX_FMT_SWAP_ENDIANNESS(RGB444); - PIX_FMT_SWAP_ENDIANNESS(BGR48); - PIX_FMT_SWAP_ENDIANNESS(BGR565); - PIX_FMT_SWAP_ENDIANNESS(BGR555); - PIX_FMT_SWAP_ENDIANNESS(BGR444); - - PIX_FMT_SWAP_ENDIANNESS(YUV420P9); - PIX_FMT_SWAP_ENDIANNESS(YUV422P9); - PIX_FMT_SWAP_ENDIANNESS(YUV444P9); - PIX_FMT_SWAP_ENDIANNESS(YUV420P10); - PIX_FMT_SWAP_ENDIANNESS(YUV422P10); - PIX_FMT_SWAP_ENDIANNESS(YUV444P10); - PIX_FMT_SWAP_ENDIANNESS(YUV420P16); - PIX_FMT_SWAP_ENDIANNESS(YUV422P16); - PIX_FMT_SWAP_ENDIANNESS(YUV444P16); - - PIX_FMT_SWAP_ENDIANNESS(GBRP9); - PIX_FMT_SWAP_ENDIANNESS(GBRP10); - PIX_FMT_SWAP_ENDIANNESS(GBRP16); - PIX_FMT_SWAP_ENDIANNESS(YUVA420P9); - PIX_FMT_SWAP_ENDIANNESS(YUVA422P9); - PIX_FMT_SWAP_ENDIANNESS(YUVA444P9); - PIX_FMT_SWAP_ENDIANNESS(YUVA420P10); - PIX_FMT_SWAP_ENDIANNESS(YUVA422P10); - PIX_FMT_SWAP_ENDIANNESS(YUVA444P10); - PIX_FMT_SWAP_ENDIANNESS(YUVA420P16); - PIX_FMT_SWAP_ENDIANNESS(YUVA422P16); - PIX_FMT_SWAP_ENDIANNESS(YUVA444P16); - - PIX_FMT_SWAP_ENDIANNESS(XYZ12); - PIX_FMT_SWAP_ENDIANNESS(NV20); - PIX_FMT_SWAP_ENDIANNESS(RGBA64); - PIX_FMT_SWAP_ENDIANNESS(BGRA64); - default: + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + char name[16]; + int i; + + if (!desc || strlen(desc->name) < 2) + return AV_PIX_FMT_NONE; + av_strlcpy(name, desc->name, sizeof(name)); + i = strlen(name) - 2; + if (strcmp(name + i, "be") && strcmp(name + i, "le")) return AV_PIX_FMT_NONE; + + name[i] ^= 'b' ^ 'l'; + + return get_pix_fmt_internal(name); +} + +#define FF_COLOR_NA -1 +#define FF_COLOR_RGB 0 /**< RGB color space */ +#define FF_COLOR_GRAY 1 /**< gray color space */ +#define FF_COLOR_YUV 2 /**< YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */ +#define FF_COLOR_YUV_JPEG 3 /**< YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */ + +#define pixdesc_has_alpha(pixdesc) \ + ((pixdesc)->nb_components == 2 || (pixdesc)->nb_components == 4 || (pixdesc)->flags & AV_PIX_FMT_FLAG_PAL) + + +static int get_color_type(const AVPixFmtDescriptor *desc) { + if (desc->flags & AV_PIX_FMT_FLAG_PAL) + return FF_COLOR_RGB; + + if(desc->nb_components == 1 || desc->nb_components == 2) + return FF_COLOR_GRAY; + + if(desc->name && !strncmp(desc->name, "yuvj", 4)) + return FF_COLOR_YUV_JPEG; + + if(desc->flags & AV_PIX_FMT_FLAG_RGB) + return FF_COLOR_RGB; + + if(desc->nb_components == 0) + return FF_COLOR_NA; + + return FF_COLOR_YUV; +} + +static int get_pix_fmt_depth(int *min, int *max, enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + int i; + + if (!desc || !desc->nb_components) { + *min = *max = 0; + return AVERROR(EINVAL); } -#undef PIX_FMT_SWAP_ENDIANNESS + + *min = INT_MAX, *max = -INT_MAX; + for (i = 0; i < desc->nb_components; i++) { + *min = FFMIN(desc->comp[i].depth_minus1+1, *min); + *max = FFMAX(desc->comp[i].depth_minus1+1, *max); + } + return 0; +} + +static int get_pix_fmt_score(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + unsigned *lossp, unsigned consider) +{ + const AVPixFmtDescriptor *src_desc = av_pix_fmt_desc_get(src_pix_fmt); + const AVPixFmtDescriptor *dst_desc = av_pix_fmt_desc_get(dst_pix_fmt); + int src_color, dst_color; + int src_min_depth, src_max_depth, dst_min_depth, dst_max_depth; + int ret, loss, i, nb_components; + int score = INT_MAX - 1; + + if (dst_pix_fmt >= AV_PIX_FMT_NB || dst_pix_fmt <= AV_PIX_FMT_NONE) + return ~0; + + /* compute loss */ + *lossp = loss = 0; + + if (dst_pix_fmt == src_pix_fmt) + return INT_MAX; + + if ((ret = get_pix_fmt_depth(&src_min_depth, &src_max_depth, src_pix_fmt)) < 0) + return ret; + if ((ret = get_pix_fmt_depth(&dst_min_depth, &dst_max_depth, dst_pix_fmt)) < 0) + return ret; + + src_color = get_color_type(src_desc); + dst_color = get_color_type(dst_desc); + if (dst_pix_fmt == AV_PIX_FMT_PAL8) + nb_components = FFMIN(src_desc->nb_components, 4); + else + nb_components = FFMIN(src_desc->nb_components, dst_desc->nb_components); + + for (i = 0; i < nb_components; i++) { + int depth_minus1 = (dst_pix_fmt == AV_PIX_FMT_PAL8) ? 7/nb_components : dst_desc->comp[i].depth_minus1; + if (src_desc->comp[i].depth_minus1 > depth_minus1 && (consider & FF_LOSS_DEPTH)) { + loss |= FF_LOSS_DEPTH; + score -= 65536 >> depth_minus1; + } + } + + if (consider & FF_LOSS_RESOLUTION) { + if (dst_desc->log2_chroma_w > src_desc->log2_chroma_w) { + loss |= FF_LOSS_RESOLUTION; + score -= 256 << dst_desc->log2_chroma_w; + } + if (dst_desc->log2_chroma_h > src_desc->log2_chroma_h) { + loss |= FF_LOSS_RESOLUTION; + score -= 256 << dst_desc->log2_chroma_h; + } + // don't favor 422 over 420 if downsampling is needed, because 420 has much better support on the decoder side + if (dst_desc->log2_chroma_w == 1 && src_desc->log2_chroma_w == 0 && + dst_desc->log2_chroma_h == 1 && src_desc->log2_chroma_h == 0 ) { + score += 512; + } + } + + if(consider & FF_LOSS_COLORSPACE) + switch(dst_color) { + case FF_COLOR_RGB: + if (src_color != FF_COLOR_RGB && + src_color != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_GRAY: + if (src_color != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_YUV: + if (src_color != FF_COLOR_YUV) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_YUV_JPEG: + if (src_color != FF_COLOR_YUV_JPEG && + src_color != FF_COLOR_YUV && + src_color != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + default: + /* fail safe test */ + if (src_color != dst_color) + loss |= FF_LOSS_COLORSPACE; + break; + } + if(loss & FF_LOSS_COLORSPACE) + score -= (nb_components * 65536) >> FFMIN(dst_desc->comp[0].depth_minus1, src_desc->comp[0].depth_minus1); + + if (dst_color == FF_COLOR_GRAY && + src_color != FF_COLOR_GRAY && (consider & FF_LOSS_CHROMA)) { + loss |= FF_LOSS_CHROMA; + score -= 2 * 65536; + } + if (!pixdesc_has_alpha(dst_desc) && (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))) { + loss |= FF_LOSS_ALPHA; + score -= 65536; + } + if (dst_pix_fmt == AV_PIX_FMT_PAL8 && (consider & FF_LOSS_COLORQUANT) && + (src_pix_fmt != AV_PIX_FMT_PAL8 && (src_color != FF_COLOR_GRAY || (pixdesc_has_alpha(src_desc) && (consider & FF_LOSS_ALPHA))))) { + loss |= FF_LOSS_COLORQUANT; + score -= 65536; + } + + *lossp = loss; + return score; +} + +int av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + int has_alpha) +{ + int loss; + int ret = get_pix_fmt_score(dst_pix_fmt, src_pix_fmt, &loss, has_alpha ? ~0 : ~FF_LOSS_ALPHA); + if (ret < 0) + return ret; + return loss; } + +enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr) +{ + enum AVPixelFormat dst_pix_fmt; + int loss1, loss2, loss_mask; + const AVPixFmtDescriptor *desc1 = av_pix_fmt_desc_get(dst_pix_fmt1); + const AVPixFmtDescriptor *desc2 = av_pix_fmt_desc_get(dst_pix_fmt2); + int score1, score2; + + loss_mask= loss_ptr?~*loss_ptr:~0; /* use loss mask if provided */ + if(!has_alpha) + loss_mask &= ~FF_LOSS_ALPHA; + + score1 = get_pix_fmt_score(dst_pix_fmt1, src_pix_fmt, &loss1, loss_mask); + score2 = get_pix_fmt_score(dst_pix_fmt2, src_pix_fmt, &loss2, loss_mask); + + if (score1 == score2) { + if(av_get_padded_bits_per_pixel(desc2) != av_get_padded_bits_per_pixel(desc1)) { + dst_pix_fmt = av_get_padded_bits_per_pixel(desc2) < av_get_padded_bits_per_pixel(desc1) ? dst_pix_fmt2 : dst_pix_fmt1; + } else { + dst_pix_fmt = desc2->nb_components < desc1->nb_components ? dst_pix_fmt2 : dst_pix_fmt1; + } + } else { + dst_pix_fmt = score1 < score2 ? dst_pix_fmt2 : dst_pix_fmt1; + } + + if (loss_ptr) + *loss_ptr = av_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha); + return dst_pix_fmt; +} + +#ifdef TEST + +int main(void){ + int i; + int err=0; + int skip = 0; + + for (i=0; i<AV_PIX_FMT_NB*2; i++) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i); + if(!desc || !desc->name) { + skip ++; + continue; + } + if (skip) { + av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip); + skip = 0; + } + av_log(NULL, AV_LOG_INFO, "pix fmt %s avg_bpp:%d colortype:%d\n", desc->name, av_get_padded_bits_per_pixel(desc), get_color_type(desc)); + if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) { + av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n"); + err = 1; + } + } + return err; +} + +#endif diff --git a/libavutil/pixdesc.h b/libavutil/pixdesc.h index 1c9e0af11f..41e81dbe13 100644 --- a/libavutil/pixdesc.h +++ b/libavutil/pixdesc.h @@ -2,20 +2,20 @@ * pixel format descriptor * Copyright (c) 2009 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -90,9 +90,12 @@ typedef struct AVPixFmtDescriptor { uint8_t flags; /** - * Parameters that describe how pixels are packed. If the format - * has chroma components, they must be stored in comp[1] and - * comp[2]. + * Parameters that describe how pixels are packed. + * If the format has 2 or 4 components, then alpha is last. + * If the format has 1 or 2 components, then luma is 0. + * If the format has 3 or 4 components, + * if the RGB flag is set then 0 is red, 1 is green and 2 is blue; + * otherwise 0 is luma, 1 is chroma-U and 2 is chroma-V. */ AVComponentDescriptor comp[4]; @@ -127,7 +130,7 @@ typedef struct AVPixFmtDescriptor { */ #define AV_PIX_FMT_FLAG_RGB (1 << 5) /** - * The pixel format is "pseudo-paletted". This means that Libav treats it as + * The pixel format is "pseudo-paletted". This means that FFmpeg treats it as * paletted internally, but the palette is generated by the decoder and is not * stored in the file. */ @@ -205,7 +208,7 @@ void av_write_image_line(const uint16_t *src, uint8_t *data[4], * For example in a little-endian system, first looks for "gray16", * then for "gray16le". * - * Finally if no pixel format has been found, returns PIX_FMT_NONE. + * Finally if no pixel format has been found, returns AV_PIX_FMT_NONE. */ enum AVPixelFormat av_get_pix_fmt(const char *name); @@ -219,7 +222,7 @@ const char *av_get_pix_fmt_name(enum AVPixelFormat pix_fmt); /** * Print in buf the string corresponding to the pixel format with - * number pix_fmt, or an header if pix_fmt is negative. + * number pix_fmt, or a header if pix_fmt is negative. * * @param buf the buffer where to write the string * @param buf_size the size of buf @@ -242,6 +245,12 @@ char *av_get_pix_fmt_string(char *buf, int buf_size, int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); /** + * Return the number of bits per pixel for the pixel format + * described by pixdesc, including any padding or unused bits. + */ +int av_get_padded_bits_per_pixel(const AVPixFmtDescriptor *pixdesc); + +/** * @return a pixel format descriptor for provided pixel format or NULL if * this pixel format is unknown. */ @@ -266,9 +275,14 @@ enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc); * Utility function to access log2_chroma_w log2_chroma_h from * the pixel format AVPixFmtDescriptor. * + * See av_get_chroma_sub_sample() for a function that asserts a + * valid pixel format instead of returning an error code. + * Its recommended that you use avcodec_get_chroma_sub_sample unless + * you do check the return code! + * * @param[in] pix_fmt the pixel format - * @param[out] h_shift store log2_chroma_h - * @param[out] v_shift store log2_chroma_w + * @param[out] h_shift store log2_chroma_w + * @param[out] v_shift store log2_chroma_h * * @return 0 on success, AVERROR(ENOSYS) on invalid or unknown pixel format */ @@ -281,6 +295,8 @@ int av_pix_fmt_get_chroma_sub_sample(enum AVPixelFormat pix_fmt, */ int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt); +void ff_check_pixfmt_descriptors(void); + /** * Utility function to swap the endianness of a pixel format. * @@ -291,4 +307,53 @@ int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt); */ enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt); +#define FF_LOSS_RESOLUTION 0x0001 /**< loss due to resolution change */ +#define FF_LOSS_DEPTH 0x0002 /**< loss due to color depth change */ +#define FF_LOSS_COLORSPACE 0x0004 /**< loss due to color space conversion */ +#define FF_LOSS_ALPHA 0x0008 /**< loss of alpha bits */ +#define FF_LOSS_COLORQUANT 0x0010 /**< loss due to color quantization */ +#define FF_LOSS_CHROMA 0x0020 /**< loss of chroma (e.g. RGB to gray conversion) */ + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +int av_get_pix_fmt_loss(enum AVPixelFormat dst_pix_fmt, + enum AVPixelFormat src_pix_fmt, + int has_alpha); + +/** + * Compute what kind of losses will occur when converting from one specific + * pixel format to another. + * When converting from one pixel format to another, information loss may occur. + * For example, when converting from RGB24 to GRAY, the color information will + * be lost. Similarly, other losses occur when converting from some formats to + * other formats. These losses can involve loss of chroma, but also loss of + * resolution, loss of color depth, loss due to the color space conversion, loss + * of the alpha bits or loss due to color quantization. + * av_get_fix_fmt_loss() informs you about the various types of losses + * which will occur when converting from one pixel format to another. + * + * @param[in] dst_pix_fmt destination pixel format + * @param[in] src_pix_fmt source pixel format + * @param[in] has_alpha Whether the source pixel format alpha channel is used. + * @return Combination of flags informing you what kind of losses will occur + * (maximum loss for an invalid dst_pix_fmt). + */ +enum AVPixelFormat av_find_best_pix_fmt_of_2(enum AVPixelFormat dst_pix_fmt1, enum AVPixelFormat dst_pix_fmt2, + enum AVPixelFormat src_pix_fmt, int has_alpha, int *loss_ptr); #endif /* AVUTIL_PIXDESC_H */ diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 835550ad18..6e4568133e 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -30,21 +30,24 @@ #include "libavutil/avconfig.h" #include "version.h" +#define AVPALETTE_SIZE 1024 +#define AVPALETTE_COUNT 256 + /** * Pixel format. * * @note - * PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA + * AV_PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA * color is put together as: * (A << 24) | (R << 16) | (G << 8) | B * This is stored as BGRA on little-endian CPU architectures and ARGB on * big-endian CPUs. * * @par - * When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized + * When the pixel format is palettized RGB (AV_PIX_FMT_PAL8), the palettized * image data is stored in AVFrame.data[0]. The palette is transported in * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is - * formatted the same as in PIX_FMT_RGB32 described above (i.e., it is + * formatted the same as in AV_PIX_FMT_RGB32 described above (i.e., it is * also endian-specific). Note also that the individual RGB palette * components stored in AVFrame.data[1] should be in the range 0..255. * This is important as many custom PAL8 video codecs that were designed @@ -56,8 +59,8 @@ * allocating the picture. * * @note - * Make sure that all newly added big-endian formats have pix_fmt & 1 == 1 - * and that all newly added little-endian formats have pix_fmt & 1 == 0. + * Make sure that all newly added big-endian formats have (pix_fmt & 1) == 1 + * and that all newly added little-endian formats have (pix_fmt & 1) == 0. * This allows simpler detection of big vs little-endian. */ enum AVPixelFormat { @@ -80,6 +83,7 @@ enum AVPixelFormat { #if FF_API_XVMC AV_PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing AV_PIX_FMT_XVMC_MPEG2_IDCT, +#define AV_PIX_FMT_XVMC AV_PIX_FMT_XVMC_MPEG2_IDCT #endif /* FF_API_XVMC */ AV_PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1 AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3 @@ -144,9 +148,16 @@ enum AVPixelFormat { AV_PIX_FMT_YA8, ///< 8bit gray, 8bit alpha AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 + AV_PIX_FMT_GRAY8A= AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8 AV_PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian AV_PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian + + /** + * The following 12 formats have the disadvantage of needing 1 format for each bit depth. + * Notice that each 9/10 bits sample is stored in 16 bits with extra padding. + * If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately is better. + */ AV_PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian AV_PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian AV_PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian @@ -160,6 +171,13 @@ enum AVPixelFormat { AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian AV_PIX_FMT_VDA_VLD, ///< hardware decoding through VDA + +#ifdef AV_PIX_FMT_ABI_GIT_MASTER + AV_PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + AV_PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian +#endif AV_PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp AV_PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big-endian AV_PIX_FMT_GBRP9LE, ///< planar GBR 4:4:4 27bpp, little-endian @@ -167,8 +185,15 @@ enum AVPixelFormat { AV_PIX_FMT_GBRP10LE, ///< planar GBR 4:4:4 30bpp, little-endian AV_PIX_FMT_GBRP16BE, ///< planar GBR 4:4:4 48bpp, big-endian AV_PIX_FMT_GBRP16LE, ///< planar GBR 4:4:4 48bpp, little-endian - AV_PIX_FMT_YUVA422P, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) - AV_PIX_FMT_YUVA444P, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + + /** + * duplicated pixel formats for compatibility with libav. + * FFmpeg supports these formats since May 8 2012 and Jan 28 2012 (commits f9ca1ac7 and 143a5c55) + * Libav added them Oct 12 2012 with incompatible values (commit 6d5600e85) + */ + AV_PIX_FMT_YUVA422P_LIBAV, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) + AV_PIX_FMT_YUVA444P_LIBAV, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + AV_PIX_FMT_YUVA420P9BE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), big-endian AV_PIX_FMT_YUVA420P9LE, ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), little-endian AV_PIX_FMT_YUVA422P9BE, ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), big-endian @@ -187,21 +212,80 @@ enum AVPixelFormat { AV_PIX_FMT_YUVA422P16LE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian) AV_PIX_FMT_YUVA444P16BE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian) AV_PIX_FMT_YUVA444P16LE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian) + AV_PIX_FMT_VDPAU, ///< HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface + AV_PIX_FMT_XYZ12LE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as little-endian, the 4 lower bits are set to 0 AV_PIX_FMT_XYZ12BE, ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as big-endian, the 4 lower bits are set to 0 AV_PIX_FMT_NV16, ///< interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples) AV_PIX_FMT_NV20LE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian AV_PIX_FMT_NV20BE, ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian - AV_PIX_FMT_RGBA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian - AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian - AV_PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian - AV_PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + /** + * duplicated pixel formats for compatibility with libav. + * FFmpeg supports these formats since Sat Sep 24 06:01:45 2011 +0200 (commits 9569a3c9f41387a8c7d1ce97d8693520477a66c3) + * also see Fri Nov 25 01:38:21 2011 +0100 92afb431621c79155fcb7171d26f137eb1bee028 + * Libav added them Sun Mar 16 23:05:47 2014 +0100 with incompatible values (commit 1481d24c3a0abf81e1d7a514547bd5305232be30) + */ + AV_PIX_FMT_RGBA64BE_LIBAV, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_RGBA64LE_LIBAV, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + AV_PIX_FMT_BGRA64BE_LIBAV, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_BGRA64LE_LIBAV, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian AV_PIX_FMT_YVYU422, ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb AV_PIX_FMT_VDA, ///< HW acceleration through VDA, data[3] contains a CVPixelBufferRef + +#ifndef AV_PIX_FMT_ABI_GIT_MASTER + AV_PIX_FMT_RGBA64BE=0x123, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_RGBA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian + AV_PIX_FMT_BGRA64BE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian + AV_PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian +#endif + AV_PIX_FMT_0RGB=0x123+4, ///< packed RGB 8:8:8, 32bpp, 0RGB0RGB... + AV_PIX_FMT_RGB0, ///< packed RGB 8:8:8, 32bpp, RGB0RGB0... + AV_PIX_FMT_0BGR, ///< packed BGR 8:8:8, 32bpp, 0BGR0BGR... + AV_PIX_FMT_BGR0, ///< packed BGR 8:8:8, 32bpp, BGR0BGR0... + AV_PIX_FMT_YUVA444P, ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples) + AV_PIX_FMT_YUVA422P, ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples) + + AV_PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + AV_PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + AV_PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian + AV_PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + AV_PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian + AV_PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian + AV_PIX_FMT_GBRP12BE, ///< planar GBR 4:4:4 36bpp, big-endian + AV_PIX_FMT_GBRP12LE, ///< planar GBR 4:4:4 36bpp, little-endian + AV_PIX_FMT_GBRP14BE, ///< planar GBR 4:4:4 42bpp, big-endian + AV_PIX_FMT_GBRP14LE, ///< planar GBR 4:4:4 42bpp, little-endian + AV_PIX_FMT_GBRAP, ///< planar GBRA 4:4:4:4 32bpp + AV_PIX_FMT_GBRAP16BE, ///< planar GBRA 4:4:4:4 64bpp, big-endian + AV_PIX_FMT_GBRAP16LE, ///< planar GBRA 4:4:4:4 64bpp, little-endian + AV_PIX_FMT_YUVJ411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of PIX_FMT_YUV411P and setting color_range + + AV_PIX_FMT_BAYER_BGGR8, ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples */ + AV_PIX_FMT_BAYER_RGGB8, ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples */ + AV_PIX_FMT_BAYER_GBRG8, ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples */ + AV_PIX_FMT_BAYER_GRBG8, ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples */ + AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian */ + AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian */ + AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian */ + AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian */ + AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian */ + AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian */ + AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian */ + AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian */ +#if !FF_API_XVMC + AV_PIX_FMT_XVMC,///< XVideo Motion Acceleration via common packet passing +#endif /* !FF_API_XVMC */ + AV_PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions #if FF_API_PIX_FMT @@ -209,6 +293,19 @@ enum AVPixelFormat { #endif }; +#if AV_HAVE_INCOMPATIBLE_LIBAV_ABI +#define AV_PIX_FMT_YUVA422P AV_PIX_FMT_YUVA422P_LIBAV +#define AV_PIX_FMT_YUVA444P AV_PIX_FMT_YUVA444P_LIBAV +#define AV_PIX_FMT_RGBA64BE AV_PIX_FMT_RGBA64BE_LIBAV +#define AV_PIX_FMT_RGBA64LE AV_PIX_FMT_RGBA64LE_LIBAV +#define AV_PIX_FMT_BGRA64BE AV_PIX_FMT_BGRA64BE_LIBAV +#define AV_PIX_FMT_BGRA64LE AV_PIX_FMT_BGRA64LE_LIBAV +#endif + + +#define AV_PIX_FMT_Y400A AV_PIX_FMT_GRAY8A +#define AV_PIX_FMT_GBR24P AV_PIX_FMT_GBRP + #if AV_HAVE_BIGENDIAN # define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##be #else @@ -219,6 +316,8 @@ enum AVPixelFormat { #define AV_PIX_FMT_RGB32_1 AV_PIX_FMT_NE(RGBA, ABGR) #define AV_PIX_FMT_BGR32 AV_PIX_FMT_NE(ABGR, RGBA) #define AV_PIX_FMT_BGR32_1 AV_PIX_FMT_NE(BGRA, ARGB) +#define AV_PIX_FMT_0RGB32 AV_PIX_FMT_NE(0RGB, BGR0) +#define AV_PIX_FMT_0BGR32 AV_PIX_FMT_NE(0BGR, RGB0) #define AV_PIX_FMT_GRAY16 AV_PIX_FMT_NE(GRAY16BE, GRAY16LE) #define AV_PIX_FMT_RGB48 AV_PIX_FMT_NE(RGB48BE, RGB48LE) @@ -238,13 +337,28 @@ enum AVPixelFormat { #define AV_PIX_FMT_YUV420P10 AV_PIX_FMT_NE(YUV420P10BE, YUV420P10LE) #define AV_PIX_FMT_YUV422P10 AV_PIX_FMT_NE(YUV422P10BE, YUV422P10LE) #define AV_PIX_FMT_YUV444P10 AV_PIX_FMT_NE(YUV444P10BE, YUV444P10LE) +#define AV_PIX_FMT_YUV420P12 AV_PIX_FMT_NE(YUV420P12BE, YUV420P12LE) +#define AV_PIX_FMT_YUV422P12 AV_PIX_FMT_NE(YUV422P12BE, YUV422P12LE) +#define AV_PIX_FMT_YUV444P12 AV_PIX_FMT_NE(YUV444P12BE, YUV444P12LE) +#define AV_PIX_FMT_YUV420P14 AV_PIX_FMT_NE(YUV420P14BE, YUV420P14LE) +#define AV_PIX_FMT_YUV422P14 AV_PIX_FMT_NE(YUV422P14BE, YUV422P14LE) +#define AV_PIX_FMT_YUV444P14 AV_PIX_FMT_NE(YUV444P14BE, YUV444P14LE) #define AV_PIX_FMT_YUV420P16 AV_PIX_FMT_NE(YUV420P16BE, YUV420P16LE) #define AV_PIX_FMT_YUV422P16 AV_PIX_FMT_NE(YUV422P16BE, YUV422P16LE) #define AV_PIX_FMT_YUV444P16 AV_PIX_FMT_NE(YUV444P16BE, YUV444P16LE) #define AV_PIX_FMT_GBRP9 AV_PIX_FMT_NE(GBRP9BE , GBRP9LE) #define AV_PIX_FMT_GBRP10 AV_PIX_FMT_NE(GBRP10BE, GBRP10LE) +#define AV_PIX_FMT_GBRP12 AV_PIX_FMT_NE(GBRP12BE, GBRP12LE) +#define AV_PIX_FMT_GBRP14 AV_PIX_FMT_NE(GBRP14BE, GBRP14LE) #define AV_PIX_FMT_GBRP16 AV_PIX_FMT_NE(GBRP16BE, GBRP16LE) +#define AV_PIX_FMT_GBRAP16 AV_PIX_FMT_NE(GBRAP16BE, GBRAP16LE) + +#define AV_PIX_FMT_BAYER_BGGR16 AV_PIX_FMT_NE(BAYER_BGGR16BE, BAYER_BGGR16LE) +#define AV_PIX_FMT_BAYER_RGGB16 AV_PIX_FMT_NE(BAYER_RGGB16BE, BAYER_RGGB16LE) +#define AV_PIX_FMT_BAYER_GBRG16 AV_PIX_FMT_NE(BAYER_GBRG16BE, BAYER_GBRG16LE) +#define AV_PIX_FMT_BAYER_GRBG16 AV_PIX_FMT_NE(BAYER_GRBG16BE, BAYER_GRBG16LE) + #define AV_PIX_FMT_YUVA420P9 AV_PIX_FMT_NE(YUVA420P9BE , YUVA420P9LE) #define AV_PIX_FMT_YUVA422P9 AV_PIX_FMT_NE(YUVA422P9BE , YUVA422P9LE) @@ -263,12 +377,17 @@ enum AVPixelFormat { #if FF_API_PIX_FMT #define PixelFormat AVPixelFormat +#define PIX_FMT_Y400A AV_PIX_FMT_Y400A +#define PIX_FMT_GBR24P AV_PIX_FMT_GBR24P + #define PIX_FMT_NE(be, le) AV_PIX_FMT_NE(be, le) #define PIX_FMT_RGB32 AV_PIX_FMT_RGB32 #define PIX_FMT_RGB32_1 AV_PIX_FMT_RGB32_1 #define PIX_FMT_BGR32 AV_PIX_FMT_BGR32 #define PIX_FMT_BGR32_1 AV_PIX_FMT_BGR32_1 +#define PIX_FMT_0RGB32 AV_PIX_FMT_0RGB32 +#define PIX_FMT_0BGR32 AV_PIX_FMT_0BGR32 #define PIX_FMT_GRAY16 AV_PIX_FMT_GRAY16 #define PIX_FMT_RGB48 AV_PIX_FMT_RGB48 @@ -286,12 +405,22 @@ enum AVPixelFormat { #define PIX_FMT_YUV420P10 AV_PIX_FMT_YUV420P10 #define PIX_FMT_YUV422P10 AV_PIX_FMT_YUV422P10 #define PIX_FMT_YUV444P10 AV_PIX_FMT_YUV444P10 +#define PIX_FMT_YUV420P12 AV_PIX_FMT_YUV420P12 +#define PIX_FMT_YUV422P12 AV_PIX_FMT_YUV422P12 +#define PIX_FMT_YUV444P12 AV_PIX_FMT_YUV444P12 +#define PIX_FMT_YUV420P14 AV_PIX_FMT_YUV420P14 +#define PIX_FMT_YUV422P14 AV_PIX_FMT_YUV422P14 +#define PIX_FMT_YUV444P14 AV_PIX_FMT_YUV444P14 #define PIX_FMT_YUV420P16 AV_PIX_FMT_YUV420P16 #define PIX_FMT_YUV422P16 AV_PIX_FMT_YUV422P16 #define PIX_FMT_YUV444P16 AV_PIX_FMT_YUV444P16 +#define PIX_FMT_RGBA64 AV_PIX_FMT_RGBA64 +#define PIX_FMT_BGRA64 AV_PIX_FMT_BGRA64 #define PIX_FMT_GBRP9 AV_PIX_FMT_GBRP9 #define PIX_FMT_GBRP10 AV_PIX_FMT_GBRP10 +#define PIX_FMT_GBRP12 AV_PIX_FMT_GBRP12 +#define PIX_FMT_GBRP14 AV_PIX_FMT_GBRP14 #define PIX_FMT_GBRP16 AV_PIX_FMT_GBRP16 #endif @@ -350,6 +479,8 @@ enum AVColorSpace { AVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance system AVCOL_SPC_NB, ///< Not part of ABI }; +#define AVCOL_SPC_YCGCO AVCOL_SPC_YCOCG + /** * MPEG vs JPEG YUV range. diff --git a/libavutil/ppc/cpu.c b/libavutil/ppc/cpu.c index 50107e1fca..d51e3fa659 100644 --- a/libavutil/ppc/cpu.c +++ b/libavutil/ppc/cpu.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -62,7 +62,7 @@ int ff_get_cpu_flags_ppc(void) if (err == 0) return has_vu ? AV_CPU_FLAG_ALTIVEC : 0; return 0; -#elif CONFIG_RUNTIME_CPUDETECT +#elif CONFIG_RUNTIME_CPUDETECT && defined(__linux__) && !ARCH_PPC64 int proc_ver; // Support of mfspr PVR emulation added in Linux 2.6.17. __asm__ volatile("mfspr %0, 287" : "=r" (proc_ver)); diff --git a/libavutil/ppc/cpu.h b/libavutil/ppc/cpu.h index f8fae58698..0a212f33cb 100644 --- a/libavutil/ppc/cpu.h +++ b/libavutil/ppc/cpu.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/ppc/float_dsp_altivec.c b/libavutil/ppc/float_dsp_altivec.c index fee4e7c7db..8cee82c1c7 100644 --- a/libavutil/ppc/float_dsp_altivec.c +++ b/libavutil/ppc/float_dsp_altivec.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2006 Luca Barbato <lu_zero@gentoo.org> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/ppc/float_dsp_altivec.h b/libavutil/ppc/float_dsp_altivec.h index 87d50a8878..e1d530afa5 100644 --- a/libavutil/ppc/float_dsp_altivec.h +++ b/libavutil/ppc/float_dsp_altivec.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2006 Luca Barbato <lu_zero@gentoo.org> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/ppc/float_dsp_init.c b/libavutil/ppc/float_dsp_init.c index 60d0f19aca..9dd2072b7a 100644 --- a/libavutil/ppc/float_dsp_init.c +++ b/libavutil/ppc/float_dsp_init.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2006 Luca Barbato <lu_zero@gentoo.org> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/ppc/intreadwrite.h b/libavutil/ppc/intreadwrite.h index fec54e63c5..733c01e48f 100644 --- a/libavutil/ppc/intreadwrite.h +++ b/libavutil/ppc/intreadwrite.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2008 Mans Rullgard <mans@mansr.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -26,46 +26,60 @@ #if HAVE_XFORM_ASM -#define AV_RL16 AV_RL16 -static av_always_inline uint16_t AV_RL16(const void *p) +#if HAVE_BIGENDIAN +#define AV_RL16 AV_RX16 +#define AV_WL16 AV_WX16 +#define AV_RL32 AV_RX32 +#define AV_WL32 AV_WX32 +#else +#define AV_RB16 AV_RX16 +#define AV_WB16 AV_WX16 +#define AV_RB32 AV_RX32 +#define AV_WB32 AV_WX32 +#endif + +static av_always_inline uint16_t AV_RX16(const void *p) { uint16_t v; __asm__ ("lhbrx %0, %y1" : "=r"(v) : "Z"(*(const uint16_t*)p)); return v; } -#define AV_WL16 AV_WL16 -static av_always_inline void AV_WL16(void *p, uint16_t v) +static av_always_inline void AV_WX16(void *p, uint16_t v) { __asm__ ("sthbrx %1, %y0" : "=Z"(*(uint16_t*)p) : "r"(v)); } -#define AV_RL32 AV_RL32 -static av_always_inline uint32_t AV_RL32(const void *p) +static av_always_inline uint32_t AV_RX32(const void *p) { uint32_t v; __asm__ ("lwbrx %0, %y1" : "=r"(v) : "Z"(*(const uint32_t*)p)); return v; } -#define AV_WL32 AV_WL32 -static av_always_inline void AV_WL32(void *p, uint32_t v) +static av_always_inline void AV_WX32(void *p, uint32_t v) { __asm__ ("stwbrx %1, %y0" : "=Z"(*(uint32_t*)p) : "r"(v)); } #if HAVE_LDBRX -#define AV_RL64 AV_RL64 -static av_always_inline uint64_t AV_RL64(const void *p) +#if HAVE_BIGENDIAN +#define AV_RL64 AV_RX64 +#define AV_WL64 AV_WX64 +#else +#define AV_RB64 AV_RX64 +#define AV_WB64 AV_WX64 +#endif + +static av_always_inline uint64_t AV_RX64(const void *p) { uint64_t v; __asm__ ("ldbrx %0, %y1" : "=r"(v) : "Z"(*(const uint64_t*)p)); return v; } -#define AV_WL64 AV_WL64 -static av_always_inline void AV_WL64(void *p, uint64_t v) +static av_always_inline void AV_WX64(void *p, uint64_t v) { __asm__ ("stdbrx %1, %y0" : "=Z"(*(uint64_t*)p) : "r"(v)); } @@ -102,7 +116,9 @@ static av_always_inline void AV_WL64(void *p, uint64_t v) * default, so we override it here. */ +#if HAVE_BIGENDIAN #define AV_RB64(p) (*(const uint64_t *)(p)) #define AV_WB64(p, v) (*(uint64_t *)(p) = (v)) +#endif #endif /* AVUTIL_PPC_INTREADWRITE_H */ diff --git a/libavutil/ppc/timer.h b/libavutil/ppc/timer.h index 8d08d2835b..b28e624566 100644 --- a/libavutil/ppc/timer.h +++ b/libavutil/ppc/timer.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2005 Luca Barbato <lu_zero@gentoo.org> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -25,8 +25,6 @@ #include "config.h" -#if HAVE_INLINE_ASM_LABELS - #define AV_READ_TIME read_time static inline uint64_t read_time(void) @@ -35,12 +33,11 @@ static inline uint64_t read_time(void) /* from section 2.2.1 of the 32-bit PowerPC PEM */ __asm__ volatile( - "1:\n" "mftbu %2\n" "mftb %0\n" "mftbu %1\n" "cmpw %2,%1\n" - "bne 1b\n" + "bne $-0x10\n" : "=r"(tbl), "=r"(tbu), "=r"(temp) : : "cc"); @@ -48,6 +45,4 @@ static inline uint64_t read_time(void) return (((uint64_t)tbu)<<32) | (uint64_t)tbl; } -#endif /* HAVE_INLINE_ASM_LABELS */ - #endif /* AVUTIL_PPC_TIMER_H */ diff --git a/libavutil/ppc/types_altivec.h b/libavutil/ppc/types_altivec.h index 0a4eaf885f..69d8957509 100644 --- a/libavutil/ppc/types_altivec.h +++ b/libavutil/ppc/types_altivec.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2006 Guillaume Poirier <gpoirier@mplayerhq.hu> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/ppc/util_altivec.h b/libavutil/ppc/util_altivec.h index 5624ac5523..2c0ad5f6c6 100644 --- a/libavutil/ppc/util_altivec.h +++ b/libavutil/ppc/util_altivec.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/qsort.h b/libavutil/qsort.h new file mode 100644 index 0000000000..30edcc8371 --- /dev/null +++ b/libavutil/qsort.h @@ -0,0 +1,117 @@ +/* + * copyright (c) 2012 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 "common.h" + + +/** + * Quicksort + * This sort is fast, and fully inplace but not stable and it is possible + * to construct input that requires O(n^2) time but this is very unlikely to + * happen with non constructed input. + */ +#define AV_QSORT(p, num, type, cmp) {\ + void *stack[64][2];\ + int sp= 1;\ + stack[0][0] = p;\ + stack[0][1] = (p)+(num)-1;\ + while(sp){\ + type *start= stack[--sp][0];\ + type *end = stack[ sp][1];\ + while(start < end){\ + if(start < end-1) {\ + int checksort=0;\ + type *right = end-2;\ + type *left = start+1;\ + type *mid = start + ((end-start)>>1);\ + if(cmp(start, end) > 0) {\ + if(cmp( end, mid) > 0) FFSWAP(type, *start, *mid);\ + else FFSWAP(type, *start, *end);\ + }else{\ + if(cmp(start, mid) > 0) FFSWAP(type, *start, *mid);\ + else checksort= 1;\ + }\ + if(cmp(mid, end) > 0){ \ + FFSWAP(type, *mid, *end);\ + checksort=0;\ + }\ + if(start == end-2) break;\ + FFSWAP(type, end[-1], *mid);\ + while(left <= right){\ + while(left<=right && cmp(left, end-1) < 0)\ + left++;\ + while(left<=right && cmp(right, end-1) > 0)\ + right--;\ + if(left <= right){\ + FFSWAP(type, *left, *right);\ + left++;\ + right--;\ + }\ + }\ + FFSWAP(type, end[-1], *left);\ + if(checksort && (mid == left-1 || mid == left)){\ + mid= start;\ + while(mid<end && cmp(mid, mid+1) <= 0)\ + mid++;\ + if(mid==end)\ + break;\ + }\ + if(end-left < left-start){\ + stack[sp ][0]= start;\ + stack[sp++][1]= right;\ + start = left+1;\ + }else{\ + stack[sp ][0]= left+1;\ + stack[sp++][1]= end;\ + end = right;\ + }\ + }else{\ + if(cmp(start, end) > 0)\ + FFSWAP(type, *start, *end);\ + break;\ + }\ + }\ + }\ +} + +/** + * Merge sort, this sort requires a temporary buffer and is stable, its worst + * case time is O(n log n) + * @param p must be a lvalue pointer, this function may exchange it with tmp + * @param tmp must be a lvalue pointer, this function may exchange it with p + */ +#define AV_MSORT(p, tmp, num, type, cmp) {\ + unsigned i, j, step;\ + for(step=1; step<(num); step+=step){\ + for(i=0; i<(num); i+=2*step){\ + unsigned a[2] = {i, i+step};\ + unsigned end = FFMIN(i+2*step, (num));\ + for(j=i; a[0]<i+step && a[1]<end; j++){\ + int idx= cmp(p+a[0], p+a[1]) > 0;\ + tmp[j] = p[ a[idx]++ ];\ + }\ + if(a[0]>=i+step) a[0] = a[1];\ + for(; j<end; j++){\ + tmp[j] = p[ a[0]++ ];\ + }\ + }\ + FFSWAP(type*, p, tmp);\ + }\ +} diff --git a/libavutil/random_seed.c b/libavutil/random_seed.c index 26884cbcd6..8aa8c3879b 100644 --- a/libavutil/random_seed.c +++ b/libavutil/random_seed.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2009 Baptiste Coudurier <baptiste.coudurier@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -23,6 +23,9 @@ #if HAVE_UNISTD_H #include <unistd.h> #endif +#if HAVE_IO_H +#include <io.h> +#endif #if HAVE_CRYPTGENRANDOM #include <windows.h> #include <wincrypt.h> @@ -30,13 +33,18 @@ #include <fcntl.h> #include <math.h> #include <time.h> +#include <string.h> +#include "avassert.h" #include "internal.h" #include "intreadwrite.h" -#include "mem.h" #include "timer.h" #include "random_seed.h" #include "sha.h" +#ifndef TEST +#define TEST 0 +#endif + static int read_random(uint32_t *dst, const char *file) { #if HAVE_UNISTD_H @@ -56,13 +64,26 @@ static int read_random(uint32_t *dst, const char *file) static uint32_t get_generic_seed(void) { - struct AVSHA *sha = av_sha_alloc(); + uint8_t tmp[120]; + struct AVSHA *sha = (void*)tmp; clock_t last_t = 0; static uint64_t i = 0; static uint32_t buffer[512] = { 0 }; unsigned char digest[20]; uint64_t last_i = i; + av_assert0(sizeof(tmp) >= av_sha_size); + + if(TEST){ + memset(buffer, 0, sizeof(buffer)); + last_i = i = 0; + }else{ +#ifdef AV_READ_TIME + buffer[13] ^= AV_READ_TIME(); + buffer[41] ^= AV_READ_TIME()>>32; +#endif + } + for (;;) { clock_t t = clock(); @@ -70,25 +91,18 @@ static uint32_t get_generic_seed(void) buffer[i & 511]++; } else { buffer[++i & 511] += (t - last_t) % 3294638521U; - if (last_i && i - last_i > 4 || i - last_i > 64) + if (last_i && i - last_i > 4 || i - last_i > 64 || TEST && i - last_i > 8) break; } last_t = t; } - if (!sha) { - uint32_t seed = 0; - int j; - // Unable to allocate an sha context, just xor the buffer together - // to create something hopefully unique. - for (j = 0; j < 512; j++) - seed ^= buffer[j]; - return seed; - } + if(TEST) + buffer[0] = buffer[1] = 0; + av_sha_init(sha, 160); - av_sha_update(sha, (const uint8_t *) buffer, sizeof(buffer)); + av_sha_update(sha, (const uint8_t *)buffer, sizeof(buffer)); av_sha_final(sha, digest); - av_free(sha); return AV_RB32(digest) + AV_RB32(digest + 16); } @@ -113,3 +127,29 @@ uint32_t av_get_random_seed(void) return seed; return get_generic_seed(); } + +#if TEST +#undef printf +#define N 256 +#include <stdio.h> + +int main(void) +{ + int i, j, retry; + uint32_t seeds[N]; + + for (retry=0; retry<3; retry++){ + for (i=0; i<N; i++){ + seeds[i] = av_get_random_seed(); + for (j=0; j<i; j++) + if (seeds[j] == seeds[i]) + goto retry; + } + printf("seeds OK\n"); + return 0; + retry:; + } + printf("FAIL at %d with %X\n", j, seeds[j]); + return 1; +} +#endif diff --git a/libavutil/random_seed.h b/libavutil/random_seed.h index b1fad13d07..0462a048e0 100644 --- a/libavutil/random_seed.h +++ b/libavutil/random_seed.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2009 Baptiste Coudurier <baptiste.coudurier@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -28,12 +28,11 @@ */ /** - * Get random data. - * - * This function can be called repeatedly to generate more random bits - * as needed. It is generally quite slow, and usually used to seed a - * PRNG. As it uses /dev/urandom and /dev/random, the quality of the - * returned random data depends on the platform. + * Get a seed to use in conjunction with random functions. + * This function tries to provide a good seed at a best effort bases. + * Its possible to call this function multiple times if more bits are needed. + * It can be quite slow, which is why it should only be used as seed for a faster + * PRNG. The quality of the seed depends on the platform. */ uint32_t av_get_random_seed(void); diff --git a/libavutil/rational.c b/libavutil/rational.c index 4053936194..55a8dd5897 100644 --- a/libavutil/rational.c +++ b/libavutil/rational.c @@ -2,20 +2,20 @@ * rational numbers * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -110,11 +110,14 @@ AVRational av_d2q(double d, int max) int64_t den; if (isnan(d)) return (AVRational) { 0,0 }; - if (isinf(d)) + if (fabs(d) > INT_MAX + 3LL) return (AVRational) { d < 0 ? -1 : 1, 0 }; exponent = FFMAX( (int)(log(fabs(d) + 1e-20)/LOG2), 0); den = 1LL << (61 - exponent); - av_reduce(&a.num, &a.den, (int64_t)(d * den + 0.5), den, max); + // (int64_t)rint() and llrint() do not work with gcc on ia64 and sparc64 + av_reduce(&a.num, &a.den, floor(d * den + 0.5), den, max); + if ((!a.num || !a.den) && d && max>0 && max<INT_MAX) + av_reduce(&a.num, &a.den, floor(d * den + 0.5), den, INT_MAX); return a; } @@ -143,3 +146,61 @@ int av_find_nearest_q_idx(AVRational q, const AVRational* q_list) return nearest_q_idx; } + +#ifdef TEST +int main(void) +{ + AVRational a,b,r; + for (a.num = -2; a.num <= 2; a.num++) { + for (a.den = -2; a.den <= 2; a.den++) { + for (b.num = -2; b.num <= 2; b.num++) { + for (b.den = -2; b.den <= 2; b.den++) { + int c = av_cmp_q(a,b); + double d = av_q2d(a) == av_q2d(b) ? + 0 : (av_q2d(a) - av_q2d(b)); + if (d > 0) d = 1; + else if (d < 0) d = -1; + else if (d != d) d = INT_MIN; + if (c != d) + av_log(NULL, AV_LOG_ERROR, "%d/%d %d/%d, %d %f\n", a.num, + a.den, b.num, b.den, c,d); + r = av_sub_q(av_add_q(b,a), b); + if(b.den && (r.num*a.den != a.num*r.den || !r.num != !a.num || !r.den != !a.den)) + av_log(NULL, AV_LOG_ERROR, "%d/%d ", r.num, r.den); + } + } + } + } + + for (a.num = 1; a.num <= 10; a.num++) { + for (a.den = 1; a.den <= 10; a.den++) { + if (av_gcd(a.num, a.den) > 1) + continue; + for (b.num = 1; b.num <= 10; b.num++) { + for (b.den = 1; b.den <= 10; b.den++) { + int start; + if (av_gcd(b.num, b.den) > 1) + continue; + if (av_cmp_q(b, a) < 0) + continue; + for (start = 0; start < 10 ; start++) { + int acc= start; + int i; + + for (i = 0; i<100; i++) { + int exact = start + av_rescale_q(i+1, b, a); + acc = av_add_stable(a, acc, b, 1); + if (FFABS(acc - exact) > 2) { + av_log(NULL, AV_LOG_ERROR, "%d/%d %d/%d, %d %d\n", a.num, + a.den, b.num, b.den, acc, exact); + return 1; + } + } + } + } + } + } + } + return 0; +} +#endif diff --git a/libavutil/rational.h b/libavutil/rational.h index 5d7dab7fd0..7439701db2 100644 --- a/libavutil/rational.h +++ b/libavutil/rational.h @@ -2,20 +2,20 @@ * rational numbers * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -46,6 +46,17 @@ typedef struct AVRational{ } AVRational; /** + * Create a rational. + * Useful for compilers that do not support compound literals. + * @note The return value is not reduced. + */ +static inline AVRational av_make_q(int num, int den) +{ + AVRational r = { num, den }; + return r; +} + +/** * Compare two rationals. * @param a first rational * @param b second rational @@ -55,7 +66,7 @@ typedef struct AVRational{ static inline int av_cmp_q(AVRational a, AVRational b){ const int64_t tmp= a.num * (int64_t)b.den - b.num * (int64_t)a.den; - if(tmp) return ((tmp ^ a.den ^ b.den)>>63)|1; + if(tmp) return (int)((tmp ^ a.den ^ b.den)>>63)|1; else if(b.den && a.den) return 0; else if(a.num && b.num) return (a.num>>31) - (b.num>>31); else return INT_MIN; diff --git a/libavutil/rc4.c b/libavutil/rc4.c index 3bf710f3f1..4e52ba5ac1 100644 --- a/libavutil/rc4.c +++ b/libavutil/rc4.c @@ -4,20 +4,20 @@ * * loosely based on LibTomCrypt by Tom St Denis * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * 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" diff --git a/libavutil/rc4.h b/libavutil/rc4.h index ec3b47cc8a..9362fd8880 100644 --- a/libavutil/rc4.h +++ b/libavutil/rc4.h @@ -1,20 +1,20 @@ /* * RC4 encryption/decryption/pseudo-random number generator * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/replaygain.h b/libavutil/replaygain.h index 7871d2c762..5c03e1993d 100644 --- a/libavutil/replaygain.h +++ b/libavutil/replaygain.h @@ -1,19 +1,19 @@ /* * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/ripemd.c b/libavutil/ripemd.c new file mode 100644 index 0000000000..1ceb24b598 --- /dev/null +++ b/libavutil/ripemd.c @@ -0,0 +1,515 @@ +/* + * Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at> + * Copyright (C) 2013 James Almer + * + * 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 "attributes.h" +#include "avutil.h" +#include "bswap.h" +#include "intreadwrite.h" +#include "ripemd.h" +#include "mem.h" + +/** hash context */ +typedef struct AVRIPEMD { + uint8_t digest_len; ///< digest length in 32-bit words + uint64_t count; ///< number of bytes in buffer + uint8_t buffer[64]; ///< 512-bit buffer of input values used in hash updating + uint32_t state[10]; ///< current hash value + uint8_t ext; ///< extension (0 for 128 and 160, 1 for 256 and 320) + /** function used to update hash for 512-bit input block */ + void (*transform)(uint32_t *state, const uint8_t buffer[64], int ext); +} AVRIPEMD; + +const int av_ripemd_size = sizeof(AVRIPEMD); + +struct AVRIPEMD *av_ripemd_alloc(void) +{ + return av_mallocz(sizeof(struct AVRIPEMD)); +} + +static const uint32_t KA[4] = { + 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e +}; + +static const uint32_t KB[4] = { + 0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9 +}; + +static const int ROTA[80] = { + 11, 14, 15, 12, 5, 8, 7 , 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7 , 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 +}; + +static const int ROTB[80] = { + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 +}; + +static const int WA[80] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 +}; + +static const int WB[80] = { + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 +}; + +#define rol(value, bits) ((value << bits) | (value >> (32 - bits))) + +#define SWAP(a,b) if (ext) { t = a; a = b; b = t; } + +#define ROUND128_0_TO_15(a,b,c,d,e,f,g,h) \ + a = rol(a + (( b ^ c ^ d) + block[WA[n]]), ROTA[n]); \ + e = rol(e + ((((f ^ g) & h) ^ g) + block[WB[n]] + KB[0]), ROTB[n]); \ + n++ + +#define ROUND128_16_TO_31(a,b,c,d,e,f,g,h) \ + a = rol(a + ((((c ^ d) & b) ^ d) + block[WA[n]] + KA[0]), ROTA[n]); \ + e = rol(e + (((~g | f) ^ h) + block[WB[n]] + KB[1]), ROTB[n]); \ + n++ + +#define ROUND128_32_TO_47(a,b,c,d,e,f,g,h) \ + a = rol(a + (((~c | b) ^ d) + block[WA[n]] + KA[1]), ROTA[n]); \ + e = rol(e + ((((g ^ h) & f) ^ h) + block[WB[n]] + KB[2]), ROTB[n]); \ + n++ + +#define ROUND128_48_TO_63(a,b,c,d,e,f,g,h) \ + a = rol(a + ((((b ^ c) & d) ^ c) + block[WA[n]] + KA[2]), ROTA[n]); \ + e = rol(e + (( f ^ g ^ h) + block[WB[n]]), ROTB[n]); \ + n++ + +static void ripemd128_transform(uint32_t *state, const uint8_t buffer[64], int ext) +{ + uint32_t a, b, c, d, e, f, g, h, t; + uint32_t block[16]; + int n; + + if (ext) { + a = state[0]; b = state[1]; c = state[2]; d = state[3]; + e = state[4]; f = state[5]; g = state[6]; h = state[7]; + } else { + a = e = state[0]; + b = f = state[1]; + c = g = state[2]; + d = h = state[3]; + } + + for (n = 0; n < 16; n++) + block[n] = AV_RL32(buffer + 4 * n); + n = 0; + +#if CONFIG_SMALL + for (; n < 16;) { + ROUND128_0_TO_15(a,b,c,d,e,f,g,h); + t = d; d = c; c = b; b = a; a = t; + t = h; h = g; g = f; f = e; e = t; + } + SWAP(a,e) + + for (; n < 32;) { + ROUND128_16_TO_31(a,b,c,d,e,f,g,h); + t = d; d = c; c = b; b = a; a = t; + t = h; h = g; g = f; f = e; e = t; + } + SWAP(b,f) + + for (; n < 48;) { + ROUND128_32_TO_47(a,b,c,d,e,f,g,h); + t = d; d = c; c = b; b = a; a = t; + t = h; h = g; g = f; f = e; e = t; + } + SWAP(c,g) + + for (; n < 64;) { + ROUND128_48_TO_63(a,b,c,d,e,f,g,h); + t = d; d = c; c = b; b = a; a = t; + t = h; h = g; g = f; f = e; e = t; + } + SWAP(d,h) +#else + +#define R128_0 \ + ROUND128_0_TO_15(a,b,c,d,e,f,g,h); \ + ROUND128_0_TO_15(d,a,b,c,h,e,f,g); \ + ROUND128_0_TO_15(c,d,a,b,g,h,e,f); \ + ROUND128_0_TO_15(b,c,d,a,f,g,h,e) + + R128_0; R128_0; R128_0; R128_0; + SWAP(a,e) + +#define R128_16 \ + ROUND128_16_TO_31(a,b,c,d,e,f,g,h); \ + ROUND128_16_TO_31(d,a,b,c,h,e,f,g); \ + ROUND128_16_TO_31(c,d,a,b,g,h,e,f); \ + ROUND128_16_TO_31(b,c,d,a,f,g,h,e) + + R128_16; R128_16; R128_16; R128_16; + SWAP(b,f) + +#define R128_32 \ + ROUND128_32_TO_47(a,b,c,d,e,f,g,h); \ + ROUND128_32_TO_47(d,a,b,c,h,e,f,g); \ + ROUND128_32_TO_47(c,d,a,b,g,h,e,f); \ + ROUND128_32_TO_47(b,c,d,a,f,g,h,e) + + R128_32; R128_32; R128_32; R128_32; + SWAP(c,g) + +#define R128_48 \ + ROUND128_48_TO_63(a,b,c,d,e,f,g,h); \ + ROUND128_48_TO_63(d,a,b,c,h,e,f,g); \ + ROUND128_48_TO_63(c,d,a,b,g,h,e,f); \ + ROUND128_48_TO_63(b,c,d,a,f,g,h,e) + + R128_48; R128_48; R128_48; R128_48; + SWAP(d,h) +#endif + + if (ext) { + state[0] += a; state[1] += b; state[2] += c; state[3] += d; + state[4] += e; state[5] += f; state[6] += g; state[7] += h; + } else { + h += c + state[1]; + state[1] = state[2] + d + e; + state[2] = state[3] + a + f; + state[3] = state[0] + b + g; + state[0] = h; + } +} + +#define ROTATE(x,y) \ + x = rol(x, 10); \ + y = rol(y, 10); \ + n++ + +#define ROUND160_0_TO_15(a,b,c,d,e,f,g,h,i,j) \ + a = rol(a + (( b ^ c ^ d) + block[WA[n]]), ROTA[n]) + e; \ + f = rol(f + (((~i | h) ^ g) + block[WB[n]] + KB[0]), ROTB[n]) + j; \ + ROTATE(c,h) + +#define ROUND160_16_TO_31(a,b,c,d,e,f,g,h,i,j) \ + a = rol(a + ((((c ^ d) & b) ^ d) + block[WA[n]] + KA[0]), ROTA[n]) + e; \ + f = rol(f + ((((g ^ h) & i) ^ h) + block[WB[n]] + KB[1]), ROTB[n]) + j; \ + ROTATE(c,h) + +#define ROUND160_32_TO_47(a,b,c,d,e,f,g,h,i,j) \ + a = rol(a + (((~c | b) ^ d) + block[WA[n]] + KA[1]), ROTA[n]) + e; \ + f = rol(f + (((~h | g) ^ i) + block[WB[n]] + KB[2]), ROTB[n]) + j; \ + ROTATE(c,h) + +#define ROUND160_48_TO_63(a,b,c,d,e,f,g,h,i,j) \ + a = rol(a + ((((b ^ c) & d) ^ c) + block[WA[n]] + KA[2]), ROTA[n]) + e; \ + f = rol(f + ((((h ^ i) & g) ^ i) + block[WB[n]] + KB[3]), ROTB[n]) + j; \ + ROTATE(c,h) + +#define ROUND160_64_TO_79(a,b,c,d,e,f,g,h,i,j) \ + a = rol(a + (((~d | c) ^ b) + block[WA[n]] + KA[3]), ROTA[n]) + e; \ + f = rol(f + (( g ^ h ^ i) + block[WB[n]]), ROTB[n]) + j; \ + ROTATE(c,h) + +static void ripemd160_transform(uint32_t *state, const uint8_t buffer[64], int ext) +{ + uint32_t a, b, c, d, e, f, g, h, i, j, t; + uint32_t block[16]; + int n; + + if (ext) { + a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; + f = state[5]; g = state[6]; h = state[7]; i = state[8]; j = state[9]; + } else { + a = f = state[0]; + b = g = state[1]; + c = h = state[2]; + d = i = state[3]; + e = j = state[4]; + } + + for (n = 0; n < 16; n++) + block[n] = AV_RL32(buffer + 4 * n); + n = 0; + +#if CONFIG_SMALL + for (; n < 16;) { + ROUND160_0_TO_15(a,b,c,d,e,f,g,h,i,j); + t = e; e = d; d = c; c = b; b = a; a = t; + t = j; j = i; i = h; h = g; g = f; f = t; + } + SWAP(b,g) + + for (; n < 32;) { + ROUND160_16_TO_31(a,b,c,d,e,f,g,h,i,j); + t = e; e = d; d = c; c = b; b = a; a = t; + t = j; j = i; i = h; h = g; g = f; f = t; + } + SWAP(d,i) + + for (; n < 48;) { + ROUND160_32_TO_47(a,b,c,d,e,f,g,h,i,j); + t = e; e = d; d = c; c = b; b = a; a = t; + t = j; j = i; i = h; h = g; g = f; f = t; + } + SWAP(a,f) + + for (; n < 64;) { + ROUND160_48_TO_63(a,b,c,d,e,f,g,h,i,j); + t = e; e = d; d = c; c = b; b = a; a = t; + t = j; j = i; i = h; h = g; g = f; f = t; + } + SWAP(c,h) + + for (; n < 80;) { + ROUND160_64_TO_79(a,b,c,d,e,f,g,h,i,j); + t = e; e = d; d = c; c = b; b = a; a = t; + t = j; j = i; i = h; h = g; g = f; f = t; + } + SWAP(e,j) +#else + +#define R160_0 \ + ROUND160_0_TO_15(a,b,c,d,e,f,g,h,i,j); \ + ROUND160_0_TO_15(e,a,b,c,d,j,f,g,h,i); \ + ROUND160_0_TO_15(d,e,a,b,c,i,j,f,g,h); \ + ROUND160_0_TO_15(c,d,e,a,b,h,i,j,f,g); \ + ROUND160_0_TO_15(b,c,d,e,a,g,h,i,j,f) + + R160_0; R160_0; R160_0; + ROUND160_0_TO_15(a,b,c,d,e,f,g,h,i,j); + SWAP(a,f) + +#define R160_16 \ + ROUND160_16_TO_31(e,a,b,c,d,j,f,g,h,i); \ + ROUND160_16_TO_31(d,e,a,b,c,i,j,f,g,h); \ + ROUND160_16_TO_31(c,d,e,a,b,h,i,j,f,g); \ + ROUND160_16_TO_31(b,c,d,e,a,g,h,i,j,f); \ + ROUND160_16_TO_31(a,b,c,d,e,f,g,h,i,j) + + R160_16; R160_16; R160_16; + ROUND160_16_TO_31(e,a,b,c,d,j,f,g,h,i); + SWAP(b,g) + +#define R160_32 \ + ROUND160_32_TO_47(d,e,a,b,c,i,j,f,g,h); \ + ROUND160_32_TO_47(c,d,e,a,b,h,i,j,f,g); \ + ROUND160_32_TO_47(b,c,d,e,a,g,h,i,j,f); \ + ROUND160_32_TO_47(a,b,c,d,e,f,g,h,i,j); \ + ROUND160_32_TO_47(e,a,b,c,d,j,f,g,h,i) + + R160_32; R160_32; R160_32; + ROUND160_32_TO_47(d,e,a,b,c,i,j,f,g,h); + SWAP(c,h) + +#define R160_48 \ + ROUND160_48_TO_63(c,d,e,a,b,h,i,j,f,g); \ + ROUND160_48_TO_63(b,c,d,e,a,g,h,i,j,f); \ + ROUND160_48_TO_63(a,b,c,d,e,f,g,h,i,j); \ + ROUND160_48_TO_63(e,a,b,c,d,j,f,g,h,i); \ + ROUND160_48_TO_63(d,e,a,b,c,i,j,f,g,h) + + R160_48; R160_48; R160_48; + ROUND160_48_TO_63(c,d,e,a,b,h,i,j,f,g); + SWAP(d,i) + +#define R160_64 \ + ROUND160_64_TO_79(b,c,d,e,a,g,h,i,j,f); \ + ROUND160_64_TO_79(a,b,c,d,e,f,g,h,i,j); \ + ROUND160_64_TO_79(e,a,b,c,d,j,f,g,h,i); \ + ROUND160_64_TO_79(d,e,a,b,c,i,j,f,g,h); \ + ROUND160_64_TO_79(c,d,e,a,b,h,i,j,f,g) + + R160_64; R160_64; R160_64; + ROUND160_64_TO_79(b,c,d,e,a,g,h,i,j,f); + SWAP(e,j) +#endif + + if (ext) { + state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; + state[5] += f; state[6] += g; state[7] += h; state[8] += i; state[9] += j; + } else { + i += c + state[1]; + state[1] = state[2] + d + j; + state[2] = state[3] + e + f; + state[3] = state[4] + a + g; + state[4] = state[0] + b + h; + state[0] = i; + } +} + +av_cold int av_ripemd_init(AVRIPEMD *ctx, int bits) +{ + ctx->digest_len = bits >> 5; + switch (bits) { + case 128: // RIPEMD-128 + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->transform = ripemd128_transform; + ctx->ext = 0; + break; + case 160: // RIPEMD-160 + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + ctx->transform = ripemd160_transform; + ctx->ext = 0; + break; + case 256: // RIPEMD-256 + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0x76543210; + ctx->state[5] = 0xFEDCBA98; + ctx->state[6] = 0x89ABCDEF; + ctx->state[7] = 0x01234567; + ctx->transform = ripemd128_transform; + ctx->ext = 1; + break; + case 320: // RIPEMD-320 + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + ctx->state[5] = 0x76543210; + ctx->state[6] = 0xFEDCBA98; + ctx->state[7] = 0x89ABCDEF; + ctx->state[8] = 0x01234567; + ctx->state[9] = 0x3C2D1E0F; + ctx->transform = ripemd160_transform; + ctx->ext = 1; + break; + default: + return -1; + } + ctx->count = 0; + return 0; +} + +void av_ripemd_update(AVRIPEMD* ctx, const uint8_t* data, unsigned int len) +{ + unsigned int i, j; + + j = ctx->count & 63; + ctx->count += len; +#if CONFIG_SMALL + for (i = 0; i < len; i++) { + ctx->buffer[j++] = data[i]; + if (64 == j) { + ctx->transform(ctx->state, ctx->buffer, ctx->ext); + j = 0; + } + } +#else + if ((j + len) > 63) { + memcpy(&ctx->buffer[j], data, (i = 64 - j)); + ctx->transform(ctx->state, ctx->buffer, ctx->ext); + for (; i + 63 < len; i += 64) + ctx->transform(ctx->state, &data[i], ctx->ext); + j = 0; + } else + i = 0; + memcpy(&ctx->buffer[j], &data[i], len - i); +#endif +} + +void av_ripemd_final(AVRIPEMD* ctx, uint8_t *digest) +{ + int i; + uint64_t finalcount = av_le2ne64(ctx->count << 3); + + av_ripemd_update(ctx, "\200", 1); + while ((ctx->count & 63) != 56) + av_ripemd_update(ctx, "", 1); + av_ripemd_update(ctx, (uint8_t *)&finalcount, 8); /* Should cause a transform() */ + for (i = 0; i < ctx->digest_len; i++) + AV_WL32(digest + i*4, ctx->state[i]); +} + +#ifdef TEST +#include <stdio.h> + +int main(void) +{ + int i, j, k; + AVRIPEMD ctx; + unsigned char digest[40]; + static const int lengths[4] = { 128, 160, 256, 320 }; + + for (j = 0; j < 4; j++) { + printf("Testing RIPEMD-%d\n", lengths[j]); + for (k = 0; k < 3; k++) { + av_ripemd_init(&ctx, lengths[j]); + if (k == 0) + av_ripemd_update(&ctx, "abc", 3); + else if (k == 1) + av_ripemd_update(&ctx, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56); + else + for (i = 0; i < 1000*1000; i++) + av_ripemd_update(&ctx, "a", 1); + av_ripemd_final(&ctx, digest); + for (i = 0; i < lengths[j] >> 3; i++) + printf("%02X", digest[i]); + putchar('\n'); + } + switch (j) { //test vectors (from ISO:IEC 10118-3 (2004) and http://homes.esat.kuleuven.be/~bosselae/ripemd160.html) + case 0: + printf("c14a1219 9c66e4ba 84636b0f 69144c77\n" + "a1aa0689 d0fafa2d dc22e88b 49133a06\n" + "4a7f5723 f954eba1 216c9d8f 6320431f\n"); + break; + case 1: + printf("8eb208f7 e05d987a 9b044a8e 98c6b087 f15a0bfc\n" + "12a05338 4a9c0c88 e405a06c 27dcf49a da62eb2b\n" + "52783243 c1697bdb e16d37f9 7f68f083 25dc1528\n"); + break; + case 2: + printf("afbd6e22 8b9d8cbb cef5ca2d 03e6dba1 0ac0bc7d cbe4680e 1e42d2e9 75459b65\n" + "38430455 83aac6c8 c8d91285 73e7a980 9afb2a0f 34ccc36e a9e72f16 f6368e3f\n" + "ac953744 e10e3151 4c150d4d 8d7b6773 42e33399 788296e4 3ae4850c e4f97978\n"); + break; + case 3: + printf("de4c01b3 054f8930 a79d09ae 738e9230 1e5a1708 5beffdc1 b8d11671 3e74f82f a942d64c dbc4682d\n" + "d034a795 0cf72202 1ba4b84d f769a5de 2060e259 df4c9bb4 a4268c0e 935bbc74 70a969c9 d072a1ac\n" + "bdee37f4 371e2064 6b8b0d86 2dda1629 2ae36f40 965e8c85 09e63d1d bddecc50 3e2b63eb 9245bb66\n"); + break; + } + } + + return 0; +} +#endif diff --git a/libavutil/ripemd.h b/libavutil/ripemd.h new file mode 100644 index 0000000000..7b0c8bc89c --- /dev/null +++ b/libavutil/ripemd.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at> + * Copyright (C) 2013 James Almer <jamrial@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_RIPEMD_H +#define AVUTIL_RIPEMD_H + +#include <stdint.h> + +#include "attributes.h" +#include "version.h" + +/** + * @defgroup lavu_ripemd RIPEMD + * @ingroup lavu_crypto + * @{ + */ + +extern const int av_ripemd_size; + +struct AVRIPEMD; + +/** + * Allocate an AVRIPEMD context. + */ +struct AVRIPEMD *av_ripemd_alloc(void); + +/** + * Initialize RIPEMD hashing. + * + * @param context pointer to the function context (of size av_ripemd_size) + * @param bits number of bits in digest (128, 160, 256 or 320 bits) + * @return zero if initialization succeeded, -1 otherwise + */ +int av_ripemd_init(struct AVRIPEMD* context, int bits); + +/** + * Update hash value. + * + * @param context hash function context + * @param data input data to update hash with + * @param len input data length + */ +void av_ripemd_update(struct AVRIPEMD* context, const uint8_t* data, unsigned int len); + +/** + * Finish hashing and output digest value. + * + * @param context hash function context + * @param digest buffer where output digest value is stored + */ +void av_ripemd_final(struct AVRIPEMD* context, uint8_t *digest); + +/** + * @} + */ + +#endif /* AVUTIL_RIPEMD_H */ diff --git a/libavutil/samplefmt.c b/libavutil/samplefmt.c index bff600447c..a1986980f0 100644 --- a/libavutil/samplefmt.c +++ b/libavutil/samplefmt.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -24,7 +24,7 @@ #include <string.h> typedef struct SampleFmtInfo { - const char *name; + char name[8]; int bits; int planar; enum AVSampleFormat altform; ///< planar<->packed alternative form @@ -61,6 +61,15 @@ enum AVSampleFormat av_get_sample_fmt(const char *name) return AV_SAMPLE_FMT_NONE; } +enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar) +{ + if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB) + return AV_SAMPLE_FMT_NONE; + if (sample_fmt_info[sample_fmt].planar == planar) + return sample_fmt; + return sample_fmt_info[sample_fmt].altform; +} + enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt) { if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB) @@ -98,6 +107,14 @@ int av_get_bytes_per_sample(enum AVSampleFormat sample_fmt) 0 : sample_fmt_info[sample_fmt].bits >> 3; } +#if FF_API_GET_BITS_PER_SAMPLE_FMT +int av_get_bits_per_sample_fmt(enum AVSampleFormat sample_fmt) +{ + return sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB ? + 0 : sample_fmt_info[sample_fmt].bits; +} +#endif + int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt) { if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB) @@ -149,14 +166,18 @@ int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, if (buf_size < 0) return buf_size; - audio_data[0] = buf; + audio_data[0] = (uint8_t *)buf; for (ch = 1; planar && ch < nb_channels; ch++) audio_data[ch] = audio_data[ch-1] + line_size; if (linesize) *linesize = line_size; +#if FF_API_SAMPLES_UTILS_RETURN_ZERO return 0; +#else + return buf_size; +#endif } int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels, @@ -181,7 +202,26 @@ int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels, av_samples_set_silence(audio_data, 0, nb_samples, nb_channels, sample_fmt); +#if FF_API_SAMPLES_UTILS_RETURN_ZERO return 0; +#else + return size; +#endif +} + +int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align) +{ + int ret, nb_planes = av_sample_fmt_is_planar(sample_fmt) ? nb_channels : 1; + + *audio_data = av_calloc(nb_planes, sizeof(**audio_data)); + if (!*audio_data) + return AVERROR(ENOMEM); + ret = av_samples_alloc(*audio_data, linesize, nb_channels, + nb_samples, sample_fmt, align); + if (ret < 0) + av_freep(audio_data); + return ret; } int av_samples_copy(uint8_t **dst, uint8_t * const *src, int dst_offset, @@ -197,8 +237,13 @@ int av_samples_copy(uint8_t **dst, uint8_t * const *src, int dst_offset, dst_offset *= block_align; src_offset *= block_align; - for (i = 0; i < planes; i++) - memcpy(dst[i] + dst_offset, src[i] + src_offset, data_size); + if((dst[0] < src[0] ? src[0] - dst[0] : dst[0] - src[0]) >= data_size) { + for (i = 0; i < planes; i++) + memcpy(dst[i] + dst_offset, src[i] + src_offset, data_size); + } else { + for (i = 0; i < planes; i++) + memmove(dst[i] + dst_offset, src[i] + src_offset, data_size); + } return 0; } diff --git a/libavutil/samplefmt.h b/libavutil/samplefmt.h index 8347fac29c..2c346a3ce3 100644 --- a/libavutil/samplefmt.h +++ b/libavutil/samplefmt.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -36,20 +36,17 @@ */ /** - * Audio Sample Formats + * Audio sample formats * - * @par - * The data described by the sample format is always in native-endian order. - * Sample values can be expressed by native C types, hence the lack of a signed - * 24-bit sample format even though it is a common raw audio data format. + * - The data described by the sample format is always in native-endian order. + * Sample values can be expressed by native C types, hence the lack of a signed + * 24-bit sample format even though it is a common raw audio data format. * - * @par - * The floating-point formats are based on full volume being in the range - * [-1.0, 1.0]. Any values outside this range are beyond full volume level. + * - The floating-point formats are based on full volume being in the range + * [-1.0, 1.0]. Any values outside this range are beyond full volume level. * - * @par - * The data layout as used in av_samples_fill_arrays() and elsewhere in Libav - * (such as AVFrame in libavcodec) is as follows: + * - The data layout as used in av_samples_fill_arrays() and elsewhere in FFmpeg + * (such as AVFrame in libavcodec) is as follows: * * @par * For planar sample formats, each audio channel is in a separate data plane, @@ -57,6 +54,7 @@ * planes must be the same size. For packed sample formats, only the first data * plane is used, and samples for each channel are interleaved. In this case, * linesize is the buffer size, in bytes, for the 1 plane. + * */ enum AVSampleFormat { AV_SAMPLE_FMT_NONE = -1, @@ -88,6 +86,14 @@ const char *av_get_sample_fmt_name(enum AVSampleFormat sample_fmt); enum AVSampleFormat av_get_sample_fmt(const char *name); /** + * Return the planar<->packed alternative form of the given sample format, or + * AV_SAMPLE_FMT_NONE on error. If the passed sample_fmt is already in the + * requested planar/packed format, the format returned is the same as the + * input. + */ +enum AVSampleFormat av_get_alt_sample_fmt(enum AVSampleFormat sample_fmt, int planar); + +/** * Get the packed alternative form of the given sample format. * * If the passed sample_fmt is already in packed format, the format returned is @@ -123,6 +129,14 @@ enum AVSampleFormat av_get_planar_sample_fmt(enum AVSampleFormat sample_fmt); */ char *av_get_sample_fmt_string(char *buf, int buf_size, enum AVSampleFormat sample_fmt); +#if FF_API_GET_BITS_PER_SAMPLE_FMT +/** + * @deprecated Use av_get_bytes_per_sample() instead. + */ +attribute_deprecated +int av_get_bits_per_sample_fmt(enum AVSampleFormat sample_fmt); +#endif + /** * Return number of bytes per sample. * @@ -163,16 +177,20 @@ int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, */ /** - * Fill channel data pointers and linesize for samples with sample + * Fill plane data pointers and linesize for samples with sample * format sample_fmt. * - * The pointers array is filled with the pointers to the samples data: + * The audio_data array is filled with the pointers to the samples data planes: * for planar, set the start point of each channel's data within the buffer, * for packed, set the start point of the entire buffer only. * - * The linesize array is filled with the aligned size of each channel's data - * buffer for planar layout, or the aligned size of the buffer for all channels - * for packed layout. + * The value pointed to by linesize is set to the aligned size of each + * channel's data buffer for planar layout, or to the aligned size of the + * buffer for all channels for packed layout. + * + * The buffer in buf must be big enough to contain all the samples + * (use av_samples_get_buffer_size() to compute its minimum size), + * otherwise the audio_data pointers will point to invalid data. * * @see enum AVSampleFormat * The documentation for AVSampleFormat describes the data layout. @@ -184,7 +202,9 @@ int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, * @param nb_samples the number of samples in a single channel * @param sample_fmt the sample format * @param align buffer size alignment (0 = default, 1 = no alignment) - * @return 0 on success or a negative error code on failure + * @return >=0 on success or a negative error code on failure + * @todo return minimum size in bytes required for the buffer in case + * of success at the next bump */ int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, const uint8_t *buf, @@ -205,13 +225,27 @@ int av_samples_fill_arrays(uint8_t **audio_data, int *linesize, * @param nb_channels number of audio channels * @param nb_samples number of samples per channel * @param align buffer size alignment (0 = default, 1 = no alignment) - * @return 0 on success or a negative error code on failure + * @return >=0 on success or a negative error code on failure + * @todo return the size of the allocated buffer in case of success at the next bump * @see av_samples_fill_arrays() + * @see av_samples_alloc_array_and_samples() */ int av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align); /** + * Allocate a data pointers array, samples buffer for nb_samples + * samples, and fill data pointers and linesize accordingly. + * + * This is the same as av_samples_alloc(), but also allocates the data + * pointers array. + * + * @see av_samples_alloc() + */ +int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align); + +/** * Copy samples from src to dst. * * @param dst destination array of pointers to data planes diff --git a/libavutil/sh4/bswap.h b/libavutil/sh4/bswap.h index 1ff1bfdd37..48dd27f806 100644 --- a/libavutil/sh4/bswap.h +++ b/libavutil/sh4/bswap.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/sha.c b/libavutil/sha.c index 2d9b58cda6..0cf94245a9 100644 --- a/libavutil/sha.c +++ b/libavutil/sha.c @@ -4,20 +4,20 @@ * based on public domain SHA-1 code by Steve Reid <steve@edmweb.com> * and on BSD-licensed SHA-2 code by Aaron D. Gifford * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -40,9 +40,7 @@ typedef struct AVSHA { void (*transform)(uint32_t *state, const uint8_t buffer[64]); } AVSHA; -#if FF_API_CONTEXT_SIZE const int av_sha_size = sizeof(AVSHA); -#endif struct AVSHA *av_sha_alloc(void) { @@ -100,39 +98,53 @@ static void sha1_transform(uint32_t state[5], const uint8_t buffer[64]) a = t; } #else - for (i = 0; i < 15; i += 5) { - R0(a, b, c, d, e, 0 + i); - R0(e, a, b, c, d, 1 + i); - R0(d, e, a, b, c, 2 + i); - R0(c, d, e, a, b, 3 + i); - R0(b, c, d, e, a, 4 + i); - } + +#define R1_0 \ + R0(a, b, c, d, e, 0 + i); \ + R0(e, a, b, c, d, 1 + i); \ + R0(d, e, a, b, c, 2 + i); \ + R0(c, d, e, a, b, 3 + i); \ + R0(b, c, d, e, a, 4 + i); \ + i += 5 + + i = 0; + R1_0; R1_0; R1_0; R0(a, b, c, d, e, 15); R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17); R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19); - for (i = 20; i < 40; i += 5) { - R2(a, b, c, d, e, 0 + i); - R2(e, a, b, c, d, 1 + i); - R2(d, e, a, b, c, 2 + i); - R2(c, d, e, a, b, 3 + i); - R2(b, c, d, e, a, 4 + i); - } - for (; i < 60; i += 5) { - R3(a, b, c, d, e, 0 + i); - R3(e, a, b, c, d, 1 + i); - R3(d, e, a, b, c, 2 + i); - R3(c, d, e, a, b, 3 + i); - R3(b, c, d, e, a, 4 + i); - } - for (; i < 80; i += 5) { - R4(a, b, c, d, e, 0 + i); - R4(e, a, b, c, d, 1 + i); - R4(d, e, a, b, c, 2 + i); - R4(c, d, e, a, b, 3 + i); - R4(b, c, d, e, a, 4 + i); - } + +#define R1_20 \ + R2(a, b, c, d, e, 0 + i); \ + R2(e, a, b, c, d, 1 + i); \ + R2(d, e, a, b, c, 2 + i); \ + R2(c, d, e, a, b, 3 + i); \ + R2(b, c, d, e, a, 4 + i); \ + i += 5 + + i = 20; + R1_20; R1_20; R1_20; R1_20; + +#define R1_40 \ + R3(a, b, c, d, e, 0 + i); \ + R3(e, a, b, c, d, 1 + i); \ + R3(d, e, a, b, c, 2 + i); \ + R3(c, d, e, a, b, 3 + i); \ + R3(b, c, d, e, a, 4 + i); \ + i += 5 + + R1_40; R1_40; R1_40; R1_40; + +#define R1_60 \ + R4(a, b, c, d, e, 0 + i); \ + R4(e, a, b, c, d, 1 + i); \ + R4(d, e, a, b, c, 2 + i); \ + R4(c, d, e, a, b, 3 + i); \ + R4(b, c, d, e, a, 4 + i); \ + i += 5 + + R1_60; R1_60; R1_60; R1_60; #endif state[0] += a; state[1] += b; @@ -162,7 +174,7 @@ static const uint32_t K256[64] = { #define Ch(x,y,z) (((x) & ((y) ^ (z))) ^ (z)) -#define Maj(x,y,z) ((((x) | (y)) & (z)) | ((x) & (y))) +#define Maj(z,y,x) ((((x) | (y)) & (z)) | ((x) & (y))) #define Sigma0_256(x) (rol((x), 30) ^ rol((x), 19) ^ rol((x), 10)) #define Sigma1_256(x) (rol((x), 26) ^ rol((x), 21) ^ rol((x), 7)) @@ -220,27 +232,32 @@ static void sha256_transform(uint32_t *state, const uint8_t buffer[64]) a = T1 + T2; } #else - for (i = 0; i < 16;) { - ROUND256_0_TO_15(a, b, c, d, e, f, g, h); - ROUND256_0_TO_15(h, a, b, c, d, e, f, g); - ROUND256_0_TO_15(g, h, a, b, c, d, e, f); - ROUND256_0_TO_15(f, g, h, a, b, c, d, e); - ROUND256_0_TO_15(e, f, g, h, a, b, c, d); - ROUND256_0_TO_15(d, e, f, g, h, a, b, c); - ROUND256_0_TO_15(c, d, e, f, g, h, a, b); - ROUND256_0_TO_15(b, c, d, e, f, g, h, a); - } - for (; i < 64;) { - ROUND256_16_TO_63(a, b, c, d, e, f, g, h); - ROUND256_16_TO_63(h, a, b, c, d, e, f, g); - ROUND256_16_TO_63(g, h, a, b, c, d, e, f); - ROUND256_16_TO_63(f, g, h, a, b, c, d, e); - ROUND256_16_TO_63(e, f, g, h, a, b, c, d); - ROUND256_16_TO_63(d, e, f, g, h, a, b, c); - ROUND256_16_TO_63(c, d, e, f, g, h, a, b); - ROUND256_16_TO_63(b, c, d, e, f, g, h, a); - } + i = 0; +#define R256_0 \ + ROUND256_0_TO_15(a, b, c, d, e, f, g, h); \ + ROUND256_0_TO_15(h, a, b, c, d, e, f, g); \ + ROUND256_0_TO_15(g, h, a, b, c, d, e, f); \ + ROUND256_0_TO_15(f, g, h, a, b, c, d, e); \ + ROUND256_0_TO_15(e, f, g, h, a, b, c, d); \ + ROUND256_0_TO_15(d, e, f, g, h, a, b, c); \ + ROUND256_0_TO_15(c, d, e, f, g, h, a, b); \ + ROUND256_0_TO_15(b, c, d, e, f, g, h, a) + + R256_0; R256_0; + +#define R256_16 \ + ROUND256_16_TO_63(a, b, c, d, e, f, g, h); \ + ROUND256_16_TO_63(h, a, b, c, d, e, f, g); \ + ROUND256_16_TO_63(g, h, a, b, c, d, e, f); \ + ROUND256_16_TO_63(f, g, h, a, b, c, d, e); \ + ROUND256_16_TO_63(e, f, g, h, a, b, c, d); \ + ROUND256_16_TO_63(d, e, f, g, h, a, b, c); \ + ROUND256_16_TO_63(c, d, e, f, g, h, a, b); \ + ROUND256_16_TO_63(b, c, d, e, f, g, h, a) + + R256_16; R256_16; R256_16; + R256_16; R256_16; R256_16; #endif state[0] += a; state[1] += b; @@ -342,7 +359,7 @@ int main(void) int i, j, k; AVSHA ctx; unsigned char digest[32]; - const int lengths[3] = { 160, 224, 256 }; + static const int lengths[3] = { 160, 224, 256 }; for (j = 0; j < 3; j++) { printf("Testing SHA-%d\n", lengths[j]); diff --git a/libavutil/sha.h b/libavutil/sha.h index 4c9a0c9095..bf4377e51b 100644 --- a/libavutil/sha.h +++ b/libavutil/sha.h @@ -1,20 +1,20 @@ /* * Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -32,9 +32,7 @@ * @{ */ -#if FF_API_CONTEXT_SIZE -extern attribute_deprecated const int av_sha_size; -#endif +extern const int av_sha_size; struct AVSHA; diff --git a/libavutil/sha512.c b/libavutil/sha512.c new file mode 100644 index 0000000000..66a864f1a6 --- /dev/null +++ b/libavutil/sha512.c @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at> + * Copyright (C) 2009 Konstantin Shishkov + * Copyright (C) 2013 James Almer + * based on BSD-licensed SHA-2 code by Aaron D. Gifford + * + * 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 "attributes.h" +#include "avutil.h" +#include "bswap.h" +#include "sha512.h" +#include "intreadwrite.h" +#include "mem.h" + +/** hash context */ +typedef struct AVSHA512 { + uint8_t digest_len; ///< digest length in 64-bit words + uint64_t count; ///< number of bytes in buffer + uint8_t buffer[128]; ///< 1024-bit buffer of input values used in hash updating + uint64_t state[8]; ///< current hash value +} AVSHA512; + +const int av_sha512_size = sizeof(AVSHA512); + +struct AVSHA512 *av_sha512_alloc(void) +{ + return av_mallocz(sizeof(struct AVSHA512)); +} + +static const uint64_t K512[80] = { + UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), + UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc), + UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019), + UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118), + UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe), + UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2), + UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), + UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694), + UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3), + UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65), + UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483), + UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5), + UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), + UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4), + UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725), + UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70), + UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926), + UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df), + UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), + UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b), + UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001), + UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30), + UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910), + UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8), + UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), + UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8), + UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb), + UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3), + UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60), + UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec), + UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), + UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b), + UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207), + UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178), + UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6), + UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b), + UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), + UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c), + UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a), + UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817), +}; + +#define ror(value, bits) (((value) >> (bits)) | ((value) << (64 - (bits)))) + +#define Ch(x,y,z) (((x) & ((y) ^ (z))) ^ (z)) +#define Maj(z,y,x) ((((x) | (y)) & (z)) | ((x) & (y))) + +#define Sigma0_512(x) (ror((x), 28) ^ ror((x), 34) ^ ror((x), 39)) +#define Sigma1_512(x) (ror((x), 14) ^ ror((x), 18) ^ ror((x), 41)) +#define sigma0_512(x) (ror((x), 1) ^ ror((x), 8) ^ ((x) >> 7)) +#define sigma1_512(x) (ror((x), 19) ^ ror((x), 61) ^ ((x) >> 6)) + +#define blk0(i) (block[i] = AV_RB64(buffer + 8 * (i))) +#define blk(i) (block[i] = block[i - 16] + sigma0_512(block[i - 15]) + \ + sigma1_512(block[i - 2]) + block[i - 7]) + +#define ROUND512(a,b,c,d,e,f,g,h) \ + T1 += (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[i]; \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + i++ + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = blk0(i); \ + ROUND512(a,b,c,d,e,f,g,h) + +#define ROUND512_16_TO_80(a,b,c,d,e,f,g,h) \ + T1 = blk(i); \ + ROUND512(a,b,c,d,e,f,g,h) + +static void sha512_transform(uint64_t *state, const uint8_t buffer[128]) +{ + uint64_t a, b, c, d, e, f, g, h; + uint64_t block[80]; + uint64_t T1; + int i; + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; +#if CONFIG_SMALL + for (i = 0; i < 80; i++) { + uint64_t T2; + if (i < 16) + T1 = blk0(i); + else + T1 = blk(i); + T1 += h + Sigma1_512(e) + Ch(e, f, g) + K512[i]; + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } +#else + +#define R512_0 \ + ROUND512_0_TO_15(a, b, c, d, e, f, g, h); \ + ROUND512_0_TO_15(h, a, b, c, d, e, f, g); \ + ROUND512_0_TO_15(g, h, a, b, c, d, e, f); \ + ROUND512_0_TO_15(f, g, h, a, b, c, d, e); \ + ROUND512_0_TO_15(e, f, g, h, a, b, c, d); \ + ROUND512_0_TO_15(d, e, f, g, h, a, b, c); \ + ROUND512_0_TO_15(c, d, e, f, g, h, a, b); \ + ROUND512_0_TO_15(b, c, d, e, f, g, h, a) + + i = 0; + R512_0; R512_0; + +#define R512_16 \ + ROUND512_16_TO_80(a, b, c, d, e, f, g, h); \ + ROUND512_16_TO_80(h, a, b, c, d, e, f, g); \ + ROUND512_16_TO_80(g, h, a, b, c, d, e, f); \ + ROUND512_16_TO_80(f, g, h, a, b, c, d, e); \ + ROUND512_16_TO_80(e, f, g, h, a, b, c, d); \ + ROUND512_16_TO_80(d, e, f, g, h, a, b, c); \ + ROUND512_16_TO_80(c, d, e, f, g, h, a, b); \ + ROUND512_16_TO_80(b, c, d, e, f, g, h, a) + + R512_16; R512_16; R512_16; R512_16; + R512_16; R512_16; R512_16; R512_16; +#endif + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; +} + + +av_cold int av_sha512_init(AVSHA512 *ctx, int bits) +{ + ctx->digest_len = bits >> 6; + switch (bits) { + case 224: // SHA-512/224 + ctx->state[0] = UINT64_C(0x8C3D37C819544DA2); + ctx->state[1] = UINT64_C(0x73E1996689DCD4D6); + ctx->state[2] = UINT64_C(0x1DFAB7AE32FF9C82); + ctx->state[3] = UINT64_C(0x679DD514582F9FCF); + ctx->state[4] = UINT64_C(0x0F6D2B697BD44DA8); + ctx->state[5] = UINT64_C(0x77E36F7304C48942); + ctx->state[6] = UINT64_C(0x3F9D85A86A1D36C8); + ctx->state[7] = UINT64_C(0x1112E6AD91D692A1); + break; + case 256: // SHA-512/256 + ctx->state[0] = UINT64_C(0x22312194FC2BF72C); + ctx->state[1] = UINT64_C(0x9F555FA3C84C64C2); + ctx->state[2] = UINT64_C(0x2393B86B6F53B151); + ctx->state[3] = UINT64_C(0x963877195940EABD); + ctx->state[4] = UINT64_C(0x96283EE2A88EFFE3); + ctx->state[5] = UINT64_C(0xBE5E1E2553863992); + ctx->state[6] = UINT64_C(0x2B0199FC2C85B8AA); + ctx->state[7] = UINT64_C(0x0EB72DDC81C52CA2); + break; + case 384: // SHA-384 + ctx->state[0] = UINT64_C(0xCBBB9D5DC1059ED8); + ctx->state[1] = UINT64_C(0x629A292A367CD507); + ctx->state[2] = UINT64_C(0x9159015A3070DD17); + ctx->state[3] = UINT64_C(0x152FECD8F70E5939); + ctx->state[4] = UINT64_C(0x67332667FFC00B31); + ctx->state[5] = UINT64_C(0x8EB44A8768581511); + ctx->state[6] = UINT64_C(0xDB0C2E0D64F98FA7); + ctx->state[7] = UINT64_C(0x47B5481DBEFA4FA4); + break; + case 512: // SHA-512 + ctx->state[0] = UINT64_C(0x6A09E667F3BCC908); + ctx->state[1] = UINT64_C(0xBB67AE8584CAA73B); + ctx->state[2] = UINT64_C(0x3C6EF372FE94F82B); + ctx->state[3] = UINT64_C(0xA54FF53A5F1D36F1); + ctx->state[4] = UINT64_C(0x510E527FADE682D1); + ctx->state[5] = UINT64_C(0x9B05688C2B3E6C1F); + ctx->state[6] = UINT64_C(0x1F83D9ABFB41BD6B); + ctx->state[7] = UINT64_C(0x5BE0CD19137E2179); + break; + default: + return -1; + } + ctx->count = 0; + return 0; +} + +void av_sha512_update(AVSHA512* ctx, const uint8_t* data, unsigned int len) +{ + unsigned int i, j; + + j = ctx->count & 127; + ctx->count += len; +#if CONFIG_SMALL + for (i = 0; i < len; i++) { + ctx->buffer[j++] = data[i]; + if (128 == j) { + sha512_transform(ctx->state, ctx->buffer); + j = 0; + } + } +#else + if ((j + len) > 127) { + memcpy(&ctx->buffer[j], data, (i = 128 - j)); + sha512_transform(ctx->state, ctx->buffer); + for (; i + 127 < len; i += 128) + sha512_transform(ctx->state, &data[i]); + j = 0; + } else + i = 0; + memcpy(&ctx->buffer[j], &data[i], len - i); +#endif +} + +void av_sha512_final(AVSHA512* ctx, uint8_t *digest) +{ + uint64_t i = 0; + uint64_t finalcount = av_be2ne64(ctx->count << 3); + + av_sha512_update(ctx, "\200", 1); + while ((ctx->count & 127) != 112) + av_sha512_update(ctx, "", 1); + av_sha512_update(ctx, (uint8_t *)&i, 8); + av_sha512_update(ctx, (uint8_t *)&finalcount, 8); /* Should cause a transform() */ + for (i = 0; i < ctx->digest_len; i++) + AV_WB64(digest + i*8, ctx->state[i]); + if (ctx->digest_len & 1) /* SHA512/224 is 28 bytes, and is not divisible by 8. */ + AV_WB32(digest + i*8, ctx->state[i] >> 32); +} + +#ifdef TEST +#include <stdio.h> + +int main(void) +{ + int i, j, k; + AVSHA512 ctx; + unsigned char digest[64]; + static const int lengths[4] = { 224, 256, 384, 512 }; + + for (j = 0; j < 4; j++) { + if (j < 2) printf("Testing SHA-512/%d\n", lengths[j]); + else printf("Testing SHA-%d\n", lengths[j]); + for (k = 0; k < 3; k++) { + av_sha512_init(&ctx, lengths[j]); + if (k == 0) + av_sha512_update(&ctx, "abc", 3); + else if (k == 1) + av_sha512_update(&ctx, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112); + else + for (i = 0; i < 1000*1000; i++) + av_sha512_update(&ctx, "a", 1); + av_sha512_final(&ctx, digest); + for (i = 0; i < lengths[j] >> 3; i++) + printf("%02X", digest[i]); + putchar('\n'); + } + switch (j) { //test vectors (from FIPS PUB 180-4 Apendix A) + case 0: + printf("4634270f 707b6a54 daae7530 460842e2 0e37ed26 5ceee9a4 3e8924aa\n" + "23fec5bb 94d60b23 30819264 0b0c4533 35d66473 4fe40e72 68674af9\n" + "37ab331d 76f0d36d e422bd0e deb22a28 accd487b 7a8453ae 965dd287\n"); + break; + case 1: + printf("53048e26 81941ef9 9b2e29b7 6b4c7dab e4c2d0c6 34fc6d46 e0e2f131 07e7af23\n" + "3928e184 fb8690f8 40da3988 121d31be 65cb9d3e f83ee614 6feac861 e19b563a\n" + "9a59a052 930187a9 7038cae6 92f30708 aa649192 3ef51943 94dc68d5 6c74fb21\n"); + break; + case 2: + printf("cb00753f 45a35e8b b5a03d69 9ac65007 272c32ab 0eded163 " + "1a8b605a 43ff5bed 8086072b a1e7cc23 58baeca1 34c825a7\n" + "09330c33 f71147e8 3d192fc7 82cd1b47 53111b17 3b3b05d2 " + "2fa08086 e3b0f712 fcc7c71a 557e2db9 66c3e9fa 91746039\n" + "9d0e1809 716474cb 086e834e 310a4a1c ed149e9c 00f24852 " + "7972cec5 704c2a5b 07b8b3dc 38ecc4eb ae97ddd8 7f3d8985\n"); + break; + case 3: + printf("ddaf35a1 93617aba cc417349 ae204131 12e6fa4e 89a97ea2 0a9eeee6 4b55d39a " + "2192992a 274fc1a8 36ba3c23 a3feebbd 454d4423 643ce80e 2a9ac94f a54ca49f\n" + "8e959b75 dae313da 8cf4f728 14fc143f 8f7779c6 eb9f7fa1 7299aead b6889018 " + "501d289e 4900f7e4 331b99de c4b5433a c7d329ee b6dd2654 5e96e55b 874be909\n" + "e718483d 0ce76964 4e2e42c7 bc15b463 8e1f98b1 3b204428 5632a803 afa973eb " + "de0ff244 877ea60a 4cb0432c e577c31b eb009c5c 2c49aa2e 4eadb217 ad8cc09b\n"); + break; + } + } + + return 0; +} +#endif diff --git a/libavutil/sha512.h b/libavutil/sha512.h new file mode 100644 index 0000000000..7b08701477 --- /dev/null +++ b/libavutil/sha512.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at> + * Copyright (C) 2013 James Almer <jamrial@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_SHA512_H +#define AVUTIL_SHA512_H + +#include <stdint.h> + +#include "attributes.h" +#include "version.h" + +/** + * @defgroup lavu_sha512 SHA512 + * @ingroup lavu_crypto + * @{ + */ + +extern const int av_sha512_size; + +struct AVSHA512; + +/** + * Allocate an AVSHA512 context. + */ +struct AVSHA512 *av_sha512_alloc(void); + +/** + * Initialize SHA-2 512 hashing. + * + * @param context pointer to the function context (of size av_sha512_size) + * @param bits number of bits in digest (224, 256, 384 or 512 bits) + * @return zero if initialization succeeded, -1 otherwise + */ +int av_sha512_init(struct AVSHA512* context, int bits); + +/** + * Update hash value. + * + * @param context hash function context + * @param data input data to update hash with + * @param len input data length + */ +void av_sha512_update(struct AVSHA512* context, const uint8_t* data, unsigned int len); + +/** + * Finish hashing and output digest value. + * + * @param context hash function context + * @param digest buffer where output digest value is stored + */ +void av_sha512_final(struct AVSHA512* context, uint8_t *digest); + +/** + * @} + */ + +#endif /* AVUTIL_SHA512_H */ diff --git a/libavutil/softfloat.c b/libavutil/softfloat.c new file mode 100644 index 0000000000..bf9cfda33a --- /dev/null +++ b/libavutil/softfloat.c @@ -0,0 +1,71 @@ +/* + * 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 <inttypes.h> +#include <stdio.h> +#include "softfloat.h" +#include "common.h" +#include "log.h" + +#undef printf + +int main(void){ + SoftFloat one= av_int2sf(1, 0); + SoftFloat sf1, sf2; + double d1, d2; + int i, j; + av_log_set_level(AV_LOG_DEBUG); + + d1= 1; + for(i= 0; i<10; i++){ + d1= 1/(d1+1); + } + printf("test1 double=%d\n", (int)(d1 * (1<<24))); + + sf1= one; + for(i= 0; i<10; i++){ + sf1= av_div_sf(one, av_normalize_sf(av_add_sf(one, sf1))); + } + printf("test1 sf =%d\n", av_sf2int(sf1, 24)); + + + for(i= 0; i<100; i++){ + START_TIMER + d1= i; + d2= i/100.0; + for(j= 0; j<1000; j++){ + d1= (d1+1)*d2; + } + STOP_TIMER("float add mul") + } + printf("test2 double=%d\n", (int)(d1 * (1<<24))); + + for(i= 0; i<100; i++){ + START_TIMER + sf1= av_int2sf(i, 0); + sf2= av_div_sf(av_int2sf(i, 2), av_int2sf(200, 3)); + for(j= 0; j<1000; j++){ + sf1= av_mul_sf(av_add_sf(sf1, one),sf2); + } + STOP_TIMER("softfloat add mul") + } + printf("test2 sf =%d (%d %d)\n", av_sf2int(sf1, 24), sf1.exp, sf1.mant); + return 0; +} diff --git a/libavutil/softfloat.h b/libavutil/softfloat.h new file mode 100644 index 0000000000..97e09ea7e7 --- /dev/null +++ b/libavutil/softfloat.h @@ -0,0 +1,126 @@ +/* + * 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_SOFTFLOAT_H +#define AVUTIL_SOFTFLOAT_H + +#include <stdint.h> +#include "common.h" + +#define MIN_EXP -126 +#define MAX_EXP 126 +#define ONE_BITS 29 + +typedef struct SoftFloat{ + int32_t exp; + int32_t mant; +}SoftFloat; + +static av_const SoftFloat av_normalize_sf(SoftFloat a){ + if(a.mant){ +#if 1 + while((a.mant + 0x20000000U)<0x40000000U){ + a.mant += a.mant; + a.exp -= 1; + } +#else + int s=ONE_BITS + 1 - av_log2(a.mant ^ (a.mant<<1)); + a.exp -= s; + a.mant <<= s; +#endif + if(a.exp < MIN_EXP){ + a.exp = MIN_EXP; + a.mant= 0; + } + }else{ + a.exp= MIN_EXP; + } + return a; +} + +static inline av_const SoftFloat av_normalize1_sf(SoftFloat a){ +#if 1 + if(a.mant + 0x40000000 < 0){ + a.exp++; + a.mant>>=1; + } + return a; +#elif 1 + int t= a.mant + 0x40000000 < 0; + return (SoftFloat){a.exp+t, a.mant>>t}; +#else + int t= (a.mant + 0x40000000U)>>31; + return (SoftFloat){a.exp+t, a.mant>>t}; +#endif +} + +/** + * @return Will not be more denormalized than a+b. So if either input is + * normalized, then the output will not be worse then the other input. + * If both are normalized, then the output will be normalized. + */ +static inline av_const SoftFloat av_mul_sf(SoftFloat a, SoftFloat b){ + a.exp += b.exp; + a.mant = (a.mant * (int64_t)b.mant) >> ONE_BITS; + return av_normalize1_sf(a); +} + +/** + * b has to be normalized and not zero. + * @return Will not be more denormalized than a. + */ +static av_const SoftFloat av_div_sf(SoftFloat a, SoftFloat b){ + a.exp -= b.exp+1; + a.mant = ((int64_t)a.mant<<(ONE_BITS+1)) / b.mant; + return av_normalize1_sf(a); +} + +static inline av_const int av_cmp_sf(SoftFloat a, SoftFloat b){ + int t= a.exp - b.exp; + if(t<0) return (a.mant >> (-t)) - b.mant ; + else return a.mant - (b.mant >> t); +} + +static inline av_const SoftFloat av_add_sf(SoftFloat a, SoftFloat b){ + int t= a.exp - b.exp; + if(t<0) return av_normalize1_sf((SoftFloat){b.exp, b.mant + (a.mant >> (-t))}); + else return av_normalize1_sf((SoftFloat){a.exp, a.mant + (b.mant >> t )}); +} + +static inline av_const SoftFloat av_sub_sf(SoftFloat a, SoftFloat b){ + return av_add_sf(a, (SoftFloat){b.exp, -b.mant}); +} + +//FIXME sqrt, log, exp, pow, sin, cos + +static inline av_const SoftFloat av_int2sf(int v, int frac_bits){ + return av_normalize_sf((SoftFloat){ONE_BITS-frac_bits, v}); +} + +/** + * Rounding is to -inf. + */ +static inline av_const int av_sf2int(SoftFloat v, int frac_bits){ + v.exp += frac_bits - ONE_BITS; + if(v.exp >= 0) return v.mant << v.exp ; + else return v.mant >>(-v.exp); +} + +#endif /* AVUTIL_SOFTFLOAT_H */ diff --git a/libavutil/stereo3d.c b/libavutil/stereo3d.c index 850fd75454..a44af21184 100644 --- a/libavutil/stereo3d.c +++ b/libavutil/stereo3d.c @@ -1,20 +1,20 @@ /* * Copyright (c) 2013 Vittorio Giovara <vittorio.giovara@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/stereo3d.h b/libavutil/stereo3d.h index b1910b1f87..1135dc9ddc 100644 --- a/libavutil/stereo3d.h +++ b/libavutil/stereo3d.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2013 Vittorio Giovara <vittorio.giovara@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/threadmessage.c b/libavutil/threadmessage.c new file mode 100644 index 0000000000..b7fcbe28c0 --- /dev/null +++ b/libavutil/threadmessage.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2014 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 "fifo.h" +#include "threadmessage.h" +#if HAVE_THREADS +#if HAVE_PTHREADS +#include <pthread.h> +#elif HAVE_W32THREADS +#include "compat/w32pthreads.h" +#elif HAVE_OS2THREADS +#include "compat/os2threads.h" +#else +#error "Unknown threads implementation" +#endif +#endif + +struct AVThreadMessageQueue { +#if HAVE_THREADS + AVFifoBuffer *fifo; + pthread_mutex_t lock; + pthread_cond_t cond; + int err_send; + int err_recv; + unsigned elsize; +#else + int dummy; +#endif +}; + +int av_thread_message_queue_alloc(AVThreadMessageQueue **mq, + unsigned nelem, + unsigned elsize) +{ +#if HAVE_THREADS + AVThreadMessageQueue *rmq; + int ret = 0; + + if (nelem > INT_MAX / elsize) + return AVERROR(EINVAL); + if (!(rmq = av_mallocz(sizeof(*rmq)))) + return AVERROR(ENOMEM); + if ((ret = pthread_mutex_init(&rmq->lock, NULL))) { + av_free(rmq); + return AVERROR(ret); + } + if ((ret = pthread_cond_init(&rmq->cond, NULL))) { + pthread_mutex_destroy(&rmq->lock); + av_free(rmq); + return AVERROR(ret); + } + if (!(rmq->fifo = av_fifo_alloc(elsize * nelem))) { + pthread_cond_destroy(&rmq->cond); + pthread_mutex_destroy(&rmq->lock); + av_free(rmq); + return AVERROR(ret); + } + rmq->elsize = elsize; + *mq = rmq; + return 0; +#else + *mq = NULL; + return AVERROR(ENOSYS); +#endif /* HAVE_THREADS */ +} + +void av_thread_message_queue_free(AVThreadMessageQueue **mq) +{ +#if HAVE_THREADS + if (*mq) { + av_fifo_freep(&(*mq)->fifo); + pthread_cond_destroy(&(*mq)->cond); + pthread_mutex_destroy(&(*mq)->lock); + av_freep(mq); + } +#endif +} + +#if HAVE_THREADS + +static int av_thread_message_queue_send_locked(AVThreadMessageQueue *mq, + void *msg, + unsigned flags) +{ + while (!mq->err_send && av_fifo_space(mq->fifo) < mq->elsize) { + if ((flags & AV_THREAD_MESSAGE_NONBLOCK)) + return AVERROR(EAGAIN); + pthread_cond_wait(&mq->cond, &mq->lock); + } + if (mq->err_send) + return mq->err_send; + av_fifo_generic_write(mq->fifo, msg, mq->elsize, NULL); + pthread_cond_signal(&mq->cond); + return 0; +} + +static int av_thread_message_queue_recv_locked(AVThreadMessageQueue *mq, + void *msg, + unsigned flags) +{ + while (!mq->err_recv && av_fifo_size(mq->fifo) < mq->elsize) { + if ((flags & AV_THREAD_MESSAGE_NONBLOCK)) + return AVERROR(EAGAIN); + pthread_cond_wait(&mq->cond, &mq->lock); + } + if (av_fifo_size(mq->fifo) < mq->elsize) + return mq->err_recv; + av_fifo_generic_read(mq->fifo, msg, mq->elsize, NULL); + pthread_cond_signal(&mq->cond); + return 0; +} + +#endif /* HAVE_THREADS */ + +int av_thread_message_queue_send(AVThreadMessageQueue *mq, + void *msg, + unsigned flags) +{ +#if HAVE_THREADS + int ret; + + pthread_mutex_lock(&mq->lock); + ret = av_thread_message_queue_send_locked(mq, msg, flags); + pthread_mutex_unlock(&mq->lock); + return ret; +#else + return AVERROR(ENOSYS); +#endif /* HAVE_THREADS */ +} + +int av_thread_message_queue_recv(AVThreadMessageQueue *mq, + void *msg, + unsigned flags) +{ +#if HAVE_THREADS + int ret; + + pthread_mutex_lock(&mq->lock); + ret = av_thread_message_queue_recv_locked(mq, msg, flags); + pthread_mutex_unlock(&mq->lock); + return ret; +#else + return AVERROR(ENOSYS); +#endif /* HAVE_THREADS */ +} + +void av_thread_message_queue_set_err_send(AVThreadMessageQueue *mq, + int err) +{ +#if HAVE_THREADS + pthread_mutex_lock(&mq->lock); + mq->err_send = err; + pthread_cond_broadcast(&mq->cond); + pthread_mutex_unlock(&mq->lock); +#endif /* HAVE_THREADS */ +} + +void av_thread_message_queue_set_err_recv(AVThreadMessageQueue *mq, + int err) +{ +#if HAVE_THREADS + pthread_mutex_lock(&mq->lock); + mq->err_recv = err; + pthread_cond_broadcast(&mq->cond); + pthread_mutex_unlock(&mq->lock); +#endif /* HAVE_THREADS */ +} diff --git a/libavutil/threadmessage.h b/libavutil/threadmessage.h new file mode 100644 index 0000000000..a8481d8ec3 --- /dev/null +++ b/libavutil/threadmessage.h @@ -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_THREADMESSAGE_H +#define AVUTIL_THREADMESSAGE_H + +typedef struct AVThreadMessageQueue AVThreadMessageQueue; + +typedef enum AVThreadMessageFlags { + + /** + * Perform non-blocking operation. + * If this flag is set, send and recv operations are non-blocking and + * return AVERROR(EAGAIN) immediately if they can not proceed. + */ + AV_THREAD_MESSAGE_NONBLOCK = 1, + +} AVThreadMessageFlags; + +/** + * Allocate a new message queue. + * + * @param mq pointer to the message queue + * @param nelem maximum number of elements in the queue + * @param elsize size of each element in the queue + * @return >=0 for success; <0 for error, in particular AVERROR(ENOSYS) if + * lavu was built without thread support + */ +int av_thread_message_queue_alloc(AVThreadMessageQueue **mq, + unsigned nelem, + unsigned elsize); + +/** + * Free a message queue. + * + * The message queue must no longer be in use by another thread. + */ +void av_thread_message_queue_free(AVThreadMessageQueue **mq); + +/** + * Send a message on the queue. + */ +int av_thread_message_queue_send(AVThreadMessageQueue *mq, + void *msg, + unsigned flags); + +/** + * Receive a message from the queue. + */ +int av_thread_message_queue_recv(AVThreadMessageQueue *mq, + void *msg, + unsigned flags); + +/** + * Set the sending error code. + * + * If the error code is set to non-zero, av_thread_message_queue_recv() will + * return it immediately when there are no longer available messages. + * Conventional values, such as AVERROR_EOF or AVERROR(EAGAIN), can be used + * to cause the receiving thread to stop or suspend its operation. + */ +void av_thread_message_queue_set_err_send(AVThreadMessageQueue *mq, + int err); + +/** + * Set the receiving error code. + * + * If the error code is set to non-zero, av_thread_message_queue_send() will + * return it immediately. Conventional values, such as AVERROR_EOF or + * AVERROR(EAGAIN), can be used to cause the sending thread to stop or + * suspend its operation. + */ +void av_thread_message_queue_set_err_recv(AVThreadMessageQueue *mq, + int err); + +#endif /* AVUTIL_THREADMESSAGE_H */ diff --git a/libavutil/time.c b/libavutil/time.c index 62cd445dbc..ce4552e767 100644 --- a/libavutil/time.c +++ b/libavutil/time.c @@ -1,18 +1,20 @@ /* - * This file is part of Libav. + * Copyright (c) 2000-2003 Fabrice Bellard * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -51,6 +53,26 @@ int64_t av_gettime(void) #endif } +int64_t av_gettime_relative(void) +{ +#if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC) + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (int64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000; +#else + return av_gettime(); +#endif +} + +int av_gettime_relative_is_monotonic(void) +{ +#if HAVE_CLOCK_GETTIME && defined(CLOCK_MONOTONIC) + return 1; +#else + return 0; +#endif +} + int av_usleep(unsigned usec) { #if HAVE_NANOSLEEP diff --git a/libavutil/time.h b/libavutil/time.h index b01a97d770..910d28e85f 100644 --- a/libavutil/time.h +++ b/libavutil/time.h @@ -1,18 +1,20 @@ /* - * This file is part of Libav. + * Copyright (c) 2000-2003 Fabrice Bellard * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -27,6 +29,21 @@ int64_t av_gettime(void); /** + * Get the current time in microseconds since some unspecified starting point. + * On platforms that support it, the time comes from a monotonic clock + * This property makes this time source ideal for measuring relative time. + * If a monotonic clock is not available on the targeted platform, the + * implementation fallsback on using av_gettime(). + */ +int64_t av_gettime_relative(void); + +/** + * Indicates with a boolean result if the av_gettime_relative() time source + * is monotonic. + */ +int av_gettime_relative_is_monotonic(void); + +/** * Sleep for a period of time. Although the duration is expressed in * microseconds, the actual delay may be rounded to the precision of the * system timer. diff --git a/libavutil/timecode.c b/libavutil/timecode.c new file mode 100644 index 0000000000..1dfd040868 --- /dev/null +++ b/libavutil/timecode.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2006 Smartjog S.A.S, Baptiste Coudurier <baptiste.coudurier@gmail.com> + * Copyright (c) 2011-2012 Smartjog S.A.S, Clément Bœsch <clement.boesch@smartjog.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 + * Timecode helpers + * @see https://en.wikipedia.org/wiki/SMPTE_time_code + * @see http://www.dropframetimecode.org + */ + +#include <stdio.h> +#include "timecode.h" +#include "log.h" +#include "error.h" + +int av_timecode_adjust_ntsc_framenum2(int framenum, int fps) +{ + /* only works for NTSC 29.97 and 59.94 */ + int drop_frames = 0; + int d, m, frames_per_10mins; + + if (fps == 30) { + drop_frames = 2; + frames_per_10mins = 17982; + } else if (fps == 60) { + drop_frames = 4; + frames_per_10mins = 35964; + } else + return framenum; + + d = framenum / frames_per_10mins; + m = framenum % frames_per_10mins; + + return framenum + 9 * drop_frames * d + drop_frames * ((m - drop_frames) / (frames_per_10mins / 10)); +} + +uint32_t av_timecode_get_smpte_from_framenum(const AVTimecode *tc, int framenum) +{ + unsigned fps = tc->fps; + int drop = !!(tc->flags & AV_TIMECODE_FLAG_DROPFRAME); + int hh, mm, ss, ff; + + framenum += tc->start; + if (drop) + framenum = av_timecode_adjust_ntsc_framenum2(framenum, tc->fps); + ff = framenum % fps; + ss = framenum / fps % 60; + mm = framenum / (fps*60) % 60; + hh = framenum / (fps*3600) % 24; + return 0 << 31 | // color frame flag (0: unsync mode, 1: sync mode) + drop << 30 | // drop frame flag (0: non drop, 1: drop) + (ff / 10) << 28 | // tens of frames + (ff % 10) << 24 | // units of frames + 0 << 23 | // PC (NTSC) or BGF0 (PAL) + (ss / 10) << 20 | // tens of seconds + (ss % 10) << 16 | // units of seconds + 0 << 15 | // BGF0 (NTSC) or BGF2 (PAL) + (mm / 10) << 12 | // tens of minutes + (mm % 10) << 8 | // units of minutes + 0 << 7 | // BGF2 (NTSC) or PC (PAL) + 0 << 6 | // BGF1 + (hh / 10) << 4 | // tens of hours + (hh % 10); // units of hours +} + +char *av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum) +{ + int fps = tc->fps; + int drop = tc->flags & AV_TIMECODE_FLAG_DROPFRAME; + int hh, mm, ss, ff, neg = 0; + + framenum += tc->start; + if (drop) + framenum = av_timecode_adjust_ntsc_framenum2(framenum, fps); + if (framenum < 0) { + framenum = -framenum; + neg = tc->flags & AV_TIMECODE_FLAG_ALLOWNEGATIVE; + } + ff = framenum % fps; + ss = framenum / fps % 60; + mm = framenum / (fps*60) % 60; + hh = framenum / (fps*3600); + if (tc->flags & AV_TIMECODE_FLAG_24HOURSMAX) + hh = hh % 24; + snprintf(buf, AV_TIMECODE_STR_SIZE, "%s%02d:%02d:%02d%c%02d", + neg ? "-" : "", + hh, mm, ss, drop ? ';' : ':', ff); + return buf; +} + +static unsigned bcd2uint(uint8_t bcd) +{ + unsigned low = bcd & 0xf; + unsigned high = bcd >> 4; + if (low > 9 || high > 9) + return 0; + return low + 10*high; +} + +char *av_timecode_make_smpte_tc_string(char *buf, uint32_t tcsmpte, int prevent_df) +{ + unsigned hh = bcd2uint(tcsmpte & 0x3f); // 6-bit hours + unsigned mm = bcd2uint(tcsmpte>>8 & 0x7f); // 7-bit minutes + unsigned ss = bcd2uint(tcsmpte>>16 & 0x7f); // 7-bit seconds + unsigned ff = bcd2uint(tcsmpte>>24 & 0x3f); // 6-bit frames + unsigned drop = tcsmpte & 1<<30 && !prevent_df; // 1-bit drop if not arbitrary bit + snprintf(buf, AV_TIMECODE_STR_SIZE, "%02u:%02u:%02u%c%02u", + hh, mm, ss, drop ? ';' : ':', ff); + return buf; +} + +char *av_timecode_make_mpeg_tc_string(char *buf, uint32_t tc25bit) +{ + snprintf(buf, AV_TIMECODE_STR_SIZE, "%02u:%02u:%02u%c%02u", + tc25bit>>19 & 0x1f, // 5-bit hours + tc25bit>>13 & 0x3f, // 6-bit minutes + tc25bit>>6 & 0x3f, // 6-bit seconds + tc25bit & 1<<24 ? ';' : ':', // 1-bit drop flag + tc25bit & 0x3f); // 6-bit frames + return buf; +} + +static int check_fps(int fps) +{ + int i; + static const int supported_fps[] = {24, 25, 30, 48, 50, 60}; + + for (i = 0; i < FF_ARRAY_ELEMS(supported_fps); i++) + if (fps == supported_fps[i]) + return 0; + return -1; +} + +static int check_timecode(void *log_ctx, AVTimecode *tc) +{ + if (tc->fps <= 0) { + av_log(log_ctx, AV_LOG_ERROR, "Timecode frame rate must be specified\n"); + return AVERROR(EINVAL); + } + if ((tc->flags & AV_TIMECODE_FLAG_DROPFRAME) && tc->fps != 30 && tc->fps != 60) { + av_log(log_ctx, AV_LOG_ERROR, "Drop frame is only allowed with 30000/1001 or 60000/1001 FPS\n"); + return AVERROR(EINVAL); + } + if (check_fps(tc->fps) < 0) { + av_log(log_ctx, AV_LOG_ERROR, "Timecode frame rate %d/%d not supported\n", + tc->rate.num, tc->rate.den); + return AVERROR_PATCHWELCOME; + } + return 0; +} + +static int fps_from_frame_rate(AVRational rate) +{ + if (!rate.den || !rate.num) + return -1; + return (rate.num + rate.den/2) / rate.den; +} + +int av_timecode_check_frame_rate(AVRational rate) +{ + return check_fps(fps_from_frame_rate(rate)); +} + +int av_timecode_init(AVTimecode *tc, AVRational rate, int flags, int frame_start, void *log_ctx) +{ + memset(tc, 0, sizeof(*tc)); + tc->start = frame_start; + tc->flags = flags; + tc->rate = rate; + tc->fps = fps_from_frame_rate(rate); + return check_timecode(log_ctx, tc); +} + +int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx) +{ + char c; + int hh, mm, ss, ff, ret; + + if (sscanf(str, "%d:%d:%d%c%d", &hh, &mm, &ss, &c, &ff) != 5) { + av_log(log_ctx, AV_LOG_ERROR, "Unable to parse timecode, " + "syntax: hh:mm:ss[:;.]ff\n"); + return AVERROR_INVALIDDATA; + } + + memset(tc, 0, sizeof(*tc)); + tc->flags = c != ':' ? AV_TIMECODE_FLAG_DROPFRAME : 0; // drop if ';', '.', ... + tc->rate = rate; + tc->fps = fps_from_frame_rate(rate); + + ret = check_timecode(log_ctx, tc); + if (ret < 0) + return ret; + + tc->start = (hh*3600 + mm*60 + ss) * tc->fps + ff; + if (tc->flags & AV_TIMECODE_FLAG_DROPFRAME) { /* adjust frame number */ + int tmins = 60*hh + mm; + tc->start -= 2 * (tmins - tmins/10); + } + return 0; +} diff --git a/libavutil/timecode.h b/libavutil/timecode.h new file mode 100644 index 0000000000..56e3975fd8 --- /dev/null +++ b/libavutil/timecode.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2006 Smartjog S.A.S, Baptiste Coudurier <baptiste.coudurier@gmail.com> + * Copyright (c) 2011-2012 Smartjog S.A.S, Clément Bœsch <clement.boesch@smartjog.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 + * Timecode helpers header + */ + +#ifndef AVUTIL_TIMECODE_H +#define AVUTIL_TIMECODE_H + +#include <stdint.h> +#include "rational.h" + +#define AV_TIMECODE_STR_SIZE 16 + +enum AVTimecodeFlag { + AV_TIMECODE_FLAG_DROPFRAME = 1<<0, ///< timecode is drop frame + AV_TIMECODE_FLAG_24HOURSMAX = 1<<1, ///< timecode wraps after 24 hours + AV_TIMECODE_FLAG_ALLOWNEGATIVE = 1<<2, ///< negative time values are allowed +}; + +typedef struct { + int start; ///< timecode frame start (first base frame number) + uint32_t flags; ///< flags such as drop frame, +24 hours support, ... + AVRational rate; ///< frame rate in rational form + unsigned fps; ///< frame per second; must be consistent with the rate field +} AVTimecode; + +/** + * Adjust frame number for NTSC drop frame time code. + * + * @param framenum frame number to adjust + * @param fps frame per second, 30 or 60 + * @return adjusted frame number + * @warning adjustment is only valid in NTSC 29.97 and 59.94 + */ +int av_timecode_adjust_ntsc_framenum2(int framenum, int fps); + +/** + * Convert frame number to SMPTE 12M binary representation. + * + * @param tc timecode data correctly initialized + * @param framenum frame number + * @return the SMPTE binary representation + * + * @note Frame number adjustment is automatically done in case of drop timecode, + * you do NOT have to call av_timecode_adjust_ntsc_framenum2(). + * @note The frame number is relative to tc->start. + * @note Color frame (CF), binary group flags (BGF) and biphase mark polarity + * correction (PC) bits are set to zero. + */ +uint32_t av_timecode_get_smpte_from_framenum(const AVTimecode *tc, int framenum); + +/** + * Load timecode string in buf. + * + * @param buf destination buffer, must be at least AV_TIMECODE_STR_SIZE long + * @param tc timecode data correctly initialized + * @param framenum frame number + * @return the buf parameter + * + * @note Timecode representation can be a negative timecode and have more than + * 24 hours, but will only be honored if the flags are correctly set. + * @note The frame number is relative to tc->start. + */ +char *av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum); + +/** + * Get the timecode string from the SMPTE timecode format. + * + * @param buf destination buffer, must be at least AV_TIMECODE_STR_SIZE long + * @param tcsmpte the 32-bit SMPTE timecode + * @param prevent_df prevent the use of a drop flag when it is known the DF bit + * is arbitrary + * @return the buf parameter + */ +char *av_timecode_make_smpte_tc_string(char *buf, uint32_t tcsmpte, int prevent_df); + +/** + * Get the timecode string from the 25-bit timecode format (MPEG GOP format). + * + * @param buf destination buffer, must be at least AV_TIMECODE_STR_SIZE long + * @param tc25bit the 25-bits timecode + * @return the buf parameter + */ +char *av_timecode_make_mpeg_tc_string(char *buf, uint32_t tc25bit); + +/** + * Init a timecode struct with the passed parameters. + * + * @param log_ctx a pointer to an arbitrary struct of which the first field + * is a pointer to an AVClass struct (used for av_log) + * @param tc pointer to an allocated AVTimecode + * @param rate frame rate in rational form + * @param flags miscellaneous flags such as drop frame, +24 hours, ... + * (see AVTimecodeFlag) + * @param frame_start the first frame number + * @return 0 on success, AVERROR otherwise + */ +int av_timecode_init(AVTimecode *tc, AVRational rate, int flags, int frame_start, void *log_ctx); + +/** + * Parse timecode representation (hh:mm:ss[:;.]ff). + * + * @param log_ctx a pointer to an arbitrary struct of which the first field is a + * pointer to an AVClass struct (used for av_log). + * @param tc pointer to an allocated AVTimecode + * @param rate frame rate in rational form + * @param str timecode string which will determine the frame start + * @return 0 on success, AVERROR otherwise + */ +int av_timecode_init_from_string(AVTimecode *tc, AVRational rate, const char *str, void *log_ctx); + +/** + * Check if the timecode feature is available for the given frame rate + * + * @return 0 if supported, <0 otherwise + */ +int av_timecode_check_frame_rate(AVRational rate); + +#endif /* AVUTIL_TIMECODE_H */ diff --git a/libavutil/timer.h b/libavutil/timer.h index 0d93d7c0ef..3fff77ff1c 100644 --- a/libavutil/timer.h +++ b/libavutil/timer.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -56,6 +56,10 @@ # endif #endif +#ifndef FF_TIMER_UNITS +# define FF_TIMER_UNITS "UNITS" +#endif + #ifdef AV_READ_TIME #define START_TIMER \ uint64_t tend; \ @@ -76,7 +80,7 @@ tskip_count++; \ if (((tcount + tskip_count) & (tcount + tskip_count - 1)) == 0) { \ av_log(NULL, AV_LOG_ERROR, \ - "%"PRIu64" UNITS in %s, %d runs, %d skips\n", \ + "%"PRIu64" " FF_TIMER_UNITS " in %s, %d runs, %d skips\n", \ tsum * 10 / tcount, id, tcount, tskip_count); \ } \ } diff --git a/libavutil/timestamp.h b/libavutil/timestamp.h new file mode 100644 index 0000000000..f010a7ee38 --- /dev/null +++ b/libavutil/timestamp.h @@ -0,0 +1,78 @@ +/* + * 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 + * timestamp utils, mostly useful for debugging/logging purposes + */ + +#ifndef AVUTIL_TIMESTAMP_H +#define AVUTIL_TIMESTAMP_H + +#include "common.h" + +#if defined(__cplusplus) && !defined(__STDC_FORMAT_MACROS) && !defined(PRId64) +#error missing -D__STDC_FORMAT_MACROS / #define __STDC_FORMAT_MACROS +#endif + +#define AV_TS_MAX_STRING_SIZE 32 + +/** + * Fill the provided buffer with a string containing a timestamp + * representation. + * + * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE + * @param ts the timestamp to represent + * @return the buffer in input + */ +static inline char *av_ts_make_string(char *buf, int64_t ts) +{ + if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS"); + else snprintf(buf, AV_TS_MAX_STRING_SIZE, "%"PRId64, ts); + return buf; +} + +/** + * Convenience macro, the return value should be used only directly in + * function arguments but never stand-alone. + */ +#define av_ts2str(ts) av_ts_make_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts) + +/** + * Fill the provided buffer with a string containing a timestamp time + * representation. + * + * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE + * @param ts the timestamp to represent + * @param tb the timebase of the timestamp + * @return the buffer in input + */ +static inline char *av_ts_make_time_string(char *buf, int64_t ts, AVRational *tb) +{ + if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS"); + else snprintf(buf, AV_TS_MAX_STRING_SIZE, "%.6g", av_q2d(*tb) * ts); + return buf; +} + +/** + * Convenience macro, the return value should be used only directly in + * function arguments but never stand-alone. + */ +#define av_ts2timestr(ts, tb) av_ts_make_time_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts, tb) + +#endif /* AVUTIL_TIMESTAMP_H */ diff --git a/libavutil/tomi/intreadwrite.h b/libavutil/tomi/intreadwrite.h index baf592a7e1..7dec4158d3 100644 --- a/libavutil/tomi/intreadwrite.h +++ b/libavutil/tomi/intreadwrite.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2010 Mans Rullgard <mans@mansr.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/tree.c b/libavutil/tree.c index d48d01af5b..d0b67efc5d 100644 --- a/libavutil/tree.c +++ b/libavutil/tree.c @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -29,9 +29,7 @@ typedef struct AVTreeNode { int state; } AVTreeNode; -#if FF_API_CONTEXT_SIZE const int av_tree_node_size = sizeof(AVTreeNode); -#endif struct AVTreeNode *av_tree_node_alloc(void) { @@ -209,29 +207,27 @@ static int cmp(void *a, const void *b) return (uint8_t *) a - (const uint8_t *) b; } -int main(void) +int main(int argc, char **argv) { int i; + void *k; AVTreeNode *root = NULL, *node = NULL; AVLFG prng; + int log_level = argc <= 1 ? AV_LOG_INFO : atoi(argv[1]); + + av_log_set_level(log_level); av_lfg_init(&prng, 1); for (i = 0; i < 10000; i++) { - AVTreeNode *node2 = NULL; intptr_t j = av_lfg_get(&prng) % 86294; - void *ret, *jj = (void *)(j + 1); - - while (ret = av_tree_find(root, jj, cmp, NULL)) { - j = av_lfg_get(&prng) % 86294; - jj = (void *)(j + 1); - } if (check(root) > 999) { av_log(NULL, AV_LOG_ERROR, "FATAL error %d\n", i); print(root, 0); return 1; } + av_log(NULL, AV_LOG_DEBUG, "inserting %4d\n", (int)j); if (!node) node = av_tree_node_alloc(); @@ -239,20 +235,20 @@ int main(void) av_log(NULL, AV_LOG_ERROR, "Memory allocation failure.\n"); return 1; } - av_tree_insert(&root, jj, cmp, &node); + av_tree_insert(&root, (void *)(j + 1), cmp, &node); - while (ret = av_tree_find(root, jj, cmp, NULL)) { - j = av_lfg_get(&prng) % 86294; - jj = (void *)(j + 1); + j = av_lfg_get(&prng) % 86294; + { + AVTreeNode *node2 = NULL; + av_log(NULL, AV_LOG_DEBUG, "removing %4d\n", (int)j); + av_tree_insert(&root, (void *)(j + 1), cmp, &node2); + k = av_tree_find(root, (void *)(j + 1), cmp, NULL); + if (k) + av_log(NULL, AV_LOG_ERROR, "removal failure %d\n", i); + av_free(node2); } - - ret = av_tree_insert(&root, jj, cmp, &node2); - if (ret != jj) - av_tree_destroy(node2); - ret = av_tree_find(root, jj, cmp, NULL); - if (ret) - av_log(NULL, AV_LOG_ERROR, "removal failure %d\n", i); } + av_free(node); av_tree_destroy(root); diff --git a/libavutil/tree.h b/libavutil/tree.h index 424656e06a..a14fa9156a 100644 --- a/libavutil/tree.h +++ b/libavutil/tree.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -43,9 +43,7 @@ struct AVTreeNode; -#if FF_API_CONTEXT_SIZE -extern attribute_deprecated const int av_tree_node_size; -#endif +extern const int av_tree_node_size; /** * Allocate an AVTreeNode. @@ -66,18 +64,21 @@ void *av_tree_find(const struct AVTreeNode *root, void *key, /** * Insert or remove an element. + * * If *next is NULL, then the supplied element will be removed if it exists. - * If *next is not NULL, then the supplied element will be inserted, unless + * If *next is non-NULL, then the supplied element will be inserted, unless * it already exists in the tree. + * * @param rootp A pointer to a pointer to the root node of the tree; note that * the root node can change during insertions, this is required * to keep the tree balanced. + * @param key pointer to the element key to insert in the tree * @param next Used to allocate and free AVTreeNodes. For insertion the user * must set it to an allocated and zeroed object of at least * av_tree_node_size bytes size. av_tree_insert() will set it to * NULL if it has been consumed. * For deleting elements *next is set to NULL by the user and - * av_tree_node_size() will set it to the AVTreeNode which was + * av_tree_insert() will set it to the AVTreeNode which was * used for the removed element. * This allows the use of flat arrays, which have * lower overhead compared to many malloced elements. @@ -98,6 +99,7 @@ void *av_tree_find(const struct AVTreeNode *root, void *key, * return av_tree_insert(rootp, key, cmp, next); * } * @endcode + * @param cmp compare function used to compare elements in the tree * @return If no insertion happened, the found element; if an insertion or * removal happened, then either key or NULL will be returned. * Which one it is depends on the tree state and the implementation. You diff --git a/libavutil/utf8.c b/libavutil/utf8.c new file mode 100644 index 0000000000..3447a5192b --- /dev/null +++ b/libavutil/utf8.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013 Stefano Sabatini + * + * 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 + */ + +#ifdef TEST +#include <stdio.h> + +#include "libavutil/avstring.h" +#include "libavutil/file.h" + +static void print_sequence(const char *p, int l, int indent) +{ + int i; + for (i = 0; i < l; i++) + printf("%02X", (uint8_t)p[i]); + printf("%*s", indent-l*2, ""); +} + +int main(int argc, char **argv) +{ + int ret; + char *filename = argv[1]; + uint8_t *file_buf; + size_t file_buf_size; + uint32_t code; + const uint8_t *p, *endp; + + ret = av_file_map(filename, &file_buf, &file_buf_size, 0, NULL); + if (ret < 0) + return 1; + + p = file_buf; + endp = file_buf + file_buf_size; + while (p < endp) { + int l, r; + const uint8_t *p0 = p; + code = UINT32_MAX; + r = av_utf8_decode(&code, &p, endp, 0); + l = (int)(p-p0); + print_sequence(p0, l, 20); + if (code != UINT32_MAX) { + printf("%-10d 0x%-10X %-5d ", code, code, l); + if (r >= 0) { + if (*p0 == '\n') printf("\\n\n"); + else printf ("%.*s\n", l, p0); + } else { + printf("invalid code range\n"); + } + } else { + printf("invalid sequence\n"); + } + } + + av_file_unmap(file_buf, file_buf_size); + return 0; +} +#endif diff --git a/libavutil/utils.c b/libavutil/utils.c index c8c161dccb..aafd3b909e 100644 --- a/libavutil/utils.c +++ b/libavutil/utils.c @@ -1,23 +1,26 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * 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 "avutil.h" +#include "avassert.h" +#include "samplefmt.h" +#include "pixdesc.h" /** * @file @@ -26,18 +29,56 @@ unsigned avutil_version(void) { + static int checks_done; + if (checks_done) + return LIBAVUTIL_VERSION_INT; + + av_assert0(AV_PIX_FMT_VDA_VLD == 81); //check if the pix fmt enum has not had anything inserted or removed by mistake + av_assert0(AV_SAMPLE_FMT_DBLP == 9); + av_assert0(AVMEDIA_TYPE_ATTACHMENT == 4); + av_assert0(AV_PICTURE_TYPE_BI == 7); + av_assert0(LIBAVUTIL_VERSION_MICRO >= 100); + av_assert0(HAVE_MMX2 == HAVE_MMXEXT); + + av_assert0(((size_t)-1) > 0); // C guarantees this but if false on a platform we care about revert at least b284e1ffe343d6697fb950d1ee517bafda8a9844 + + if (av_sat_dadd32(1, 2) != 5) { + av_log(NULL, AV_LOG_FATAL, "Libavutil has been build with a broken binutils, please upgrade binutils and rebuild\n"); + abort(); + } + + if (llrint(1LL<<60) != 1LL<<60) { + av_log(NULL, AV_LOG_ERROR, "Libavutil has been linked to a broken llrint()\n"); + } + +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 0 + ff_check_pixfmt_descriptors(); +#endif + checks_done = 1; return LIBAVUTIL_VERSION_INT; } const char *avutil_configuration(void) { - return LIBAV_CONFIGURATION; + return FFMPEG_CONFIGURATION; } const char *avutil_license(void) { #define LICENSE_PREFIX "libavutil license: " - return LICENSE_PREFIX LIBAV_LICENSE + sizeof(LICENSE_PREFIX) - 1; + return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1; +} + +const char *av_get_media_type_string(enum AVMediaType media_type) +{ + switch (media_type) { + case AVMEDIA_TYPE_VIDEO: return "video"; + case AVMEDIA_TYPE_AUDIO: return "audio"; + case AVMEDIA_TYPE_DATA: return "data"; + case AVMEDIA_TYPE_SUBTITLE: return "subtitle"; + case AVMEDIA_TYPE_ATTACHMENT: return "attachment"; + default: return NULL; + } } char av_get_picture_type_char(enum AVPictureType pict_type) @@ -54,6 +95,25 @@ char av_get_picture_type_char(enum AVPictureType pict_type) } } +unsigned av_int_list_length_for_size(unsigned elsize, + const void *list, uint64_t term) +{ + unsigned i; + + if (!list) + return 0; +#define LIST_LENGTH(type) \ + { type t = term, *l = (type *)list; for (i = 0; l[i] != t; i++); } + switch (elsize) { + case 1: LIST_LENGTH(uint8_t); break; + case 2: LIST_LENGTH(uint16_t); break; + case 4: LIST_LENGTH(uint32_t); break; + case 8: LIST_LENGTH(uint64_t); break; + default: av_assert0(!"valid element size"); + } + return i; +} + AVRational av_get_time_base_q(void) { return (AVRational){1, AV_TIME_BASE}; diff --git a/libavutil/version.h b/libavutil/version.h index 15ab8903bc..c31c1501d3 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -1,18 +1,20 @@ /* - * This file is part of Libav. + * copyright (c) 2003 Fabrice Bellard * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -22,7 +24,7 @@ #include "macros.h" /** - * @defgroup version_utils Library Version Macros + * @addtogroup version_utils * * Useful to check and match library version in order to maintain * backward compatibility. @@ -53,9 +55,9 @@ * @{ */ -#define LIBAVUTIL_VERSION_MAJOR 53 -#define LIBAVUTIL_VERSION_MINOR 21 -#define LIBAVUTIL_VERSION_MICRO 1 +#define LIBAVUTIL_VERSION_MAJOR 52 +#define LIBAVUTIL_VERSION_MINOR 96 +#define LIBAVUTIL_VERSION_MICRO 101 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ LIBAVUTIL_VERSION_MINOR, \ @@ -78,6 +80,15 @@ * @{ */ +#ifndef FF_API_GET_BITS_PER_SAMPLE_FMT +#define FF_API_GET_BITS_PER_SAMPLE_FMT (LIBAVUTIL_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_FIND_OPT +#define FF_API_FIND_OPT (LIBAVUTIL_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_OLD_AVOPTIONS +#define FF_API_OLD_AVOPTIONS (LIBAVUTIL_VERSION_MAJOR < 54) +#endif #ifndef FF_API_PIX_FMT #define FF_API_PIX_FMT (LIBAVUTIL_VERSION_MAJOR < 54) #endif @@ -96,28 +107,52 @@ #ifndef FF_API_CPU_FLAG_MMX2 #define FF_API_CPU_FLAG_MMX2 (LIBAVUTIL_VERSION_MAJOR < 54) #endif +#ifndef FF_API_SAMPLES_UTILS_RETURN_ZERO +#define FF_API_SAMPLES_UTILS_RETURN_ZERO (LIBAVUTIL_VERSION_MAJOR < 54) +#endif #ifndef FF_API_LLS_PRIVATE #define FF_API_LLS_PRIVATE (LIBAVUTIL_VERSION_MAJOR < 54) #endif +#ifndef FF_API_LLS1 +#define FF_API_LLS1 (LIBAVUTIL_VERSION_MAJOR < 54) +#endif #ifndef FF_API_AVFRAME_LAVC #define FF_API_AVFRAME_LAVC (LIBAVUTIL_VERSION_MAJOR < 54) #endif #ifndef FF_API_VDPAU #define FF_API_VDPAU (LIBAVUTIL_VERSION_MAJOR < 54) #endif +#ifndef FF_API_GET_CHANNEL_LAYOUT_COMPAT +#define FF_API_GET_CHANNEL_LAYOUT_COMPAT (LIBAVUTIL_VERSION_MAJOR < 54) +#endif +#ifndef FF_API_OLD_OPENCL +#define FF_API_OLD_OPENCL (LIBAVUTIL_VERSION_MAJOR < 54) +#endif #ifndef FF_API_XVMC #define FF_API_XVMC (LIBAVUTIL_VERSION_MAJOR < 54) #endif +#ifndef FF_API_INTFLOAT +#define FF_API_INTFLOAT (LIBAVUTIL_VERSION_MAJOR < 54) +#endif #ifndef FF_API_OPT_TYPE_METADATA #define FF_API_OPT_TYPE_METADATA (LIBAVUTIL_VERSION_MAJOR < 54) #endif #ifndef FF_API_AVFRAME_COLORSPACE -#define FF_API_AVFRAME_COLORSPACE (LIBAVUTIL_VERSION_MAJOR >= 54) +#define FF_API_AVFRAME_COLORSPACE (LIBAVUTIL_VERSION_MAJOR >= 52) #endif +#ifndef FF_CONST_AVUTIL53 +#if LIBAVUTIL_VERSION_MAJOR >= 53 +#define FF_CONST_AVUTIL53 const +#else +#define FF_CONST_AVUTIL53 +#endif +#endif + /** * @} */ #endif /* AVUTIL_VERSION_H */ + diff --git a/libavutil/x86/asm.h b/libavutil/x86/asm.h index e30f5dbaf7..616ad6c96f 100644 --- a/libavutil/x86/asm.h +++ b/libavutil/x86/asm.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -25,6 +25,7 @@ #include "config.h" typedef struct xmm_reg { uint64_t a, b; } xmm_reg; +typedef struct ymm_reg { uint64_t a, b, c, d; } ymm_reg; #if ARCH_X86_64 # define OPSIZE "q" @@ -107,6 +108,46 @@ typedef int x86_reg; # define LOCAL_MANGLE(a) #a #endif -#define MANGLE(a) EXTERN_PREFIX LOCAL_MANGLE(a) +#if HAVE_INLINE_ASM_DIRECT_SYMBOL_REFS +# define MANGLE(a) EXTERN_PREFIX LOCAL_MANGLE(a) +# define NAMED_CONSTRAINTS_ADD(...) +# define NAMED_CONSTRAINTS(...) +# define NAMED_CONSTRAINTS_ARRAY_ADD(...) +# define NAMED_CONSTRAINTS_ARRAY(...) +#else + /* When direct symbol references are used in code passed to a compiler that does not support them + * then these references need to be converted to named asm constraints instead. + * Instead of returning a direct symbol MANGLE now returns a named constraint for that specific symbol. + * In order for this to work there must also be a corresponding entry in the asm-interface. To add this + * entry use the macro NAMED_CONSTRAINTS() and pass in a list of each symbol reference used in the + * corresponding block of code. (e.g. NAMED_CONSTRAINTS(var1,var2,var3) where var1 is the first symbol etc. ). + * If there are already existing constraints then use NAMED_CONSTRAINTS_ADD to add to the existing constraint list. + */ +# define MANGLE(a) "%["#a"]" + // Intel/MSVC does not correctly expand va-args so we need a rather ugly hack in order to get it to work +# define FE_0(P,X) P(X) +# define FE_1(P,X,X1) P(X), FE_0(P,X1) +# define FE_2(P,X,X1,X2) P(X), FE_1(P,X1,X2) +# define FE_3(P,X,X1,X2,X3) P(X), FE_2(P,X1,X2,X3) +# define FE_4(P,X,X1,X2,X3,X4) P(X), FE_3(P,X1,X2,X3,X4) +# define FE_5(P,X,X1,X2,X3,X4,X5) P(X), FE_4(P,X1,X2,X3,X4,X5) +# define FE_6(P,X,X1,X2,X3,X4,X5,X6) P(X), FE_5(P,X1,X2,X3,X4,X5,X6) +# define FE_7(P,X,X1,X2,X3,X4,X5,X6,X7) P(X), FE_6(P,X1,X2,X3,X4,X5,X6,X7) +# define FE_8(P,X,X1,X2,X3,X4,X5,X6,X7,X8) P(X), FE_7(P,X1,X2,X3,X4,X5,X6,X7,X8) +# define FE_9(P,X,X1,X2,X3,X4,X5,X6,X7,X8,X9) P(X), FE_8(P,X1,X2,X3,X4,X5,X6,X7,X8,X9) +# define GET_FE_IMPL(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,NAME,...) NAME +# define GET_FE(A) GET_FE_IMPL A +# define GET_FE_GLUE(x, y) x y +# define FOR_EACH_VA(P,...) GET_FE_GLUE(GET_FE((__VA_ARGS__,FE_9,FE_8,FE_7,FE_6,FE_5,FE_4,FE_3,FE_2,FE_1,FE_0)), (P,__VA_ARGS__)) +# define NAME_CONSTRAINT(x) [x] "m"(x) + // Parameters are a list of each symbol reference required +# define NAMED_CONSTRAINTS_ADD(...) , FOR_EACH_VA(NAME_CONSTRAINT,__VA_ARGS__) + // Same but without comma for when there are no previously defined constraints +# define NAMED_CONSTRAINTS(...) FOR_EACH_VA(NAME_CONSTRAINT,__VA_ARGS__) + // Same as above NAMED_CONSTRAINTS except used for passing arrays/pointers instead of normal variables +# define NAME_CONSTRAINT_ARRAY(x) [x] "m"(*x) +# define NAMED_CONSTRAINTS_ARRAY_ADD(...) , FOR_EACH_VA(NAME_CONSTRAINT_ARRAY,__VA_ARGS__) +# define NAMED_CONSTRAINTS_ARRAY(...) FOR_EACH_VA(NAME_CONSTRAINT_ARRAY,__VA_ARGS__) +#endif #endif /* AVUTIL_X86_ASM_H */ diff --git a/libavutil/x86/bswap.h b/libavutil/x86/bswap.h index c73be9af81..08e2a62520 100644 --- a/libavutil/x86/bswap.h +++ b/libavutil/x86/bswap.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index 8be6d94742..8ad478400c 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -3,20 +3,20 @@ * (c)1997-99 by H. Dietz and R. Fisher * Converted to C and improved by Fabrice Bellard. * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -143,7 +143,7 @@ int ff_get_cpu_flags_x86(void) if (max_std_level >= 7) { cpuid(7, eax, ebx, ecx, edx); #if HAVE_AVX2 - if (ebx & 0x00000020) + if ((rval & AV_CPU_FLAG_AVX) && (ebx & 0x00000020)) rval |= AV_CPU_FLAG_AVX2; #endif /* HAVE_AVX2 */ /* BMI1/2 don't need OS support */ diff --git a/libavutil/x86/cpu.h b/libavutil/x86/cpu.h index 50da30e389..bc64b1b3bd 100644 --- a/libavutil/x86/cpu.h +++ b/libavutil/x86/cpu.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/x86/cpuid.asm b/libavutil/x86/cpuid.asm index 1cb8e94ea3..c3f7866ec7 100644 --- a/libavutil/x86/cpuid.asm +++ b/libavutil/x86/cpuid.asm @@ -4,20 +4,20 @@ ;* Authors: Loren Merritt <lorenm@u.washington.edu> ;* Fiona Glaser <fiona@x264.com> ;* -;* This file is part of Libav. +;* This file is part of FFmpeg. ;* -;* Libav is free software; you can redistribute it and/or +;* 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. ;* -;* Libav is distributed in the hope that it will be useful, +;* 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 Libav; if not, write to the Free Software +;* License along with FFmpeg; if not, write to the Free Software ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;****************************************************************************** diff --git a/libavutil/x86/emms.asm b/libavutil/x86/emms.asm index a6851acc99..0aad34af3f 100644 --- a/libavutil/x86/emms.asm +++ b/libavutil/x86/emms.asm @@ -1,20 +1,20 @@ ;***************************************************************************** ;* Copyright (C) 2013 Martin Storsjo ;* -;* This file is part of Libav. +;* This file is part of FFmpeg. ;* -;* Libav is free software; you can redistribute it and/or +;* 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. ;* -;* Libav is distributed in the hope that it will be useful, +;* 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 Libav; if not, write to the Free Software +;* License along with FFmpeg; if not, write to the Free Software ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;****************************************************************************** diff --git a/libavutil/x86/emms.h b/libavutil/x86/emms.h index 2ed9e5d09d..a529b6bbbe 100644 --- a/libavutil/x86/emms.h +++ b/libavutil/x86/emms.h @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -21,6 +21,7 @@ #include "config.h" #include "libavutil/attributes.h" +#include "libavutil/cpu.h" void avpriv_emms_yasm(void); @@ -33,7 +34,8 @@ void avpriv_emms_yasm(void); */ static av_always_inline void emms_c(void) { - __asm__ volatile ("emms" ::: "memory"); + if(av_get_cpu_flags() & AV_CPU_FLAG_MMX) + __asm__ volatile ("emms" ::: "memory"); } #elif HAVE_MMX && HAVE_MM_EMPTY # include <mmintrin.h> diff --git a/libavutil/x86/float_dsp.asm b/libavutil/x86/float_dsp.asm index d96249978a..ec3d22b230 100644 --- a/libavutil/x86/float_dsp.asm +++ b/libavutil/x86/float_dsp.asm @@ -1,20 +1,22 @@ ;***************************************************************************** ;* x86-optimized Float DSP functions ;* -;* This file is part of Libav. +;* Copyright 2006 Loren Merritt ;* -;* Libav is free software; you can redistribute it and/or +;* 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. ;* -;* Libav is distributed in the hope that it will be useful, +;* 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 Libav; if not, write to the Free Software +;* License along with FFmpeg; if not, write to the Free Software ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;****************************************************************************** @@ -48,8 +50,10 @@ ALIGN 16 INIT_XMM sse VECTOR_FMUL +%if HAVE_AVX_EXTERNAL INIT_YMM avx VECTOR_FMUL +%endif ;------------------------------------------------------------------------------ ; void ff_vector_fmac_scalar(float *dst, const float *src, float mul, int len) @@ -57,33 +61,48 @@ VECTOR_FMUL %macro VECTOR_FMAC_SCALAR 0 %if UNIX64 -cglobal vector_fmac_scalar, 3,3,3, dst, src, len +cglobal vector_fmac_scalar, 3,3,5, dst, src, len %else -cglobal vector_fmac_scalar, 4,4,3, dst, src, mul, len +cglobal vector_fmac_scalar, 4,4,5, dst, src, mul, len %endif %if ARCH_X86_32 VBROADCASTSS m0, mulm %else %if WIN64 - mova xmm0, xmm2 + SWAP 0, 2 %endif - shufps xmm0, xmm0, 0 + shufps xm0, xm0, 0 %if cpuflag(avx) - vinsertf128 m0, m0, xmm0, 1 + vinsertf128 m0, m0, xm0, 1 %endif %endif lea lenq, [lend*4-64] .loop: -%assign a 0 -%rep 32/mmsize - mulps m1, m0, [srcq+lenq+(a+0)*mmsize] - mulps m2, m0, [srcq+lenq+(a+1)*mmsize] - addps m1, m1, [dstq+lenq+(a+0)*mmsize] - addps m2, m2, [dstq+lenq+(a+1)*mmsize] - mova [dstq+lenq+(a+0)*mmsize], m1 - mova [dstq+lenq+(a+1)*mmsize], m2 -%assign a a+2 -%endrep +%if cpuflag(fma3) + mova m1, [dstq+lenq] + mova m2, [dstq+lenq+1*mmsize] + fmaddps m1, m0, [srcq+lenq], m1 + fmaddps m2, m0, [srcq+lenq+1*mmsize], m2 +%else ; cpuflag + mulps m1, m0, [srcq+lenq] + mulps m2, m0, [srcq+lenq+1*mmsize] +%if mmsize < 32 + mulps m3, m0, [srcq+lenq+2*mmsize] + mulps m4, m0, [srcq+lenq+3*mmsize] +%endif ; mmsize + addps m1, m1, [dstq+lenq] + addps m2, m2, [dstq+lenq+1*mmsize] +%if mmsize < 32 + addps m3, m3, [dstq+lenq+2*mmsize] + addps m4, m4, [dstq+lenq+3*mmsize] +%endif ; mmsize +%endif ; cpuflag + mova [dstq+lenq], m1 + mova [dstq+lenq+1*mmsize], m2 +%if mmsize < 32 + mova [dstq+lenq+2*mmsize], m3 + mova [dstq+lenq+3*mmsize], m4 +%endif ; mmsize sub lenq, 64 jge .loop REP_RET @@ -91,8 +110,14 @@ cglobal vector_fmac_scalar, 4,4,3, dst, src, mul, len INIT_XMM sse VECTOR_FMAC_SCALAR +%if HAVE_AVX_EXTERNAL INIT_YMM avx VECTOR_FMAC_SCALAR +%endif +%if HAVE_FMA3_EXTERNAL +INIT_YMM fma3 +VECTOR_FMAC_SCALAR +%endif ;------------------------------------------------------------------------------ ; void ff_vector_fmul_scalar(float *dst, const float *src, float mul, int len) @@ -141,16 +166,11 @@ cglobal vector_dmul_scalar, 4,4,3, dst, src, mul, len VBROADCASTSD m0, mulm %else %if WIN64 - movlhps xmm2, xmm2 -%if cpuflag(avx) - vinsertf128 ymm2, ymm2, xmm2, 1 -%endif SWAP 0, 2 -%else - movlhps xmm0, xmm0 -%if cpuflag(avx) - vinsertf128 ymm0, ymm0, xmm0, 1 %endif + movlhps xm0, xm0 +%if cpuflag(avx) + vinsertf128 ym0, ym0, xm0, 1 %endif %endif lea lenq, [lend*8-2*mmsize] @@ -172,20 +192,85 @@ VECTOR_DMUL_SCALAR %endif ;----------------------------------------------------------------------------- +; vector_fmul_window(float *dst, const float *src0, +; const float *src1, const float *win, int len); +;----------------------------------------------------------------------------- +%macro VECTOR_FMUL_WINDOW 0 +cglobal vector_fmul_window, 5, 6, 6, dst, src0, src1, win, len, len1 + shl lend, 2 + lea len1q, [lenq - mmsize] + add src0q, lenq + add dstq, lenq + add winq, lenq + neg lenq +.loop + mova m0, [winq + lenq] + mova m4, [src0q + lenq] +%if cpuflag(sse) + mova m1, [winq + len1q] + mova m5, [src1q + len1q] + shufps m1, m1, 0x1b + shufps m5, m5, 0x1b + mova m2, m0 + mova m3, m1 + mulps m2, m4 + mulps m3, m5 + mulps m1, m4 + mulps m0, m5 + addps m2, m3 + subps m1, m0 + shufps m2, m2, 0x1b +%else + pswapd m1, [winq + len1q] + pswapd m5, [src1q + len1q] + mova m2, m0 + mova m3, m1 + pfmul m2, m4 + pfmul m3, m5 + pfmul m1, m4 + pfmul m0, m5 + pfadd m2, m3 + pfsub m1, m0 + pswapd m2, m2 +%endif + mova [dstq + lenq], m1 + mova [dstq + len1q], m2 + sub len1q, mmsize + add lenq, mmsize + jl .loop +%if mmsize == 8 + femms +%endif + REP_RET +%endmacro + +INIT_MMX 3dnowext +VECTOR_FMUL_WINDOW +INIT_XMM sse +VECTOR_FMUL_WINDOW + +;----------------------------------------------------------------------------- ; vector_fmul_add(float *dst, const float *src0, const float *src1, ; const float *src2, int len) ;----------------------------------------------------------------------------- %macro VECTOR_FMUL_ADD 0 -cglobal vector_fmul_add, 5,5,2, dst, src0, src1, src2, len +cglobal vector_fmul_add, 5,5,4, dst, src0, src1, src2, len lea lenq, [lend*4 - 2*mmsize] ALIGN 16 .loop: mova m0, [src0q + lenq] mova m1, [src0q + lenq + mmsize] +%if cpuflag(fma3) + mova m2, [src2q + lenq] + mova m3, [src2q + lenq + mmsize] + fmaddps m0, m0, [src1q + lenq], m2 + fmaddps m1, m1, [src1q + lenq + mmsize], m3 +%else mulps m0, m0, [src1q + lenq] mulps m1, m1, [src1q + lenq + mmsize] addps m0, m0, [src2q + lenq] addps m1, m1, [src2q + lenq + mmsize] +%endif mova [dstq + lenq], m0 mova [dstq + lenq + mmsize], m1 @@ -196,8 +281,14 @@ ALIGN 16 INIT_XMM sse VECTOR_FMUL_ADD +%if HAVE_AVX_EXTERNAL INIT_YMM avx VECTOR_FMUL_ADD +%endif +%if HAVE_FMA3_EXTERNAL +INIT_YMM fma3 +VECTOR_FMUL_ADD +%endif ;----------------------------------------------------------------------------- ; void vector_fmul_reverse(float *dst, const float *src0, const float *src1, @@ -233,8 +324,10 @@ ALIGN 16 INIT_XMM sse VECTOR_FMUL_REVERSE +%if HAVE_AVX_EXTERNAL INIT_YMM avx VECTOR_FMUL_REVERSE +%endif ; float scalarproduct_float_sse(const float *v1, const float *v2, int len) INIT_XMM sse @@ -272,8 +365,8 @@ cglobal butterflies_float, 3,3,3, src0, src1, len test lenq, lenq jz .end shl lenq, 2 - lea src0q, [src0q + lenq] - lea src1q, [src1q + lenq] + add src0q, lenq + add src1q, lenq neg lenq .loop: mova m0, [src0q + lenq] diff --git a/libavutil/x86/float_dsp_init.c b/libavutil/x86/float_dsp_init.c index a04d91c923..64b3a4d6bd 100644 --- a/libavutil/x86/float_dsp_init.c +++ b/libavutil/x86/float_dsp_init.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -33,6 +33,8 @@ void ff_vector_fmac_scalar_sse(float *dst, const float *src, float mul, int len); void ff_vector_fmac_scalar_avx(float *dst, const float *src, float mul, int len); +void ff_vector_fmac_scalar_fma3(float *dst, const float *src, float mul, + int len); void ff_vector_fmul_scalar_sse(float *dst, const float *src, float mul, int len); @@ -42,10 +44,17 @@ void ff_vector_dmul_scalar_sse2(double *dst, const double *src, void ff_vector_dmul_scalar_avx(double *dst, const double *src, double mul, int len); +void ff_vector_fmul_window_3dnowext(float *dst, const float *src0, + const float *src1, const float *win, int len); +void ff_vector_fmul_window_sse(float *dst, const float *src0, + const float *src1, const float *win, int len); + void ff_vector_fmul_add_sse(float *dst, const float *src0, const float *src1, const float *src2, int len); void ff_vector_fmul_add_avx(float *dst, const float *src0, const float *src1, const float *src2, int len); +void ff_vector_fmul_add_fma3(float *dst, const float *src0, const float *src1, + const float *src2, int len); void ff_vector_fmul_reverse_sse(float *dst, const float *src0, const float *src1, int len); @@ -56,88 +65,18 @@ float ff_scalarproduct_float_sse(const float *v1, const float *v2, int order); void ff_butterflies_float_sse(float *src0, float *src1, int len); -#if HAVE_6REGS && HAVE_INLINE_ASM -static void vector_fmul_window_3dnowext(float *dst, const float *src0, - const float *src1, const float *win, - int len) -{ - x86_reg i = -len * 4; - x86_reg j = len * 4 - 8; - __asm__ volatile ( - "1: \n" - "pswapd (%5, %1), %%mm1 \n" - "movq (%5, %0), %%mm0 \n" - "pswapd (%4, %1), %%mm5 \n" - "movq (%3, %0), %%mm4 \n" - "movq %%mm0, %%mm2 \n" - "movq %%mm1, %%mm3 \n" - "pfmul %%mm4, %%mm2 \n" // src0[len + i] * win[len + i] - "pfmul %%mm5, %%mm3 \n" // src1[j] * win[len + j] - "pfmul %%mm4, %%mm1 \n" // src0[len + i] * win[len + j] - "pfmul %%mm5, %%mm0 \n" // src1[j] * win[len + i] - "pfadd %%mm3, %%mm2 \n" - "pfsub %%mm0, %%mm1 \n" - "pswapd %%mm2, %%mm2 \n" - "movq %%mm1, (%2, %0) \n" - "movq %%mm2, (%2, %1) \n" - "sub $8, %1 \n" - "add $8, %0 \n" - "jl 1b \n" - "femms \n" - : "+r"(i), "+r"(j) - : "r"(dst + len), "r"(src0 + len), "r"(src1), "r"(win + len) - ); -} - -static void vector_fmul_window_sse(float *dst, const float *src0, - const float *src1, const float *win, int len) -{ - x86_reg i = -len * 4; - x86_reg j = len * 4 - 16; - __asm__ volatile ( - "1: \n" - "movaps (%5, %1), %%xmm1 \n" - "movaps (%5, %0), %%xmm0 \n" - "movaps (%4, %1), %%xmm5 \n" - "movaps (%3, %0), %%xmm4 \n" - "shufps $0x1b, %%xmm1, %%xmm1 \n" - "shufps $0x1b, %%xmm5, %%xmm5 \n" - "movaps %%xmm0, %%xmm2 \n" - "movaps %%xmm1, %%xmm3 \n" - "mulps %%xmm4, %%xmm2 \n" // src0[len + i] * win[len + i] - "mulps %%xmm5, %%xmm3 \n" // src1[j] * win[len + j] - "mulps %%xmm4, %%xmm1 \n" // src0[len + i] * win[len + j] - "mulps %%xmm5, %%xmm0 \n" // src1[j] * win[len + i] - "addps %%xmm3, %%xmm2 \n" - "subps %%xmm0, %%xmm1 \n" - "shufps $0x1b, %%xmm2, %%xmm2 \n" - "movaps %%xmm1, (%2, %0) \n" - "movaps %%xmm2, (%2, %1) \n" - "sub $16, %1 \n" - "add $16, %0 \n" - "jl 1b \n" - : "+r"(i), "+r"(j) - : "r"(dst + len), "r"(src0 + len), "r"(src1), "r"(win + len) - ); -} -#endif /* HAVE_6REGS && HAVE_INLINE_ASM */ - av_cold void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp) { int cpu_flags = av_get_cpu_flags(); -#if HAVE_6REGS && HAVE_INLINE_ASM - if (INLINE_AMD3DNOWEXT(cpu_flags)) { - fdsp->vector_fmul_window = vector_fmul_window_3dnowext; + if (EXTERNAL_AMD3DNOWEXT(cpu_flags)) { + fdsp->vector_fmul_window = ff_vector_fmul_window_3dnowext; } - if (INLINE_SSE(cpu_flags)) { - fdsp->vector_fmul_window = vector_fmul_window_sse; - } -#endif if (EXTERNAL_SSE(cpu_flags)) { fdsp->vector_fmul = ff_vector_fmul_sse; fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_sse; fdsp->vector_fmul_scalar = ff_vector_fmul_scalar_sse; + fdsp->vector_fmul_window = ff_vector_fmul_window_sse; fdsp->vector_fmul_add = ff_vector_fmul_add_sse; fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_sse; fdsp->scalarproduct_float = ff_scalarproduct_float_sse; @@ -153,4 +92,8 @@ av_cold void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp) fdsp->vector_fmul_add = ff_vector_fmul_add_avx; fdsp->vector_fmul_reverse = ff_vector_fmul_reverse_avx; } + if (EXTERNAL_FMA3(cpu_flags)) { + fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_fma3; + fdsp->vector_fmul_add = ff_vector_fmul_add_fma3; + } } diff --git a/libavutil/x86/intreadwrite.h b/libavutil/x86/intreadwrite.h index 635096e569..4061d19231 100644 --- a/libavutil/x86/intreadwrite.h +++ b/libavutil/x86/intreadwrite.h @@ -1,20 +1,20 @@ /* * Copyright (c) 2010 Alexander Strange <astrange@ithinksw.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/x86/lls.asm b/libavutil/x86/lls.asm index eab85ed050..c2aead38ef 100644 --- a/libavutil/x86/lls.asm +++ b/libavutil/x86/lls.asm @@ -3,20 +3,20 @@ ;* ;* Copyright (c) 2013 Loren Merritt ;* -;* This file is part of Libav. +;* This file is part of FFmpeg. ;* -;* Libav is free software; you can redistribute it and/or +;* 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. ;* -;* Libav is distributed in the hope that it will be useful, +;* 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 Libav; if not, write to the Free Software +;* License along with FFmpeg; if not, write to the Free Software ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;****************************************************************************** @@ -29,7 +29,7 @@ SECTION .text %define COVAR_STRIDE MAX_VARS_ALIGN*8 %define COVAR(x,y) [covarq + (x)*8 + (y)*COVAR_STRIDE] -struc LLSModel +struc LLSModel2 .covariance: resq MAX_VARS_ALIGN*MAX_VARS_ALIGN .coeff: resq MAX_VARS*MAX_VARS .variance: resq MAX_VARS @@ -49,7 +49,7 @@ INIT_XMM sse2 %define movdqa movaps cglobal update_lls, 2,5,8, ctx, var, i, j, covar2 %define covarq ctxq - mov id, [ctxq + LLSModel.indep_count] + mov id, [ctxq + LLSModel2.indep_count] lea varq, [varq + iq*8] neg iq mov covar2q, covarq @@ -125,10 +125,11 @@ cglobal update_lls, 2,5,8, ctx, var, i, j, covar2 .ret: REP_RET +%if HAVE_AVX_EXTERNAL INIT_YMM avx cglobal update_lls, 3,6,8, ctx, var, count, i, j, count2 %define covarq ctxq - mov countd, [ctxq + LLSModel.indep_count] + mov countd, [ctxq + LLSModel2.indep_count] lea count2d, [countq-2] xor id, id .loopi: @@ -194,7 +195,7 @@ cglobal update_lls, 3,6,8, ctx, var, count, i, j, count2 jle .loop2x1 .ret: REP_RET - +%endif INIT_XMM sse2 cglobal evaluate_lls, 3,4,2, ctx, var, order, i @@ -205,7 +206,7 @@ cglobal evaluate_lls, 3,4,2, ctx, var, order, i %define coefsq ctxq mov id, orderd imul orderd, MAX_VARS - lea coefsq, [ctxq + LLSModel.coeff + orderq*8] + lea coefsq, [ctxq + LLSModel2.coeff + orderq*8] movsd m0, [varq] movhpd m0, [varq + 8] mulpd m0, [coefsq] diff --git a/libavutil/x86/lls_init.c b/libavutil/x86/lls_init.c index 888bc54a39..bf999d5fc3 100644 --- a/libavutil/x86/lls_init.c +++ b/libavutil/x86/lls_init.c @@ -3,31 +3,31 @@ * * Copyright (c) 2013 Loren Merritt * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * 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/lls.h" +#include "libavutil/lls2.h" #include "libavutil/x86/cpu.h" -void ff_update_lls_sse2(LLSModel *m, double *var); -void ff_update_lls_avx(LLSModel *m, double *var); -double ff_evaluate_lls_sse2(LLSModel *m, double *var, int order); +void ff_update_lls_sse2(LLSModel2 *m, double *var); +void ff_update_lls_avx(LLSModel2 *m, double *var); +double ff_evaluate_lls_sse2(LLSModel2 *m, double *var, int order); -av_cold void ff_init_lls_x86(LLSModel *m) +av_cold void ff_init_lls_x86(LLSModel2 *m) { int cpu_flags = av_get_cpu_flags(); if (EXTERNAL_SSE2(cpu_flags)) { diff --git a/libavutil/x86/timer.h b/libavutil/x86/timer.h index cdd67ddbb5..5b24b511c1 100644 --- a/libavutil/x86/timer.h +++ b/libavutil/x86/timer.h @@ -1,20 +1,20 @@ /* * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -25,6 +25,7 @@ #if HAVE_INLINE_ASM +#define FF_TIMER_UNITS "decicycles" #define AV_READ_TIME read_time static inline uint64_t read_time(void) diff --git a/libavutil/x86/w64xmmtest.h b/libavutil/x86/w64xmmtest.h index b4ce7d3daf..9df499f7f6 100644 --- a/libavutil/x86/w64xmmtest.h +++ b/libavutil/x86/w64xmmtest.h @@ -2,20 +2,20 @@ * check XMM registers for clobbers on Win64 * Copyright (c) 2008 Ramiro Polla <ramiro.polla@gmail.com> * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ diff --git a/libavutil/x86/x86inc.asm b/libavutil/x86/x86inc.asm index 2d4d1d3ca6..1cfb05509a 100644 --- a/libavutil/x86/x86inc.asm +++ b/libavutil/x86/x86inc.asm @@ -853,6 +853,14 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits INIT_CPUFLAGS %1 %endmacro +; FIXME: INIT_AVX can be replaced by INIT_XMM avx +%macro INIT_AVX 0 + INIT_XMM + %assign avx_enabled 1 + %define PALIGNR PALIGNR_SSSE3 + %define RESET_MM_PERMUTATION INIT_AVX +%endmacro + %macro INIT_YMM 0-1+ %assign avx_enabled 1 %define RESET_MM_PERMUTATION INIT_YMM %1 @@ -1399,21 +1407,6 @@ AVX_INSTR pfmul, 1, 0, 1 %undef i %undef j -%macro FMA_INSTR 3 - %macro %1 4-7 %1, %2, %3 - %if cpuflag(xop) - v%5 %1, %2, %3, %4 - %else - %6 %1, %2, %3 - %7 %1, %4 - %endif - %endmacro -%endmacro - -FMA_INSTR pmacsdd, pmulld, paddd -FMA_INSTR pmacsww, pmullw, paddw -FMA_INSTR pmadcswd, pmaddwd, paddd - ; tzcnt is equivalent to "rep bsf" and is backwards-compatible with bsf. ; This lets us use tzcnt without bumping the yasm version requirement yet. %define tzcnt rep bsf diff --git a/libavutil/x86/x86util.asm b/libavutil/x86/x86util.asm index 11779cf07f..0d0ef0799d 100644 --- a/libavutil/x86/x86util.asm +++ b/libavutil/x86/x86util.asm @@ -6,20 +6,20 @@ ;* Authors: Loren Merritt <lorenm@u.washington.edu> ;* Holger Lubitz <holger@lubitz.org> ;* -;* This file is part of Libav. +;* This file is part of FFmpeg. ;* -;* Libav is free software; you can redistribute it and/or +;* 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. ;* -;* Libav is distributed in the hope that it will be useful, +;* 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 Libav; if not, write to the Free Software +;* License along with FFmpeg; if not, write to the Free Software ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;****************************************************************************** @@ -69,6 +69,15 @@ SWAP %2, %3 %endmacro +%macro TRANSPOSE2x4x4B 5 + SBUTTERFLY bw, %1, %2, %5 + SBUTTERFLY bw, %3, %4, %5 + SBUTTERFLY wd, %1, %3, %5 + SBUTTERFLY wd, %2, %4, %5 + SBUTTERFLY dq, %1, %2, %5 + SBUTTERFLY dq, %3, %4, %5 +%endmacro + %macro TRANSPOSE2x4x4W 5 SBUTTERFLY wd, %1, %2, %5 SBUTTERFLY wd, %3, %4, %5 @@ -273,6 +282,44 @@ %endif %endmacro +%macro HADDD 2 ; sum junk +%if sizeof%1 == 32 +%define %2 xmm%2 + vextracti128 %2, %1, 1 +%define %1 xmm%1 + paddd %1, %2 +%endif +%if mmsize >= 16 +%if cpuflag(xop) && sizeof%1 == 16 + vphadddq %1, %1 +%endif + movhlps %2, %1 + paddd %1, %2 +%endif +%if notcpuflag(xop) || sizeof%1 != 16 +%if cpuflag(mmxext) + PSHUFLW %2, %1, q0032 +%else ; mmx + mova %2, %1 + psrlq %2, 32 +%endif + paddd %1, %2 +%endif +%undef %1 +%undef %2 +%endmacro + +%macro HADDW 2 ; reg, tmp +%if cpuflag(xop) && sizeof%1 == 16 + vphaddwq %1, %1 + movhlps %2, %1 + paddd %1, %2 +%else + pmaddwd %1, [pw_1] + HADDD %1, %2 +%endif +%endmacro + %macro PALIGNR 4-5 %if cpuflag(ssse3) %if %0==5 @@ -302,11 +349,19 @@ %endif %endmacro -%macro PAVGB 2 +%macro PAVGB 2-4 %if cpuflag(mmxext) pavgb %1, %2 %elif cpuflag(3dnow) pavgusb %1, %2 +%elif cpuflag(mmx) + movu %3, %2 + por %3, %1 + pxor %1, %2 + pand %1, %4 + psrlq %1, 1 + psubb %3, %1 + SWAP %1, %3 %endif %endmacro @@ -552,7 +607,9 @@ %endmacro %macro SPLATW 2-3 0 -%if mmsize == 16 +%if cpuflag(avx2) && %3 == 0 + vpbroadcastw %1, %2 +%elif mmsize == 16 pshuflw %1, %2, (%3)*0x55 punpcklqdq %1, %1 %elif cpuflag(mmxext) @@ -666,6 +723,25 @@ %endif %endmacro +%macro PMA_EMU 4 + %macro %1 5-8 %2, %3, %4 + %if cpuflag(xop) + v%6 %1, %2, %3, %4 + %elifidn %1, %4 + %7 %5, %2, %3 + %8 %1, %4, %5 + %else + %7 %1, %2, %3 + %8 %1, %4 + %endif + %endmacro +%endmacro + +PMA_EMU PMACSWW, pmacsww, pmullw, paddw +PMA_EMU PMACSDD, pmacsdd, pmulld, paddd ; sse4 emulation +PMA_EMU PMACSDQL, pmacsdql, pmuldq, paddq ; sse4 emulation +PMA_EMU PMADCSWD, pmadcswd, pmaddwd, paddd + ; Wrapper for non-FMA version of fmaddps %macro FMULADD_PS 5 %if cpuflag(fma3) || cpuflag(fma4) @@ -678,3 +754,19 @@ addps %1, %4 %endif %endmacro + +%macro LSHIFT 2 +%if mmsize > 8 + pslldq %1, %2 +%else + psllq %1, 8*(%2) +%endif +%endmacro + +%macro RSHIFT 2 +%if mmsize > 8 + psrldq %1, %2 +%else + psrlq %1, 8*(%2) +%endif +%endmacro diff --git a/libavutil/x86_cpu.h b/libavutil/x86_cpu.h new file mode 100644 index 0000000000..bec1c77776 --- /dev/null +++ b/libavutil/x86_cpu.h @@ -0,0 +1 @@ +#include "libavutil/x86/asm.h" diff --git a/libavutil/xga_font_data.c b/libavutil/xga_font_data.c new file mode 100644 index 0000000000..3aed3142cf --- /dev/null +++ b/libavutil/xga_font_data.c @@ -0,0 +1,417 @@ +/* + * CGA/EGA/VGA ROM font data + * + * 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 + * CGA/EGA/VGA ROM font data + */ + +#include <stdint.h> +#include "xga_font_data.h" + +const uint8_t avpriv_cga_font[2048] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, + 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, + 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c, + 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, + 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, + 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78, + 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0, + 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0, 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99, + 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, + 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, + 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00, 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff, + 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, + 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00, + 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, + 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00, 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, + 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, + 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, + 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00, 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00, + 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00, + 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00, 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, + 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00, 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60, + 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, + 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, + 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, + 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, + 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00, + 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, + 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, + 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00, + 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00, + 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00, + 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, + 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, + 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00, + 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00, + 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00, + 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e, + 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00, + 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00, + 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00, + 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00, + 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, + 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, 0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00, + 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, 0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, + 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, 0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38, + 0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, 0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00, + 0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00, 0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00, + 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, 0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, 0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, 0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00, + 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, + 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00, 0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30, + 0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7, 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, + 0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, + 0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00, 0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00, + 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, + 0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f, + 0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00, + 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, + 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00, 0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0, + 0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, + 0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00, + 0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00, + 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00, 0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0, + 0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, + 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00, + 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00, + 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, + 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, + 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, + 0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const uint8_t avpriv_vga16_font[4096] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, + 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, + 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, 0x0c, 0x1f, 0x00, 0x00, + 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, + 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; diff --git a/libavutil/xga_font_data.h b/libavutil/xga_font_data.h new file mode 100644 index 0000000000..5e40f542e4 --- /dev/null +++ b/libavutil/xga_font_data.h @@ -0,0 +1,35 @@ +/* + * CGA/EGA/VGA ROM font data + * + * 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 + * CGA/EGA/VGA ROM font data + */ + +#ifndef AVUTIL_XGA_FONT_DATA_H +#define AVUTIL_XGA_FONT_DATA_H + +#include <stdint.h> +#include "internal.h" + +extern av_export const uint8_t avpriv_cga_font[2048]; +extern av_export const uint8_t avpriv_vga16_font[4096]; + +#endif /* AVUTIL_XGA_FONT_DATA_H */ diff --git a/libavutil/xtea.c b/libavutil/xtea.c index 53c0bfe603..1750cbc45a 100644 --- a/libavutil/xtea.c +++ b/libavutil/xtea.c @@ -4,20 +4,20 @@ * * loosely based on the implementation of David Wheeler and Roger Needham * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -45,32 +45,116 @@ static void xtea_crypt_ecb(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int decrypt, uint8_t *iv) { uint32_t v0, v1; - int i; +#if !CONFIG_SMALL + uint32_t k0 = ctx->key[0]; + uint32_t k1 = ctx->key[1]; + uint32_t k2 = ctx->key[2]; + uint32_t k3 = ctx->key[3]; +#endif v0 = AV_RB32(src); v1 = AV_RB32(src + 4); if (decrypt) { - uint32_t delta = 0x9E3779B9, sum = delta * 32; +#if CONFIG_SMALL + int i; + uint32_t delta = 0x9E3779B9U, sum = delta * 32; for (i = 0; i < 32; i++) { v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + ctx->key[(sum >> 11) & 3]); sum -= delta; v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + ctx->key[sum & 3]); } +#else +#define DSTEP(SUM, K0, K1) \ + v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (SUM + K0); \ + v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (SUM - 0x9E3779B9U + K1) + + DSTEP(0xC6EF3720U, k2, k3); + DSTEP(0x28B7BD67U, k3, k2); + DSTEP(0x8A8043AEU, k0, k1); + DSTEP(0xEC48C9F5U, k1, k0); + DSTEP(0x4E11503CU, k2, k3); + DSTEP(0xAFD9D683U, k2, k2); + DSTEP(0x11A25CCAU, k3, k1); + DSTEP(0x736AE311U, k0, k0); + DSTEP(0xD5336958U, k1, k3); + DSTEP(0x36FBEF9FU, k1, k2); + DSTEP(0x98C475E6U, k2, k1); + DSTEP(0xFA8CFC2DU, k3, k0); + DSTEP(0x5C558274U, k0, k3); + DSTEP(0xBE1E08BBU, k1, k2); + DSTEP(0x1FE68F02U, k1, k1); + DSTEP(0x81AF1549U, k2, k0); + DSTEP(0xE3779B90U, k3, k3); + DSTEP(0x454021D7U, k0, k2); + DSTEP(0xA708A81EU, k1, k1); + DSTEP(0x08D12E65U, k1, k0); + DSTEP(0x6A99B4ACU, k2, k3); + DSTEP(0xCC623AF3U, k3, k2); + DSTEP(0x2E2AC13AU, k0, k1); + DSTEP(0x8FF34781U, k0, k0); + DSTEP(0xF1BBCDC8U, k1, k3); + DSTEP(0x5384540FU, k2, k2); + DSTEP(0xB54CDA56U, k3, k1); + DSTEP(0x1715609DU, k0, k0); + DSTEP(0x78DDE6E4U, k0, k3); + DSTEP(0xDAA66D2BU, k1, k2); + DSTEP(0x3C6EF372U, k2, k1); + DSTEP(0x9E3779B9U, k3, k0); +#endif if (iv) { v0 ^= AV_RB32(iv); v1 ^= AV_RB32(iv + 4); memcpy(iv, src, 8); } } else { - uint32_t sum = 0, delta = 0x9E3779B9; +#if CONFIG_SMALL + int i; + uint32_t sum = 0, delta = 0x9E3779B9U; for (i = 0; i < 32; i++) { v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + ctx->key[sum & 3]); sum += delta; v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + ctx->key[(sum >> 11) & 3]); } +#else +#define ESTEP(SUM, K0, K1) \ + v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (SUM + K0);\ + v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (SUM + 0x9E3779B9U + K1) + ESTEP(0x00000000U, k0, k3); + ESTEP(0x9E3779B9U, k1, k2); + ESTEP(0x3C6EF372U, k2, k1); + ESTEP(0xDAA66D2BU, k3, k0); + ESTEP(0x78DDE6E4U, k0, k0); + ESTEP(0x1715609DU, k1, k3); + ESTEP(0xB54CDA56U, k2, k2); + ESTEP(0x5384540FU, k3, k1); + ESTEP(0xF1BBCDC8U, k0, k0); + ESTEP(0x8FF34781U, k1, k0); + ESTEP(0x2E2AC13AU, k2, k3); + ESTEP(0xCC623AF3U, k3, k2); + ESTEP(0x6A99B4ACU, k0, k1); + ESTEP(0x08D12E65U, k1, k1); + ESTEP(0xA708A81EU, k2, k0); + ESTEP(0x454021D7U, k3, k3); + ESTEP(0xE3779B90U, k0, k2); + ESTEP(0x81AF1549U, k1, k1); + ESTEP(0x1FE68F02U, k2, k1); + ESTEP(0xBE1E08BBU, k3, k0); + ESTEP(0x5C558274U, k0, k3); + ESTEP(0xFA8CFC2DU, k1, k2); + ESTEP(0x98C475E6U, k2, k1); + ESTEP(0x36FBEF9FU, k3, k1); + ESTEP(0xD5336958U, k0, k0); + ESTEP(0x736AE311U, k1, k3); + ESTEP(0x11A25CCAU, k2, k2); + ESTEP(0xAFD9D683U, k3, k2); + ESTEP(0x4E11503CU, k0, k1); + ESTEP(0xEC48C9F5U, k1, k0); + ESTEP(0x8A8043AEU, k2, k3); + ESTEP(0x28B7BD67U, k3, k2); +#endif } AV_WB32(dst, v0); @@ -166,7 +250,7 @@ int main(void) AVXTEA ctx; uint8_t buf[8], iv[8]; int i; - const uint8_t src[32] = "HelloWorldHelloWorldHelloWorld"; + static const uint8_t src[32] = "HelloWorldHelloWorldHelloWorld"; uint8_t ct[32]; uint8_t pl[32]; @@ -187,6 +271,7 @@ int main(void) memcpy(iv, "HALLO123", 8); test_xtea(&ctx, ct, ct, src, 4, iv, 1, "CBC inplace decryption"); } + printf("Test encryption/decryption success.\n"); return 0; diff --git a/libavutil/xtea.h b/libavutil/xtea.h index 0fc3810dd2..6f1e71e345 100644 --- a/libavutil/xtea.h +++ b/libavutil/xtea.h @@ -1,20 +1,21 @@ /* * A 32-bit implementation of the XTEA algorithm + * Copyright (c) 2012 Samuel Pitoiset * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ |