Updated FFMPEG to version 1.1.2, using this project: http://sourceforge.net/projects/ffmpeg4android/

This commit is contained in:
Sergii Pylypenko
2013-02-21 18:29:51 +02:00
parent 758a9658d2
commit fff7a99a41
3492 changed files with 886704 additions and 5414 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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 &lt; l.length ; i++) {
d.body.appendChild(p = d.createElement("p"));
p.appendChild(a = d.createElement("a"));
a.appendChild(d.createTextNode(l[i].textContent));
a.href="http://www.ted.com/talks/subtitles/id/" + talkID+"/lang/" + l[i].value;
}
</pre>
</body>
</html>

View File

@@ -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

View File

@@ -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'

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,233 @@
/*
* 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"
"-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 'full', 'lazy', 'quote', default is 'lazy'\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");
}
#define WHITESPACES " \n\t"
enum EscapeMode {
ESCAPE_MODE_FULL,
ESCAPE_MODE_LAZY,
ESCAPE_MODE_QUOTE,
};
static int escape(char **dst, const char *src, const char *special_chars,
enum EscapeMode mode)
{
AVBPrint dstbuf;
av_bprint_init(&dstbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
switch (mode) {
case ESCAPE_MODE_FULL:
case ESCAPE_MODE_LAZY:
/* \-escape characters */
if (mode == ESCAPE_MODE_LAZY && strchr(WHITESPACES, *src))
av_bprintf(&dstbuf, "\\%c", *src++);
for (; *src; src++) {
if ((special_chars && strchr(special_chars, *src)) ||
strchr("'\\", *src) ||
(mode == ESCAPE_MODE_FULL && strchr(WHITESPACES, *src)))
av_bprintf(&dstbuf, "\\%c", *src);
else
av_bprint_chars(&dstbuf, *src, 1);
}
if (mode == ESCAPE_MODE_LAZY && strchr(WHITESPACES, dstbuf.str[dstbuf.len-1])) {
char c = dstbuf.str[dstbuf.len-1];
dstbuf.str[dstbuf.len-1] = '\\';
av_bprint_chars(&dstbuf, c, 1);
}
break;
case ESCAPE_MODE_QUOTE:
/* enclose between '' the string */
av_bprint_chars(&dstbuf, '\'', 1);
for (; *src; src++) {
if (*src == '\'')
av_bprintf(&dstbuf, "'\\''");
else
av_bprint_chars(&dstbuf, *src, 1);
}
av_bprint_chars(&dstbuf, '\'', 1);
break;
default:
/* unknown escape mode */
return AVERROR(EINVAL);
}
if (!av_bprint_is_complete(&dstbuf)) {
av_bprint_finalize(&dstbuf, NULL);
return AVERROR(ENOMEM);
} else {
av_bprint_finalize(&dstbuf, dst);
return 0;
}
}
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 EscapeMode escape_mode = ESCAPE_MODE_LAZY;
int level = 1;
int echo = 0;
char *special_chars = NULL;
int c;
while ((c = getopt(argc, argv, "ehi:l:o:m:p:s:")) != -1) {
switch (c) {
case 'e':
echo = 1;
break;
case 'h':
usage();
return 0;
case 'i':
infilename = optarg;
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, "full")) escape_mode = ESCAPE_MODE_FULL;
else if (!strcmp(optarg, "lazy")) escape_mode = ESCAPE_MODE_LAZY;
else if (!strcmp(optarg, "quote")) escape_mode = ESCAPE_MODE_QUOTE;
else {
av_log(NULL, AV_LOG_ERROR,
"Invalid value '%s' for option -m, "
"valid arguments are 'full', 'lazy', '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 (escape(&dst_buf, src_buf, special_chars, escape_mode) < 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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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->filter_count; 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;
}

View File

@@ -0,0 +1,557 @@
/*
* 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 "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 VideoFile {
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 VideoFiles {
int nb_files;
int64_t duration;
struct VideoFile **files;
int video_file, audio_file;
int nb_video_files, nb_audio_files;
};
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 VideoFiles *files, int start_index,
AVIOContext *in)
{
char dirname[100], filename[500];
int i, j;
for (i = start_index; i < files->nb_files; i++) {
struct VideoFile *vf = files->files[i];
const char *type = vf->is_video ? "video" : "audio";
snprintf(dirname, sizeof(dirname), "QualityLevels(%d)", vf->bitrate);
mkdir(dirname, 0777);
for (j = 0; j < vf->chunks; j++) {
snprintf(filename, sizeof(filename), "%s/Fragments(%s=%"PRId64")",
dirname, type, vf->offsets[j].time);
avio_seek(in, vf->offsets[j].offset, SEEK_SET);
write_fragment(filename, in);
}
}
return 0;
}
static int read_tfra(struct VideoFiles *files, 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 VideoFile *vf = 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 < files->nb_files && !vf; i++)
if (files->files[i]->track_id == track_id)
vf = files->files[i];
if (!vf) {
/* Ok, continue parsing the next atom */
ret = 0;
goto fail;
}
fieldlength = avio_rb32(f);
vf->chunks = avio_rb32(f);
vf->offsets = av_mallocz(sizeof(*vf->offsets) * vf->chunks);
if (!vf->offsets) {
ret = AVERROR(ENOMEM);
goto fail;
}
for (i = 0; i < vf->chunks; i++) {
if (version == 1) {
vf->offsets[i].time = avio_rb64(f);
vf->offsets[i].offset = avio_rb64(f);
} else {
vf->offsets[i].time = avio_rb32(f);
vf->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)
vf->offsets[i - 1].duration = vf->offsets[i].time -
vf->offsets[i - 1].time;
}
if (vf->chunks > 0)
vf->offsets[vf->chunks - 1].duration = vf->duration -
vf->offsets[vf->chunks - 1].time;
ret = 0;
fail:
avio_seek(f, pos + size, SEEK_SET);
return ret;
}
static int read_mfra(struct VideoFiles *files, 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(files, start_index, f)) {
/* Empty */
}
if (split)
write_fragments(files, 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 VideoFile *vf, AVCodecContext *codec)
{
vf->codec_private_size = codec->extradata_size;
vf->codec_private = av_mallocz(codec->extradata_size);
if (!vf->codec_private)
return AVERROR(ENOMEM);
memcpy(vf->codec_private, codec->extradata, codec->extradata_size);
return 0;
}
static int get_video_private_data(struct VideoFile *vf, 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(vf, 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:
vf->codec_private_size = avio_close_dyn_buf(io, &vf->codec_private);
return err;
}
static int handle_file(struct VideoFiles *files, const char *file, int split)
{
AVFormatContext *ctx = NULL;
int err = 0, i, orig_files = files->nb_files;
char errbuf[50], *ptr;
struct VideoFile *vf;
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 (!files->duration)
files->duration = ctx->duration;
for (i = 0; i < ctx->nb_streams; i++) {
AVStream *st = ctx->streams[i];
vf = av_mallocz(sizeof(*vf));
files->files = av_realloc(files->files,
sizeof(*files->files) * (files->nb_files + 1));
files->files[files->nb_files] = vf;
vf->name = file;
if ((ptr = strrchr(file, '/')) != NULL)
vf->name = ptr + 1;
vf->bitrate = st->codec->bit_rate;
vf->track_id = st->id;
vf->timescale = st->time_base.den;
vf->duration = av_rescale_rnd(ctx->duration, vf->timescale,
AV_TIME_BASE, AV_ROUND_UP);
vf->is_audio = st->codec->codec_type == AVMEDIA_TYPE_AUDIO;
vf->is_video = st->codec->codec_type == AVMEDIA_TYPE_VIDEO;
if (!vf->is_audio && !vf->is_video) {
fprintf(stderr,
"Track %d in %s is neither video nor audio, skipping\n",
vf->track_id, file);
av_freep(&files->files[files->nb_files]);
continue;
}
if (vf->is_audio) {
if (files->audio_file < 0)
files->audio_file = files->nb_files;
files->nb_audio_files++;
vf->channels = st->codec->channels;
vf->sample_rate = st->codec->sample_rate;
if (st->codec->codec_id == AV_CODEC_ID_AAC) {
vf->fourcc = "AACL";
vf->tag = 255;
vf->blocksize = 4;
} else if (st->codec->codec_id == AV_CODEC_ID_WMAPRO) {
vf->fourcc = "WMAP";
vf->tag = st->codec->codec_tag;
vf->blocksize = st->codec->block_align;
}
get_private_data(vf, st->codec);
}
if (vf->is_video) {
if (files->video_file < 0)
files->video_file = files->nb_files;
files->nb_video_files++;
vf->width = st->codec->width;
vf->height = st->codec->height;
if (st->codec->codec_id == AV_CODEC_ID_H264)
vf->fourcc = "H264";
else if (st->codec->codec_id == AV_CODEC_ID_VC1)
vf->fourcc = "WVC1";
get_video_private_data(vf, st->codec);
}
files->nb_files++;
}
avformat_close_input(&ctx);
err = read_mfra(files, orig_files, file, split);
fail:
if (ctx)
avformat_close_input(&ctx);
return err;
}
static void output_server_manifest(struct VideoFiles *files,
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 < files->nb_files; i++) {
struct VideoFile *vf = files->files[i];
const char *type = vf->is_video ? "video" : "audio";
fprintf(out, "\t\t\t<%s src=\"%s\" systemBitrate=\"%d\">\n",
type, vf->name, vf->bitrate);
fprintf(out, "\t\t\t\t<param name=\"trackID\" value=\"%d\" "
"valueType=\"data\" />\n", vf->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 output_client_manifest(struct VideoFiles *files,
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", files->duration * 10);
if (files->video_file >= 0) {
struct VideoFile *vf = files->files[files->video_file];
struct VideoFile *first_vf = vf;
int index = 0;
fprintf(out,
"\t<StreamIndex Type=\"video\" QualityLevels=\"%d\" "
"Chunks=\"%d\" "
"Url=\"QualityLevels({bitrate})/Fragments(video={start time})\">\n",
files->nb_video_files, vf->chunks);
for (i = 0; i < files->nb_files; i++) {
vf = files->files[i];
if (!vf->is_video)
continue;
fprintf(out,
"\t\t<QualityLevel Index=\"%d\" Bitrate=\"%d\" "
"FourCC=\"%s\" MaxWidth=\"%d\" MaxHeight=\"%d\" "
"CodecPrivateData=\"",
index, vf->bitrate, vf->fourcc, vf->width, vf->height);
for (j = 0; j < vf->codec_private_size; j++)
fprintf(out, "%02X", vf->codec_private[j]);
fprintf(out, "\" />\n");
index++;
if (vf->chunks != first_vf->chunks)
fprintf(stderr, "Mismatched number of video chunks in %s and %s\n",
vf->name, first_vf->name);
}
vf = first_vf;
for (i = 0; i < vf->chunks; i++) {
for (j = files->video_file + 1; j < files->nb_files; j++) {
if (files->files[j]->is_video &&
vf->offsets[i].duration != files->files[j]->offsets[i].duration)
fprintf(stderr, "Mismatched duration of video chunk %d in %s and %s\n",
i, vf->name, files->files[j]->name);
}
fprintf(out, "\t\t<c n=\"%d\" d=\"%d\" />\n", i,
vf->offsets[i].duration);
}
fprintf(out, "\t</StreamIndex>\n");
}
if (files->audio_file >= 0) {
struct VideoFile *vf = files->files[files->audio_file];
struct VideoFile *first_vf = vf;
int index = 0;
fprintf(out,
"\t<StreamIndex Type=\"audio\" QualityLevels=\"%d\" "
"Chunks=\"%d\" "
"Url=\"QualityLevels({bitrate})/Fragments(audio={start time})\">\n",
files->nb_audio_files, vf->chunks);
for (i = 0; i < files->nb_files; i++) {
vf = files->files[i];
if (!vf->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, vf->bitrate, vf->fourcc, vf->sample_rate,
vf->channels, vf->blocksize, vf->tag);
for (j = 0; j < vf->codec_private_size; j++)
fprintf(out, "%02X", vf->codec_private[j]);
fprintf(out, "\" />\n");
index++;
if (vf->chunks != first_vf->chunks)
fprintf(stderr, "Mismatched number of audio chunks in %s and %s\n",
vf->name, first_vf->name);
}
vf = first_vf;
for (i = 0; i < vf->chunks; i++) {
for (j = files->audio_file + 1; j < files->nb_files; j++) {
if (files->files[j]->is_audio &&
vf->offsets[i].duration != files->files[j]->offsets[i].duration)
fprintf(stderr, "Mismatched duration of audio chunk %d in %s and %s\n",
i, vf->name, files->files[j]->name);
}
fprintf(out, "\t\t<c n=\"%d\" d=\"%d\" />\n",
i, vf->offsets[i].duration);
}
fprintf(out, "\t</StreamIndex>\n");
}
fprintf(out, "</SmoothStreamingMedia>\n");
fclose(out);
}
static void clean_files(struct VideoFiles *files)
{
int i;
for (i = 0; i < files->nb_files; i++) {
av_freep(&files->files[i]->codec_private);
av_freep(&files->files[i]->offsets);
av_freep(&files->files[i]);
}
av_freep(&files->files);
files->nb_files = 0;
}
int main(int argc, char **argv)
{
const char *basename = NULL;
int split = 0, i;
struct VideoFiles vf = { 0, .video_file = -1, .audio_file = -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(&vf, argv[i], split))
return 1;
}
}
if (!vf.nb_files || (!basename && !split))
return usage(argv[0], 1);
if (!split)
output_server_manifest(&vf, basename);
output_client_manifest(&vf, basename, split);
clean_files(&vf);
return 0;
}

View File

@@ -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";

View File

@@ -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

180
project/jni/ffmpeg/tools/patcheck Executable file
View File

@@ -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(DCTELEM)); -> 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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,2 @@
#!/bin/sh
tr '\n' '\001' | sed 's/\x01\x01/\x01 \x01/g' | sed 's/\x01\([^-+ @]\)/ \1/g' | tr '\001' '\n'

View File

@@ -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;
}