summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/.gitignore10
-rw-r--r--tools/Makefile6
-rw-r--r--tools/aviocat.c8
-rwxr-xr-xtools/bisect-create46
-rw-r--r--tools/bookmarklets.html53
-rwxr-xr-xtools/clean-diff11
-rw-r--r--tools/coverity.c79
-rw-r--r--tools/crypto_bench.c591
-rw-r--r--tools/cws2fws.c16
-rwxr-xr-xtools/dvd2concat127
-rw-r--r--tools/enum_options.c143
-rw-r--r--tools/ffescape.c180
-rw-r--r--tools/ffeval.c139
-rw-r--r--tools/ffhash.c152
-rw-r--r--tools/fourcc2pixfmt.c117
-rwxr-xr-xtools/gen-rc121
-rw-r--r--tools/graph2dot.c49
-rw-r--r--tools/ismindex.c23
-rwxr-xr-xtools/libav-merge-next-commit22
-rwxr-xr-xtools/loudnorm.rb61
-rwxr-xr-xtools/make_chlayout_test114
-rwxr-xr-xtools/missing_codec_desc36
-rwxr-xr-xtools/murge11
-rwxr-xr-xtools/normalize.py33
-rwxr-xr-xtools/patcheck15
-rw-r--r--tools/pktdumper.c8
-rwxr-xr-xtools/plotframes164
-rw-r--r--tools/probetest.c99
-rw-r--r--tools/qt-faststart.c18
-rw-r--r--tools/seek_print.c105
-rw-r--r--tools/sidxindex.c14
-rw-r--r--tools/sofa2wavs.c99
-rw-r--r--tools/target_dec_fuzzer.c240
-rw-r--r--tools/trasher.c23
-rw-r--r--tools/uncoded_frame.c279
-rwxr-xr-xtools/unwrap-diff2
-rw-r--r--tools/yuvcmp.c184
-rw-r--r--tools/zmqsend.c168
-rwxr-xr-xtools/zmqshell.py26
39 files changed, 3514 insertions, 78 deletions
diff --git a/tools/.gitignore b/tools/.gitignore
index 21202faf21..c0958f40cb 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -1,5 +1,12 @@
/aviocat
+/ffbisect
+/bisect.need
+/crypto_bench
/cws2fws
+/fourcc2pixfmt
+/ffescape
+/ffeval
+/ffhash
/graph2dot
/ismindex
/pktdumper
@@ -7,3 +14,6 @@
/qt-faststart
/sidxindex
/trasher
+/seek_print
+/uncoded_frame
+/zmqsend
diff --git a/tools/Makefile b/tools/Makefile
index 372287b452..3909e7cfdd 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -1,7 +1,9 @@
-TOOLS = qt-faststart trasher
+TOOLS = qt-faststart trasher uncoded_frame
+TOOLS-$(CONFIG_LIBMYSOFA) += sofa2wavs
TOOLS-$(CONFIG_ZLIB) += cws2fws
-tools/cws2fws$(EXESUF): ELIBS = $(ZLIB)
+tools/target_dec_%_fuzzer.o: tools/target_dec_fuzzer.c
+ $(COMPILE_C) -DFFMPEG_DECODER=$*
OBJDIRS += tools
diff --git a/tools/aviocat.c b/tools/aviocat.c
index 73104da174..28529b06d6 100644
--- a/tools/aviocat.c
+++ b/tools/aviocat.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
*/
diff --git a/tools/bisect-create b/tools/bisect-create
new file mode 100755
index 0000000000..fc60e86669
--- /dev/null
+++ b/tools/bisect-create
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+set -e
+
+if test "bisect-create" = "`basename $0`" ; then
+ echo tools/ffbisect created
+ git show master:tools/bisect-create > tools/ffbisect
+ chmod u+x tools/ffbisect
+ exit 1
+fi
+
+if ! git show master:tools/bisect-create | diff - tools/ffbisect > /dev/null ; then
+ echo updating tools/ffbisect script to HEAD.
+ git show master:tools/bisect-create > tools/ffbisect
+ chmod u+x tools/ffbisect
+ tools/ffbisect $*
+ exit 0
+fi
+
+case "$1" in
+ need)
+ case $2 in
+ ffmpeg|ffplay|ffprobe|ffserver)
+ echo $2.c >> tools/bisect.need
+ ;;
+ esac
+ ;;
+ start|reset)
+ echo . > tools/bisect.need
+ git bisect $*
+ ;;
+ skip)
+ git bisect $*
+ ;;
+ good|bad)
+ git bisect $*
+
+ until ls `cat tools/bisect.need` > /dev/null 2> /dev/null; do
+ git bisect skip || break
+ done
+ ;;
+ run)
+ shift # remove "run" from arguments
+ git bisect run sh -c "ls \`cat tools/bisect.need\` > /dev/null 2> /dev/null || exit 125; \"\$@\"" sh "$@"
+ ;;
+esac
diff --git a/tools/bookmarklets.html b/tools/bookmarklets.html
new file mode 100644
index 0000000000..6034b57575
--- /dev/null
+++ b/tools/bookmarklets.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<!--
+ This file is part of FFmpeg.
+
+ All scripts contained in this file can be considered public domain.
+ -->
+<title>FFmpeg bookmarklets</title>
+<meta charset="UTF-8">
+<script type="text/javascript">
+function convert(js) {
+ js = js.replace(/\/\*.*?\*\//g, ""); /* comments */
+ js = js.replace(/\s+/g, " ");
+ js = js.replace(/\s+\z/, "");
+ js = "(function(){" + js + "})();void 0";
+ return "javascript:" + escape(js);
+}
+function init() {
+ var pre = document.getElementsByTagName("pre");
+ for (var i = 0; pre.length > i; i++) {
+ document.getElementById(pre[i].id + "-link").href = convert(pre[i].textContent);
+ }
+}
+</script>
+<style type="text/css">
+pre { border: solid black 1px; padding: 0.2ex; font-size: 80% }
+</style>
+</head>
+<body onload="init()">
+
+<h1>Introduction</h1>
+<p>The scripts in this page are
+<a href="http://en.wikipedia.org/wiki/Bookmarklet">bookmarklets</a>: store
+their link version in a bookmark, and later activate the bookmark on a page
+to run the script.</p>
+
+<h1>TED Talks captions</h1>
+<p><a id="ted_talks_captions-link" href="#">Get links to the captions</a></p>
+
+<pre id="ted_talks_captions">
+d = window.open("", "sub", "width=256,height=512,resizable=yes,scrollbars=yes").document;
+l = document.getElementById("languageCode").getElementsByTagName("option");
+for (i = 1; i &lt; l.length ; i++) {
+ d.body.appendChild(p = d.createElement("p"));
+ p.appendChild(a = d.createElement("a"));
+ a.appendChild(d.createTextNode(l[i].textContent));
+ a.href="http://www.ted.com/talks/subtitles/id/" + talkID+"/lang/" + l[i].value;
+}
+</pre>
+
+</body>
+</html>
diff --git a/tools/clean-diff b/tools/clean-diff
new file mode 100755
index 0000000000..4600702b10
--- /dev/null
+++ b/tools/clean-diff
@@ -0,0 +1,11 @@
+#!/bin/sh
+sed '/^+[^+]/!s/ /TaBBaT/g' |\
+ expand -t $(seq -s , 9 8 200) |\
+ sed 's/TaBBaT/ /g' |\
+ sed '/^+[^+]/s/ * $//' |\
+ tr -d '\015' |\
+ tr '\n' '°' |\
+ sed 's/\(@@[^@]*@@°[^@]*\)/\n\1/g' |\
+ egrep -v '@@[^@]*@@°(( [^°]*°)|([+-][[:space:]]*°)|(-[[:space:]]*([^°]*)°\+[[:space:]]*\5°))*$' |\
+ tr -d '\n' |\
+ tr '°' '\n'
diff --git a/tools/coverity.c b/tools/coverity.c
new file mode 100644
index 0000000000..19a132a976
--- /dev/null
+++ b/tools/coverity.c
@@ -0,0 +1,79 @@
+/* Coverity Scan model
+*
+* Copyright (C) 2014 Red Hat, Inc.
+*
+* Authors:
+* Markus Armbruster <armbru@redhat.com>
+* Paolo Bonzini <pbonzini@redhat.com>
+*
+* This work is licensed under the terms of the GNU GPL, version 2 or, at your
+* option, any later version. See the COPYING file in the top-level directory.
+*/
+/*
+* This is the source code for our Coverity user model file. The
+* purpose of user models is to increase scanning accuracy by explaining
+* code Coverity can't see (out of tree libraries) or doesn't
+* sufficiently understand. Better accuracy means both fewer false
+* positives and more true defects. Memory leaks in particular.
+*
+* - A model file can't import any header files. Some built-in primitives are
+* available but not wchar_t, NULL etc.
+* - Modeling doesn't need full structs and typedefs. Rudimentary structs
+* and similar types are sufficient.
+* - An uninitialized local variable signifies that the variable could be
+* any value.
+*
+* The model file must be uploaded by an admin in the analysis settings of
+* https://scan.coverity.com/projects/54
+*
+* above text is based on https://github.com/qemu/qemu/blob/master/scripts/coverity-model.c
+*/
+
+#define NULL (void *)0
+
+// Based on https://scan.coverity.com/models
+void *av_malloc(size_t size) {
+ int has_memory;
+ __coverity_negative_sink__(size);
+ if (has_memory) {
+ void *ptr = __coverity_alloc__(size);
+ __coverity_mark_as_uninitialized_buffer__(ptr);
+ __coverity_mark_as_afm_allocated__(ptr, "av_free");
+ return ptr;
+ } else {
+ return 0;
+ }
+}
+
+void *av_mallocz(size_t size) {
+ int has_memory;
+ __coverity_negative_sink__(size);
+ if (has_memory) {
+ void *ptr = __coverity_alloc__(size);
+ __coverity_writeall0__(ptr);
+ __coverity_mark_as_afm_allocated__(ptr, "av_free");
+ return ptr;
+ } else {
+ return 0;
+ }
+}
+
+void *av_realloc(void *ptr, size_t size) {
+ int has_memory;
+ __coverity_negative_sink__(size);
+ if (has_memory) {
+ __coverity_escape__(ptr);
+ ptr = __coverity_alloc__(size);
+ __coverity_writeall__(ptr);
+ __coverity_mark_as_afm_allocated__(ptr, "av_free");
+ return ptr;
+ } else {
+ return 0;
+ }
+}
+
+void *av_free(void *ptr) {
+ __coverity_free__(ptr);
+ __coverity_mark_as_afm_freed__(ptr, "av_free");
+}
+
diff --git a/tools/crypto_bench.c b/tools/crypto_bench.c
new file mode 100644
index 0000000000..203bffe198
--- /dev/null
+++ b/tools/crypto_bench.c
@@ -0,0 +1,591 @@
+/*
+ * Copyright (c) 2013 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
+ */
+
+/* Optional external libraries; can be enabled using:
+ * make VERSUS=crypto+gcrypt+tomcrypt tools/crypto_bench */
+#define USE_crypto 0x01 /* OpenSSL's libcrypto */
+#define USE_gcrypt 0x02 /* GnuTLS's libgcrypt */
+#define USE_tomcrypt 0x04 /* LibTomCrypt */
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "libavutil/avutil.h"
+#include "libavutil/avstring.h"
+#include "libavutil/crc.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/timer.h"
+
+#ifndef AV_READ_TIME
+#define AV_READ_TIME(x) 0
+#endif
+
+#if HAVE_UNISTD_H
+#include <unistd.h> /* for getopt */
+#endif
+#if !HAVE_GETOPT
+#include "compat/getopt.c"
+#endif
+
+#define MAX_INPUT_SIZE 1048576
+#define MAX_OUTPUT_SIZE 128
+
+static const char *enabled_libs;
+static const char *enabled_algos;
+static unsigned specified_runs;
+
+static const uint8_t *hardcoded_key = "FFmpeg is the best program ever.";
+
+static void fatal_error(const char *tag)
+{
+ av_log(NULL, AV_LOG_ERROR, "Fatal error: %s\n", tag);
+ exit(1);
+}
+
+struct hash_impl {
+ const char *lib;
+ const char *name;
+ void (*run)(uint8_t *output, const uint8_t *input, unsigned size);
+ const char *output;
+};
+
+/***************************************************************************
+ * lavu: libavutil
+ ***************************************************************************/
+
+#include "libavutil/md5.h"
+#include "libavutil/sha.h"
+#include "libavutil/sha512.h"
+#include "libavutil/ripemd.h"
+#include "libavutil/aes.h"
+#include "libavutil/blowfish.h"
+#include "libavutil/camellia.h"
+#include "libavutil/cast5.h"
+#include "libavutil/des.h"
+#include "libavutil/twofish.h"
+#include "libavutil/rc4.h"
+#include "libavutil/xtea.h"
+
+#define IMPL_USE_lavu IMPL_USE
+
+static void run_lavu_md5(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ av_md5_sum(output, input, size);
+}
+
+#define DEFINE_LAVU_MD(suffix, type, namespace, hsize) \
+static void run_lavu_ ## suffix(uint8_t *output, \
+ const uint8_t *input, unsigned size) \
+{ \
+ static struct type *h; \
+ if (!h && !(h = av_ ## namespace ## _alloc())) \
+ fatal_error("out of memory"); \
+ av_ ## namespace ## _init(h, hsize); \
+ av_ ## namespace ## _update(h, input, size); \
+ av_ ## namespace ## _final(h, output); \
+}
+
+DEFINE_LAVU_MD(sha1, AVSHA, sha, 160);
+DEFINE_LAVU_MD(sha256, AVSHA, sha, 256);
+DEFINE_LAVU_MD(sha512, AVSHA512, sha512, 512);
+DEFINE_LAVU_MD(ripemd128, AVRIPEMD, ripemd, 128);
+DEFINE_LAVU_MD(ripemd160, AVRIPEMD, ripemd, 160);
+
+static void run_lavu_aes128(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ static struct AVAES *aes;
+ if (!aes && !(aes = av_aes_alloc()))
+ fatal_error("out of memory");
+ av_aes_init(aes, hardcoded_key, 128, 0);
+ av_aes_crypt(aes, output, input, size >> 4, NULL, 0);
+}
+
+static void run_lavu_blowfish(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ static struct AVBlowfish *blowfish;
+ if (!blowfish && !(blowfish = av_blowfish_alloc()))
+ fatal_error("out of memory");
+ av_blowfish_init(blowfish, hardcoded_key, 16);
+ av_blowfish_crypt(blowfish, output, input, size >> 3, NULL, 0);
+}
+
+static void run_lavu_camellia(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ static struct AVCAMELLIA *camellia;
+ if (!camellia && !(camellia = av_camellia_alloc()))
+ fatal_error("out of memory");
+ av_camellia_init(camellia, hardcoded_key, 128);
+ av_camellia_crypt(camellia, output, input, size >> 4, NULL, 0);
+}
+
+static void run_lavu_cast128(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ static struct AVCAST5 *cast;
+ if (!cast && !(cast = av_cast5_alloc()))
+ fatal_error("out of memory");
+ av_cast5_init(cast, hardcoded_key, 128);
+ av_cast5_crypt(cast, output, input, size >> 3, 0);
+}
+
+static void run_lavu_des(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ static struct AVDES *des;
+ if (!des && !(des = av_des_alloc()))
+ fatal_error("out of memory");
+ av_des_init(des, hardcoded_key, 64, 0);
+ av_des_crypt(des, output, input, size >> 3, NULL, 0);
+}
+
+static void run_lavu_twofish(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ static struct AVTWOFISH *twofish;
+ if (!twofish && !(twofish = av_twofish_alloc()))
+ fatal_error("out of memory");
+ av_twofish_init(twofish, hardcoded_key, 128);
+ av_twofish_crypt(twofish, output, input, size >> 4, NULL, 0);
+}
+
+static void run_lavu_rc4(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ static struct AVRC4 *rc4;
+ if (!rc4 && !(rc4 = av_rc4_alloc()))
+ fatal_error("out of memory");
+ av_rc4_init(rc4, hardcoded_key, 128, 0);
+ av_rc4_crypt(rc4, output, input, size, NULL, 0);
+}
+
+static void run_lavu_xtea(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ static struct AVXTEA *xtea;
+ if (!xtea && !(xtea = av_xtea_alloc()))
+ fatal_error("out of memory");
+ av_xtea_init(xtea, hardcoded_key);
+ av_xtea_crypt(xtea, output, input, size >> 3, NULL, 0);
+}
+
+/***************************************************************************
+ * crypto: OpenSSL's libcrypto
+ ***************************************************************************/
+
+#if (USE_EXT_LIBS) & USE_crypto
+
+#define OPENSSL_DISABLE_OLD_DES_SUPPORT
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+#include <openssl/ripemd.h>
+#include <openssl/aes.h>
+#include <openssl/blowfish.h>
+#include <openssl/camellia.h>
+#include <openssl/cast.h>
+#include <openssl/des.h>
+#include <openssl/rc4.h>
+
+#define DEFINE_CRYPTO_WRAPPER(suffix, function) \
+static void run_crypto_ ## suffix(uint8_t *output, \
+ const uint8_t *input, unsigned size) \
+{ \
+ function(input, size, output); \
+}
+
+DEFINE_CRYPTO_WRAPPER(md5, MD5)
+DEFINE_CRYPTO_WRAPPER(sha1, SHA1)
+DEFINE_CRYPTO_WRAPPER(sha256, SHA256)
+DEFINE_CRYPTO_WRAPPER(sha512, SHA512)
+DEFINE_CRYPTO_WRAPPER(ripemd160, RIPEMD160)
+
+static void run_crypto_aes128(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ AES_KEY aes;
+ unsigned i;
+
+ AES_set_encrypt_key(hardcoded_key, 128, &aes);
+ size -= 15;
+ for (i = 0; i < size; i += 16)
+ AES_encrypt(input + i, output + i, &aes);
+}
+
+static void run_crypto_blowfish(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ BF_KEY blowfish;
+ unsigned i;
+
+ BF_set_key(&blowfish, 16, hardcoded_key);
+ for (i = 0; i < size; i += 8)
+ BF_ecb_encrypt(input + i, output + i, &blowfish, 1);
+}
+
+static void run_crypto_camellia(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ CAMELLIA_KEY camellia;
+ unsigned i;
+
+ Camellia_set_key(hardcoded_key, 128, &camellia);
+ size -= 15;
+ for (i = 0; i < size; i += 16)
+ Camellia_ecb_encrypt(input + i, output + i, &camellia, 1);
+}
+
+static void run_crypto_cast128(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ CAST_KEY cast;
+ unsigned i;
+
+ CAST_set_key(&cast, 16, hardcoded_key);
+ for (i = 0; i < size; i += 8)
+ CAST_ecb_encrypt(input + i, output + i, &cast, 1);
+}
+
+static void run_crypto_des(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ DES_key_schedule des;
+ unsigned i;
+
+ DES_set_key(hardcoded_key, &des);
+ for (i = 0; i < size; i += 8)
+ DES_ecb_encrypt(input + i, output + i, &des, 1);
+}
+
+static void run_crypto_rc4(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ RC4_KEY rc4;
+
+ RC4_set_key(&rc4, 16, hardcoded_key);
+ RC4(&rc4, size, input, output);
+}
+
+#define IMPL_USE_crypto(...) IMPL_USE(__VA_ARGS__)
+#else
+#define IMPL_USE_crypto(...) /* ignore */
+#endif
+
+/***************************************************************************
+ * gcrypt: GnuTLS's libgcrypt
+ ***************************************************************************/
+
+#if (USE_EXT_LIBS) & USE_gcrypt
+
+#include <gcrypt.h>
+
+#define DEFINE_GCRYPT_WRAPPER(suffix, algo) \
+static void run_gcrypt_ ## suffix(uint8_t *output, \
+ const uint8_t *input, unsigned size) \
+{ \
+ gcry_md_hash_buffer(GCRY_MD_ ## algo, output, input, size); \
+}
+
+DEFINE_GCRYPT_WRAPPER(md5, MD5)
+DEFINE_GCRYPT_WRAPPER(sha1, SHA1)
+DEFINE_GCRYPT_WRAPPER(sha256, SHA256)
+DEFINE_GCRYPT_WRAPPER(sha512, SHA512)
+DEFINE_GCRYPT_WRAPPER(ripemd160, RMD160)
+
+#define DEFINE_GCRYPT_CYPHER_WRAPPER(suffix, cypher, sz) \
+static void run_gcrypt_ ## suffix(uint8_t *output, \
+ const uint8_t *input, unsigned size) \
+{ \
+ static gcry_cipher_hd_t suffix; \
+ if (!suffix) \
+ gcry_cipher_open(&suffix, GCRY_CIPHER_ ## cypher, GCRY_CIPHER_MODE_ECB, 0); \
+ gcry_cipher_setkey(suffix, hardcoded_key, sz); \
+ gcry_cipher_encrypt(suffix, output, size, input, size); \
+}
+
+DEFINE_GCRYPT_CYPHER_WRAPPER(aes128, AES128, 16)
+DEFINE_GCRYPT_CYPHER_WRAPPER(blowfish, BLOWFISH, 16)
+DEFINE_GCRYPT_CYPHER_WRAPPER(camellia, CAMELLIA128, 16)
+DEFINE_GCRYPT_CYPHER_WRAPPER(cast128, CAST5, 16)
+DEFINE_GCRYPT_CYPHER_WRAPPER(des, DES, 8)
+DEFINE_GCRYPT_CYPHER_WRAPPER(twofish, TWOFISH128, 16)
+
+#define IMPL_USE_gcrypt(...) IMPL_USE(__VA_ARGS__)
+#else
+#define IMPL_USE_gcrypt(...) /* ignore */
+#endif
+
+/***************************************************************************
+ * tomcrypt: LibTomCrypt
+ ***************************************************************************/
+
+#if (USE_EXT_LIBS) & USE_tomcrypt
+
+#include <tomcrypt.h>
+
+#define DEFINE_TOMCRYPT_WRAPPER(suffix, namespace, algo) \
+static void run_tomcrypt_ ## suffix(uint8_t *output, \
+ const uint8_t *input, unsigned size) \
+{ \
+ hash_state md; \
+ namespace ## _init(&md); \
+ namespace ## _process(&md, input, size); \
+ namespace ## _done(&md, output); \
+}
+
+DEFINE_TOMCRYPT_WRAPPER(md5, md5, MD5)
+DEFINE_TOMCRYPT_WRAPPER(sha1, sha1, SHA1)
+DEFINE_TOMCRYPT_WRAPPER(sha256, sha256, SHA256)
+DEFINE_TOMCRYPT_WRAPPER(sha512, sha512, SHA512)
+DEFINE_TOMCRYPT_WRAPPER(ripemd128, rmd128, RIPEMD128)
+DEFINE_TOMCRYPT_WRAPPER(ripemd160, rmd160, RIPEMD160)
+
+static void run_tomcrypt_aes128(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ symmetric_key aes;
+ unsigned i;
+
+ aes_setup(hardcoded_key, 16, 0, &aes);
+ size -= 15;
+ for (i = 0; i < size; i += 16)
+ aes_ecb_encrypt(input + i, output + i, &aes);
+}
+
+static void run_tomcrypt_blowfish(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ symmetric_key blowfish;
+ unsigned i;
+
+ blowfish_setup(hardcoded_key, 16, 0, &blowfish);
+ for (i = 0; i < size; i += 8)
+ blowfish_ecb_encrypt(input + i, output + i, &blowfish);
+}
+
+static void run_tomcrypt_camellia(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ symmetric_key camellia;
+ unsigned i;
+
+ camellia_setup(hardcoded_key, 16, 0, &camellia);
+ size -= 15;
+ for (i = 0; i < size; i += 16)
+ camellia_ecb_encrypt(input + i, output + i, &camellia);
+}
+
+static void run_tomcrypt_cast128(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ symmetric_key cast;
+ unsigned i;
+
+ cast5_setup(hardcoded_key, 16, 0, &cast);
+ for (i = 0; i < size; i += 8)
+ cast5_ecb_encrypt(input + i, output + i, &cast);
+}
+
+static void run_tomcrypt_des(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ symmetric_key des;
+ unsigned i;
+
+ des_setup(hardcoded_key, 8, 0, &des);
+ for (i = 0; i < size; i += 8)
+ des_ecb_encrypt(input + i, output + i, &des);
+}
+
+static void run_tomcrypt_twofish(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ symmetric_key twofish;
+ unsigned i;
+
+ twofish_setup(hardcoded_key, 16, 0, &twofish);
+ size -= 15;
+ for (i = 0; i < size; i += 16)
+ twofish_ecb_encrypt(input + i, output + i, &twofish);
+}
+
+static void run_tomcrypt_xtea(uint8_t *output,
+ const uint8_t *input, unsigned size)
+{
+ symmetric_key xtea;
+ unsigned i;
+
+ xtea_setup(hardcoded_key, 16, 0, &xtea);
+ for (i = 0; i < size; i += 8)
+ xtea_ecb_encrypt(input + i, output + i, &xtea);
+}
+
+
+#define IMPL_USE_tomcrypt(...) IMPL_USE(__VA_ARGS__)
+#else
+#define IMPL_USE_tomcrypt(...) /* ignore */
+#endif
+
+/***************************************************************************
+ * Driver code
+ ***************************************************************************/
+
+static unsigned crc32(const uint8_t *data, unsigned size)
+{
+ return av_crc(av_crc_get_table(AV_CRC_32_IEEE), 0, data, size);
+}
+
+static void run_implementation(const uint8_t *input, uint8_t *output,
+ struct hash_impl *impl, unsigned size)
+{
+ uint64_t t0, t1;
+ unsigned nruns = specified_runs ? specified_runs : (1 << 30) / size;
+ unsigned outlen = 0, outcrc = 0;
+ unsigned i, j, val;
+ double mtime, ttime = 0, ttime2 = 0, stime;
+ uint8_t outref[MAX_OUTPUT_SIZE];
+
+ if (enabled_libs && !av_stristr(enabled_libs, impl->lib) ||
+ enabled_algos && !av_stristr(enabled_algos, impl->name))
+ return;
+ if (!sscanf(impl->output, "crc:%x", &outcrc)) {
+ outlen = strlen(impl->output) / 2;
+ for (i = 0; i < outlen; i++) {
+ sscanf(impl->output + i * 2, "%02x", &val);
+ outref[i] = val;
+ }
+ }
+ for (i = 0; i < 8; i++) /* heat caches */
+ impl->run(output, input, size);
+ for (i = 0; i < nruns; i++) {
+ memset(output, 0, size); /* avoid leftovers from previous runs */
+ t0 = AV_READ_TIME();
+ impl->run(output, input, size);
+ t1 = AV_READ_TIME();
+ if (outlen ? memcmp(output, outref, outlen) :
+ crc32(output, size) != outcrc) {
+ fprintf(stderr, "Expected: ");
+ if (outlen)
+ for (j = 0; j < outlen; j++)
+ fprintf(stderr, "%02x", output[j]);
+ else
+ fprintf(stderr, "%08x", crc32(output, size));
+ fprintf(stderr, "\n");
+ fatal_error("output mismatch");
+ }
+ mtime = (double)(t1 - t0) / size;
+ ttime += mtime;
+ ttime2 += mtime * mtime;
+ }
+
+ ttime /= nruns;
+ ttime2 /= nruns;
+ stime = sqrt(ttime2 - ttime * ttime);
+ printf("%-10s %-12s size: %7d runs: %6d time: %8.3f +- %.3f\n",
+ impl->lib, impl->name, size, nruns, ttime, stime);
+ fflush(stdout);
+}
+
+#define IMPL_USE(lib, name, symbol, output) \
+ { #lib, name, run_ ## lib ## _ ## symbol, output },
+#define IMPL(lib, ...) IMPL_USE_ ## lib(lib, __VA_ARGS__)
+#define IMPL_ALL(...) \
+ IMPL(lavu, __VA_ARGS__) \
+ IMPL(crypto, __VA_ARGS__) \
+ IMPL(gcrypt, __VA_ARGS__) \
+ IMPL(tomcrypt, __VA_ARGS__)
+
+struct hash_impl implementations[] = {
+ IMPL_ALL("MD5", md5, "aa26ff5b895356bcffd9292ba9f89e66")
+ IMPL_ALL("SHA-1", sha1, "1fd8bd1fa02f5b0fe916b0d71750726b096c5744")
+ IMPL_ALL("SHA-256", sha256, "14028ac673b3087e51a1d407fbf0df4deeec8f217119e13b07bf2138f93db8c5")
+ IMPL_ALL("SHA-512", sha512, "3afdd44a80d99af15c87bd724cb717243193767835ce866dd5d58c02d674bb57"
+ "7c25b9e118c200a189fcd5a01ef106a4e200061f3e97dbf50ba065745fd46bef")
+ IMPL(lavu, "RIPEMD-128", ripemd128, "9ab8bfba2ddccc5d99c9d4cdfb844a5f")
+ IMPL(tomcrypt, "RIPEMD-128", ripemd128, "9ab8bfba2ddccc5d99c9d4cdfb844a5f")
+ IMPL_ALL("RIPEMD-160", ripemd160, "62a5321e4fc8784903bb43ab7752c75f8b25af00")
+ IMPL_ALL("AES-128", aes128, "crc:ff6bc888")
+ IMPL_ALL("CAMELLIA", camellia, "crc:7abb59a7")
+ IMPL_ALL("CAST-128", cast128, "crc:456aa584")
+ IMPL_ALL("BLOWFISH", blowfish, "crc:33e8aa74")
+ IMPL_ALL("DES", des, "crc:31291e0b")
+ IMPL(lavu, "TWOFISH", twofish, "crc:9edbd5c1")
+ IMPL(gcrypt, "TWOFISH", twofish, "crc:9edbd5c1")
+ IMPL(tomcrypt, "TWOFISH", twofish, "crc:9edbd5c1")
+ IMPL(lavu, "RC4", rc4, "crc:538d37b2")
+ IMPL(crypto, "RC4", rc4, "crc:538d37b2")
+ IMPL(lavu, "XTEA", xtea, "crc:931fc270")
+ IMPL(tomcrypt, "XTEA", xtea, "crc:931fc270")
+};
+
+int main(int argc, char **argv)
+{
+ uint8_t *input = av_malloc(MAX_INPUT_SIZE * 2);
+ uint8_t *output = input + MAX_INPUT_SIZE;
+ unsigned i, impl, size;
+ int opt;
+
+ while ((opt = getopt(argc, argv, "hl:a:r:")) != -1) {
+ switch (opt) {
+ case 'l':
+ enabled_libs = optarg;
+ break;
+ case 'a':
+ enabled_algos = optarg;
+ break;
+ case 'r':
+ specified_runs = strtol(optarg, NULL, 0);
+ break;
+ case 'h':
+ default:
+ fprintf(stderr, "Usage: %s [-l libs] [-a algos] [-r runs]\n",
+ argv[0]);
+ if ((USE_EXT_LIBS)) {
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "%s%s%s",
+ ((USE_EXT_LIBS) & USE_crypto) ? "+crypto" : "",
+ ((USE_EXT_LIBS) & USE_gcrypt) ? "+gcrypt" : "",
+ ((USE_EXT_LIBS) & USE_tomcrypt) ? "+tomcrypt" : "");
+ fprintf(stderr, "Built with the following external libraries:\n"
+ "make VERSUS=%s\n", buf + 1);
+ } else {
+ fprintf(stderr, "Built without external libraries; use\n"
+ "make VERSUS=crypto+gcrypt+tomcrypt tools/crypto_bench\n"
+ "to enable them.\n");
+ }
+ exit(opt != 'h');
+ }
+ }
+
+ if (!input)
+ fatal_error("out of memory");
+ for (i = 0; i < MAX_INPUT_SIZE; i += 4)
+ AV_WB32(input + i, i);
+
+ size = MAX_INPUT_SIZE;
+ for (impl = 0; impl < FF_ARRAY_ELEMS(implementations); impl++)
+ run_implementation(input, output, &implementations[impl], size);
+
+ av_free(input);
+
+ return 0;
+}
diff --git a/tools/cws2fws.c b/tools/cws2fws.c
index 72980f4e2d..7046b69957 100644
--- a/tools/cws2fws.c
+++ b/tools/cws2fws.c
@@ -22,7 +22,7 @@
#ifdef DEBUG
#define dbgprintf printf
#else
-#define dbgprintf(...)
+#define dbgprintf(...) do { if (0) printf(__VA_ARGS__); } while (0)
#endif
int main(int argc, char *argv[])
@@ -61,7 +61,10 @@ int main(int argc, char *argv[])
goto out;
}
- fstat(fd_in, &statbuf);
+ if (fstat(fd_in, &statbuf) < 0) {
+ perror("fstat failed");
+ return 1;
+ }
comp_len = statbuf.st_size;
uncomp_len = buf_in[4] | (buf_in[5] << 8) | (buf_in[6] << 16) | (buf_in[7] << 24);
@@ -78,7 +81,10 @@ int main(int argc, char *argv[])
zstream.zalloc = NULL;
zstream.zfree = NULL;
zstream.opaque = NULL;
- inflateInit(&zstream);
+ if (inflateInit(&zstream) != Z_OK) {
+ fprintf(stderr, "inflateInit failed\n");
+ return 1;
+ }
for (i = 0; i < comp_len - 8;) {
int ret, len = read(fd_in, &buf_in, 1024);
@@ -125,8 +131,8 @@ int main(int argc, char *argv[])
buf_in[2] = ((zstream.total_out + 8) >> 16) & 0xff;
buf_in[3] = ((zstream.total_out + 8) >> 24) & 0xff;
- lseek(fd_out, 4, SEEK_SET);
- if (write(fd_out, &buf_in, 4) < 4) {
+ if ( lseek(fd_out, 4, SEEK_SET) < 0
+ || write(fd_out, &buf_in, 4) < 4) {
perror("Error writing output file");
inflateEnd(&zstream);
goto out;
diff --git a/tools/dvd2concat b/tools/dvd2concat
new file mode 100755
index 0000000000..8effee86b9
--- /dev/null
+++ b/tools/dvd2concat
@@ -0,0 +1,127 @@
+#!/usr/bin/env perl
+
+# 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
+
+=head1 NAME
+
+dvd2concat - create a concat script for a DVD title
+
+=head1 SYNOPSIS
+
+tools/dvd2concat I<path/to/dvd/structure> > I<file.concat>
+
+=head1 DESCRIPTION
+
+This script uses B<lsdvd> to produce concat script for a DVD title.
+The resulting script can be used to play the DVD using B<ffplay>, to
+transcode it using B<ffmpeg> or any other similar use.
+
+I<path/to/dvd/structure> is the path to the DVD structure hierarchy; it
+normally contains a directory named B<VIDEO_TS>. It must not be encrypted
+with CSS.
+
+I<file.concat> is the output file. It can be used as an input to ffmpeg.
+It will require the B<-safe 0> option.
+
+=cut
+
+use strict;
+use warnings;
+use Getopt::Long ":config" => "require_order";
+use Pod::Usage;
+
+my $title;
+
+GetOptions (
+ "help|usage|?|h" => sub { pod2usage({ -verbose => 1, -exitval => 0 }) },
+ "manpage|m" => sub { pod2usage({ -verbose => 2, -exitval => 0 }) },
+ "title|t=i" => \$title,
+) and @ARGV == 1 or pod2usage({ -verbose => 1, -exitval => 1 });
+my ($path) = @ARGV;
+
+my $lsdvd_message =
+"Make sure your lsdvd version has the two following patches applied:\n" .
+"http://sourceforge.net/p/lsdvd/feature-requests/1/\n" .
+"https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=603826\n";
+
+my $lsdvd = do {
+ open my $l, "-|", "lsdvd", "-Op", "-x", $path
+ or die "You need to install lsdvd for this script to work.\n$lsdvd_message";
+ local $/;
+ <$l>;
+};
+my %lsdvd = eval $lsdvd;
+die $@ if $@;
+
+if (!defined $title) {
+ $title = $lsdvd{longest_track};
+ warn "Using longest title $title\n";
+}
+my $track = $lsdvd{track}[$title - 1]
+ or die "Title $title does not exist (1-", scalar(@{$lsdvd{track}}), ")\n";
+my $vts_base = sprintf "%s/VIDEO_TS/VTS_%02d_", $path, $track->{vts};
+my @frag;
+for my $i (1 .. 9) {
+ my $file = sprintf "%s%d.VOB", $vts_base, $i;
+ my $size = -s $file or last;
+ push @frag, { file => $file, size => $size >> 11 };
+}
+
+my $concat = "ffconcat version 1.0\n";
+$concat .= "\nstream\nexact_stream_id 0x1E0\n";
+for my $audio (@{$track->{audio}}) {
+ $concat .= "\nstream\nexact_stream_id " . $audio->{streamid} . "\n";
+}
+for my $subp (@{$track->{subp}}) {
+ $concat .= "\nstream\nexact_stream_id " . $subp->{streamid} . "\n";
+}
+for my $cell (@{$track->{cell}}) {
+ my $off = $cell->{first_sector};
+ die "Your lsdvd version does not print cell sectors.\n$lsdvd_message"
+ unless defined $off;
+ my $size = $cell->{last_sector} + 1 - $cell->{first_sector};
+
+ my $frag = 0;
+ while ($frag < @frag) {
+ last if $off < $frag[$frag]->{size};
+ $off -= $frag[$frag++]->{size};
+ }
+ die "Cell beyond VOB data\n" unless $frag < @frag;
+ my $cur_off = $off;
+ my $cur_size = $size;
+ my @files;
+ while ($cur_size > $frag[$frag]->{size} - $cur_off) {
+ push @files, $frag[$frag]->{file};
+ $cur_size -= $frag[$frag]->{size} - $cur_off;
+ $cur_off = 0;
+ die "Cell end beyond VOB data\n" unless ++$frag < @frag;
+ }
+ push @files, $frag[$frag]->{file};
+ my $file = @files == 1 ? $files[0] : "concat:" . join("|", @files);
+ my $start = $off << 11;
+ my $end = ($off + $size) << 11;
+ $file = "subfile,,start,${start},end,${end},,:$file";
+
+ my $dur = int(1000 * $cell->{length});
+ $concat .= sprintf "\nfile '%s'\nduration %02d:%02d:%02d.%03d\n", $file,
+ int($dur / 3600000), int($dur / 60000) % 60, int($dur / 1000) % 60,
+ $dur % 1000;
+}
+
+print $concat;
diff --git a/tools/enum_options.c b/tools/enum_options.c
new file mode 100644
index 0000000000..c2a295cad6
--- /dev/null
+++ b/tools/enum_options.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2011 Anton Khirnov
+ *
+ * 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
+ */
+
+/*
+ * enumerate avoptions and format them in texinfo format
+ */
+
+#include <string.h>
+
+#include "libavformat/avformat.h"
+#include "libavcodec/avcodec.h"
+#include "libavutil/log.h"
+#include "libavutil/opt.h"
+
+static void print_usage(void)
+{
+ fprintf(stderr, "Usage: enum_options type\n"
+ "type: format codec\n");
+ exit(1);
+}
+
+static void print_option(const AVClass *class, const AVOption *o)
+{
+ printf("@item -%s @var{", o->name);
+ switch (o->type) {
+ case FF_OPT_TYPE_BINARY: printf("hexadecimal string"); break;
+ case FF_OPT_TYPE_STRING: printf("string"); break;
+ case FF_OPT_TYPE_INT:
+ case FF_OPT_TYPE_INT64: printf("integer"); break;
+ case FF_OPT_TYPE_FLOAT:
+ case FF_OPT_TYPE_DOUBLE: printf("float"); break;
+ case FF_OPT_TYPE_RATIONAL: printf("rational number"); break;
+ case FF_OPT_TYPE_FLAGS: printf("flags"); break;
+ default: printf("value"); break;
+ }
+ printf("} (@emph{");
+
+ if (o->flags & AV_OPT_FLAG_ENCODING_PARAM) {
+ printf("input");
+ if (o->flags & AV_OPT_FLAG_ENCODING_PARAM)
+ printf("/");
+ }
+ if (o->flags & AV_OPT_FLAG_ENCODING_PARAM)
+ printf("output");
+
+ printf("})\n");
+ if (o->help)
+ printf("%s\n", o->help);
+
+ if (o->unit) {
+ const AVOption *u = NULL;
+ printf("\nPossible values:\n@table @samp\n");
+
+ while ((u = av_next_option(&class, u)))
+ if (u->type == FF_OPT_TYPE_CONST && u->unit && !strcmp(u->unit, o->unit))
+ printf("@item %s\n%s\n", u->name, u->help ? u->help : "");
+ printf("@end table\n");
+ }
+}
+
+static void show_opts(const AVClass *class)
+{
+ const AVOption *o = NULL;
+
+ printf("@table @option\n");
+ while ((o = av_next_option(&class, o)))
+ if (o->type != FF_OPT_TYPE_CONST)
+ print_option(class, o);
+ printf("@end table\n");
+}
+
+static void show_format_opts(void)
+{
+ AVInputFormat *iformat = NULL;
+ AVOutputFormat *oformat = NULL;
+
+ printf("@section Generic format AVOptions\n");
+ show_opts(avformat_get_class());
+
+ printf("@section Format-specific AVOptions\n");
+ while ((iformat = av_iformat_next(iformat))) {
+ if (!iformat->priv_class)
+ continue;
+ printf("@subsection %s AVOptions\n", iformat->priv_class->class_name);
+ show_opts(iformat->priv_class);
+ }
+ while ((oformat = av_oformat_next(oformat))) {
+ if (!oformat->priv_class)
+ continue;
+ printf("@subsection %s AVOptions\n", oformat->priv_class->class_name);
+ show_opts(oformat->priv_class);
+ }
+}
+
+static void show_codec_opts(void)
+{
+ AVCodec *c = NULL;
+
+ printf("@section Generic codec AVOptions\n");
+ show_opts(avcodec_get_class());
+
+ printf("@section Codec-specific AVOptions\n");
+ while ((c = av_codec_next(c))) {
+ if (!c->priv_class)
+ continue;
+ printf("@subsection %s AVOptions\n", c->priv_class->class_name);
+ show_opts(c->priv_class);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 2)
+ print_usage();
+
+ av_register_all();
+
+ if (!strcmp(argv[1], "format"))
+ show_format_opts();
+ else if (!strcmp(argv[1], "codec"))
+ show_codec_opts();
+ else
+ print_usage();
+
+ return 0;
+}
diff --git a/tools/ffescape.c b/tools/ffescape.c
new file mode 100644
index 0000000000..0530d28c6d
--- /dev/null
+++ b/tools/ffescape.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2012 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
+ */
+
+#include "config.h"
+#if HAVE_UNISTD_H
+#include <unistd.h> /* getopt */
+#endif
+
+#include "libavutil/log.h"
+#include "libavutil/bprint.h"
+
+#if !HAVE_GETOPT
+#include "compat/getopt.c"
+#endif
+
+/**
+ * @file
+ * escaping utility
+ */
+
+static void usage(void)
+{
+ printf("Escape an input string, adopting the av_get_token() escaping logic\n");
+ printf("usage: ffescape [OPTIONS]\n");
+ printf("\n"
+ "Options:\n"
+ "-e echo each input line on output\n"
+ "-f flag select an escape flag, can assume the values 'whitespace' and 'strict'\n"
+ "-h print this help\n"
+ "-i INFILE set INFILE as input file, stdin if omitted\n"
+ "-l LEVEL set the number of escaping levels, 1 if omitted\n"
+ "-m ESCAPE_MODE select escape mode between 'auto', 'backslash', 'quote'\n"
+ "-o OUTFILE set OUTFILE as output file, stdout if omitted\n"
+ "-p PROMPT set output prompt, is '=> ' by default\n"
+ "-s SPECIAL_CHARS set the list of special characters\n");
+}
+
+int main(int argc, char **argv)
+{
+ AVBPrint src;
+ char *src_buf, *dst_buf;
+ const char *outfilename = NULL, *infilename = NULL;
+ FILE *outfile = NULL, *infile = NULL;
+ const char *prompt = "=> ";
+ enum AVEscapeMode escape_mode = AV_ESCAPE_MODE_AUTO;
+ int escape_flags = 0;
+ int level = 1;
+ int echo = 0;
+ char *special_chars = NULL;
+ int c;
+
+ while ((c = getopt(argc, argv, "ef:hi:l:o:m:p:s:")) != -1) {
+ switch (c) {
+ case 'e':
+ echo = 1;
+ break;
+ case 'h':
+ usage();
+ return 0;
+ case 'i':
+ infilename = optarg;
+ break;
+ case 'f':
+ if (!strcmp(optarg, "whitespace")) escape_flags |= AV_ESCAPE_FLAG_WHITESPACE;
+ else if (!strcmp(optarg, "strict")) escape_flags |= AV_ESCAPE_FLAG_STRICT;
+ else {
+ av_log(NULL, AV_LOG_ERROR,
+ "Invalid value '%s' for option -f, "
+ "valid arguments are 'whitespace', and 'strict'\n", optarg);
+ return 1;
+ }
+ break;
+ case 'l':
+ {
+ char *tail;
+ long int li = strtol(optarg, &tail, 10);
+ if (*tail || li > INT_MAX || li < 0) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Invalid value '%s' for option -l, argument must be a non negative integer\n",
+ optarg);
+ return 1;
+ }
+ level = li;
+ break;
+ }
+ case 'm':
+ if (!strcmp(optarg, "auto")) escape_mode = AV_ESCAPE_MODE_AUTO;
+ else if (!strcmp(optarg, "backslash")) escape_mode = AV_ESCAPE_MODE_BACKSLASH;
+ else if (!strcmp(optarg, "quote")) escape_mode = AV_ESCAPE_MODE_QUOTE;
+ else {
+ av_log(NULL, AV_LOG_ERROR,
+ "Invalid value '%s' for option -m, "
+ "valid arguments are 'backslash', and 'quote'\n", optarg);
+ return 1;
+ }
+ break;
+ case 'o':
+ outfilename = optarg;
+ break;
+ case 'p':
+ prompt = optarg;
+ break;
+ case 's':
+ special_chars = optarg;
+ break;
+ case '?':
+ return 1;
+ }
+ }
+
+ if (!infilename || !strcmp(infilename, "-")) {
+ infilename = "stdin";
+ infile = stdin;
+ } else {
+ infile = fopen(infilename, "r");
+ }
+ if (!infile) {
+ av_log(NULL, AV_LOG_ERROR, "Impossible to open input file '%s': %s\n", infilename, strerror(errno));
+ return 1;
+ }
+
+ if (!outfilename || !strcmp(outfilename, "-")) {
+ outfilename = "stdout";
+ outfile = stdout;
+ } else {
+ outfile = fopen(outfilename, "w");
+ }
+ if (!outfile) {
+ av_log(NULL, AV_LOG_ERROR, "Impossible to open output file '%s': %s\n", outfilename, strerror(errno));
+ return 1;
+ }
+
+ /* grab the input and store it in src */
+ av_bprint_init(&src, 1, AV_BPRINT_SIZE_UNLIMITED);
+ while ((c = fgetc(infile)) != EOF)
+ av_bprint_chars(&src, c, 1);
+ av_bprint_chars(&src, 0, 1);
+
+ if (!av_bprint_is_complete(&src)) {
+ av_log(NULL, AV_LOG_ERROR, "Could not allocate a buffer for the source string\n");
+ av_bprint_finalize(&src, NULL);
+ return 1;
+ }
+ av_bprint_finalize(&src, &src_buf);
+
+ if (echo)
+ fprintf(outfile, "%s", src_buf);
+
+ /* escape */
+ dst_buf = src_buf;
+ while (level--) {
+ if (av_escape(&dst_buf, src_buf, special_chars, escape_mode, escape_flags) < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Could not escape string\n");
+ return 1;
+ }
+ av_free(src_buf);
+ src_buf = dst_buf;
+ }
+
+ fprintf(outfile, "%s%s", prompt, dst_buf);
+ av_free(dst_buf);
+ return 0;
+}
diff --git a/tools/ffeval.c b/tools/ffeval.c
new file mode 100644
index 0000000000..944f374727
--- /dev/null
+++ b/tools/ffeval.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2012 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
+ */
+
+#include "config.h"
+#if HAVE_UNISTD_H
+#include <unistd.h> /* getopt */
+#endif
+
+#include "libavutil/eval.h"
+#include "libavutil/mem.h"
+
+#if !HAVE_GETOPT
+#include "compat/getopt.c"
+#endif
+
+/**
+ * @file
+ * simple arithmetic expression evaluator
+ */
+
+static void usage(void)
+{
+ printf("Simple expression evalutor, please *don't* turn me to a feature-complete language interpreter\n");
+ printf("usage: ffeval [OPTIONS]\n");
+ printf("\n"
+ "Options:\n"
+ "-e echo each input line on output\n"
+ "-h print this help\n"
+ "-i INFILE set INFILE as input file, stdin if omitted\n"
+ "-o OUTFILE set OUTFILE as output file, stdout if omitted\n"
+ "-p PROMPT set output prompt\n");
+}
+
+int main(int argc, char **argv)
+{
+ int buf_size = 0;
+ char *buf = NULL;
+ const char *outfilename = NULL, *infilename = NULL;
+ FILE *outfile = NULL, *infile = NULL;
+ const char *prompt = "=> ";
+ int count = 0, echo = 0;
+ int c;
+
+#define GROW_ARRAY() \
+ do { \
+ if (!av_dynarray2_add((void **)&buf, &buf_size, 1, NULL)) { \
+ av_log(NULL, AV_LOG_ERROR, \
+ "Memory allocation problem occurred\n"); \
+ return 1; \
+ } \
+ } while (0)
+
+ GROW_ARRAY();
+ while ((c = getopt(argc, argv, "ehi:o:p:")) != -1) {
+ switch (c) {
+ case 'e':
+ echo = 1;
+ break;
+ case 'h':
+ usage();
+ return 0;
+ case 'i':
+ infilename = optarg;
+ break;
+ case 'o':
+ outfilename = optarg;
+ break;
+ case 'p':
+ prompt = optarg;
+ break;
+ case '?':
+ return 1;
+ }
+ }
+
+ if (!infilename || !strcmp(infilename, "-")) {
+ infilename = "stdin";
+ infile = stdin;
+ } else {
+ infile = fopen(infilename, "r");
+ }
+ if (!infile) {
+ fprintf(stderr, "Impossible to open input file '%s': %s\n", infilename, strerror(errno));
+ return 1;
+ }
+
+ if (!outfilename || !strcmp(outfilename, "-")) {
+ outfilename = "stdout";
+ outfile = stdout;
+ } else {
+ outfile = fopen(outfilename, "w");
+ }
+ if (!outfile) {
+ fprintf(stderr, "Impossible to open output file '%s': %s\n", outfilename, strerror(errno));
+ return 1;
+ }
+
+ while ((c = fgetc(infile)) != EOF) {
+ if (c == '\n') {
+ double d;
+
+ buf[count] = 0;
+ if (buf[0] != '#') {
+ int ret = av_expr_parse_and_eval(&d, buf,
+ NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, 0, NULL);
+ if (echo)
+ fprintf(outfile, "%s ", buf);
+ if (ret >= 0) fprintf(outfile, "%s%f\n", prompt, d);
+ else fprintf(outfile, "%s%f (%s)\n", prompt, d, av_err2str(ret));
+ }
+ count = 0;
+ } else {
+ if (count >= buf_size-1)
+ GROW_ARRAY();
+ buf[count++] = c;
+ }
+ }
+
+ av_free(buf);
+ return 0;
+}
diff --git a/tools/ffhash.c b/tools/ffhash.c
new file mode 100644
index 0000000000..6942527732
--- /dev/null
+++ b/tools/ffhash.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2002 Fabrice Bellard
+ * Copyright (c) 2013 Michael Niedermayer
+ * 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 "config.h"
+#include "libavutil/avstring.h"
+#include "libavutil/error.h"
+#include "libavutil/hash.h"
+#include "libavutil/mem.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
+#if HAVE_IO_H
+#include <io.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#define SIZE 65536
+
+static struct AVHashContext *hash;
+static int out_b64;
+
+static void usage(void)
+{
+ int i = 0;
+ const char *name;
+
+ printf("usage: ffhash [b64:]algorithm [input]...\n");
+ printf("Supported hash algorithms:");
+ do {
+ name = av_hash_names(i);
+ if (name)
+ printf(" %s", name);
+ i++;
+ } while(name);
+ printf("\n");
+}
+
+static void finish(void)
+{
+ char res[2 * AV_HASH_MAX_SIZE + 4];
+
+ printf("%s=", av_hash_get_name(hash));
+ if (out_b64) {
+ av_hash_final_b64(hash, res, sizeof(res));
+ printf("b64:%s", res);
+ } else {
+ av_hash_final_hex(hash, res, sizeof(res));
+ printf("0x%s", res);
+ }
+}
+
+static int check(char *file)
+{
+ uint8_t buffer[SIZE];
+ int fd, flags = O_RDONLY;
+ int ret = 0;
+
+#ifdef O_BINARY
+ flags |= O_BINARY;
+#endif
+ if (file) fd = open(file, flags);
+ else fd = 0;
+ if (fd == -1) {
+ printf("%s=OPEN-FAILED: %s:", av_hash_get_name(hash), strerror(errno));
+ ret = 1;
+ goto end;
+ }
+
+ av_hash_init(hash);
+ for (;;) {
+ int size = read(fd, buffer, SIZE);
+ if (size < 0) {
+ int err = errno;
+ close(fd);
+ finish();
+ printf("+READ-FAILED: %s", strerror(err));
+ ret = 2;
+ goto end;
+ } else if(!size)
+ break;
+ av_hash_update(hash, buffer, size);
+ }
+ close(fd);
+
+ finish();
+end:
+ if (file)
+ printf(" *%s", file);
+ printf("\n");
+
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+ int ret = 0;
+ const char *hash_name;
+
+ if (argc == 1) {
+ usage();
+ return 0;
+ }
+
+ hash_name = argv[1];
+ out_b64 = av_strstart(hash_name, "b64:", &hash_name);
+ if ((ret = av_hash_alloc(&hash, hash_name)) < 0) {
+ switch(ret) {
+ case AVERROR(EINVAL):
+ printf("Invalid hash type: %s\n", hash_name);
+ break;
+ case AVERROR(ENOMEM):
+ printf("%s\n", strerror(errno));
+ break;
+ }
+ return 1;
+ }
+
+ for (i = 2; i < argc; i++)
+ ret |= check(argv[i]);
+
+ if (argc < 3)
+ ret |= check(NULL);
+
+ av_hash_freep(&hash);
+
+ return ret;
+}
diff --git a/tools/fourcc2pixfmt.c b/tools/fourcc2pixfmt.c
new file mode 100644
index 0000000000..75bb6077b5
--- /dev/null
+++ b/tools/fourcc2pixfmt.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2012 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
+ */
+
+#include "config.h"
+#if HAVE_UNISTD_H
+#include <unistd.h> /* getopt */
+#endif
+
+#include "libavutil/pixdesc.h"
+#include "libavcodec/avcodec.h"
+#include "libavutil/common.h"
+#include "libavcodec/raw.h"
+
+#undef printf
+#undef fprintf
+
+#if !HAVE_GETOPT
+#include "compat/getopt.c"
+#endif
+
+static void usage(void)
+{
+ printf("Show the relationships between rawvideo pixel formats and FourCC tags.\n");
+ printf("usage: fourcc2pixfmt [OPTIONS]\n");
+ printf("\n"
+ "Options:\n"
+ "-l list the pixel format for each fourcc\n"
+ "-L list the fourccs for each pixel format\n"
+ "-p PIX_FMT given a pixel format, print the list of associated fourccs (one per line)\n"
+ "-h print this help\n");
+}
+
+static void print_pix_fmt_fourccs(enum AVPixelFormat pix_fmt, const PixelFormatTag *pix_fmt_tags, char sep)
+{
+ int i;
+
+ for (i = 0; pix_fmt_tags[i].pix_fmt != AV_PIX_FMT_NONE; i++)
+ if (pix_fmt_tags[i].pix_fmt == pix_fmt)
+ printf("%s%c", av_fourcc2str(pix_fmt_tags[i].fourcc), sep);
+}
+
+int main(int argc, char **argv)
+{
+ int i, list_fourcc_pix_fmt = 0, list_pix_fmt_fourccs = 0;
+ const PixelFormatTag *pix_fmt_tags = avpriv_get_raw_pix_fmt_tags();
+ const char *pix_fmt_name = NULL;
+ char c;
+
+ if (argc == 1) {
+ usage();
+ return 0;
+ }
+
+ while ((c = getopt(argc, argv, "hp:lL")) != -1) {
+ switch (c) {
+ case 'h':
+ usage();
+ return 0;
+ case 'l':
+ list_fourcc_pix_fmt = 1;
+ break;
+ case 'L':
+ list_pix_fmt_fourccs = 1;
+ break;
+ case 'p':
+ pix_fmt_name = optarg;
+ break;
+ case '?':
+ usage();
+ return 1;
+ }
+ }
+
+ if (list_fourcc_pix_fmt)
+ for (i = 0; pix_fmt_tags[i].pix_fmt != AV_PIX_FMT_NONE; i++)
+ printf("%s: %s\n", av_fourcc2str(pix_fmt_tags[i].fourcc),
+ av_get_pix_fmt_name(pix_fmt_tags[i].pix_fmt));
+
+ if (list_pix_fmt_fourccs) {
+ for (i = 0; av_pix_fmt_desc_get(i); i++) {
+ const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(i);
+ if (!pix_desc->name || pix_desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
+ continue;
+ printf("%s: ", pix_desc->name);
+ print_pix_fmt_fourccs(i, pix_fmt_tags, ' ');
+ printf("\n");
+ }
+ }
+
+ if (pix_fmt_name) {
+ enum AVPixelFormat pix_fmt = av_get_pix_fmt(pix_fmt_name);
+ if (pix_fmt == AV_PIX_FMT_NONE) {
+ fprintf(stderr, "Invalid pixel format selected '%s'\n", pix_fmt_name);
+ return 1;
+ }
+ print_pix_fmt_fourccs(pix_fmt, pix_fmt_tags, '\n');
+ }
+
+ return 0;
+}
diff --git a/tools/gen-rc b/tools/gen-rc
new file mode 100755
index 0000000000..d9ca37e9ff
--- /dev/null
+++ b/tools/gen-rc
@@ -0,0 +1,121 @@
+#!/bin/sh
+#
+# 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
+
+## Help
+die() {
+ cat <<EOF >&2
+This script is used to generate Windows resources file for the FFmpeg libraries.
+The output .rc file is to be compiled by windres(1). It is mainly useful for
+FFmpeg developers to tweak and regenerate all resources files at once.
+
+Usage: $0 <libname> <comment>
+
+The script will output the file to '<libname>/<libname-without-lib>res.rc'.
+
+Example: $0 libavcodec 'FFmpeg codecs library'
+EOF
+ exit 1
+}
+
+# Script to generate all:
+# (to remove prefix '# ' and add 'tools/' as prefix: sed -r 's/^.{2}/tools\//')
+# gen-rc libavutil "FFmpeg utility library"
+# gen-rc libavcodec "FFmpeg codec library"
+# gen-rc libavformat "FFmpeg container format library"
+# gen-rc libavdevice "FFmpeg device handling library"
+# gen-rc libavfilter "FFmpeg audio/video filtering library"
+# gen-rc libpostproc "FFmpeg postprocessing library"
+# gen-rc libavresample "Libav audio resampling library"
+# gen-rc libswscale "FFmpeg image rescaling library"
+# gen-rc libswresample "FFmpeg audio resampling library"
+
+## Sanity checks and argument parsing
+if test $# -lt 2 || test $# -gt 3; then
+ die
+fi
+
+name=$1
+shortname=${name#lib}
+comment=$2
+capname=`echo $name | awk '{print toupper($0)}'`
+version=${capname}_VERSION
+
+mkdir -p "$name"
+output="$name/${shortname}res.rc"
+
+## REAL magic
+cat <<EOF > $output
+/*
+ * Windows resource file for $name
+ *
+ * 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 "$name/version.h"
+#include "libavutil/ffversion.h"
+#include "config.h"
+
+1 VERSIONINFO
+FILEVERSION ${version}_MAJOR, ${version}_MINOR, ${version}_MICRO, 0
+PRODUCTVERSION ${version}_MAJOR, ${version}_MINOR, ${version}_MICRO, 0
+FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+FILEOS VOS_NT_WINDOWS32
+FILETYPE VFT_DLL
+{
+ BLOCK "StringFileInfo"
+ {
+ BLOCK "040904B0"
+ {
+ VALUE "CompanyName", "FFmpeg Project"
+ VALUE "FileDescription", "$comment"
+ VALUE "FileVersion", AV_STRINGIFY($version)
+ VALUE "InternalName", "$name"
+ VALUE "LegalCopyright", "Copyright (C) 2000-" AV_STRINGIFY(CONFIG_THIS_YEAR) " FFmpeg Project"
+ VALUE "OriginalFilename", "$shortname" BUILDSUF "-" AV_STRINGIFY(${version}_MAJOR) SLIBSUF
+ VALUE "ProductName", "FFmpeg"
+ VALUE "ProductVersion", FFMPEG_VERSION
+ }
+ }
+
+ BLOCK "VarFileInfo"
+ {
+ VALUE "Translation", 0x0409, 0x04B0
+ }
+}
+EOF
diff --git a/tools/graph2dot.c b/tools/graph2dot.c
index fbf8902146..21d0795e88 100644
--- a/tools/graph2dot.c
+++ b/tools/graph2dot.c
@@ -1,20 +1,20 @@
/*
* Copyright (c) 2008-2010 Stefano Sabatini
*
- * 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 @@ static void print_digraph(FILE *outfile, AVFilterGraph *graph)
char filter_ctx_label[128];
const AVFilterContext *filter_ctx = graph->filters[i];
- snprintf(filter_ctx_label, sizeof(filter_ctx_label), "%s (%s)",
+ snprintf(filter_ctx_label, sizeof(filter_ctx_label), "%s\\n(%s)",
filter_ctx->name,
filter_ctx->filter->name);
@@ -73,28 +73,33 @@ static void print_digraph(FILE *outfile, AVFilterGraph *graph)
const AVFilterContext *dst_filter_ctx = link->dst;
snprintf(dst_filter_ctx_label, sizeof(dst_filter_ctx_label),
- "%s (%s)",
+ "%s\\n(%s)",
dst_filter_ctx->name,
dst_filter_ctx->filter->name);
- fprintf(outfile, "\"%s\" -> \"%s\"",
- filter_ctx_label, dst_filter_ctx_label);
+ fprintf(outfile, "\"%s\" -> \"%s\" [ label= \"inpad:%s -> outpad:%s\\n",
+ filter_ctx_label, dst_filter_ctx_label,
+ avfilter_pad_get_name(link->srcpad, 0),
+ avfilter_pad_get_name(link->dstpad, 0));
+
if (link->type == AVMEDIA_TYPE_VIDEO) {
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
fprintf(outfile,
- " [ label= \"fmt:%s w:%d h:%d tb:%d/%d\" ]",
- desc->name, link->w, link->h, link->time_base.num,
- link->time_base.den);
+ "fmt:%s w:%d h:%d tb:%d/%d",
+ desc->name,
+ link->w, link->h,
+ link->time_base.num, link->time_base.den);
} else if (link->type == AVMEDIA_TYPE_AUDIO) {
char buf[255];
av_get_channel_layout_string(buf, sizeof(buf), -1,
link->channel_layout);
fprintf(outfile,
- " [ label= \"fmt:%s sr:%d cl:%s\" ]",
+ "fmt:%s sr:%d cl:%s tb:%d/%d",
av_get_sample_fmt_name(link->format),
- link->sample_rate, buf);
+ link->sample_rate, buf,
+ link->time_base.num, link->time_base.den);
}
- fprintf(outfile, ";\n");
+ fprintf(outfile, "\" ];\n");
}
}
}
@@ -149,13 +154,21 @@ int main(int argc, char **argv)
/* read from infile and put it in a buffer */
{
- unsigned int count = 0;
+ int64_t count = 0;
struct line *line, *last_line, *first_line;
char *p;
last_line = first_line = av_malloc(sizeof(struct line));
+ if (!last_line) {
+ fprintf(stderr, "Memory allocation failure\n");
+ return 1;
+ }
while (fgets(last_line->data, sizeof(last_line->data), infile)) {
struct line *new_line = av_malloc(sizeof(struct line));
+ if (!new_line) {
+ fprintf(stderr, "Memory allocation failure\n");
+ return 1;
+ }
count += strlen(last_line->data);
last_line->next = new_line;
last_line = new_line;
@@ -163,9 +176,13 @@ int main(int argc, char **argv)
last_line->next = NULL;
graph_string = av_malloc(count + 1);
+ if (!graph_string) {
+ fprintf(stderr, "Memory allocation failure\n");
+ return 1;
+ }
p = graph_string;
for (line = first_line; line->next; line = line->next) {
- unsigned int l = strlen(line->data);
+ size_t l = strlen(line->data);
memcpy(p, line->data, l);
p += l;
}
diff --git a/tools/ismindex.c b/tools/ismindex.c
index 3d7e082b6d..0254a98ff7 100644
--- a/tools/ismindex.c
+++ b/tools/ismindex.c
@@ -1,26 +1,26 @@
/*
* 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
*/
/*
* To create a simple file for smooth streaming:
- * avconv <normal input/transcoding options> -movflags frag_keyframe foo.ismv
+ * ffmpeg <normal input/transcoding options> -movflags frag_keyframe foo.ismv
* ismindex -n foo foo.ismv
* This step creates foo.ism and foo.ismc that is required by IIS for
* serving it.
@@ -342,8 +342,9 @@ static int read_tfra(struct Tracks *tracks, int start_index, AVIOContext *f)
}
fieldlength = avio_rb32(f);
track->chunks = avio_rb32(f);
- track->offsets = av_mallocz(sizeof(*track->offsets) * track->chunks);
+ track->offsets = av_mallocz_array(track->chunks, sizeof(*track->offsets));
if (!track->offsets) {
+ track->chunks = 0;
ret = AVERROR(ENOMEM);
goto fail;
}
@@ -372,7 +373,7 @@ static int read_tfra(struct Tracks *tracks, int start_index, AVIOContext *f)
track->duration -
track->offsets[track->chunks - 1].time;
}
- // Now try and read the actual durations from the trun sample data.
+ // Now try to read the actual durations from the trun sample data.
for (i = 0; i < track->chunks; i++) {
int64_t duration = read_moof_duration(f, track->offsets[i].offset);
if (duration > 0 && llabs(duration - track->offsets[i].duration) > 3) {
@@ -452,10 +453,11 @@ fail:
static int get_private_data(struct Track *track, AVCodecParameters *codecpar)
{
- track->codec_private_size = codecpar->extradata_size;
+ track->codec_private_size = 0;
track->codec_private = av_mallocz(codecpar->extradata_size);
if (!track->codec_private)
return AVERROR(ENOMEM);
+ track->codec_private_size = codecpar->extradata_size;
memcpy(track->codec_private, codecpar->extradata, codecpar->extradata_size);
return 0;
}
@@ -534,8 +536,9 @@ static int handle_file(struct Tracks *tracks, const char *file, int split,
err = AVERROR(ENOMEM);
goto fail;
}
- temp = av_realloc(tracks->tracks,
- sizeof(*tracks->tracks) * (tracks->nb_tracks + 1));
+ temp = av_realloc_array(tracks->tracks,
+ tracks->nb_tracks + 1,
+ sizeof(*tracks->tracks));
if (!temp) {
av_free(track);
err = AVERROR(ENOMEM);
diff --git a/tools/libav-merge-next-commit b/tools/libav-merge-next-commit
new file mode 100755
index 0000000000..9bd03fabf8
--- /dev/null
+++ b/tools/libav-merge-next-commit
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+if [ "$1" != "merge" -a "$1" != "noop" ]; then
+ printf "Usage: $0 <merge|noop [REF_HASH]>\n"
+ exit 0
+fi
+
+[ "$1" = "noop" ] && merge_opts="-s ours"
+
+nextrev=$(git rev-list libav/master --not master --no-merges | tail -n1)
+if [ -z "$nextrev" ]; then
+ printf "Nothing to merge..\n"
+ exit 0
+fi
+printf "Merging $(git log -n 1 --oneline $nextrev)\n"
+git merge --no-commit $merge_opts --no-ff --log $nextrev
+
+if [ "$1" = "noop" -a -n "$2" ]; then
+ printf "\nThis commit is a noop, see $2\n" >> .git/MERGE_MSG
+fi
+
+printf "\nMerged-by: $(git config --get user.name) <$(git config --get user.email)>\n" >> .git/MERGE_MSG
diff --git a/tools/loudnorm.rb b/tools/loudnorm.rb
new file mode 100755
index 0000000000..4ad374a247
--- /dev/null
+++ b/tools/loudnorm.rb
@@ -0,0 +1,61 @@
+#!/usr/bin/env ruby
+
+require 'open3'
+require 'json'
+
+ffmpeg_bin = 'ffmpeg'
+target_il = -24.0
+target_lra = +11.0
+target_tp = -2.0
+samplerate = '48k'
+
+if ARGF.argv.count != 2
+ puts "Usage: #{$PROGRAM_NAME} input.wav output.wav"
+ exit 1
+end
+
+ff_cmd = Array.new([
+ ffmpeg_bin,
+ '-hide_banner',
+ '-i', ARGF.argv[0],
+ '-af', "loudnorm='I=#{target_il}:LRA=#{target_lra}:tp=#{target_tp}:print_format=json'",
+ '-f', 'null',
+ '-']);
+
+_stdin, _stdout, stderr, wait_thr = Open3.popen3(*ff_cmd)
+
+if wait_thr.value.success?
+ stats = JSON.parse(stderr.read.lines[-12, 12].join)
+ loudnorm_string = 'loudnorm='
+ loudnorm_string += 'print_format=summary:'
+ loudnorm_string += 'linear=true:'
+ loudnorm_string += "I=#{target_il}:"
+ loudnorm_string += "LRA=#{target_lra}:"
+ loudnorm_string += "tp=#{target_tp}:"
+ loudnorm_string += "measured_I=#{stats['input_i']}:"
+ loudnorm_string += "measured_LRA=#{stats['input_lra']}:"
+ loudnorm_string += "measured_tp=#{stats['input_tp']}:"
+ loudnorm_string += "measured_thresh=#{stats['input_thresh']}:"
+ loudnorm_string += "offset=#{stats['target_offset']}"
+else
+ puts stderr.read
+ exit 1
+end
+
+ff_cmd = Array.new([
+ ffmpeg_bin,
+ '-y', '-hide_banner',
+ '-i', ARGF.argv[0],
+ '-af', loudnorm_string,
+ '-ar', samplerate,
+ ARGF.argv[1].to_s]);
+
+_stdin, _stdout, stderr, wait_thr = Open3.popen3(*ff_cmd)
+
+if wait_thr.value.success?
+ puts stderr.read.lines[-12, 12].join
+ exit 0
+else
+ puts stderr.read
+ exit 1
+end
diff --git a/tools/make_chlayout_test b/tools/make_chlayout_test
new file mode 100755
index 0000000000..fcdbda3b73
--- /dev/null
+++ b/tools/make_chlayout_test
@@ -0,0 +1,114 @@
+#!/usr/bin/env perl
+
+# 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
+
+=head1 NAME
+
+make_chlayout_test - produce a multichannel test file with the channels
+clearly identified
+
+=head1 SYNOPSIS
+
+tools/make_chlayout_test I<channels> I<out_options>
+
+=head1 DESCRIPTION
+
+This script uses B<ffmpeg> and B<libflite> to produce a file with audio
+channels clearly identified by their name. The resulting file can be used to
+check that the layout and order of channels is correctly handled by a piece
+of software, either a part of B<FFmpeg> or not.
+
+I<channels> is a list of channels or channel layouts, separated by '+'.
+
+I<out_options> is a list of valid ffmpeg outout options, including the
+output file.
+
+Note that some output codecs or formats can not handle arbitrary channel
+layout.
+
+This script requires a B<ffmpeg> binary, either in the source tree or in the
+search path; it must have the flite audio source enabled.
+
+=head1 EXAMPLES
+
+Check that the speakers are correctly plugged:
+
+ tools/make_chlayout_test FL+FR -f alsa default
+
+Produce a 5.1 FLAC file:
+
+ tools/make_chlayout_test 5.1 surround.flac
+
+=cut
+
+use strict;
+use warnings;
+use Getopt::Long ":config" => "require_order";
+use Pod::Usage;
+
+GetOptions (
+ "help|usage|?|h" => sub { pod2usage({ -verbose => 1, -exitval => 0 }) },
+ "manpage|m" => sub { pod2usage({ -verbose => 2, -exitval => 0 }) },
+) and @ARGV >= 2 or pod2usage({ -verbose => 1, -exitval => 1 });
+
+my $channels = shift @ARGV;
+my @out_options = @ARGV;
+
+my $ffmpeg = exists $ENV{FFMPEG} ? $ENV{FFMPEG} :
+ $0 =~ /(.*)\// && -e "$1/../ffmpeg" ? "$1/../ffmpeg" :
+ "ffmpeg";
+
+my %channel_label_to_descr;
+my %layout_to_channels;
+
+{
+ open my $stderr, ">&STDERR";
+ open STDERR, ">", "/dev/null";
+ open my $f, "-|", $ffmpeg, "-layouts" or die "$ffmpeg: $!\n";
+ open STDERR, ">&", $stderr;
+ while (<$f>) {
+ chomp;
+ next if /^NAME/ or /:$/ or /^$/; # skip headings
+ my ($name, $descr) = split " ", $_, 2;
+ next unless $descr;
+ if ($descr =~ /^[[:upper:]]+(?:\+[[:upper:]]+)*$/) {
+ $layout_to_channels{$name} = [ split /\+/, $descr ];
+ } else {
+ $channel_label_to_descr{$name} = $descr;
+ }
+ }
+}
+
+my @channels = map { @{$layout_to_channels{$_} // [$_]} } split /\+/, $channels;
+
+my $layout = join "+", @channels;
+my $graph = "";
+my $concat_in = "";
+for my $i (0 .. $#channels) {
+ my $label = $channels[$i];
+ my $descr = $channel_label_to_descr{$label}
+ or die "Channel $label not found\n";
+ $graph .= "flite=text='${descr}', aformat=channel_layouts=mono, " .
+ "pan=${layout}:${label}=c0 [ch$i] ;\n";
+ $concat_in .= "[ch$i] ";
+}
+$graph .= "${concat_in}concat=v=0:a=1:n=" . scalar(@channels);
+
+exec $ffmpeg, "-f", "lavfi", "-i", $graph, @out_options
+ or die "$ffmpeg: $!\n";
diff --git a/tools/missing_codec_desc b/tools/missing_codec_desc
new file mode 100755
index 0000000000..e1d3d60b4f
--- /dev/null
+++ b/tools/missing_codec_desc
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+srcdir=${0%/*}/..
+
+while read -r field equal value; do
+ case "$field $equal" in
+ ".id =")
+ eval "known_${value%,}=1"
+ ;;
+ esac
+done < $srcdir/libavcodec/codec_desc.c
+
+known_AV_CODEC_ID_NONE=1
+known_AV_CODEC_ID_FIRST_AUDIO=1
+known_AV_CODEC_ID_FIRST_SUBTITLE=1
+known_AV_CODEC_ID_FIRST_UNKNOWN=1
+known_AV_CODEC_ID_PROBE=1
+known_AV_CODEC_ID_MPEG2TS=1
+known_AV_CODEC_ID_MPEG4SYSTEMS=1
+known_AV_CODEC_ID_FFMETADATA=1
+
+in=0
+while read -r line; do
+ case "$in-$line" in
+ 0-"enum AVCodecID"*) in=1;;
+ 1-*"};"*) in=0;;
+ 1-*AV_CODEC_ID_*,*)
+ cid="${line%%[, =]*}"
+ eval "known=\$known_$cid"
+ case "$known" in
+ 1) ;;
+ *) echo "$cid missing";;
+ esac
+ ;;
+ esac
+done < $srcdir/libavcodec/avcodec.h
diff --git a/tools/murge b/tools/murge
new file mode 100755
index 0000000000..f22fcfda81
--- /dev/null
+++ b/tools/murge
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+grep -A99999 '^<<<<<<<' | grep -B99999 '^>>>>>>>' >murge.X
+grep -A99999 '^====' murge.X | egrep -v '^(=======|<<<<<<<|>>>>>>>|\|\|\|\|\|\|\|)' >murge.theirs
+grep -B99999 '^||||' murge.X | egrep -v '^(=======|<<<<<<<|>>>>>>>|\|\|\|\|\|\|\|)' >murge.ours
+grep -B99999 '^====' murge.X | grep -A99999 '^||||' | egrep -v '^(=======|<<<<<<<|>>>>>>>|\|\|\|\|\|\|\|)' >murge.common
+
+colordiff -du $* murge.ours murge.theirs
+grep . murge.common > /dev/null && colordiff -du $* murge.common murge.theirs
+grep . murge.common > /dev/null && colordiff -du $* murge.common murge.ours
+rm murge.theirs murge.common murge.ours murge.X
diff --git a/tools/normalize.py b/tools/normalize.py
new file mode 100755
index 0000000000..7d87c5e154
--- /dev/null
+++ b/tools/normalize.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python2
+
+import sys, subprocess
+
+if len(sys.argv) > 2:
+ ifile = sys.argv[1]
+ encopt = sys.argv[2:-1]
+ ofile = sys.argv[-1]
+else:
+ print 'usage: %s <input> [encode_options] <output>' % sys.argv[0]
+ sys.exit(1)
+
+analysis_cmd = 'ffprobe -v error -of compact=p=0:nk=1 '
+analysis_cmd += '-show_entries frame_tags=lavfi.r128.I -f lavfi '
+analysis_cmd += "amovie='%s',ebur128=metadata=1" % ifile
+try:
+ probe_out = subprocess.check_output(analysis_cmd, shell=True)
+except subprocess.CalledProcessError, e:
+ sys.exit(e.returncode)
+loudness = ref = -23
+for line in probe_out.splitlines():
+ sline = line.rstrip()
+ if sline:
+ loudness = sline
+adjust = ref - float(loudness)
+if abs(adjust) < 0.0001:
+ print 'No normalization needed for ' + ifile
+else:
+ print "Adjust %s by %.1fdB" % (ifile, adjust)
+ norm_cmd = ['ffmpeg', '-i', ifile, '-af', 'volume=%fdB' % adjust]
+ norm_cmd += encopt + [ofile]
+ print ' => %s' % ' '.join(norm_cmd)
+ subprocess.call(norm_cmd)
diff --git a/tools/patcheck b/tools/patcheck
index e681d6d29e..26137d6b21 100755
--- a/tools/patcheck
+++ b/tools/patcheck
@@ -15,11 +15,11 @@ OPT="-nH"
#FILES=$($GREP '^+++' $* | sed 's/+++ //g')
echo patCHeck 1e10.0
-echo This tool is intended to help a human check/review patches it is very far from
-echo being free of false positives and negatives, its output are just hints of what
+echo This tool is intended to help a human check/review patches. It is very far from
+echo being free of false positives and negatives, and its output are just hints of what
echo may or may not be bad. When you use it and it misses something or detects
-echo something wrong, fix it and send a patch to the libav-devel mailing list.
-echo License:GPL Author: Michael Niedermayer
+echo something wrong, fix it and send a patch to the ffmpeg-devel mailing list.
+echo License: GPL, Author: Michael Niedermayer
ERE_PRITYP='(unsigned *|)(char|short|long|int|long *int|short *int|void|float|double|(u|)int(8|16|32|64)_t)'
ERE_TYPES='(const|static|av_cold|inline| *)*('$ERE_PRITYP'|[a-zA-Z][a-zA-Z0-9_]*)[* ]{1,}[a-zA-Z][a-zA-Z0-9_]*'
@@ -42,6 +42,7 @@ hiegrep2(){
cat $TMP
}
+hiegrep 'static[^(]*\*[a-zA-Z_]*\[' 'pointer array is not const' $*
hiegrep '[[:space:]]$' 'trailing whitespace' $*
hiegrep "$(echo x | tr 'x' '\t')" 'tabs' $*
#hiegrep ':\+$' 'Empty lines' $*
@@ -50,7 +51,7 @@ hiegrep2 '\b_[a-zA-Z0-9_]{1,}' '__(asm|attribute)([^a-zA-Z0-9]|$)' 'reserved ide
hiegrep '//[-/<\* ]*$' 'empty comment' $*
hiegrep '/\*[-<\* ]*\*/' 'empty comment' $*
hiegrep 'for *\( *'"$ERE_PRITYP"' ' 'not gcc 2.95 compatible' $*
-hiegrep '(static|inline|const) *\1' 'duplicate word' $*
+hiegrep '(static|inline|const) *\1[^_a-zA-Z]' 'duplicate word' $*
hiegrep 'INIT_VLC_USE_STATIC' 'forbidden ancient vlc type' $*
hiegrep '=[-+\*\&] ' 'looks like compound assignment' $*
hiegrep2 '/\*\* *[a-zA-Z0-9].*' '\*/' 'Inconsistently formatted doxygen comment' $*
@@ -67,7 +68,7 @@ $EGREP $OPT '^\+ *(const *|)static' $*| $EGREP --color=always '[^=]= *(0|NULL)[^
cat $TMP
hiegrep '# *ifdef * (HAVE|CONFIG)_' 'ifdefs that should be #if' $*
-hiegrep '\b(awnser|cant|dont|wont|doesnt|usefull|successfull|occured|teh|alot|wether|skiped|heigth|informations|colums|loosy|loosing|seperate|preceed|upto|paket|posible|unkown|inpossible|dimention|acheive)\b' 'common typos' $*
+hiegrep '\b(awnser|cant|dont|wont|doesnt|usefull|successfull|occured|teh|alot|wether|skiped|skiping|heigth|informations|colums|loosy|loosing|ouput|seperate|preceed|upto|paket|posible|unkown|inpossible|dimention|acheive|funtions|overriden|outputing|seperation|initalize|compatibilty|bistream|knwon|unknwon|choosen|additonal|gurantee|availble|wich|begining|milisecond|missmatch)\b' 'common typos' $*
hiegrep 'av_log\( *NULL' 'Missing context in av_log' $*
hiegrep '[^sn]printf' 'Please use av_log' $*
@@ -142,7 +143,7 @@ fi
$GREP '^+++ .*Changelog' $* >/dev/null || printf "\nMissing changelog entry (ignore if minor change)\n"
-cat $* | tr '\n' '@' | $EGREP --color=always -o '(fprintf|av_log|printf)\([^)]*\)[+ ;@]*\1' >$TMP && printf "\nMergeable calls\n"
+cat $* | $GREP -v '^-' | tr '\n' '@' | $EGREP --color=always -o '(fprintf|av_log|printf)\([^)]*\)[+ ;@]*\1' >$TMP && printf "\nMergeable calls\n"
cat $TMP | tr '@' '\n'
cat $* | tr '\n' '@' | $EGREP --color=always -o '\+ *if *\( *([A-Za-z0-9_]*) *[<>]=? *[0-9]* *\) * \1 *= *[0-9]* *;[ @\\+]*else *if *\( *\1 *[<>]=? *[0-9]* *\) *\1 *= *[0-9]* *;' >$TMP && printf "\nav_clip / av_clip_uint8 / av_clip_int16 / ...\n"
diff --git a/tools/pktdumper.c b/tools/pktdumper.c
index d71a6b5742..6516ad3a22 100644
--- a/tools/pktdumper.c
+++ b/tools/pktdumper.c
@@ -1,20 +1,20 @@
/*
* Copyright (c) 2005 Francois Revol
*
- * 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/tools/plotframes b/tools/plotframes
new file mode 100755
index 0000000000..f379723a9b
--- /dev/null
+++ b/tools/plotframes
@@ -0,0 +1,164 @@
+#!/usr/bin/env perl
+
+# Copyright (c) 2007-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
+
+=head1 NAME
+
+plotframes - Plot video frame sizes using ffprobe and gnuplot
+
+=head1 SYNOPSIS
+
+plotframes [I<options>] [I<input>]
+
+=head1 DESCRIPTION
+
+plotframes reads a multimedia files with ffprobe, and plots the
+collected video sizes with gnuplot.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--input|-i> I<infile>
+
+Specify multimedia file to read. This is the file passed to the
+ffprobe command. If not specified it is the first argument passed to
+the script.
+
+=item B<--help|--usage|-h|-?>
+
+Print a brief help message and exit.
+
+=item B<--manpage|-m>
+
+Print the man page.
+
+=item B<--output|-o> I<outfile>
+
+Set the name of the output used by gnuplot. If not specified no output
+is created. Must be used in conjunction with the B<terminal> option.
+
+=item B<--stream|--s> I<stream_specifier>
+
+Specify stream. The value must be a string containing a stream
+specifier. Default value is "v".
+
+=item B<--terminal|-t> I<terminal>
+
+Set the name of the terminal used by gnuplot. By default it is
+"x11". Must be used in conjunction with the B<output> option. Check
+the gnuplot manual for the valid values.
+
+=back
+
+=cut
+
+=head1 SEE ALSO
+
+ffprobe(1), gnuplot(1)
+
+=cut
+
+use warnings;
+use strict;
+
+use File::Temp;
+use JSON -support_by_pp;
+use Getopt::Long;
+use Pod::Usage;
+
+my $input = $ARGV[0];
+my $stream_specifier = "v";
+my $gnuplot_terminal = "x11";
+my $gnuplot_output;
+
+GetOptions (
+ 'input|i=s' => \$input,
+ 'help|usage|?|h' => sub { pod2usage ( { -verbose => 1, -exitval => 0 }) },
+ 'manpage|m' => sub { pod2usage ( { -verbose => 2, -exitval => 0 }) },
+ 'stream|s=s' => \$stream_specifier,
+ 'terminal|t=s' => \$gnuplot_terminal,
+ 'output|o=s' => \$gnuplot_output,
+ ) or pod2usage( { -message=> "Parsing error", -verbose => 1, -exitval => 1 });
+
+die "You must specify an input file\n" unless $input;
+
+# fetch data
+my @cmd = (qw{ffprobe -show_entries frame -select_streams}, $stream_specifier, "-of", "json", $input);
+print STDERR "Executing command: @cmd\n";
+my $json_struct;
+{
+ open(FH, "-|", @cmd) or die "ffprobe command failed: $!\n";
+ local $/;
+ my $json_text = <FH>;
+ close FH;
+ die "ffprobe command failed" if $?;
+ eval { $json_struct = decode_json($json_text); };
+ die "JSON parsing error: $@\n" if $@;
+}
+
+# collect and print frame statistics per pict_type
+my %stats;
+my $frames = $json_struct->{frames};
+my $frame_count = 0;
+foreach my $frame (@{$frames}) {
+ my $type = $frame->{pict_type};
+ $frame->{count} = $frame_count++;
+ if (not $stats{$type}) {
+ $stats{$type}->{tmpfile} = File::Temp->new(SUFFIX => '.dat');
+ my $fn = $stats{$type}->{tmpfile}->filename;
+ open($stats{$type}->{fh}, ">", $fn) or die "Can't open $fn";
+ }
+
+ print { $stats{$type}->{fh} }
+ "$frame->{count} ", $frame->{pkt_size} * 8 / 1000, "\n";
+}
+foreach (keys %stats) { close $stats{$_}->{fh}; }
+
+# write gnuplot script
+my %type_color_map = (
+ "I" => "red",
+ "P" => "green",
+ "B" => "blue"
+ );
+
+my $gnuplot_script_tmpfile = File::Temp->new(SUFFIX => '.gnuplot');
+my $fn = $gnuplot_script_tmpfile->filename;
+open(FH, ">", $fn) or die "Couldn't open $fn: $!";
+print FH << "EOF";
+set title "video frame sizes"
+set xlabel "frame time"
+set ylabel "frame size (Kbits)"
+set grid
+set terminal "$gnuplot_terminal"
+EOF
+
+print FH "set output \"$gnuplot_output\"\n" if $gnuplot_output;
+print FH "plot";
+my $sep = "";
+foreach my $type (keys %stats) {
+ my $fn = $stats{$type}->{tmpfile}->filename;
+ print FH "$sep\"$fn\" title \"$type frames\" with impulses";
+ print FH " linecolor rgb \"$type_color_map{$type}\"" if $type_color_map{$type};
+ $sep = ", ";
+}
+close FH;
+
+# launch gnuplot with the generated script
+system ("gnuplot", "--persist", $gnuplot_script_tmpfile->filename);
diff --git a/tools/probetest.c b/tools/probetest.c
index 678f4dd3a7..74045eb498 100644
--- a/tools/probetest.c
+++ b/tools/probetest.c
@@ -1,20 +1,20 @@
/*
* 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
*/
@@ -23,9 +23,17 @@
#include "libavformat/avformat.h"
#include "libavcodec/put_bits.h"
#include "libavutil/lfg.h"
+#include "libavutil/timer.h"
-static int score_array[1000]; //this must be larger than the number of formats
+#define MAX_FORMATS 1000 //this must be larger than the number of formats
+static int score_array[MAX_FORMATS];
+static int64_t time_array[MAX_FORMATS];
static int failures = 0;
+static const char *single_format;
+
+#ifndef AV_READ_TIME
+#define AV_READ_TIME(x) 0
+#endif
static void probe(AVProbeData *pd, int type, int p, int size)
{
@@ -35,8 +43,13 @@ static void probe(AVProbeData *pd, int type, int p, int size)
while ((fmt = av_iformat_next(fmt))) {
if (fmt->flags & AVFMT_NOFILE)
continue;
- if (fmt->read_probe) {
- int score = fmt->read_probe(pd);
+ if (fmt->read_probe &&
+ (!single_format || !strcmp(single_format, fmt->name))
+ ) {
+ int score;
+ int64_t start = AV_READ_TIME();
+ score = fmt->read_probe(pd);
+ time_array[i] += AV_READ_TIME() - start;
if (score > score_array[i] && score > AVPROBE_SCORE_MAX / 4) {
score_array[i] = score;
fprintf(stderr,
@@ -49,12 +62,67 @@ static void probe(AVProbeData *pd, int type, int p, int size)
}
}
-int main(void)
+static void print_times(void)
+{
+ int i = 0;
+ AVInputFormat *fmt = NULL;
+
+ while ((fmt = av_iformat_next(fmt))) {
+ if (fmt->flags & AVFMT_NOFILE)
+ continue;
+ if (time_array[i] > 1000000) {
+ fprintf(stderr, "%12"PRIu64" cycles, %12s\n",
+ time_array[i], fmt->name);
+ }
+ i++;
+ }
+}
+
+static int read_int(char *arg) {
+ int ret;
+
+ if (!arg || !*arg)
+ return -1;
+ ret = strtol(arg, &arg, 0);
+ if (*arg)
+ return -1;
+ return ret;
+}
+
+int main(int argc, char **argv)
{
unsigned int p, i, type, size, retry;
- AVProbeData pd;
+ AVProbeData pd = { 0 };
AVLFG state;
PutBitContext pb;
+ int retry_count= 4097;
+ int max_size = 65537;
+ int j;
+
+ for (j = i = 1; i<argc; i++) {
+ if (!strcmp(argv[i], "-f") && i+1<argc && !single_format) {
+ single_format = argv[++i];
+ } else if (read_int(argv[i])>0 && j == 1) {
+ retry_count = read_int(argv[i]);
+ j++;
+ } else if (read_int(argv[i])>0 && j == 2) {
+ max_size = read_int(argv[i]);
+ j++;
+ } else {
+ fprintf(stderr, "probetest [-f <input format>] [<retry_count> [<max_size>]]\n");
+ return 1;
+ }
+ }
+
+ if (max_size > 1000000000U/8) {
+ fprintf(stderr, "max_size out of bounds\n");
+ return 1;
+ }
+
+ if (retry_count > 1000000000U) {
+ fprintf(stderr, "retry_count out of bounds\n");
+ return 1;
+ }
avcodec_register_all();
av_register_all();
@@ -62,14 +130,21 @@ int main(void)
av_lfg_init(&state, 0xdeadbeef);
pd.buf = NULL;
- for (size = 1; size < 65537; size *= 2) {
+ for (size = 1; size < max_size; size *= 2) {
pd.buf_size = size;
pd.buf = av_realloc(pd.buf, size + AVPROBE_PADDING_SIZE);
pd.filename = "";
+ if (!pd.buf) {
+ fprintf(stderr, "out of memory\n");
+ return 1;
+ }
+
+ memset(pd.buf, 0, size + AVPROBE_PADDING_SIZE);
+
fprintf(stderr, "testing size=%d\n", size);
- for (retry = 0; retry < 4097; retry += FFMAX(size, 32)) {
+ for (retry = 0; retry < retry_count; retry += FFMAX(size, 32)) {
for (type = 0; type < 4; type++) {
for (p = 0; p < 4096; p++) {
unsigned hist = 0;
@@ -122,5 +197,7 @@ int main(void)
}
}
}
+ if(AV_READ_TIME())
+ print_times();
return failures;
}
diff --git a/tools/qt-faststart.c b/tools/qt-faststart.c
index 0db5ca2138..97be019c58 100644
--- a/tools/qt-faststart.c
+++ b/tools/qt-faststart.c
@@ -8,7 +8,7 @@
* is in front of the data, thus facilitating network streaming.
*
* To compile this program, start from the base directory from which you
- * are building Libav and type:
+ * are building FFmpeg and type:
* make tools/qt-faststart
* The qt-faststart program will be built in the tools/ directory. If you
* do not build the program in this manner, correct results are not
@@ -83,7 +83,7 @@
#define CO64_ATOM QT_ATOM('c', 'o', '6', '4')
#define ATOM_PREAMBLE_SIZE 8
-#define COPY_BUFFER_SIZE 65536
+#define COPY_BUFFER_SIZE 33554432
int main(int argc, char *argv[])
{
@@ -102,12 +102,12 @@ int main(int argc, char *argv[])
uint32_t offset_count;
uint64_t current_offset;
int64_t start_offset = 0;
- unsigned char copy_buffer[COPY_BUFFER_SIZE];
+ unsigned char *copy_buffer = NULL;
int bytes_to_copy;
if (argc != 3) {
printf("Usage: qt-faststart <infile.mov> <outfile.mov>\n"
- "Note: alternatively you can use -movflags +faststart in avconv\n");
+ "Note: alternatively you can use -movflags +faststart in ffmpeg\n");
return 0;
}
@@ -324,9 +324,15 @@ int main(int argc, char *argv[])
}
/* copy the remainder of the infile, from offset 0 -> last_offset - 1 */
+ bytes_to_copy = MIN(COPY_BUFFER_SIZE, last_offset);
+ copy_buffer = malloc(bytes_to_copy);
+ if (!copy_buffer) {
+ printf("could not allocate %d bytes for copy_buffer\n", bytes_to_copy);
+ goto error_out;
+ }
printf(" copying rest of file...\n");
while (last_offset) {
- bytes_to_copy = MIN(COPY_BUFFER_SIZE, last_offset);
+ bytes_to_copy = MIN(bytes_to_copy, last_offset);
if (fread(copy_buffer, bytes_to_copy, 1, infile) != 1) {
perror(argv[1]);
@@ -343,6 +349,7 @@ int main(int argc, char *argv[])
fclose(outfile);
free(moov_atom);
free(ftyp_atom);
+ free(copy_buffer);
return 0;
@@ -353,5 +360,6 @@ error_out:
fclose(outfile);
free(moov_atom);
free(ftyp_atom);
+ free(copy_buffer);
return 1;
}
diff --git a/tools/seek_print.c b/tools/seek_print.c
new file mode 100644
index 0000000000..de876b487c
--- /dev/null
+++ b/tools/seek_print.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013 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 "config.h"
+#if HAVE_UNISTD_H
+#include <unistd.h> /* getopt */
+#endif
+
+#include "libavformat/avformat.h"
+#include "libavutil/timestamp.h"
+
+#if !HAVE_GETOPT
+#include "compat/getopt.c"
+#endif
+
+static void usage(int ret)
+{
+ fprintf(ret ? stderr : stdout,
+ "Usage: seek_print file [command ...]\n"
+ "Commands:\n"
+ " read\n"
+ " seek:stream:min_ts:ts:max_ts:flags\n"
+ );
+ exit(ret);
+}
+
+int main(int argc, char **argv)
+{
+ int opt, ret, stream, flags;
+ const char *filename;
+ AVFormatContext *avf = NULL;
+ int64_t min_ts, max_ts, ts;
+ AVPacket packet;
+
+ while ((opt = getopt(argc, argv, "h")) != -1) {
+ switch (opt) {
+ case 'h':
+ usage(0);
+ default:
+ usage(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (!argc)
+ usage(1);
+ filename = *argv;
+ argv++;
+ argc--;
+
+ av_register_all();
+ if ((ret = avformat_open_input(&avf, filename, NULL, NULL)) < 0) {
+ fprintf(stderr, "%s: %s\n", filename, av_err2str(ret));
+ return 1;
+ }
+ if ((ret = avformat_find_stream_info(avf, NULL)) < 0) {
+ fprintf(stderr, "%s: could not find codec parameters: %s\n", filename,
+ av_err2str(ret));
+ return 1;
+ }
+
+ for (; argc; argc--, argv++) {
+ if (!strcmp(*argv, "read")) {
+ ret = av_read_frame(avf, &packet);
+ if (ret < 0) {
+ printf("read: %d (%s)\n", ret, av_err2str(ret));
+ } else {
+ AVRational *tb = &avf->streams[packet.stream_index]->time_base;
+ printf("read: %d size=%d stream=%d dts=%s (%s) pts=%s (%s)\n",
+ ret, packet.size, packet.stream_index,
+ av_ts2str(packet.dts), av_ts2timestr(packet.dts, tb),
+ av_ts2str(packet.pts), av_ts2timestr(packet.pts, tb));
+ av_packet_unref(&packet);
+ }
+ } else if (sscanf(*argv, "seek:%i:%"SCNi64":%"SCNi64":%"SCNi64":%i",
+ &stream, &min_ts, &ts, &max_ts, &flags) == 5) {
+ ret = avformat_seek_file(avf, stream, min_ts, ts, max_ts, flags);
+ printf("seek: %d (%s)\n", ret, av_err2str(ret));
+ } else {
+ fprintf(stderr, "'%s': unknown command\n", *argv);
+ return 1;
+ }
+ }
+
+ avformat_close_input(&avf);
+
+ return 0;
+}
diff --git a/tools/sidxindex.c b/tools/sidxindex.c
index e740a94b98..be284610d5 100644
--- a/tools/sidxindex.c
+++ b/tools/sidxindex.c
@@ -1,20 +1,20 @@
/*
* Copyright (c) 2014 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
*/
@@ -157,8 +157,8 @@ static int handle_file(struct Tracks *tracks, const char *file)
err = AVERROR(ENOMEM);
goto fail;
}
- temp = av_realloc(tracks->tracks,
- sizeof(*tracks->tracks) * (tracks->nb_tracks + 1));
+ temp = av_realloc_array(tracks->tracks, tracks->nb_tracks + 1,
+ sizeof(*tracks->tracks));
if (!temp) {
av_free(track);
err = AVERROR(ENOMEM);
@@ -245,7 +245,7 @@ static int output_mpd(struct Tracks *tracks, const char *filename)
nb_tracks = nb_tracks_buf;
nb_sets = 2;
for (i = 0; i < 2; i++) {
- adaptation_sets[i] = av_malloc(sizeof(*adaptation_sets[i]) * tracks->nb_tracks);
+ adaptation_sets[i] = av_malloc_array(tracks->nb_tracks, sizeof(*adaptation_sets[i]));
if (!adaptation_sets[i]) {
ret = AVERROR(ENOMEM);
goto err;
diff --git a/tools/sofa2wavs.c b/tools/sofa2wavs.c
new file mode 100644
index 0000000000..1f1075b22f
--- /dev/null
+++ b/tools/sofa2wavs.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017 Paul B Mahol
+ *
+ * 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 <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <mysofa.h>
+
+int main(int argc, char **argv)
+{
+ struct MYSOFA_HRTF *hrtf;
+ int sample_rate;
+ int err, i, j;
+
+ if (argc < 3) {
+ printf("usage: %s input_SOFA_file output_directory\n", argv[0]);
+ return 1;
+ }
+
+ hrtf = mysofa_load(argv[1], &err);
+ if (!hrtf || err) {
+ printf("invalid input SOFA file: %s\n", argv[1]);
+ return 1;
+ }
+
+ if (hrtf->DataSamplingRate.elements != 1)
+ goto fail;
+ sample_rate = hrtf->DataSamplingRate.values[0];
+
+ err = mkdir(argv[2], 0744);
+ if (err)
+ goto fail;
+
+ err = chdir(argv[2]);
+ if (err)
+ goto fail;
+
+ for (i = 0; i < hrtf->M; i++) {
+ FILE *file;
+ int bps = 32;
+ int blkalign = 8;
+ int bytespersec = blkalign * sample_rate;
+ char filename[1024];
+ int azi = hrtf->SourcePosition.values[i * 3];
+ int ele = hrtf->SourcePosition.values[i * 3 + 1];
+ int dis = hrtf->SourcePosition.values[i * 3 + 2];
+ int size = 8 * hrtf->N;
+ int offset = i * 2 * hrtf->N;
+
+ snprintf(filename, sizeof(filename), "azi_%d_ele_%d_dis_%d.wav", azi, ele, dis);
+ file = fopen(filename, "w+");
+ fwrite("RIFF", 4, 1, file);
+ fwrite("\xFF\xFF\xFF\xFF", 4, 1, file);
+ fwrite("WAVE", 4, 1, file);
+ fwrite("fmt ", 4, 1, file);
+ fwrite("\x10\x00\00\00", 4, 1, file);
+ fwrite("\x03\x00", 2, 1, file);
+ fwrite("\x02\x00", 2, 1, file);
+ fwrite(&sample_rate, 4, 1, file);
+ fwrite(&bytespersec, 4, 1, file);
+ fwrite(&blkalign, 2, 1, file);
+ fwrite(&bps, 2, 1, file);
+ fwrite("data", 4, 1, file);
+ fwrite(&size, 4, 1, file);
+
+ for (j = 0; j < hrtf->N; j++) {
+ float l, r;
+
+ l = hrtf->DataIR.values[offset + j];
+ r = hrtf->DataIR.values[offset + j + hrtf->N];
+ fwrite(&l, 4, 1, file);
+ fwrite(&r, 4, 1, file);
+ }
+ fclose(file);
+ }
+
+fail:
+ mysofa_free(hrtf);
+
+ return 0;
+}
diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c
new file mode 100644
index 0000000000..62d62a9de3
--- /dev/null
+++ b/tools/target_dec_fuzzer.c
@@ -0,0 +1,240 @@
+/*
+ * 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
+ */
+
+/* Targeted fuzzer that targets specific codecs depending on two
+ compile-time flags.
+ INSTRUCTIONS:
+
+ * Get the very fresh clang, e.g. see http://libfuzzer.info#versions
+ * Get and build libFuzzer:
+ svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer
+ ./Fuzzer/build.sh
+ * build ffmpeg for fuzzing:
+ FLAGS="-fsanitize=address -fsanitize-coverage=trace-pc-guard,trace-cmp -g" CC="clang $FLAGS" CXX="clang++ $FLAGS" ./configure --disable-x86asm
+ make clean && make -j
+ * build the fuzz target.
+ Choose the value of FFMPEG_CODEC (e.g. AV_CODEC_ID_DVD_SUBTITLE) and
+ choose one of FUZZ_FFMPEG_VIDEO, FUZZ_FFMPEG_AUDIO, FUZZ_FFMPEG_SUBTITLE.
+ clang -fsanitize=address -fsanitize-coverage=trace-pc-guard,trace-cmp tools/target_dec_fuzzer.c -o target_dec_fuzzer -I. -DFFMPEG_CODEC=AV_CODEC_ID_MPEG1VIDEO -DFUZZ_FFMPEG_VIDEO ../../libfuzzer/libFuzzer.a -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavresample -Llibavutil -Llibpostproc -Llibswscale -Llibswresample -Wl,--as-needed -Wl,-z,noexecstack -Wl,--warn-common -Wl,-rpath-link=libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil:libavresample -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -ldl -lxcb -lxcb-shm -lxcb -lxcb-xfixes -lxcb -lxcb-shape -lxcb -lX11 -lasound -lm -lbz2 -lz -pthread
+ * create a corpus directory and put some samples there (empty dir is ok too):
+ mkdir CORPUS && cp some-files CORPUS
+
+ * Run fuzzing:
+ ./target_dec_fuzzer -max_len=100000 CORPUS
+
+ More info:
+ http://libfuzzer.info
+ http://tutorial.libfuzzer.info
+ https://github.com/google/oss-fuzz
+ http://lcamtuf.coredump.cx/afl/
+ https://security.googleblog.com/2016/08/guided-in-process-fuzzing-of-chrome.html
+*/
+
+#include "config.h"
+#include "libavutil/avassert.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/intreadwrite.h"
+
+#include "libavcodec/avcodec.h"
+#include "libavcodec/bytestream.h"
+#include "libavformat/avformat.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
+
+static void error(const char *err)
+{
+ fprintf(stderr, "%s", err);
+ exit(1);
+}
+
+static AVCodec *c = NULL;
+static AVCodec *AVCodecInitialize(enum AVCodecID codec_id)
+{
+ AVCodec *res;
+
+ res = avcodec_find_decoder(codec_id);
+ if (!res)
+ error("Failed to find decoder");
+ return res;
+}
+
+static int subtitle_handler(AVCodecContext *avctx, void *frame,
+ int *got_sub_ptr, AVPacket *avpkt)
+{
+ AVSubtitle sub;
+ int ret = avcodec_decode_subtitle2(avctx, &sub, got_sub_ptr, avpkt);
+ if (ret >= 0 && *got_sub_ptr)
+ avsubtitle_free(&sub);
+ return ret;
+}
+
+// Class to handle buffer allocation and resize for each frame
+typedef struct FuzzDataBuffer {
+ size_t size_;
+ uint8_t *data_;
+} FuzzDataBuffer;
+
+static void FDBCreate(FuzzDataBuffer *FDB) {
+ FDB->size_ = 0x1000;
+ FDB->data_ = av_malloc(FDB->size_);
+ if (!FDB->data_)
+ error("Failed memory allocation");
+}
+
+static void FDBDesroy(FuzzDataBuffer *FDB) { av_free(FDB->data_); }
+
+static void FDBRealloc(FuzzDataBuffer *FDB, size_t size) {
+ size_t needed = size + AV_INPUT_BUFFER_PADDING_SIZE;
+ av_assert0(needed > size);
+ if (needed > FDB->size_) {
+ av_free(FDB->data_);
+ FDB->size_ = needed;
+ FDB->data_ = av_malloc(FDB->size_);
+ if (!FDB->data_)
+ error("Failed memory allocation");
+ }
+}
+
+static void FDBPrepare(FuzzDataBuffer *FDB, AVPacket *dst, const uint8_t *data,
+ size_t size)
+{
+ FDBRealloc(FDB, size);
+ memcpy(FDB->data_, data, size);
+ size_t padd = FDB->size_ - size;
+ if (padd > AV_INPUT_BUFFER_PADDING_SIZE)
+ padd = AV_INPUT_BUFFER_PADDING_SIZE;
+ memset(FDB->data_ + size, 0, padd);
+ av_init_packet(dst);
+ dst->data = FDB->data_;
+ dst->size = size;
+}
+
+// Ensure we don't loop forever
+const uint32_t maxiteration = 8096;
+
+static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL;
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ const uint64_t fuzz_tag = FUZZ_TAG;
+ FuzzDataBuffer buffer;
+ const uint8_t *last = data;
+ const uint8_t *end = data + size;
+ uint32_t it = 0;
+ int (*decode_handler)(AVCodecContext *avctx, AVFrame *picture,
+ int *got_picture_ptr,
+ const AVPacket *avpkt) = NULL;
+
+ if (!c) {
+#ifdef FFMPEG_DECODER
+#define DECODER_SYMBOL0(CODEC) ff_##CODEC##_decoder
+#define DECODER_SYMBOL(CODEC) DECODER_SYMBOL0(CODEC)
+ extern AVCodec DECODER_SYMBOL(FFMPEG_DECODER);
+ avcodec_register(&DECODER_SYMBOL(FFMPEG_DECODER));
+
+ c = &DECODER_SYMBOL(FFMPEG_DECODER);
+#else
+ avcodec_register_all();
+ c = AVCodecInitialize(FFMPEG_CODEC); // Done once.
+#endif
+ av_log_set_level(AV_LOG_PANIC);
+ }
+
+ switch (c->type) {
+ case AVMEDIA_TYPE_AUDIO : decode_handler = avcodec_decode_audio4; break;
+ case AVMEDIA_TYPE_VIDEO : decode_handler = avcodec_decode_video2; break;
+ case AVMEDIA_TYPE_SUBTITLE: decode_handler = subtitle_handler ; break;
+ }
+
+ AVCodecContext* ctx = avcodec_alloc_context3(NULL);
+ if (!ctx)
+ error("Failed memory allocation");
+
+ ctx->max_pixels = 4096 * 4096; //To reduce false positive OOM and hangs
+
+ if (size > 1024) {
+ GetByteContext gbc;
+ bytestream2_init(&gbc, data + size - 1024, 1024);
+ ctx->width = bytestream2_get_le32(&gbc);
+ ctx->height = bytestream2_get_le32(&gbc);
+ ctx->bit_rate = bytestream2_get_le64(&gbc);
+ ctx->bits_per_coded_sample = bytestream2_get_le32(&gbc);
+ if (av_image_check_size(ctx->width, ctx->height, 0, ctx))
+ ctx->width = ctx->height = 0;
+ size -= 1024;
+ }
+
+ int res = avcodec_open2(ctx, c, NULL);
+ if (res < 0) {
+ av_free(ctx);
+ return 0; // Failure of avcodec_open2() does not imply that a issue was found
+ }
+
+ FDBCreate(&buffer);
+ int got_frame;
+ AVFrame *frame = av_frame_alloc();
+ if (!frame)
+ error("Failed memory allocation");
+
+ // Read very simple container
+ AVPacket avpkt;
+ while (data < end && it < maxiteration) {
+ // Search for the TAG
+ while (data + sizeof(fuzz_tag) < end) {
+ if (data[0] == (fuzz_tag & 0xFF) && AV_RN64(data) == fuzz_tag)
+ break;
+ data++;
+ }
+ if (data + sizeof(fuzz_tag) > end)
+ data = end;
+
+ FDBPrepare(&buffer, &avpkt, last, data - last);
+ data += sizeof(fuzz_tag);
+ last = data;
+
+ // Iterate through all data
+ while (avpkt.size > 0 && it++ < maxiteration) {
+ av_frame_unref(frame);
+ int ret = decode_handler(ctx, frame, &got_frame, &avpkt);
+
+ if (it > 20)
+ ctx->error_concealment = 0;
+
+ if (ret <= 0 || ret > avpkt.size)
+ break;
+ if (ctx->codec_type != AVMEDIA_TYPE_AUDIO)
+ ret = avpkt.size;
+ avpkt.data += ret;
+ avpkt.size -= ret;
+ }
+ }
+
+ av_init_packet(&avpkt);
+ avpkt.data = NULL;
+ avpkt.size = 0;
+
+ do {
+ got_frame = 0;
+ decode_handler(ctx, frame, &got_frame, &avpkt);
+ } while (got_frame == 1 && it++ < maxiteration);
+
+ av_frame_free(&frame);
+ avcodec_free_context(&ctx);
+ av_freep(&ctx);
+ FDBDesroy(&buffer);
+ return 0;
+}
diff --git a/tools/trasher.c b/tools/trasher.c
index 35625e9a62..0b89cfed87 100644
--- a/tools/trasher.c
+++ b/tools/trasher.c
@@ -1,20 +1,20 @@
/*
* Copyright (c) 2007 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
*/
@@ -30,6 +30,15 @@ static uint32_t ran(void)
return state = state * 1664525 + 1013904223;
}
+static void checked_seek(FILE *stream, int64_t offset, int whence)
+{
+ offset = fseek(stream, offset, whence);
+ if (offset < 0) {
+ fprintf(stderr, "seek failed\n");
+ exit(1);
+ }
+}
+
int main(int argc, char **argv)
{
FILE *f;
@@ -49,14 +58,14 @@ int main(int argc, char **argv)
maxburst = atoi(argv[3]);
state = atoi(argv[4]);
- fseek(f, 0, SEEK_END);
+ checked_seek(f, 0, SEEK_END);
length = ftell(f);
- fseek(f, 0, SEEK_SET);
+ checked_seek(f, 0, SEEK_SET);
while (count--) {
int burst = 1 + ran() * (uint64_t) (abs(maxburst) - 1) / UINT32_MAX;
int pos = ran() * (uint64_t) length / UINT32_MAX;
- fseek(f, pos, SEEK_SET);
+ checked_seek(f, pos, SEEK_SET);
if (maxburst < 0)
burst = -maxburst;
diff --git a/tools/uncoded_frame.c b/tools/uncoded_frame.c
new file mode 100644
index 0000000000..3ca2ba4bbe
--- /dev/null
+++ b/tools/uncoded_frame.c
@@ -0,0 +1,279 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "libavutil/avassert.h"
+#include "libavdevice/avdevice.h"
+#include "libavfilter/avfilter.h"
+#include "libavfilter/buffersink.h"
+#include "libavformat/avformat.h"
+
+typedef struct {
+ AVFormatContext *mux;
+ AVStream *stream;
+ AVFilterContext *sink;
+ AVFilterLink *link;
+} Stream;
+
+static int create_sink(Stream *st, AVFilterGraph *graph,
+ AVFilterContext *f, int idx)
+{
+ enum AVMediaType type = avfilter_pad_get_type(f->output_pads, idx);
+ const char *sink_name;
+ int ret;
+
+ switch (type) {
+ case AVMEDIA_TYPE_VIDEO: sink_name = "buffersink"; break;
+ case AVMEDIA_TYPE_AUDIO: sink_name = "abuffersink"; break;
+ default:
+ av_log(NULL, AV_LOG_ERROR, "Stream type not supported\n");
+ return AVERROR(EINVAL);
+ }
+ ret = avfilter_graph_create_filter(&st->sink,
+ avfilter_get_by_name(sink_name),
+ NULL, NULL, NULL, graph);
+ if (ret < 0)
+ return ret;
+ ret = avfilter_link(f, idx, st->sink, 0);
+ if (ret < 0)
+ return ret;
+ st->link = st->sink->inputs[0];
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ char *in_graph_desc, **out_dev_name;
+ int nb_out_dev = 0, nb_streams = 0;
+ AVFilterGraph *in_graph = NULL;
+ Stream *streams = NULL, *st;
+ AVFrame *frame = NULL;
+ int i, j, run = 1, ret;
+
+ //av_log_set_level(AV_LOG_DEBUG);
+
+ if (argc < 3) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Usage: %s filter_graph dev:out [dev2:out2...]\n\n"
+ "Examples:\n"
+ "%s movie=file.nut:s=v+a xv:- alsa:default\n"
+ "%s movie=file.nut:s=v+a uncodedframecrc:pipe:0\n",
+ argv[0], argv[0], argv[0]);
+ exit(1);
+ }
+ in_graph_desc = argv[1];
+ out_dev_name = argv + 2;
+ nb_out_dev = argc - 2;
+
+ av_register_all();
+ avdevice_register_all();
+ avfilter_register_all();
+
+ /* Create input graph */
+ if (!(in_graph = avfilter_graph_alloc())) {
+ ret = AVERROR(ENOMEM);
+ av_log(NULL, AV_LOG_ERROR, "Unable to alloc graph graph: %s\n",
+ av_err2str(ret));
+ goto fail;
+ }
+ ret = avfilter_graph_parse_ptr(in_graph, in_graph_desc, NULL, NULL, NULL);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Unable to parse graph: %s\n",
+ av_err2str(ret));
+ goto fail;
+ }
+ nb_streams = 0;
+ for (i = 0; i < in_graph->nb_filters; i++) {
+ AVFilterContext *f = in_graph->filters[i];
+ for (j = 0; j < f->nb_inputs; j++) {
+ if (!f->inputs[j]) {
+ av_log(NULL, AV_LOG_ERROR, "Graph has unconnected inputs\n");
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+ }
+ for (j = 0; j < f->nb_outputs; j++)
+ if (!f->outputs[j])
+ nb_streams++;
+ }
+ if (!nb_streams) {
+ av_log(NULL, AV_LOG_ERROR, "Graph has no output stream\n");
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+ if (nb_out_dev != 1 && nb_out_dev != nb_streams) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Graph has %d output streams, %d devices given\n",
+ nb_streams, nb_out_dev);
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+
+ if (!(streams = av_calloc(nb_streams, sizeof(*streams)))) {
+ ret = AVERROR(ENOMEM);
+ av_log(NULL, AV_LOG_ERROR, "Could not allocate streams\n");
+ }
+ st = streams;
+ for (i = 0; i < in_graph->nb_filters; i++) {
+ AVFilterContext *f = in_graph->filters[i];
+ for (j = 0; j < f->nb_outputs; j++) {
+ if (!f->outputs[j]) {
+ if ((ret = create_sink(st++, in_graph, f, j)) < 0)
+ goto fail;
+ }
+ }
+ }
+ av_assert0(st - streams == nb_streams);
+ if ((ret = avfilter_graph_config(in_graph, NULL)) < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Failed to configure graph\n");
+ goto fail;
+ }
+
+ /* Create output devices */
+ for (i = 0; i < nb_out_dev; i++) {
+ char *fmt = NULL, *dev = out_dev_name[i];
+ st = &streams[i];
+ if ((dev = strchr(dev, ':'))) {
+ *(dev++) = 0;
+ fmt = out_dev_name[i];
+ }
+ ret = avformat_alloc_output_context2(&st->mux, NULL, fmt, dev);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Failed to allocate output: %s\n",
+ av_err2str(ret));
+ goto fail;
+ }
+ if (!(st->mux->oformat->flags & AVFMT_NOFILE)) {
+ ret = avio_open2(&st->mux->pb, st->mux->filename, AVIO_FLAG_WRITE,
+ NULL, NULL);
+ if (ret < 0) {
+ av_log(st->mux, AV_LOG_ERROR, "Failed to init output: %s\n",
+ av_err2str(ret));
+ goto fail;
+ }
+ }
+ }
+ for (; i < nb_streams; i++)
+ streams[i].mux = streams[0].mux;
+
+ /* Create output device streams */
+ for (i = 0; i < nb_streams; i++) {
+ st = &streams[i];
+ if (!(st->stream = avformat_new_stream(st->mux, NULL))) {
+ ret = AVERROR(ENOMEM);
+ av_log(NULL, AV_LOG_ERROR, "Failed to create output stream\n");
+ goto fail;
+ }
+ st->stream->codec->codec_type = st->link->type;
+ st->stream->time_base = st->stream->codec->time_base =
+ st->link->time_base;
+ switch (st->link->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ st->stream->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
+ st->stream->avg_frame_rate =
+ st->stream-> r_frame_rate = av_buffersink_get_frame_rate(st->sink);
+ st->stream->codec->width = st->link->w;
+ st->stream->codec->height = st->link->h;
+ st->stream->codec->sample_aspect_ratio = st->link->sample_aspect_ratio;
+ st->stream->codec->pix_fmt = st->link->format;
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ st->stream->codec->channel_layout = st->link->channel_layout;
+ st->stream->codec->channels = avfilter_link_get_channels(st->link);
+ st->stream->codec->sample_rate = st->link->sample_rate;
+ st->stream->codec->sample_fmt = st->link->format;
+ st->stream->codec->codec_id =
+ av_get_pcm_codec(st->stream->codec->sample_fmt, -1);
+ break;
+ default:
+ av_assert0(!"reached");
+ }
+ }
+
+ /* Init output devices */
+ for (i = 0; i < nb_out_dev; i++) {
+ st = &streams[i];
+ if ((ret = avformat_write_header(st->mux, NULL)) < 0) {
+ av_log(st->mux, AV_LOG_ERROR, "Failed to init output: %s\n",
+ av_err2str(ret));
+ goto fail;
+ }
+ }
+
+ /* Check output devices */
+ for (i = 0; i < nb_streams; i++) {
+ st = &streams[i];
+ ret = av_write_uncoded_frame_query(st->mux, st->stream->index);
+ if (ret < 0) {
+ av_log(st->mux, AV_LOG_ERROR,
+ "Uncoded frames not supported on stream #%d: %s\n",
+ i, av_err2str(ret));
+ goto fail;
+ }
+ }
+
+ while (run) {
+ ret = avfilter_graph_request_oldest(in_graph);
+ if (ret < 0) {
+ if (ret == AVERROR_EOF) {
+ run = 0;
+ } else {
+ av_log(NULL, AV_LOG_ERROR, "Error filtering: %s\n",
+ av_err2str(ret));
+ break;
+ }
+ }
+ for (i = 0; i < nb_streams; i++) {
+ st = &streams[i];
+ while (1) {
+ if (!frame && !(frame = av_frame_alloc())) {
+ ret = AVERROR(ENOMEM);
+ av_log(NULL, AV_LOG_ERROR, "Could not allocate frame\n");
+ goto fail;
+ }
+ ret = av_buffersink_get_frame_flags(st->sink, frame,
+ AV_BUFFERSINK_FLAG_NO_REQUEST);
+ if (ret < 0) {
+ if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
+ av_log(NULL, AV_LOG_WARNING, "Error in sink: %s\n",
+ av_err2str(ret));
+ break;
+ }
+ if (frame->pts != AV_NOPTS_VALUE)
+ frame->pts = av_rescale_q(frame->pts,
+ st->link ->time_base,
+ st->stream->time_base);
+ ret = av_interleaved_write_uncoded_frame(st->mux,
+ st->stream->index,
+ frame);
+ frame = NULL;
+ if (ret < 0) {
+ av_log(st->stream->codec, AV_LOG_ERROR,
+ "Error writing frame: %s\n", av_err2str(ret));
+ goto fail;
+ }
+ }
+ }
+ }
+ ret = 0;
+
+ for (i = 0; i < nb_out_dev; i++) {
+ st = &streams[i];
+ av_write_trailer(st->mux);
+ }
+
+fail:
+ av_frame_free(&frame);
+ avfilter_graph_free(&in_graph);
+ if (streams) {
+ for (i = 0; i < nb_out_dev; i++) {
+ st = &streams[i];
+ if (st->mux) {
+ if (st->mux->pb)
+ avio_closep(&st->mux->pb);
+ avformat_free_context(st->mux);
+ }
+ }
+ }
+ av_freep(&streams);
+ return ret < 0;
+}
diff --git a/tools/unwrap-diff b/tools/unwrap-diff
new file mode 100755
index 0000000000..ccea99b7b4
--- /dev/null
+++ b/tools/unwrap-diff
@@ -0,0 +1,2 @@
+#!/bin/sh
+tr '\n' '\001' | sed 's/\x01\x01/\x01 \x01/g' | sed 's/\x01\([^-+ @]\)/ \1/g' | tr '\001' '\n'
diff --git a/tools/yuvcmp.c b/tools/yuvcmp.c
new file mode 100644
index 0000000000..65b1794d07
--- /dev/null
+++ b/tools/yuvcmp.c
@@ -0,0 +1,184 @@
+/*
+ * originally by Andreas Ă–man (andoma)
+ * some changes by Alexander Strange
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+int
+main(int argc, char **argv)
+{
+ int fd[2];
+ int print_pixels = 0;
+ int dump_blocks = 0;
+
+ int width;
+ int height;
+ int to_skip = 0;
+
+ if (argc < 6) {
+ fprintf(stderr, "%s [YUV file 1] [YUV file 2] width height pixelcmp|blockdump (# to skip)\n", argv[0]);
+ return 1;
+ }
+
+ width = atoi(argv[3]);
+ height = atoi(argv[4]);
+ if (argc > 6)
+ to_skip = atoi(argv[6]);
+
+ uint8_t *Y[2], *C[2][2];
+ int i, v, c, p;
+ int lsiz = width * height;
+ int csiz = width * height / 4;
+ int x, y;
+ int cwidth = width / 2;
+ int fr = to_skip;
+ int mb;
+ char *mberrors;
+ int mb_x, mb_y;
+ uint8_t *a;
+ uint8_t *b;
+ int die = 0;
+
+ print_pixels = strstr(argv[5], "pixelcmp") ? 1 : 0;
+ dump_blocks = strstr(argv[5], "blockdump") ? 1 : 0;
+
+ for(i = 0; i < 2; i++) {
+ Y[i] = malloc(lsiz);
+ C[0][i] = malloc(csiz);
+ C[1][i] = malloc(csiz);
+
+ fd[i] = open(argv[1 + i], O_RDONLY);
+ if(fd[i] == -1) {
+ perror("open");
+ exit(1);
+ }
+ fcntl(fd[i], F_NOCACHE, 1);
+
+ if (to_skip)
+ lseek(fd[i], to_skip * (lsiz + 2*csiz), SEEK_SET);
+ }
+
+ mb_x = width / 16;
+ mb_y = height / 16;
+
+ mberrors = malloc(mb_x * mb_y);
+
+ while(!die) {
+ memset(mberrors, 0, mb_x * mb_y);
+
+ printf("Loading frame %d\n", ++fr);
+
+ for(i = 0; i < 2; i++) {
+ v = read(fd[i], Y[i], lsiz);
+ if(v != lsiz) {
+ fprintf(stderr, "Unable to read Y from file %d, exiting\n", i + 1);
+ return 1;
+ }
+ }
+
+
+ for(c = 0; c < lsiz; c++) {
+ if(Y[0][c] != Y[1][c]) {
+ x = c % width;
+ y = c / width;
+
+ mb = x / 16 + (y / 16) * mb_x;
+
+ if(print_pixels)
+ printf("Luma diff 0x%02x != 0x%02x at pixel (%4d,%-4d) mb(%d,%d) #%d\n",
+ Y[0][c],
+ Y[1][c],
+ x, y,
+ x / 16,
+ y / 16,
+ mb);
+
+ mberrors[mb] |= 1;
+ }
+ }
+
+ /* Chroma planes */
+
+ for(p = 0; p < 2; p++) {
+
+ for(i = 0; i < 2; i++) {
+ v = read(fd[i], C[p][i], csiz);
+ if(v != csiz) {
+ fprintf(stderr, "Unable to read %c from file %d, exiting\n",
+ "UV"[p], i + 1);
+ return 1;
+ }
+ }
+
+ for(c = 0; c < csiz; c++) {
+ if(C[p][0][c] != C[p][1][c]) {
+ x = c % cwidth;
+ y = c / cwidth;
+
+ mb = x / 8 + (y / 8) * mb_x;
+
+ mberrors[mb] |= 2 << p;
+
+ if(print_pixels)
+
+ printf("c%c diff 0x%02x != 0x%02x at pixel (%4d,%-4d) "
+ "mb(%3d,%-3d) #%d\n",
+ p ? 'r' : 'b',
+ C[p][0][c],
+ C[p][1][c],
+
+ x, y,
+ x / 8,
+ y / 8,
+ x / 8 + y / 8 * cwidth / 8);
+ }
+ }
+ }
+
+ for(i = 0; i < mb_x * mb_y; i++) {
+ x = i % mb_x;
+ y = i / mb_x;
+
+ if(mberrors[i]) {
+ die = 1;
+
+ printf("MB (%3d,%-3d) %4d %d %c%c%c damaged\n",
+ x, y, i, mberrors[i],
+ mberrors[i] & 1 ? 'Y' : ' ',
+ mberrors[i] & 2 ? 'U' : ' ',
+ mberrors[i] & 4 ? 'V' : ' ');
+
+ if(dump_blocks) {
+ a = Y[0] + x * 16 + y * 16 * width;
+ b = Y[1] + x * 16 + y * 16 * width;
+
+ for(y = 0; y < 16; y++) {
+ printf("%c ", "TB"[y&1]);
+ for(x = 0; x < 16; x++)
+ printf("%02x%c", a[x + y * width],
+ a[x + y * width] != b[x + y * width] ? '<' : ' ');
+
+ printf("| ");
+ for(x = 0; x < 16; x++)
+ printf("%02x%c", b[x + y * width],
+ a[x + y * width] != b[x + y * width] ? '<' : ' ');
+
+ printf("\n");
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/tools/zmqsend.c b/tools/zmqsend.c
new file mode 100644
index 0000000000..7bd7fe4199
--- /dev/null
+++ b/tools/zmqsend.c
@@ -0,0 +1,168 @@
+/*
+ * 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
+ */
+
+#include "config.h"
+
+#include <zmq.h>
+
+#include "libavutil/mem.h"
+#include "libavutil/bprint.h"
+
+#if HAVE_UNISTD_H
+#include <unistd.h> /* getopt */
+#endif
+
+#if !HAVE_GETOPT
+#include "compat/getopt.c"
+#endif
+
+/**
+ * @file
+ * zmq message sender example, meant to be used with the zmq filters
+ */
+
+static void usage(void)
+{
+ printf("send message to ZMQ recipient, to use with the zmq filters\n");
+ printf("usage: zmqsend [OPTIONS]\n");
+ printf("\n"
+ "Options:\n"
+ "-b ADDRESS set bind address\n"
+ "-h print this help\n"
+ "-i INFILE set INFILE as input file, stdin if omitted\n");
+}
+
+int main(int argc, char **argv)
+{
+ AVBPrint src;
+ char *src_buf, *recv_buf;
+ int c;
+ int recv_buf_size, ret = 0;
+ void *zmq_ctx, *socket;
+ const char *bind_address = "tcp://localhost:5555";
+ const char *infilename = NULL;
+ FILE *infile = NULL;
+ zmq_msg_t msg;
+
+ while ((c = getopt(argc, argv, "b:hi:")) != -1) {
+ switch (c) {
+ case 'b':
+ bind_address = optarg;
+ break;
+ case 'h':
+ usage();
+ return 0;
+ case 'i':
+ infilename = optarg;
+ break;
+ case '?':
+ return 1;
+ }
+ }
+
+ if (!infilename || !strcmp(infilename, "-")) {
+ infilename = "stdin";
+ infile = stdin;
+ } else {
+ infile = fopen(infilename, "r");
+ }
+ if (!infile) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Impossible to open input file '%s': %s\n", infilename, strerror(errno));
+ return 1;
+ }
+
+ zmq_ctx = zmq_ctx_new();
+ if (!zmq_ctx) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Could not create ZMQ context: %s\n", zmq_strerror(errno));
+ return 1;
+ }
+
+ socket = zmq_socket(zmq_ctx, ZMQ_REQ);
+ if (!socket) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Could not create ZMQ socket: %s\n", zmq_strerror(errno));
+ ret = 1;
+ goto end;
+ }
+
+ if (zmq_connect(socket, bind_address) == -1) {
+ av_log(NULL, AV_LOG_ERROR, "Could not bind ZMQ responder to address '%s': %s\n",
+ bind_address, zmq_strerror(errno));
+ ret = 1;
+ goto end;
+ }
+
+ /* grab the input and store it in src */
+ av_bprint_init(&src, 1, AV_BPRINT_SIZE_UNLIMITED);
+ while ((c = fgetc(infile)) != EOF)
+ av_bprint_chars(&src, c, 1);
+ av_bprint_chars(&src, 0, 1);
+
+ if (!av_bprint_is_complete(&src)) {
+ av_log(NULL, AV_LOG_ERROR, "Could not allocate a buffer for the source string\n");
+ av_bprint_finalize(&src, NULL);
+ ret = 1;
+ goto end;
+ }
+ av_bprint_finalize(&src, &src_buf);
+
+ if (zmq_send(socket, src_buf, strlen(src_buf), 0) == -1) {
+ av_log(NULL, AV_LOG_ERROR, "Could not send message: %s\n", zmq_strerror(errno));
+ ret = 1;
+ goto end;
+ }
+
+ if (zmq_msg_init(&msg) == -1) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Could not initialize receiving message: %s\n", zmq_strerror(errno));
+ ret = 1;
+ goto end;
+ }
+
+ if (zmq_msg_recv(&msg, socket, 0) == -1) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Could not receive message: %s\n", zmq_strerror(errno));
+ zmq_msg_close(&msg);
+ ret = 1;
+ goto end;
+ }
+
+ recv_buf_size = zmq_msg_size(&msg) + 1;
+ recv_buf = av_malloc(recv_buf_size);
+ if (!recv_buf) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Could not allocate receiving message buffer\n");
+ zmq_msg_close(&msg);
+ ret = 1;
+ goto end;
+ }
+ memcpy(recv_buf, zmq_msg_data(&msg), recv_buf_size);
+ recv_buf[recv_buf_size-1] = 0;
+ printf("%s\n", recv_buf);
+ zmq_msg_close(&msg);
+ av_free(recv_buf);
+
+end:
+ zmq_close(socket);
+ zmq_ctx_destroy(zmq_ctx);
+ return ret;
+}
diff --git a/tools/zmqshell.py b/tools/zmqshell.py
new file mode 100755
index 0000000000..a7d1126006
--- /dev/null
+++ b/tools/zmqshell.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python2
+
+import sys, zmq, cmd
+
+class LavfiCmd(cmd.Cmd):
+ prompt = 'lavfi> '
+
+ def __init__(self, bind_address):
+ context = zmq.Context()
+ self.requester = context.socket(zmq.REQ)
+ self.requester.connect(bind_address)
+ cmd.Cmd.__init__(self)
+
+ def onecmd(self, cmd):
+ if cmd == 'EOF':
+ sys.exit(0)
+ print 'Sending command:[%s]' % cmd
+ self.requester.send(cmd)
+ message = self.requester.recv()
+ print 'Received reply:[%s]' % message
+
+try:
+ bind_address = sys.argv[1] if len(sys.argv) > 1 else "tcp://localhost:5555"
+ LavfiCmd(bind_address).cmdloop('FFmpeg libavfilter interactive shell')
+except KeyboardInterrupt:
+ pass