diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/aviocat.c | 8 | ||||
-rwxr-xr-x | tools/bisect-create | 46 | ||||
-rw-r--r-- | tools/bookmarklets.html | 55 | ||||
-rw-r--r-- | tools/build_libstagefright | 58 | ||||
-rwxr-xr-x | tools/clean-diff | 11 | ||||
-rw-r--r-- | tools/crypto_bench.c | 358 | ||||
-rw-r--r-- | tools/cws2fws.c | 14 | ||||
-rw-r--r-- | tools/enum_options.c | 143 | ||||
-rw-r--r-- | tools/ffescape.c | 180 | ||||
-rw-r--r-- | tools/ffeval.c | 139 | ||||
-rw-r--r-- | tools/ffhash.c | 149 | ||||
-rw-r--r-- | tools/fourcc2pixfmt.c | 123 | ||||
-rw-r--r-- | tools/graph2dot.c | 38 | ||||
-rw-r--r-- | tools/ismindex.c | 22 | ||||
-rwxr-xr-x | tools/make_chlayout_test | 114 | ||||
-rwxr-xr-x | tools/missing_codec_desc | 37 | ||||
-rwxr-xr-x | tools/normalize.py | 33 | ||||
-rwxr-xr-x | tools/patcheck | 12 | ||||
-rw-r--r-- | tools/pktdumper.c | 8 | ||||
-rwxr-xr-x | tools/plotframes | 164 | ||||
-rw-r--r-- | tools/probetest.c | 33 | ||||
-rw-r--r-- | tools/qt-faststart.c | 63 | ||||
-rw-r--r-- | tools/seek_print.c | 105 | ||||
-rw-r--r-- | tools/trasher.c | 13 | ||||
-rwxr-xr-x | tools/unwrap-diff | 2 | ||||
-rw-r--r-- | tools/yuvcmp.c | 182 | ||||
-rw-r--r-- | tools/zmqsend.c | 167 | ||||
-rwxr-xr-x | tools/zmqshell.py | 26 |
28 files changed, 2230 insertions, 73 deletions
diff --git a/tools/aviocat.c b/tools/aviocat.c index 52a96bde2f..e161d58603 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..9800ab5aef --- /dev/null +++ b/tools/bookmarklets.html @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<html> +<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> + +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. + +<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 < 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/build_libstagefright b/tools/build_libstagefright new file mode 100644 index 0000000000..8b3a0930f9 --- /dev/null +++ b/tools/build_libstagefright @@ -0,0 +1,58 @@ +#!/bin/bash + +if [ "$NDK" = "" ]; then + echo NDK variable not set, assuming ${HOME}/android-ndk + export NDK=${HOME}/android-ndk +fi + +echo "Fetching Android system headers" +git clone --depth=1 --branch gingerbread-release git://github.com/CyanogenMod/android_frameworks_base.git ../android-source/frameworks/base +git clone --depth=1 --branch gingerbread-release git://github.com/CyanogenMod/android_system_core.git ../android-source/system/core + +echo "Fetching Android libraries for linking" +# Libraries from any froyo/gingerbread device/emulator should work +# fine, since the symbols used should be available on most of them. +if [ ! -d "../android-libs" ]; then + if [ ! -f "../update-cm-7.0.3-N1-signed.zip" ]; then + wget http://download.cyanogenmod.com/get/update-cm-7.0.3-N1-signed.zip -P../ + fi + unzip ../update-cm-7.0.3-N1-signed.zip system/lib/* -d../ + mv ../system/lib ../android-libs + rmdir ../system +fi + + +SYSROOT=$NDK/platforms/android-9/arch-arm +# Expand the prebuilt/* path into the correct one +TOOLCHAIN=`echo $NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/*-x86` +export PATH=$TOOLCHAIN/bin:$PATH +ANDROID_SOURCE=../android-source +ANDROID_LIBS=../android-libs +ABI="armeabi-v7a" + +rm -rf ../build/stagefright +mkdir -p ../build/stagefright + +DEST=../build/stagefright +FLAGS="--target-os=linux --cross-prefix=arm-linux-androideabi- --arch=arm --cpu=armv7-a" +FLAGS="$FLAGS --sysroot=$SYSROOT" +FLAGS="$FLAGS --disable-avdevice --disable-decoder=h264 --disable-decoder=h264_vdpau --enable-libstagefright-h264" + +EXTRA_CFLAGS="-I$ANDROID_SOURCE/frameworks/base/include -I$ANDROID_SOURCE/system/core/include" +EXTRA_CFLAGS="$EXTRA_CFLAGS -I$ANDROID_SOURCE/frameworks/base/media/libstagefright" +EXTRA_CFLAGS="$EXTRA_CFLAGS -I$ANDROID_SOURCE/frameworks/base/include/media/stagefright/openmax" +EXTRA_CFLAGS="$EXTRA_CFLAGS -I$NDK/sources/cxx-stl/gnu-libstdc++/include -I$NDK/sources/cxx-stl/gnu-libstdc++/libs/$ABI/include" + +EXTRA_CFLAGS="$EXTRA_CFLAGS -march=armv7-a -mfloat-abi=softfp -mfpu=neon" +EXTRA_LDFLAGS="-Wl,--fix-cortex-a8 -L$ANDROID_LIBS -Wl,-rpath-link,$ANDROID_LIBS -L$NDK/sources/cxx-stl/gnu-libstdc++/libs/$ABI" +EXTRA_CXXFLAGS="-Wno-multichar -fno-exceptions -fno-rtti" +DEST="$DEST/$ABI" +FLAGS="$FLAGS --prefix=$DEST" + +mkdir -p $DEST + +echo $FLAGS --extra-cflags="$EXTRA_CFLAGS" --extra-ldflags="$EXTRA_LDFLAGS" --extra-cxxflags="$EXTRA_CXXFLAGS" > $DEST/info.txt +./configure $FLAGS --extra-cflags="$EXTRA_CFLAGS" --extra-ldflags="$EXTRA_LDFLAGS" --extra-cxxflags="$EXTRA_CXXFLAGS" | tee $DEST/configuration.txt +[ $PIPESTATUS == 0 ] || exit 1 +make clean +make -j4 || exit 1 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/crypto_bench.c b/tools/crypto_bench.c new file mode 100644 index 0000000000..1a699ce684 --- /dev/null +++ b/tools/crypto_bench.c @@ -0,0 +1,358 @@ +/* + * 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" + +#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" + +#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(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); +} + +/*************************************************************************** + * crypto: OpenSSL's libcrypto + ***************************************************************************/ + +#if (USE_EXT_LIBS) & USE_crypto + +#include <openssl/md5.h> +#include <openssl/sha.h> +#include <openssl/ripemd.h> +#include <openssl/aes.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); +} + +#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) + +static void run_gcrypt_aes128(uint8_t *output, + const uint8_t *input, unsigned size) +{ + static gcry_cipher_hd_t aes; + if (aes == NULL) + gcry_cipher_open(&aes, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, 0); + gcry_cipher_setkey(aes, hardcoded_key, 16); + gcry_cipher_encrypt(aes, output, size, input, size); +} + +#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(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); +} + +#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_ALL("RIPEMD-160", ripemd160, "62a5321e4fc8784903bb43ab7752c75f8b25af00") + IMPL_ALL("AES-128", aes128, "crc:ff6bc888") +}; + +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 74588c10a6..84feda959e 100644 --- a/tools/cws2fws.c +++ b/tools/cws2fws.c @@ -62,7 +62,10 @@ int main(int argc, char *argv[]) return 1; } - 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); @@ -79,7 +82,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"); return 1; } 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..66b103294f --- /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%s\n", prompt, 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..086d48a7ab --- /dev/null +++ b/tools/ffhash.c @@ -0,0 +1,149 @@ +/* + * 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/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 uint8_t *res; + +static void usage(void) +{ + int i = 0; + const char *name; + + printf("usage: ffhash [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) +{ + int i, len = av_hash_get_size(hash); + + printf("%s=0x", av_hash_get_name(hash)); + av_hash_final(hash, res); + for (i = 0; i < len; i++) + printf("%02x", res[i]); +} + +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) { + close(fd); + finish(); + printf("+READ-FAILED: %s", strerror(errno)); + 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; + + if (argc == 1) { + usage(); + return 0; + } + + if ((ret = av_hash_alloc(&hash, argv[1])) < 0) { + switch(ret) { + case AVERROR(EINVAL): + printf("Invalid hash type: %s\n", argv[1]); + break; + case AVERROR(ENOMEM): + printf("%s\n", strerror(errno)); + break; + } + return 1; + } + res = av_malloc(av_hash_get_size(hash)); + if (!res) { + printf("%s\n", strerror(errno)); + return 1; + } + + for (i = 2; i < argc; i++) + ret |= check(argv[i]); + + if (argc < 3) + ret |= check(NULL); + + av_hash_freep(&hash); + av_freep(&res); + + return ret; +} diff --git a/tools/fourcc2pixfmt.c b/tools/fourcc2pixfmt.c new file mode 100644 index 0000000000..1a653eda2e --- /dev/null +++ b/tools/fourcc2pixfmt.c @@ -0,0 +1,123 @@ +/* + * 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, char sep) +{ + int i; + + for (i = 0; ff_raw_pix_fmt_tags[i].pix_fmt != AV_PIX_FMT_NONE; i++) { + if (ff_raw_pix_fmt_tags[i].pix_fmt == pix_fmt) { + char buf[32]; + av_get_codec_tag_string(buf, sizeof(buf), ff_raw_pix_fmt_tags[i].fourcc); + printf("%s%c", buf, sep); + } + } +} + +int main(int argc, char **argv) +{ + int i, list_fourcc_pix_fmt = 0, list_pix_fmt_fourccs = 0; + 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; ff_raw_pix_fmt_tags[i].pix_fmt != AV_PIX_FMT_NONE; i++) { + char buf[32]; + av_get_codec_tag_string(buf, sizeof(buf), ff_raw_pix_fmt_tags[i].fourcc); + printf("%s: %s\n", buf, av_get_pix_fmt_name(ff_raw_pix_fmt_tags[i].pix_fmt)); + } + } + + if (list_pix_fmt_fourccs) { + for (i = 0; i < AV_PIX_FMT_NB; 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, ' '); + 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, '\n'); + } + + return 0; +} diff --git a/tools/graph2dot.c b/tools/graph2dot.c index 692ada258c..964322d080 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 */ @@ -25,9 +25,9 @@ #include <stdio.h> #include <string.h> +#include "libavutil/channel_layout.h" #include "libavutil/mem.h" #include "libavutil/pixdesc.h" -#include "libavutil/audioconvert.h" #include "libavfilter/avfilter.h" #if !HAVE_GETOPT @@ -58,43 +58,47 @@ static void print_digraph(FILE *outfile, AVFilterGraph *graph) fprintf(outfile, "node [shape=box]\n"); fprintf(outfile, "rankdir=LR\n"); - for (i = 0; i < graph->filter_count; i++) { + for (i = 0; i < graph->nb_filters; i++) { 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); - for (j = 0; j < filter_ctx->output_count; j++) { + for (j = 0; j < filter_ctx->nb_outputs; j++) { AVFilterLink *link = filter_ctx->outputs[j]; if (link) { char dst_filter_ctx_label[128]; 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, + link->srcpad->name, link->dstpad->name); + 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"); } } } diff --git a/tools/ismindex.c b/tools/ismindex.c index a51c5b748f..4dc3e125e3 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. @@ -35,6 +35,8 @@ #include <stdio.h> #include <string.h> +#include "cmdutils.h" + #include "libavformat/avformat.h" #include "libavformat/os_support.h" #include "libavutil/intreadwrite.h" @@ -126,7 +128,8 @@ static int write_fragments(struct Tracks *tracks, int start_index, struct Track *track = tracks->tracks[i]; const char *type = track->is_video ? "video" : "audio"; snprintf(dirname, sizeof(dirname), "QualityLevels(%d)", track->bitrate); - mkdir(dirname, 0777); + if (mkdir(dirname, 0777) == -1) + return AVERROR(errno); for (j = 0; j < track->chunks; j++) { snprintf(filename, sizeof(filename), "%s/Fragments(%s=%"PRId64")", dirname, type, track->offsets[j].time); @@ -218,7 +221,7 @@ static int read_mfra(struct Tracks *tracks, int start_index, } if (split) - write_fragments(tracks, start_index, f); + err = write_fragments(tracks, start_index, f); fail: if (f) @@ -247,7 +250,10 @@ static int get_video_private_data(struct Track *track, AVCodecContext *codec) if (codec->codec_id == AV_CODEC_ID_VC1) return get_private_data(track, codec); - avio_open_dyn_buf(&io); + if (avio_open_dyn_buf(&io) < 0) { + err = AVERROR(ENOMEM); + goto fail; + } if (codec->extradata_size < 11 || codec->extradata[0] != 1) goto fail; sps_size = AV_RB16(&codec->extradata[6]); 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..093d02e02e --- /dev/null +++ b/tools/missing_codec_desc @@ -0,0 +1,37 @@ +#!/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_TTF=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/normalize.py b/tools/normalize.py new file mode 100755 index 0000000000..e0159133a6 --- /dev/null +++ b/tools/normalize.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python2 + +import sys, subprocess + +if len(sys.argv) > 1: + 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..59a16efa97 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_]*' @@ -50,7 +50,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 +67,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)\b' 'common typos' $* hiegrep 'av_log\( *NULL' 'Missing context in av_log' $* hiegrep '[^sn]printf' 'Please use av_log' $* diff --git a/tools/pktdumper.c b/tools/pktdumper.c index c6398fe517..61cb5cc8ee 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..b13c6f96d7 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 */ @@ -49,12 +49,29 @@ static void probe(AVProbeData *pd, int type, int p, int size) } } -int main(void) +int main(int argc, char **argv) { unsigned int p, i, type, size, retry; AVProbeData pd; AVLFG state; PutBitContext pb; + int retry_count= 4097; + int max_size = 65537; + + if(argc >= 2) + retry_count = atoi(argv[1]); + if(argc >= 3) + max_size = atoi(argv[2]); + + 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 +79,16 @@ 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 = ""; + 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; diff --git a/tools/qt-faststart.c b/tools/qt-faststart.c index f33d6fa80c..cb36c4331e 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 @@ -37,6 +37,8 @@ #define ftello(x) _ftelli64(x) #endif +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) + #define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1]) #define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \ @@ -77,7 +79,7 @@ #define CO64_ATOM QT_ATOM('c', 'o', '6', '4') #define ATOM_PREAMBLE_SIZE 8 -#define COPY_BUFFER_SIZE 1024 +#define COPY_BUFFER_SIZE 33554432 int main(int argc, char *argv[]) { @@ -95,8 +97,8 @@ int main(int argc, char *argv[]) uint64_t i, j; uint32_t offset_count; uint64_t current_offset; - uint64_t start_offset = 0; - unsigned char copy_buffer[COPY_BUFFER_SIZE]; + int64_t start_offset = 0; + unsigned char *copy_buffer = NULL; int bytes_to_copy; if (argc != 3) { @@ -134,22 +136,27 @@ int main(int argc, char *argv[]) atom_size); goto error_out; } - fseeko(infile, -ATOM_PREAMBLE_SIZE, SEEK_CUR); - if (fread(ftyp_atom, atom_size, 1, infile) != 1) { + if ( fseeko(infile, -ATOM_PREAMBLE_SIZE, SEEK_CUR) + || fread(ftyp_atom, atom_size, 1, infile) != 1 + || (start_offset = ftello(infile))<0) { perror(argv[1]); goto error_out; } - start_offset = ftello(infile); } else { + int ret; /* 64-bit special case */ if (atom_size == 1) { if (fread(atom_bytes, ATOM_PREAMBLE_SIZE, 1, infile) != 1) { break; } atom_size = BE_64(&atom_bytes[0]); - fseeko(infile, atom_size - ATOM_PREAMBLE_SIZE * 2, SEEK_CUR); + ret = fseeko(infile, atom_size - ATOM_PREAMBLE_SIZE * 2, SEEK_CUR); } else { - fseeko(infile, atom_size - ATOM_PREAMBLE_SIZE, SEEK_CUR); + ret = fseeko(infile, atom_size - ATOM_PREAMBLE_SIZE, SEEK_CUR); + } + if(ret) { + perror(argv[1]); + goto error_out; } } printf("%c%c%c%c %10"PRIu64" %"PRIu64"\n", @@ -190,7 +197,10 @@ int main(int argc, char *argv[]) /* moov atom was, in fact, the last atom in the chunk; load the whole * moov atom */ - fseeko(infile, -atom_size, SEEK_END); + if (fseeko(infile, -atom_size, SEEK_END)) { + perror(argv[1]); + goto error_out; + } last_offset = ftello(infile); moov_atom_size = atom_size; moov_atom = malloc(moov_atom_size); @@ -219,14 +229,18 @@ int main(int argc, char *argv[]) atom_type = BE_32(&moov_atom[i]); if (atom_type == STCO_ATOM) { printf(" patching stco atom...\n"); - atom_size = BE_32(&moov_atom[i - 4]); + atom_size = (uint32_t)BE_32(&moov_atom[i - 4]); if (i + atom_size - 4 > moov_atom_size) { printf(" bad atom size\n"); goto error_out; } offset_count = BE_32(&moov_atom[i + 8]); + if (i + 12LL + offset_count * 4LL > moov_atom_size) { + printf(" bad atom size\n"); + goto error_out; + } for (j = 0; j < offset_count; j++) { - current_offset = BE_32(&moov_atom[i + 12 + j * 4]); + current_offset = (uint32_t)BE_32(&moov_atom[i + 12 + j * 4]); current_offset += moov_atom_size; moov_atom[i + 12 + j * 4 + 0] = (current_offset >> 24) & 0xFF; moov_atom[i + 12 + j * 4 + 1] = (current_offset >> 16) & 0xFF; @@ -236,12 +250,16 @@ int main(int argc, char *argv[]) i += atom_size - 4; } else if (atom_type == CO64_ATOM) { printf(" patching co64 atom...\n"); - atom_size = BE_32(&moov_atom[i - 4]); + atom_size = (uint32_t)BE_32(&moov_atom[i - 4]); if (i + atom_size - 4 > moov_atom_size) { printf(" bad atom size\n"); goto error_out; } offset_count = BE_32(&moov_atom[i + 8]); + if (i + 12LL + offset_count * 8LL > moov_atom_size) { + printf(" bad atom size\n"); + goto error_out; + } for (j = 0; j < offset_count; j++) { current_offset = BE_64(&moov_atom[i + 12 + j * 8]); current_offset += moov_atom_size; @@ -266,7 +284,11 @@ int main(int argc, char *argv[]) } if (start_offset > 0) { /* seek after ftyp atom */ - fseeko(infile, start_offset, SEEK_SET); + if (fseeko(infile, start_offset, SEEK_SET)) { + perror(argv[1]); + goto error_out; + } + last_offset -= start_offset; } @@ -293,12 +315,15 @@ int main(int argc, char *argv[]) } /* copy the remainder of the infile, from offset 0 -> last_offset - 1 */ + bytes_to_copy = FFMIN(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) { - if (last_offset > COPY_BUFFER_SIZE) - bytes_to_copy = COPY_BUFFER_SIZE; - else - bytes_to_copy = last_offset; + bytes_to_copy = FFMIN(bytes_to_copy, last_offset); if (fread(copy_buffer, bytes_to_copy, 1, infile) != 1) { perror(argv[1]); @@ -315,6 +340,7 @@ int main(int argc, char *argv[]) fclose(outfile); free(moov_atom); free(ftyp_atom); + free(copy_buffer); return 0; @@ -325,5 +351,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..c42b28dd44 --- /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_free_packet(&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/trasher.c b/tools/trasher.c index 35625e9a62..aaa09f4ca8 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 */ @@ -56,7 +56,10 @@ int main(int argc, char **argv) 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); + if (fseek(f, pos, SEEK_SET) < 0) { + fprintf(stderr, "seek failed\n"); + return 1; + } if (maxburst < 0) burst = -maxburst; 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..11585f9b4c --- /dev/null +++ b/tools/yuvcmp.c @@ -0,0 +1,182 @@ +/* + * 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> +#include <unistd.h> + + +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..ae3c8d7aa4 --- /dev/null +++ b/tools/zmqsend.c @@ -0,0 +1,167 @@ +/* + * 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 c, *src_buf, *recv_buf; + int recv_buf_size, ret; + void *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; + } + + ctx = zmq_ctx_new(); + if (!ctx) { + av_log(NULL, AV_LOG_ERROR, + "Could not create ZMQ context: %s\n", zmq_strerror(errno)); + return 1; + } + + socket = zmq_socket(ctx, ZMQ_REQ); + if (!socket) { + av_log(ctx, 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(ctx, 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(ctx, 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(ctx, 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(ctx, 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(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 |