diff options
| author | Tim Redfern <tim@eclectronics.org> | 2013-08-26 15:10:18 +0100 |
|---|---|---|
| committer | Tim Redfern <tim@eclectronics.org> | 2013-08-26 15:10:18 +0100 |
| commit | 150c9823e71a161e97003849cf8b2f55b21520bd (patch) | |
| tree | 3559c840cf403d1386708b2591d58f928c7b160d /ffmpeg1/tools | |
| parent | b4b1e2630c95d5e6014463f7608d59dc2322a3b8 (diff) | |
adding ffmpeg specific version
Diffstat (limited to 'ffmpeg1/tools')
| -rw-r--r-- | ffmpeg1/tools/aviocat.c | 96 | ||||
| -rwxr-xr-x | ffmpeg1/tools/bisect-create | 46 | ||||
| -rw-r--r-- | ffmpeg1/tools/bookmarklets.html | 55 | ||||
| -rw-r--r-- | ffmpeg1/tools/build_libstagefright | 58 | ||||
| -rwxr-xr-x | ffmpeg1/tools/clean-diff | 11 | ||||
| -rw-r--r-- | ffmpeg1/tools/cws2fws.c | 145 | ||||
| -rw-r--r-- | ffmpeg1/tools/enum_options.c | 143 | ||||
| -rw-r--r-- | ffmpeg1/tools/ffescape.c | 180 | ||||
| -rw-r--r-- | ffmpeg1/tools/ffeval.c | 142 | ||||
| -rw-r--r-- | ffmpeg1/tools/fourcc2pixfmt.c | 123 | ||||
| -rw-r--r-- | ffmpeg1/tools/graph2dot.c | 193 | ||||
| -rw-r--r-- | ffmpeg1/tools/ismindex.c | 567 | ||||
| -rwxr-xr-x | ffmpeg1/tools/make_chlayout_test | 114 | ||||
| -rwxr-xr-x | ffmpeg1/tools/missing_codec_desc | 37 | ||||
| -rwxr-xr-x | ffmpeg1/tools/patcheck | 180 | ||||
| -rw-r--r-- | ffmpeg1/tools/pktdumper.c | 137 | ||||
| -rwxr-xr-x | ffmpeg1/tools/plotframes | 164 | ||||
| -rw-r--r-- | ffmpeg1/tools/probetest.c | 145 | ||||
| -rw-r--r-- | ffmpeg1/tools/qt-faststart.c | 356 | ||||
| -rw-r--r-- | ffmpeg1/tools/seek_print.c | 107 | ||||
| -rw-r--r-- | ffmpeg1/tools/trasher.c | 81 | ||||
| -rwxr-xr-x | ffmpeg1/tools/unwrap-diff | 2 | ||||
| -rw-r--r-- | ffmpeg1/tools/yuvcmp.c | 182 |
23 files changed, 3264 insertions, 0 deletions
diff --git a/ffmpeg1/tools/aviocat.c b/ffmpeg1/tools/aviocat.c new file mode 100644 index 0000000..52a96bd --- /dev/null +++ b/ffmpeg1/tools/aviocat.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2012 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "libavutil/time.h" +#include "libavformat/avformat.h" + +static int usage(const char *argv0, int ret) +{ + fprintf(stderr, "%s [-b bytespersec] input_url output_url\n", argv0); + return ret; +} + +int main(int argc, char **argv) +{ + int bps = 0, ret, i; + const char *input_url = NULL, *output_url = NULL; + int64_t stream_pos = 0; + int64_t start_time; + char errbuf[50]; + AVIOContext *input, *output; + + av_register_all(); + avformat_network_init(); + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-b")) { + bps = atoi(argv[i + 1]); + i++; + } else if (!input_url) { + input_url = argv[i]; + } else if (!output_url) { + output_url = argv[i]; + } else { + return usage(argv[0], 1); + } + } + if (!output_url) + return usage(argv[0], 1); + + ret = avio_open2(&input, input_url, AVIO_FLAG_READ, NULL, NULL); + if (ret) { + av_strerror(ret, errbuf, sizeof(errbuf)); + fprintf(stderr, "Unable to open %s: %s\n", input_url, errbuf); + return 1; + } + ret = avio_open2(&output, output_url, AVIO_FLAG_WRITE, NULL, NULL); + if (ret) { + av_strerror(ret, errbuf, sizeof(errbuf)); + fprintf(stderr, "Unable to open %s: %s\n", output_url, errbuf); + goto fail; + } + + start_time = av_gettime(); + while (1) { + uint8_t buf[1024]; + int n; + n = avio_read(input, buf, sizeof(buf)); + if (n <= 0) + break; + avio_write(output, buf, n); + stream_pos += n; + if (bps) { + avio_flush(output); + while ((av_gettime() - start_time) * bps / AV_TIME_BASE < stream_pos) + av_usleep(50 * 1000); + } + } + + avio_flush(output); + avio_close(output); + +fail: + avio_close(input); + avformat_network_deinit(); + return ret ? 1 : 0; +} diff --git a/ffmpeg1/tools/bisect-create b/ffmpeg1/tools/bisect-create new file mode 100755 index 0000000..fc60e86 --- /dev/null +++ b/ffmpeg1/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/ffmpeg1/tools/bookmarklets.html b/ffmpeg1/tools/bookmarklets.html new file mode 100644 index 0000000..9800ab5 --- /dev/null +++ b/ffmpeg1/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/ffmpeg1/tools/build_libstagefright b/ffmpeg1/tools/build_libstagefright new file mode 100644 index 0000000..8b3a093 --- /dev/null +++ b/ffmpeg1/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/ffmpeg1/tools/clean-diff b/ffmpeg1/tools/clean-diff new file mode 100755 index 0000000..4600702 --- /dev/null +++ b/ffmpeg1/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/ffmpeg1/tools/cws2fws.c b/ffmpeg1/tools/cws2fws.c new file mode 100644 index 0000000..84feda9 --- /dev/null +++ b/ffmpeg1/tools/cws2fws.c @@ -0,0 +1,145 @@ +/* + * cws2fws by Alex Beregszaszi + * This file is placed in the public domain. + * Use the program however you see fit. + * + * This utility converts compressed Macromedia Flash files to uncompressed ones. + */ + +#include "config.h" +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#if HAVE_IO_H +#include <io.h> +#endif +#include <zlib.h> + +#ifdef DEBUG +#define dbgprintf printf +#else +#define dbgprintf(...) +#endif + +int main(int argc, char *argv[]) +{ + int fd_in, fd_out, comp_len, uncomp_len, i, last_out; + char buf_in[1024], buf_out[65536]; + z_stream zstream; + struct stat statbuf; + + if (argc < 3) { + printf("Usage: %s <infile.swf> <outfile.swf>\n", argv[0]); + return 1; + } + + fd_in = open(argv[1], O_RDONLY); + if (fd_in < 0) { + perror("Error opening input file"); + return 1; + } + + fd_out = open(argv[2], O_WRONLY | O_CREAT, 00644); + if (fd_out < 0) { + perror("Error opening output file"); + close(fd_in); + return 1; + } + + if (read(fd_in, &buf_in, 8) != 8) { + printf("Header error\n"); + close(fd_in); + close(fd_out); + return 1; + } + + if (buf_in[0] != 'C' || buf_in[1] != 'W' || buf_in[2] != 'S') { + printf("Not a compressed flash file\n"); + return 1; + } + + 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); + + printf("Compressed size: %d Uncompressed size: %d\n", + comp_len - 4, uncomp_len - 4); + + // write out modified header + buf_in[0] = 'F'; + if (write(fd_out, &buf_in, 8) < 8) { + perror("Error writing output file"); + return 1; + } + + zstream.zalloc = NULL; + zstream.zfree = NULL; + zstream.opaque = NULL; + 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); + + dbgprintf("read %d bytes\n", len); + + last_out = zstream.total_out; + + zstream.next_in = &buf_in[0]; + zstream.avail_in = len; + zstream.next_out = &buf_out[0]; + zstream.avail_out = 65536; + + ret = inflate(&zstream, Z_SYNC_FLUSH); + if (ret != Z_STREAM_END && ret != Z_OK) { + printf("Error while decompressing: %d\n", ret); + inflateEnd(&zstream); + return 1; + } + + dbgprintf("a_in: %d t_in: %lu a_out: %d t_out: %lu -- %lu out\n", + zstream.avail_in, zstream.total_in, zstream.avail_out, + zstream.total_out, zstream.total_out - last_out); + + if (write(fd_out, &buf_out, zstream.total_out - last_out) < + zstream.total_out - last_out) { + perror("Error writing output file"); + return 1; + } + + i += len; + + if (ret == Z_STREAM_END || ret == Z_BUF_ERROR) + break; + } + + if (zstream.total_out != uncomp_len - 8) { + printf("Size mismatch (%lu != %d), updating header...\n", + zstream.total_out, uncomp_len - 8); + + buf_in[0] = (zstream.total_out + 8) & 0xff; + buf_in[1] = ((zstream.total_out + 8) >> 8) & 0xff; + buf_in[2] = ((zstream.total_out + 8) >> 16) & 0xff; + buf_in[3] = ((zstream.total_out + 8) >> 24) & 0xff; + + if ( lseek(fd_out, 4, SEEK_SET) < 0 + || write(fd_out, &buf_in, 4) < 4) { + perror("Error writing output file"); + return 1; + } + } + + inflateEnd(&zstream); + close(fd_in); + close(fd_out); + return 0; +} diff --git a/ffmpeg1/tools/enum_options.c b/ffmpeg1/tools/enum_options.c new file mode 100644 index 0000000..45ac727 --- /dev/null +++ b/ffmpeg1/tools/enum_options.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2011 Anton Khirnov + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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 + * 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/ffmpeg1/tools/ffescape.c b/ffmpeg1/tools/ffescape.c new file mode 100644 index 0000000..0530d28 --- /dev/null +++ b/ffmpeg1/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/ffmpeg1/tools/ffeval.c b/ffmpeg1/tools/ffeval.c new file mode 100644 index 0000000..0fab877 --- /dev/null +++ b/ffmpeg1/tools/ffeval.c @@ -0,0 +1,142 @@ +/* + * 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" + +#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"); +} + +#define MAX_BLOCK_SIZE SIZE_MAX + +int main(int argc, char **argv) +{ + size_t buf_size = 256; + char *buf = av_malloc(buf_size); + const char *outfilename = NULL, *infilename = NULL; + FILE *outfile = NULL, *infile = NULL; + const char *prompt = "=> "; + int count = 0, echo = 0; + int c; + + av_max_alloc(MAX_BLOCK_SIZE); + + 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] != '#') { + av_expr_parse_and_eval(&d, buf, + NULL, NULL, + NULL, NULL, NULL, NULL, NULL, 0, NULL); + if (echo) + fprintf(outfile, "%s ", buf); + fprintf(outfile, "%s%f\n", prompt, d); + } + count = 0; + } else { + if (count >= buf_size-1) { + if (buf_size == MAX_BLOCK_SIZE) { + av_log(NULL, AV_LOG_ERROR, "Memory allocation problem, " + "max block size '%zd' reached\n", MAX_BLOCK_SIZE); + return 1; + } + buf_size = FFMIN(buf_size, MAX_BLOCK_SIZE / 2) * 2; + buf = av_realloc_f((void *)buf, buf_size, 1); + if (!buf) { + av_log(NULL, AV_LOG_ERROR, "Memory allocation problem occurred\n"); + return 1; + } + } + buf[count++] = c; + } + } + + av_free(buf); + return 0; +} diff --git a/ffmpeg1/tools/fourcc2pixfmt.c b/ffmpeg1/tools/fourcc2pixfmt.c new file mode 100644 index 0000000..77cb0b6 --- /dev/null +++ b/ffmpeg1/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 & PIX_FMT_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/ffmpeg1/tools/graph2dot.c b/ffmpeg1/tools/graph2dot.c new file mode 100644 index 0000000..d53642f --- /dev/null +++ b/ffmpeg1/tools/graph2dot.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2008-2010 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 <stdio.h> +#include <string.h> + +#include "libavutil/channel_layout.h" +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" +#include "libavfilter/avfiltergraph.h" + +#if !HAVE_GETOPT +#include "compat/getopt.c" +#endif + +static void usage(void) +{ + printf("Convert a libavfilter graph to a dot file\n"); + printf("Usage: graph2dot [OPTIONS]\n"); + printf("\n" + "Options:\n" + "-i INFILE set INFILE as input file, stdin if omitted\n" + "-o OUTFILE set OUTFILE as output file, stdout if omitted\n" + "-h print this help\n"); +} + +struct line { + char data[256]; + struct line *next; +}; + +static void print_digraph(FILE *outfile, AVFilterGraph *graph) +{ + int i, j; + + fprintf(outfile, "digraph G {\n"); + fprintf(outfile, "node [shape=box]\n"); + fprintf(outfile, "rankdir=LR\n"); + + 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\\n(%s)", + filter_ctx->name, + filter_ctx->filter->name); + + for (j = 0; j < filter_ctx->output_count; 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\\n(%s)", + dst_filter_ctx->name, + dst_filter_ctx->filter->name); + + 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, + "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, + "fmt:%s sr:%d cl:%s tb:%d/%d", + av_get_sample_fmt_name(link->format), + link->sample_rate, buf, + link->time_base.num, link->time_base.den); + } + fprintf(outfile, "\" ];\n"); + } + } + } + fprintf(outfile, "}\n"); +} + +int main(int argc, char **argv) +{ + const char *outfilename = NULL; + const char *infilename = NULL; + FILE *outfile = NULL; + FILE *infile = NULL; + char *graph_string = NULL; + AVFilterGraph *graph = av_mallocz(sizeof(AVFilterGraph)); + char c; + + av_log_set_level(AV_LOG_DEBUG); + + while ((c = getopt(argc, argv, "hi:o:")) != -1) { + switch (c) { + case 'h': + usage(); + return 0; + case 'i': + infilename = optarg; + break; + case 'o': + outfilename = optarg; + break; + case '?': + return 1; + } + } + + if (!infilename || !strcmp(infilename, "-")) + infilename = "/dev/stdin"; + 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 = "/dev/stdout"; + outfile = fopen(outfilename, "w"); + if (!outfile) { + fprintf(stderr, "Impossible to open output file '%s': %s\n", + outfilename, strerror(errno)); + return 1; + } + + /* read from infile and put it in a buffer */ + { + unsigned int count = 0; + struct line *line, *last_line, *first_line; + char *p; + last_line = first_line = av_malloc(sizeof(struct line)); + + while (fgets(last_line->data, sizeof(last_line->data), infile)) { + struct line *new_line = av_malloc(sizeof(struct line)); + count += strlen(last_line->data); + last_line->next = new_line; + last_line = new_line; + } + last_line->next = NULL; + + graph_string = av_malloc(count + 1); + p = graph_string; + for (line = first_line; line->next; line = line->next) { + unsigned int l = strlen(line->data); + memcpy(p, line->data, l); + p += l; + } + *p = '\0'; + } + + avfilter_register_all(); + + if (avfilter_graph_parse(graph, graph_string, NULL, NULL, NULL) < 0) { + fprintf(stderr, "Impossible to parse the graph description\n"); + return 1; + } + + if (avfilter_graph_config(graph, NULL) < 0) + return 1; + + print_digraph(outfile, graph); + fflush(outfile); + + return 0; +} diff --git a/ffmpeg1/tools/ismindex.c b/ffmpeg1/tools/ismindex.c new file mode 100644 index 0000000..502a7dc --- /dev/null +++ b/ffmpeg1/tools/ismindex.c @@ -0,0 +1,567 @@ +/* + * Copyright (c) 2012 Martin Storsjo + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * To create a simple file for smooth streaming: + * 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. + * + * To pre-split files for serving as static files by a web server without + * any extra server support, create the ismv file as above, and split it: + * ismindex -split foo.ismv + * This step creates a file Manifest and directories QualityLevel(...), + * that can be read directly by a smooth streaming player. + */ + +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#ifdef _WIN32 +#include <direct.h> +#define mkdir(a, b) _mkdir(a) +#endif + +#include "cmdutils.h" + +#include "libavformat/avformat.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mathematics.h" + +static int usage(const char *argv0, int ret) +{ + fprintf(stderr, "%s [-split] [-n basename] file1 [file2] ...\n", argv0); + return ret; +} + +struct MoofOffset { + int64_t time; + int64_t offset; + int duration; +}; + +struct Track { + const char *name; + int64_t duration; + int bitrate; + int track_id; + int is_audio, is_video; + int width, height; + int chunks; + int sample_rate, channels; + uint8_t *codec_private; + int codec_private_size; + struct MoofOffset *offsets; + int timescale; + const char *fourcc; + int blocksize; + int tag; +}; + +struct Tracks { + int nb_tracks; + int64_t duration; + struct Track **tracks; + int video_track, audio_track; + int nb_video_tracks, nb_audio_tracks; +}; + +static int copy_tag(AVIOContext *in, AVIOContext *out, int32_t tag_name) +{ + int32_t size, tag; + + size = avio_rb32(in); + tag = avio_rb32(in); + avio_wb32(out, size); + avio_wb32(out, tag); + if (tag != tag_name) + return -1; + size -= 8; + while (size > 0) { + char buf[1024]; + int len = FFMIN(sizeof(buf), size); + if (avio_read(in, buf, len) != len) + break; + avio_write(out, buf, len); + size -= len; + } + return 0; +} + +static int write_fragment(const char *filename, AVIOContext *in) +{ + AVIOContext *out = NULL; + int ret; + + if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, NULL, NULL)) < 0) + return ret; + copy_tag(in, out, MKBETAG('m', 'o', 'o', 'f')); + copy_tag(in, out, MKBETAG('m', 'd', 'a', 't')); + + avio_flush(out); + avio_close(out); + + return ret; +} + +static int write_fragments(struct Tracks *tracks, int start_index, + AVIOContext *in) +{ + char dirname[100], filename[500]; + int i, j; + + for (i = start_index; i < tracks->nb_tracks; i++) { + 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); + for (j = 0; j < track->chunks; j++) { + snprintf(filename, sizeof(filename), "%s/Fragments(%s=%"PRId64")", + dirname, type, track->offsets[j].time); + avio_seek(in, track->offsets[j].offset, SEEK_SET); + write_fragment(filename, in); + } + } + return 0; +} + +static int read_tfra(struct Tracks *tracks, int start_index, AVIOContext *f) +{ + int ret = AVERROR_EOF, track_id; + int version, fieldlength, i, j; + int64_t pos = avio_tell(f); + uint32_t size = avio_rb32(f); + struct Track *track = NULL; + + if (avio_rb32(f) != MKBETAG('t', 'f', 'r', 'a')) + goto fail; + version = avio_r8(f); + avio_rb24(f); + track_id = avio_rb32(f); /* track id */ + for (i = start_index; i < tracks->nb_tracks && !track; i++) + if (tracks->tracks[i]->track_id == track_id) + track = tracks->tracks[i]; + if (!track) { + /* Ok, continue parsing the next atom */ + ret = 0; + goto fail; + } + fieldlength = avio_rb32(f); + track->chunks = avio_rb32(f); + track->offsets = av_mallocz(sizeof(*track->offsets) * track->chunks); + if (!track->offsets) { + ret = AVERROR(ENOMEM); + goto fail; + } + for (i = 0; i < track->chunks; i++) { + if (version == 1) { + track->offsets[i].time = avio_rb64(f); + track->offsets[i].offset = avio_rb64(f); + } else { + track->offsets[i].time = avio_rb32(f); + track->offsets[i].offset = avio_rb32(f); + } + for (j = 0; j < ((fieldlength >> 4) & 3) + 1; j++) + avio_r8(f); + for (j = 0; j < ((fieldlength >> 2) & 3) + 1; j++) + avio_r8(f); + for (j = 0; j < ((fieldlength >> 0) & 3) + 1; j++) + avio_r8(f); + if (i > 0) + track->offsets[i - 1].duration = track->offsets[i].time - + track->offsets[i - 1].time; + } + if (track->chunks > 0) + track->offsets[track->chunks - 1].duration = track->duration - + track->offsets[track->chunks - 1].time; + ret = 0; + +fail: + avio_seek(f, pos + size, SEEK_SET); + return ret; +} + +static int read_mfra(struct Tracks *tracks, int start_index, + const char *file, int split) +{ + int err = 0; + AVIOContext *f = NULL; + int32_t mfra_size; + + if ((err = avio_open2(&f, file, AVIO_FLAG_READ, NULL, NULL)) < 0) + goto fail; + avio_seek(f, avio_size(f) - 4, SEEK_SET); + mfra_size = avio_rb32(f); + avio_seek(f, -mfra_size, SEEK_CUR); + if (avio_rb32(f) != mfra_size) { + err = AVERROR_INVALIDDATA; + goto fail; + } + if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) { + err = AVERROR_INVALIDDATA; + goto fail; + } + while (!read_tfra(tracks, start_index, f)) { + /* Empty */ + } + + if (split) + write_fragments(tracks, start_index, f); + +fail: + if (f) + avio_close(f); + if (err) + fprintf(stderr, "Unable to read the MFRA atom in %s\n", file); + return err; +} + +static int get_private_data(struct Track *track, AVCodecContext *codec) +{ + track->codec_private_size = codec->extradata_size; + track->codec_private = av_mallocz(codec->extradata_size); + if (!track->codec_private) + return AVERROR(ENOMEM); + memcpy(track->codec_private, codec->extradata, codec->extradata_size); + return 0; +} + +static int get_video_private_data(struct Track *track, AVCodecContext *codec) +{ + AVIOContext *io = NULL; + uint16_t sps_size, pps_size; + int err = AVERROR(EINVAL); + + if (codec->codec_id == AV_CODEC_ID_VC1) + return get_private_data(track, codec); + + 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]); + if (11 + sps_size > codec->extradata_size) + goto fail; + avio_wb32(io, 0x00000001); + avio_write(io, &codec->extradata[8], sps_size); + pps_size = AV_RB16(&codec->extradata[9 + sps_size]); + if (11 + sps_size + pps_size > codec->extradata_size) + goto fail; + avio_wb32(io, 0x00000001); + avio_write(io, &codec->extradata[11 + sps_size], pps_size); + err = 0; + +fail: + track->codec_private_size = avio_close_dyn_buf(io, &track->codec_private); + return err; +} + +static int handle_file(struct Tracks *tracks, const char *file, int split) +{ + AVFormatContext *ctx = NULL; + int err = 0, i, orig_tracks = tracks->nb_tracks; + char errbuf[50], *ptr; + struct Track *track; + + err = avformat_open_input(&ctx, file, NULL, NULL); + if (err < 0) { + av_strerror(err, errbuf, sizeof(errbuf)); + fprintf(stderr, "Unable to open %s: %s\n", file, errbuf); + return 1; + } + + err = avformat_find_stream_info(ctx, NULL); + if (err < 0) { + av_strerror(err, errbuf, sizeof(errbuf)); + fprintf(stderr, "Unable to identify %s: %s\n", file, errbuf); + goto fail; + } + + if (ctx->nb_streams < 1) { + fprintf(stderr, "No streams found in %s\n", file); + goto fail; + } + if (!tracks->duration) + tracks->duration = ctx->duration; + + for (i = 0; i < ctx->nb_streams; i++) { + struct Track **temp; + AVStream *st = ctx->streams[i]; + track = av_mallocz(sizeof(*track)); + if (!track) { + err = AVERROR(ENOMEM); + goto fail; + } + temp = av_realloc(tracks->tracks, + sizeof(*tracks->tracks) * (tracks->nb_tracks + 1)); + if (!temp) { + av_free(track); + err = AVERROR(ENOMEM); + goto fail; + } + tracks->tracks = temp; + tracks->tracks[tracks->nb_tracks] = track; + + track->name = file; + if ((ptr = strrchr(file, '/')) != NULL) + track->name = ptr + 1; + + track->bitrate = st->codec->bit_rate; + track->track_id = st->id; + track->timescale = st->time_base.den; + track->duration = av_rescale_rnd(ctx->duration, track->timescale, + AV_TIME_BASE, AV_ROUND_UP); + track->is_audio = st->codec->codec_type == AVMEDIA_TYPE_AUDIO; + track->is_video = st->codec->codec_type == AVMEDIA_TYPE_VIDEO; + + if (!track->is_audio && !track->is_video) { + fprintf(stderr, + "Track %d in %s is neither video nor audio, skipping\n", + track->track_id, file); + av_freep(&tracks->tracks[tracks->nb_tracks]); + continue; + } + + if (track->is_audio) { + if (tracks->audio_track < 0) + tracks->audio_track = tracks->nb_tracks; + tracks->nb_audio_tracks++; + track->channels = st->codec->channels; + track->sample_rate = st->codec->sample_rate; + if (st->codec->codec_id == AV_CODEC_ID_AAC) { + track->fourcc = "AACL"; + track->tag = 255; + track->blocksize = 4; + } else if (st->codec->codec_id == AV_CODEC_ID_WMAPRO) { + track->fourcc = "WMAP"; + track->tag = st->codec->codec_tag; + track->blocksize = st->codec->block_align; + } + get_private_data(track, st->codec); + } + if (track->is_video) { + if (tracks->video_track < 0) + tracks->video_track = tracks->nb_tracks; + tracks->nb_video_tracks++; + track->width = st->codec->width; + track->height = st->codec->height; + if (st->codec->codec_id == AV_CODEC_ID_H264) + track->fourcc = "H264"; + else if (st->codec->codec_id == AV_CODEC_ID_VC1) + track->fourcc = "WVC1"; + get_video_private_data(track, st->codec); + } + + tracks->nb_tracks++; + } + + avformat_close_input(&ctx); + + err = read_mfra(tracks, orig_tracks, file, split); + +fail: + if (ctx) + avformat_close_input(&ctx); + return err; +} + +static void output_server_manifest(struct Tracks *tracks, + const char *basename) +{ + char filename[1000]; + FILE *out; + int i; + + snprintf(filename, sizeof(filename), "%s.ism", basename); + out = fopen(filename, "w"); + if (!out) { + perror(filename); + return; + } + fprintf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); + fprintf(out, "<smil xmlns=\"http://www.w3.org/2001/SMIL20/Language\">\n"); + fprintf(out, "\t<head>\n"); + fprintf(out, "\t\t<meta name=\"clientManifestRelativePath\" " + "content=\"%s.ismc\" />\n", basename); + fprintf(out, "\t</head>\n"); + fprintf(out, "\t<body>\n"); + fprintf(out, "\t\t<switch>\n"); + for (i = 0; i < tracks->nb_tracks; i++) { + struct Track *track = tracks->tracks[i]; + const char *type = track->is_video ? "video" : "audio"; + fprintf(out, "\t\t\t<%s src=\"%s\" systemBitrate=\"%d\">\n", + type, track->name, track->bitrate); + fprintf(out, "\t\t\t\t<param name=\"trackID\" value=\"%d\" " + "valueType=\"data\" />\n", track->track_id); + fprintf(out, "\t\t\t</%s>\n", type); + } + fprintf(out, "\t\t</switch>\n"); + fprintf(out, "\t</body>\n"); + fprintf(out, "</smil>\n"); + fclose(out); +} + +static void print_track_chunks(FILE *out, struct Tracks *tracks, int main, + const char *type) +{ + int i, j; + struct Track *track = tracks->tracks[main]; + for (i = 0; i < track->chunks; i++) { + for (j = main + 1; j < tracks->nb_tracks; j++) { + if (tracks->tracks[j]->is_audio == track->is_audio && + track->offsets[i].duration != tracks->tracks[j]->offsets[i].duration) + fprintf(stderr, "Mismatched duration of %s chunk %d in %s and %s\n", + type, i, track->name, tracks->tracks[j]->name); + } + fprintf(out, "\t\t<c n=\"%d\" d=\"%d\" />\n", + i, track->offsets[i].duration); + } +} + +static void output_client_manifest(struct Tracks *tracks, + const char *basename, int split) +{ + char filename[1000]; + FILE *out; + int i, j; + + if (split) + snprintf(filename, sizeof(filename), "Manifest"); + else + snprintf(filename, sizeof(filename), "%s.ismc", basename); + out = fopen(filename, "w"); + if (!out) { + perror(filename); + return; + } + fprintf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); + fprintf(out, "<SmoothStreamingMedia MajorVersion=\"2\" MinorVersion=\"0\" " + "Duration=\"%"PRId64 "\">\n", tracks->duration * 10); + if (tracks->video_track >= 0) { + struct Track *track = tracks->tracks[tracks->video_track]; + struct Track *first_track = track; + int index = 0; + fprintf(out, + "\t<StreamIndex Type=\"video\" QualityLevels=\"%d\" " + "Chunks=\"%d\" " + "Url=\"QualityLevels({bitrate})/Fragments(video={start time})\">\n", + tracks->nb_video_tracks, track->chunks); + for (i = 0; i < tracks->nb_tracks; i++) { + track = tracks->tracks[i]; + if (!track->is_video) + continue; + fprintf(out, + "\t\t<QualityLevel Index=\"%d\" Bitrate=\"%d\" " + "FourCC=\"%s\" MaxWidth=\"%d\" MaxHeight=\"%d\" " + "CodecPrivateData=\"", + index, track->bitrate, track->fourcc, track->width, track->height); + for (j = 0; j < track->codec_private_size; j++) + fprintf(out, "%02X", track->codec_private[j]); + fprintf(out, "\" />\n"); + index++; + if (track->chunks != first_track->chunks) + fprintf(stderr, "Mismatched number of video chunks in %s and %s\n", + track->name, first_track->name); + } + print_track_chunks(out, tracks, tracks->video_track, "video"); + fprintf(out, "\t</StreamIndex>\n"); + } + if (tracks->audio_track >= 0) { + struct Track *track = tracks->tracks[tracks->audio_track]; + struct Track *first_track = track; + int index = 0; + fprintf(out, + "\t<StreamIndex Type=\"audio\" QualityLevels=\"%d\" " + "Chunks=\"%d\" " + "Url=\"QualityLevels({bitrate})/Fragments(audio={start time})\">\n", + tracks->nb_audio_tracks, track->chunks); + for (i = 0; i < tracks->nb_tracks; i++) { + track = tracks->tracks[i]; + if (!track->is_audio) + continue; + fprintf(out, + "\t\t<QualityLevel Index=\"%d\" Bitrate=\"%d\" " + "FourCC=\"%s\" SamplingRate=\"%d\" Channels=\"%d\" " + "BitsPerSample=\"16\" PacketSize=\"%d\" " + "AudioTag=\"%d\" CodecPrivateData=\"", + index, track->bitrate, track->fourcc, track->sample_rate, + track->channels, track->blocksize, track->tag); + for (j = 0; j < track->codec_private_size; j++) + fprintf(out, "%02X", track->codec_private[j]); + fprintf(out, "\" />\n"); + index++; + if (track->chunks != first_track->chunks) + fprintf(stderr, "Mismatched number of audio chunks in %s and %s\n", + track->name, first_track->name); + } + print_track_chunks(out, tracks, tracks->audio_track, "audio"); + fprintf(out, "\t</StreamIndex>\n"); + } + fprintf(out, "</SmoothStreamingMedia>\n"); + fclose(out); +} + +static void clean_tracks(struct Tracks *tracks) +{ + int i; + for (i = 0; i < tracks->nb_tracks; i++) { + av_freep(&tracks->tracks[i]->codec_private); + av_freep(&tracks->tracks[i]->offsets); + av_freep(&tracks->tracks[i]); + } + av_freep(&tracks->tracks); + tracks->nb_tracks = 0; +} + +int main(int argc, char **argv) +{ + const char *basename = NULL; + int split = 0, i; + struct Tracks tracks = { 0, .video_track = -1, .audio_track = -1 }; + + av_register_all(); + + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-n")) { + basename = argv[i + 1]; + i++; + } else if (!strcmp(argv[i], "-split")) { + split = 1; + } else if (argv[i][0] == '-') { + return usage(argv[0], 1); + } else { + if (handle_file(&tracks, argv[i], split)) + return 1; + } + } + if (!tracks.nb_tracks || (!basename && !split)) + return usage(argv[0], 1); + + if (!split) + output_server_manifest(&tracks, basename); + output_client_manifest(&tracks, basename, split); + + clean_tracks(&tracks); + + return 0; +} diff --git a/ffmpeg1/tools/make_chlayout_test b/ffmpeg1/tools/make_chlayout_test new file mode 100755 index 0000000..fcdbda3 --- /dev/null +++ b/ffmpeg1/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/ffmpeg1/tools/missing_codec_desc b/ffmpeg1/tools/missing_codec_desc new file mode 100755 index 0000000..093d02e --- /dev/null +++ b/ffmpeg1/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/ffmpeg1/tools/patcheck b/ffmpeg1/tools/patcheck new file mode 100755 index 0000000..83db4c0 --- /dev/null +++ b/ffmpeg1/tools/patcheck @@ -0,0 +1,180 @@ +#!/bin/sh + +# if no argument provided, write stdin to a file and re-run the script +if [ $# = 0 ]; then + cat > patcheck.stdout + $0 patcheck.stdout + rm -f patcheck.stdout + exit +fi + +GREP=grep +EGREP=egrep +TMP=patcheck.tmp +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, 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 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_]*' +ERE_FUNCS="$ERE_TYPES"' *\(' + +hiegrep(){ + arg="$1" + msg="$2" + shift 2 + $GREP $OPT '^+' $* | $GREP -v ':+++'| $EGREP --color=always -- "$arg"> $TMP && printf "\n$msg\n" + cat $TMP +} + +hiegrep2(){ + arg="$1" + varg="$2" + msg="$3" + shift 3 + $GREP $OPT '^+' $* | $GREP -v ':+++' | $EGREP -v -- "$varg" | $EGREP --color=always -- "$arg" > $TMP && printf "\n$msg\n" + cat $TMP +} + +hiegrep '[[:space:]]$' 'trailing whitespace' $* +hiegrep "$(echo x | tr 'x' '\t')" 'tabs' $* +#hiegrep ':\+$' 'Empty lines' $* +hiegrep ';;' 'double ;' $* +hiegrep2 '\b_[a-zA-Z0-9_]{1,}' '__(asm|attribute)([^a-zA-Z0-9]|$)' 'reserved identifer' $* +hiegrep '//[-/<\* ]*$' 'empty comment' $* +hiegrep '/\*[-<\* ]*\*/' 'empty comment' $* +hiegrep 'for *\( *'"$ERE_PRITYP"' ' 'not gcc 2.95 compatible' $* +hiegrep '(static|inline|const) *\1' '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' $* +hiegrep '; */\*\*[^<]' 'Misformatted doxygen comment' $* +hiegrep '//!|/\*!' 'inconsistent doxygen syntax' $* + +hiegrep2 '(int|unsigned|static|void)[a-zA-Z0-9 _]*(init|end)[a-zA-Z0-9 _]*\(.*[^;]$' '(av_cold|:\+[^a-zA-Z_])' 'These functions may need av_cold, please review the whole patch for similar functions needing av_cold' $* + +hiegrep '\+= *1 *;' 'can be simplified to ++' $* +hiegrep '-= *1 *;' 'can be simplified to --' $* +hiegrep '((!|=)= *(0|NULL)[^0-9a-z]|[^0-9a-z](0|NULL) *(!|=)=)' 'x==0 / x!=0 can be simplified to !x / x' $* + +$EGREP $OPT '^\+ *(const *|)static' $*| $EGREP --color=always '[^=]= *(0|NULL)[^0-9a-zA-Z]'> $TMP && printf '\nuseless 0 init\n' +cat $TMP +hiegrep '# *ifdef * (HAVE|CONFIG)_' 'ifdefs that should be #if' $* + +hiegrep '\b(awnser|cant|dont|wont|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' $* +hiegrep '\bmalloc' 'Please use av_malloc' $* +hiegrep '\) *av_malloc' 'useless casts' $* +hiegrep ':\+ *'"$ERE_PRITYP"' *inline' 'non static inline or strangely ordered inline+static' $* +hiegrep "$ERE_FUNCS"' *\)' 'missing void' $* +hiegrep '(sprintf|strcat|strcpy)' 'Possible security issue, make sure this is safe or use snprintf/av_strl*' $* +hiegrep '/ *(2|4|8|16|32|64|128|256|512|1024|2048|4096|8192|16384|32768|65536)[^0-9]' 'divide by 2^x could use >> maybe' $* +hiegrep '#(el|)if *(0|1)' 'useless #if' $* +hiegrep 'if *\( *(0|1) *\)' 'useless if()' $* +hiegrep '& *[a-zA-Z0-9_]* *\[ *0 *\]' 'useless & [0]' $* +hiegrep '(\( *[0-9] *(&&|\|\|)|(&&|\|\|) *[0-9] *\))' 'overriding condition' $* +hiegrep '(:\+|,|;)( *|static|\*)*'"$ERE_PRITYP"' *\*( |\*)*(src|source|input|in[^a-z])' 'missing const?' $* +hiegrep '(:\+|,|;)( *|static|\*)*'"$ERE_PRITYP"' *(src|source|input|in)([0-9A-Z_][0-9A-Za-z_]*){1,} *\[' 'missing const (test2)?' $* +hiegrep ' *static *'"$ERE_FUNCS"'[^)]*\);' 'static prototype, maybe you should reorder your functions' $* +hiegrep '@file: *[a-zA-Z0-9_]' 'doxy filetag with filename can in the future cause problems when forgotten during a rename' $* +hiegrep '\bassert' 'Please use av_assert0, av_assert1 or av_assert2' $* + +hiegrep2 '\.long_name *=' 'NULL_IF_CONFIG_SMAL' 'missing NULL_IF_CONFIG_SMAL' $* +hiegrep2 '\.pix_fmts *= *\(' 'const' 'missing const for pix_fmts array' $* +hiegrep2 '\.sample_fmts *= *\(' 'const' 'missing const for sample_fmts array' $* +hiegrep2 '\.supported_framerates *= *\(' 'const' 'missing const for supported_framerates array' $* +hiegrep2 '\.channel_layouts *= *\(' 'const' 'missing const for channel_layouts array' $* + +#$EGREP $OPT '^\+.*const ' $*| $GREP -v 'static'> $TMP && printf '\nnon static const\n' +#cat $TMP + +hiegrep2 "$ERE_TYPES" '(static|av_|ff_|typedef|:\+[^a-zA-Z_])' 'Non static with no ff_/av_ prefix' $* + +hiegrep ':\+[^}#]*else' 'missing } prior to else' $* +hiegrep '(if|while|for)\(' 'missing whitespace between keyword and ( (feel free to ignore)' $* +hiegrep '(else|do){' 'missing whitespace between keyword and { (feel free to ignore)' $* +hiegrep '}(else|while)' 'missing whitespace between } and keyword (feel free to ignore)' $* + +#FIXME this should print the previous statement maybe +hiegrep ':\+ *{ *$' '{ should be on the same line as the related previous statement' $* + + +rm $TMP +for i in $($GREP -H '^+.*@param' $*| sed 's/^\([^:]*\):.*@param\(\[.*\]\|\) *\([a-zA-Z0-9_]*\) .*$/\1:\3/') ; do + doxpar=$(echo $i | sed 's/^.*:\(.*\)$/\1/') + file=$(echo $i | sed 's/^\([^:]*\):.*$/\1/') + $GREP " *$doxpar *[),]" $file | $GREP -v '@param' >/dev/null || $GREP --color=always "@param *$doxpar" $file >>$TMP +done +if test -e $TMP ; then + printf '\nmismatching doxy params\n' + cat $TMP +fi + +$EGREP -B2 $OPT '^(\+|) *('"$ERE_TYPES"'|# *define)' $* | $EGREP -A2 --color=always '(:|-)\+[^/]*/(\*([^*]|$)|/([^/]|$))' > $TMP && printf "\n Non doxy comments\n" +cat $TMP + +rm $TMP +for i in \ + $($EGREP -H '^\+ *'"$ERE_TYPES" $* |\ + $GREP -v '(' | $EGREP -v '\Wgoto\W' |\ + xargs -d '\n' -n 1 |\ + $GREP -o '[* ][* ]*[a-zA-Z][0-9a-zA-Z_]* *[,;=]' |\ + sed 's/.[* ]*\([a-zA-Z][0-9a-zA-Z_]*\) *[,;=]/\1/') \ + ; do + echo $i | $GREP '^NULL$' && continue + $EGREP $i' *(\+|-|\*|/|\||&|%|)=[^=]' $* >/dev/null || echo "possibly never written:"$i >> $TMP + $EGREP '(=|\(|return).*'$i'(==|[^=])*$' $* >/dev/null || echo "possibly never read :"$i >> $TMP + $EGREP -o $i' *((\+|-|\*|/|\||&|%|)=[^=]|\+\+|--) *(0x|)[0-9]*(;|)' $* |\ + $EGREP -v $i' *= *(0x|)[0-9]{1,};'>/dev/null || echo "possibly constant :"$i >> $TMP +done +if test -e $TMP ; then + printf '\npossibly unused variables\n' + cat $TMP +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 $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" +cat $TMP | tr '@' '\n' + +cat $* | tr '\n' '@' | $EGREP --color=always -o '\+ *if *\( *([A-Za-z0-9_]*) *[<>]=? *([A-Za-z0-9_]*) *\)[ @\\+]*(\1|\2) *= *(\1|\2) *;' >$TMP && printf "\nFFMIN/FFMAX\n" +cat $TMP | tr '@' '\n' + +cat $* | tr '\n' '@' | $EGREP --color=always -o '\+ *if *\( *([A-Za-z0-9_]*) *\)[ @\\+]*av_free(p|) *\( *(&|) *\1[^-.]' >$TMP && printf "\nav_free(NULL) is safe\n" +cat $TMP | tr '@' '\n' + +cat $* | tr '\n' '@' | $EGREP --color=always -o '[^a-zA-Z0-9_]([a-zA-Z0-9_]*) *= *av_malloc *\([^)]*\)[ @;\\+]*memset *\( *\1' >$TMP && printf "\nav_mallocz()\n" +cat $TMP | tr '@' '\n' + + +# does not work +#cat $* | tr '\n' '@' | $EGREP -o '[^a-zA-Z_0-9]([a-zA-Z][a-zA-Z_0-9]*) *=[^=].*\1' | $EGREP -o '[^a-zA-Z_0-9]([a-zA-Z][a-zA-Z_0-9]*) *=[^=].*\1 *=[^=]' >$TMP && printf "\nPossibly written 2x before read\n" +#cat $TMP | tr '@' '\n' + +exit + +TODO/idea list: + +for all demuxers & muxers + $EGREP for "avctx->priv_data" + +vertical align = +/* and * align +arrays fitting in smaller types +variables written to twice with no interspaced read +memset(block, 0, 6*64*sizeof(int16_t)); -> clear_blocks +check existence of long_name in AVCodec +check that the patch does not touch codec & (de)muxer layer at the same time ->split + +write a regression test containing at least a line that triggers each warning once diff --git a/ffmpeg1/tools/pktdumper.c b/ffmpeg1/tools/pktdumper.c new file mode 100644 index 0000000..920397b --- /dev/null +++ b/ffmpeg1/tools/pktdumper.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2005 Francois Revol + * + * 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 <limits.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#if HAVE_IO_H +#include <io.h> +#endif + +#define FILENAME_BUF_SIZE 4096 + +#include "libavutil/avstring.h" +#include "libavutil/time.h" +#include "libavformat/avformat.h" + +#define PKTFILESUFF "_%08" PRId64 "_%02d_%010" PRId64 "_%06d_%c.bin" + +static int usage(int ret) +{ + fprintf(stderr, "dump (up to maxpkts) AVPackets as they are demuxed by libavformat.\n"); + fprintf(stderr, "each packet is dumped in its own file named like `basename file.ext`_$PKTNUM_$STREAMINDEX_$STAMP_$SIZE_$FLAGS.bin\n"); + fprintf(stderr, "pktdumper [-nw] file [maxpkts]\n"); + fprintf(stderr, "-n\twrite No file at all, only demux.\n"); + fprintf(stderr, "-w\tWait at end of processing instead of quitting.\n"); + return ret; +} + +int main(int argc, char **argv) +{ + char fntemplate[FILENAME_BUF_SIZE]; + char pktfilename[FILENAME_BUF_SIZE]; + AVFormatContext *fctx = NULL; + AVPacket pkt; + int64_t pktnum = 0; + int64_t maxpkts = 0; + int donotquit = 0; + int nowrite = 0; + int err; + + if ((argc > 1) && !strncmp(argv[1], "-", 1)) { + if (strchr(argv[1], 'w')) + donotquit = 1; + if (strchr(argv[1], 'n')) + nowrite = 1; + argv++; + argc--; + } + if (argc < 2) + return usage(1); + if (argc > 2) + maxpkts = atoi(argv[2]); + av_strlcpy(fntemplate, argv[1], sizeof(fntemplate)); + if (strrchr(argv[1], '/')) + av_strlcpy(fntemplate, strrchr(argv[1], '/') + 1, sizeof(fntemplate)); + if (strrchr(fntemplate, '.')) + *strrchr(fntemplate, '.') = '\0'; + if (strchr(fntemplate, '%')) { + fprintf(stderr, "can't use filenames containing '%%'\n"); + return usage(1); + } + if (strlen(fntemplate) + sizeof(PKTFILESUFF) >= sizeof(fntemplate) - 1) { + fprintf(stderr, "filename too long\n"); + return usage(1); + } + strcat(fntemplate, PKTFILESUFF); + printf("FNTEMPLATE: '%s'\n", fntemplate); + + // register all file formats + av_register_all(); + + err = avformat_open_input(&fctx, argv[1], NULL, NULL); + if (err < 0) { + fprintf(stderr, "cannot open input: error %d\n", err); + return 1; + } + + err = avformat_find_stream_info(fctx, NULL); + if (err < 0) { + fprintf(stderr, "avformat_find_stream_info: error %d\n", err); + return 1; + } + + av_init_packet(&pkt); + + while ((err = av_read_frame(fctx, &pkt)) >= 0) { + int fd; + snprintf(pktfilename, sizeof(pktfilename), fntemplate, pktnum, + pkt.stream_index, pkt.pts, pkt.size, + (pkt.flags & AV_PKT_FLAG_KEY) ? 'K' : '_'); + printf(PKTFILESUFF "\n", pktnum, pkt.stream_index, pkt.pts, pkt.size, + (pkt.flags & AV_PKT_FLAG_KEY) ? 'K' : '_'); + if (!nowrite) { + fd = open(pktfilename, O_WRONLY | O_CREAT, 0644); + err = write(fd, pkt.data, pkt.size); + if (err < 0) { + fprintf(stderr, "write: error %d\n", err); + return 1; + } + close(fd); + } + av_free_packet(&pkt); + pktnum++; + if (maxpkts && (pktnum >= maxpkts)) + break; + } + + avformat_close_input(&fctx); + + while (donotquit) + av_usleep(60 * 1000000); + + return 0; +} diff --git a/ffmpeg1/tools/plotframes b/ffmpeg1/tools/plotframes new file mode 100755 index 0000000..f379723 --- /dev/null +++ b/ffmpeg1/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/ffmpeg1/tools/probetest.c b/ffmpeg1/tools/probetest.c new file mode 100644 index 0000000..b13c6f9 --- /dev/null +++ b/ffmpeg1/tools/probetest.c @@ -0,0 +1,145 @@ +/* + * copyright (c) 2009 Michael Niedermayer <michaelni@gmx.at> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdlib.h> + +#include "libavformat/avformat.h" +#include "libavcodec/put_bits.h" +#include "libavutil/lfg.h" + +static int score_array[1000]; //this must be larger than the number of formats +static int failures = 0; + +static void probe(AVProbeData *pd, int type, int p, int size) +{ + int i = 0; + AVInputFormat *fmt = NULL; + + while ((fmt = av_iformat_next(fmt))) { + if (fmt->flags & AVFMT_NOFILE) + continue; + if (fmt->read_probe) { + int score = fmt->read_probe(pd); + if (score > score_array[i] && score > AVPROBE_SCORE_MAX / 4) { + score_array[i] = score; + fprintf(stderr, + "Failure of %s probing code with score=%d type=%d p=%X size=%d\n", + fmt->name, score, type, p, size); + failures++; + } + } + i++; + } +} + +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(); + + av_lfg_init(&state, 0xdeadbeef); + + pd.buf = NULL; + 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 < retry_count; retry += FFMAX(size, 32)) { + for (type = 0; type < 4; type++) { + for (p = 0; p < 4096; p++) { + unsigned hist = 0; + init_put_bits(&pb, pd.buf, size); + switch (type) { + case 0: + for (i = 0; i < size * 8; i++) + put_bits(&pb, 1, (av_lfg_get(&state) & 0xFFFFFFFF) > p << 20); + break; + case 1: + for (i = 0; i < size * 8; i++) { + unsigned int p2 = hist ? p & 0x3F : (p >> 6); + unsigned int v = (av_lfg_get(&state) & 0xFFFFFFFF) > p2 << 26; + put_bits(&pb, 1, v); + hist = v; + } + break; + case 2: + for (i = 0; i < size * 8; i++) { + unsigned int p2 = (p >> (hist * 3)) & 7; + unsigned int v = (av_lfg_get(&state) & 0xFFFFFFFF) > p2 << 29; + put_bits(&pb, 1, v); + hist = (2 * hist + v) & 3; + } + break; + case 3: + for (i = 0; i < size; i++) { + int c = 0; + while (p & 63) { + c = (av_lfg_get(&state) & 0xFFFFFFFF) >> 24; + if (c >= 'a' && c <= 'z' && (p & 1)) + break; + else if (c >= 'A' && c <= 'Z' && (p & 2)) + break; + else if (c >= '0' && c <= '9' && (p & 4)) + break; + else if (c == ' ' && (p & 8)) + break; + else if (c == 0 && (p & 16)) + break; + else if (c == 1 && (p & 32)) + break; + } + pd.buf[i] = c; + } + } + flush_put_bits(&pb); + probe(&pd, type, p, size); + } + } + } + } + return failures; +} diff --git a/ffmpeg1/tools/qt-faststart.c b/ffmpeg1/tools/qt-faststart.c new file mode 100644 index 0000000..c9aa6e8 --- /dev/null +++ b/ffmpeg1/tools/qt-faststart.c @@ -0,0 +1,356 @@ +/* + * qt-faststart.c, v0.2 + * by Mike Melanson (melanson@pcisys.net) + * This file is placed in the public domain. Use the program however you + * see fit. + * + * This utility rearranges a Quicktime file such that the moov atom + * is in front of the data, thus facilitating network streaming. + * + * To compile this program, start from the base directory from which you + * 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 + * guaranteed, particularly on 64-bit platforms. + * Invoke the program with: + * qt-faststart <infile.mov> <outfile.mov> + * + * Notes: Quicktime files can come in many configurations of top-level + * atoms. This utility stipulates that the very last atom in the file needs + * to be a moov atom. When given such a file, this utility will rearrange + * the top-level atoms by shifting the moov atom from the back of the file + * to the front, and patch the chunk offsets along the way. This utility + * presently only operates on uncompressed moov atoms. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> + +#ifdef __MINGW32__ +#define fseeko(x, y, z) fseeko64(x, y, z) +#define ftello(x) ftello64(x) +#elif defined(_WIN32) +#define fseeko(x, y, z) _fseeki64(x, y, z) +#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) | \ + (((uint8_t*)(x))[1] << 16) | \ + (((uint8_t*)(x))[2] << 8) | \ + ((uint8_t*)(x))[3]) + +#define BE_64(x) (((uint64_t)(((uint8_t*)(x))[0]) << 56) | \ + ((uint64_t)(((uint8_t*)(x))[1]) << 48) | \ + ((uint64_t)(((uint8_t*)(x))[2]) << 40) | \ + ((uint64_t)(((uint8_t*)(x))[3]) << 32) | \ + ((uint64_t)(((uint8_t*)(x))[4]) << 24) | \ + ((uint64_t)(((uint8_t*)(x))[5]) << 16) | \ + ((uint64_t)(((uint8_t*)(x))[6]) << 8) | \ + ((uint64_t)( (uint8_t*)(x))[7])) + +#define BE_FOURCC(ch0, ch1, ch2, ch3) \ + ( (uint32_t)(unsigned char)(ch3) | \ + ((uint32_t)(unsigned char)(ch2) << 8) | \ + ((uint32_t)(unsigned char)(ch1) << 16) | \ + ((uint32_t)(unsigned char)(ch0) << 24) ) + +#define QT_ATOM BE_FOURCC +/* top level atoms */ +#define FREE_ATOM QT_ATOM('f', 'r', 'e', 'e') +#define JUNK_ATOM QT_ATOM('j', 'u', 'n', 'k') +#define MDAT_ATOM QT_ATOM('m', 'd', 'a', 't') +#define MOOV_ATOM QT_ATOM('m', 'o', 'o', 'v') +#define PNOT_ATOM QT_ATOM('p', 'n', 'o', 't') +#define SKIP_ATOM QT_ATOM('s', 'k', 'i', 'p') +#define WIDE_ATOM QT_ATOM('w', 'i', 'd', 'e') +#define PICT_ATOM QT_ATOM('P', 'I', 'C', 'T') +#define FTYP_ATOM QT_ATOM('f', 't', 'y', 'p') +#define UUID_ATOM QT_ATOM('u', 'u', 'i', 'd') + +#define CMOV_ATOM QT_ATOM('c', 'm', 'o', 'v') +#define STCO_ATOM QT_ATOM('s', 't', 'c', 'o') +#define CO64_ATOM QT_ATOM('c', 'o', '6', '4') + +#define ATOM_PREAMBLE_SIZE 8 +#define COPY_BUFFER_SIZE 33554432 + +int main(int argc, char *argv[]) +{ + FILE *infile = NULL; + FILE *outfile = NULL; + unsigned char atom_bytes[ATOM_PREAMBLE_SIZE]; + uint32_t atom_type = 0; + uint64_t atom_size = 0; + uint64_t atom_offset = 0; + uint64_t last_offset; + unsigned char *moov_atom = NULL; + unsigned char *ftyp_atom = NULL; + uint64_t moov_atom_size; + uint64_t ftyp_atom_size = 0; + uint64_t i, j; + uint32_t offset_count; + uint64_t current_offset; + int64_t start_offset = 0; + unsigned char *copy_buffer = NULL; + int bytes_to_copy; + + if (argc != 3) { + printf("Usage: qt-faststart <infile.mov> <outfile.mov>\n"); + return 0; + } + + if (!strcmp(argv[1], argv[2])) { + fprintf(stderr, "input and output files need to be different\n"); + return 1; + } + + infile = fopen(argv[1], "rb"); + if (!infile) { + perror(argv[1]); + goto error_out; + } + + /* traverse through the atoms in the file to make sure that 'moov' is + * at the end */ + while (!feof(infile)) { + if (fread(atom_bytes, ATOM_PREAMBLE_SIZE, 1, infile) != 1) { + break; + } + atom_size = (uint32_t) BE_32(&atom_bytes[0]); + atom_type = BE_32(&atom_bytes[4]); + + /* keep ftyp atom */ + if (atom_type == FTYP_ATOM) { + ftyp_atom_size = atom_size; + free(ftyp_atom); + ftyp_atom = malloc(ftyp_atom_size); + if (!ftyp_atom) { + printf("could not allocate %"PRIu64" bytes for ftyp atom\n", + atom_size); + goto error_out; + } + 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; + } + } 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]); + ret = fseeko(infile, atom_size - ATOM_PREAMBLE_SIZE * 2, SEEK_CUR); + } else { + 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", + (atom_type >> 24) & 255, + (atom_type >> 16) & 255, + (atom_type >> 8) & 255, + (atom_type >> 0) & 255, + atom_offset, + atom_size); + if ((atom_type != FREE_ATOM) && + (atom_type != JUNK_ATOM) && + (atom_type != MDAT_ATOM) && + (atom_type != MOOV_ATOM) && + (atom_type != PNOT_ATOM) && + (atom_type != SKIP_ATOM) && + (atom_type != WIDE_ATOM) && + (atom_type != PICT_ATOM) && + (atom_type != UUID_ATOM) && + (atom_type != FTYP_ATOM)) { + printf("encountered non-QT top-level atom (is this a QuickTime file?)\n"); + break; + } + atom_offset += atom_size; + + /* The atom header is 8 (or 16 bytes), if the atom size (which + * includes these 8 or 16 bytes) is less than that, we won't be + * able to continue scanning sensibly after this atom, so break. */ + if (atom_size < 8) + break; + } + + if (atom_type != MOOV_ATOM) { + printf("last atom in file was not a moov atom\n"); + free(ftyp_atom); + fclose(infile); + return 0; + } + + /* moov atom was, in fact, the last atom in the chunk; load the whole + * moov atom */ + 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); + if (!moov_atom) { + printf("could not allocate %"PRIu64" bytes for moov atom\n", atom_size); + goto error_out; + } + if (fread(moov_atom, atom_size, 1, infile) != 1) { + perror(argv[1]); + goto error_out; + } + + /* this utility does not support compressed atoms yet, so disqualify + * files with compressed QT atoms */ + if (BE_32(&moov_atom[12]) == CMOV_ATOM) { + printf("this utility does not support compressed moov atoms yet\n"); + goto error_out; + } + + /* close; will be re-opened later */ + fclose(infile); + infile = NULL; + + /* crawl through the moov chunk in search of stco or co64 atoms */ + for (i = 4; i < moov_atom_size - 4; i++) { + 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]); + 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 += 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; + moov_atom[i + 12 + j * 4 + 2] = (current_offset >> 8) & 0xFF; + moov_atom[i + 12 + j * 4 + 3] = (current_offset >> 0) & 0xFF; + } + i += atom_size - 4; + } else if (atom_type == CO64_ATOM) { + printf(" patching co64 atom...\n"); + atom_size = 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; + moov_atom[i + 12 + j * 8 + 0] = (current_offset >> 56) & 0xFF; + moov_atom[i + 12 + j * 8 + 1] = (current_offset >> 48) & 0xFF; + moov_atom[i + 12 + j * 8 + 2] = (current_offset >> 40) & 0xFF; + moov_atom[i + 12 + j * 8 + 3] = (current_offset >> 32) & 0xFF; + moov_atom[i + 12 + j * 8 + 4] = (current_offset >> 24) & 0xFF; + moov_atom[i + 12 + j * 8 + 5] = (current_offset >> 16) & 0xFF; + moov_atom[i + 12 + j * 8 + 6] = (current_offset >> 8) & 0xFF; + moov_atom[i + 12 + j * 8 + 7] = (current_offset >> 0) & 0xFF; + } + i += atom_size - 4; + } + } + + /* re-open the input file and open the output file */ + infile = fopen(argv[1], "rb"); + if (!infile) { + perror(argv[1]); + goto error_out; + } + + if (start_offset > 0) { /* seek after ftyp atom */ + if (fseeko(infile, start_offset, SEEK_SET)) { + perror(argv[1]); + goto error_out; + } + + last_offset -= start_offset; + } + + outfile = fopen(argv[2], "wb"); + if (!outfile) { + perror(argv[2]); + goto error_out; + } + + /* dump the same ftyp atom */ + if (ftyp_atom_size > 0) { + printf(" writing ftyp atom...\n"); + if (fwrite(ftyp_atom, ftyp_atom_size, 1, outfile) != 1) { + perror(argv[2]); + goto error_out; + } + } + + /* dump the new moov atom */ + printf(" writing moov atom...\n"); + if (fwrite(moov_atom, moov_atom_size, 1, outfile) != 1) { + perror(argv[2]); + goto error_out; + } + + /* 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) { + bytes_to_copy = FFMIN(bytes_to_copy, last_offset); + + if (fread(copy_buffer, bytes_to_copy, 1, infile) != 1) { + perror(argv[1]); + goto error_out; + } + if (fwrite(copy_buffer, bytes_to_copy, 1, outfile) != 1) { + perror(argv[2]); + goto error_out; + } + last_offset -= bytes_to_copy; + } + + fclose(infile); + fclose(outfile); + free(moov_atom); + free(ftyp_atom); + free(copy_buffer); + + return 0; + +error_out: + if (infile) + fclose(infile); + if (outfile) + fclose(outfile); + free(moov_atom); + free(ftyp_atom); + free(copy_buffer); + return 1; +} diff --git a/ffmpeg1/tools/seek_print.c b/ffmpeg1/tools/seek_print.c new file mode 100644 index 0000000..a99a0ad --- /dev/null +++ b/ffmpeg1/tools/seek_print.c @@ -0,0 +1,107 @@ +/* + * 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 <unistd.h> + +#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:%"PRIi64":%"PRIi64":%"PRIi64":%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/ffmpeg1/tools/trasher.c b/ffmpeg1/tools/trasher.c new file mode 100644 index 0000000..aaa09f4 --- /dev/null +++ b/ffmpeg1/tools/trasher.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2007 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <errno.h> +#include <string.h> + +static uint32_t state; +static uint32_t ran(void) +{ + return state = state * 1664525 + 1013904223; +} + +int main(int argc, char **argv) +{ + FILE *f; + int count, maxburst, length; + + if (argc < 5) { + printf("USAGE: trasher <filename> <count> <maxburst> <seed>\n"); + return 1; + } + + f = fopen(argv[1], "rb+"); + if (!f) { + perror(argv[1]); + return 2; + } + count = atoi(argv[2]); + maxburst = atoi(argv[3]); + state = atoi(argv[4]); + + fseek(f, 0, SEEK_END); + length = ftell(f); + fseek(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; + if (fseek(f, pos, SEEK_SET) < 0) { + fprintf(stderr, "seek failed\n"); + return 1; + } + + if (maxburst < 0) + burst = -maxburst; + + if (pos + burst > length) + continue; + + while (burst--) { + int val = ran() * 256ULL / UINT32_MAX; + + if (maxburst < 0) + val = 0; + + fwrite(&val, 1, 1, f); + } + } + + return 0; +} diff --git a/ffmpeg1/tools/unwrap-diff b/ffmpeg1/tools/unwrap-diff new file mode 100755 index 0000000..ccea99b --- /dev/null +++ b/ffmpeg1/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/ffmpeg1/tools/yuvcmp.c b/ffmpeg1/tools/yuvcmp.c new file mode 100644 index 0000000..11585f9 --- /dev/null +++ b/ffmpeg1/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; +} |
