Commit 7b376b39 authored by Michael Niedermayer's avatar Michael Niedermayer

Merge remote branch 'qatar/master'

* qatar/master:
  Handle unicode file names on windows
  rtp: Rename the open/close functions to alloc/free
  Lowercase all ff* program names.
  Refer to ff* tools by their lowercase names.
NOT Pulled  Replace more FFmpeg instances by Libav or ffmpeg.
  Replace `` by $() syntax in shell scripts.
  patcheck: Allow overiding grep program(s) through environment variables.
NOT Pulled  Remove stray libavcore and _g binary references.
  vorbis: Rename decoder/encoder files to follow general file naming scheme.
  aacenc: Fix whitespace after last commit.
  cook: Fix small typo in av_log_ask_for_sample message.
  aacenc: Finish 3GPP psymodel analysis for non mid/side cases.
  Remove RDFT dependency from AAC decoder.
  Add some debug log messages to AAC extradata
  Fix mov debug (u)int64_t format strings.
  bswap: use native types for av_bwap16().
  doc: FLV muxing is supported.
  applehttp: Handle AES-128 encrypted streams
  Add a protocol handler for AES CBC decryption with PKCS7 padding
  doc: Mention that DragonFly BSD requires __BSD_VISIBLE set

Conflicts:
	ffplay.c
	ffprobe.c
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents c225615b b1ac139d
...@@ -153,6 +153,66 @@ static const OptionDef* find_option(const OptionDef *po, const char *name){ ...@@ -153,6 +153,66 @@ static const OptionDef* find_option(const OptionDef *po, const char *name){
return po; return po;
} }
#if defined(_WIN32) && !defined(__MINGW32CE__)
/* Will be leaked on exit */
static char** win32_argv_utf8 = NULL;
static int win32_argc = 0;
/**
* Prepare command line arguments for executable.
* For Windows - perform wide-char to UTF-8 conversion.
* Input arguments should be main() function arguments.
* @param argc_ptr Arguments number (including executable)
* @param argv_ptr Arguments list.
*/
static void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
{
char *argstr_flat;
wchar_t **argv_w;
int i, buffsize = 0, offset = 0;
if (win32_argv_utf8) {
*argc_ptr = win32_argc;
*argv_ptr = win32_argv_utf8;
return;
}
win32_argc = 0;
argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc);
if (win32_argc <= 0 || !argv_w)
return;
/* determine the UTF-8 buffer size (including NULL-termination symbols) */
for (i = 0; i < win32_argc; i++)
buffsize += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1,
NULL, 0, NULL, NULL);
win32_argv_utf8 = av_mallocz(sizeof(char*) * (win32_argc + 1) + buffsize);
argstr_flat = (char*)win32_argv_utf8 + sizeof(char*) * (win32_argc + 1);
if (win32_argv_utf8 == NULL) {
LocalFree(argv_w);
return;
}
for (i = 0; i < win32_argc; i++) {
win32_argv_utf8[i] = &argstr_flat[offset];
offset += WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1,
&argstr_flat[offset],
buffsize - offset, NULL, NULL);
}
win32_argv_utf8[i] = NULL;
LocalFree(argv_w);
*argc_ptr = win32_argc;
*argv_ptr = win32_argv_utf8;
}
#else
static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
{
/* nothing to do */
}
#endif /* WIN32 && !__MINGW32CE__ */
void parse_options(int argc, char **argv, const OptionDef *options, void parse_options(int argc, char **argv, const OptionDef *options,
void (* parse_arg_function)(const char*)) void (* parse_arg_function)(const char*))
{ {
...@@ -160,6 +220,9 @@ void parse_options(int argc, char **argv, const OptionDef *options, ...@@ -160,6 +220,9 @@ void parse_options(int argc, char **argv, const OptionDef *options,
int optindex, handleoptions=1; int optindex, handleoptions=1;
const OptionDef *po; const OptionDef *po;
/* perform system-dependent conversions for arguments list */
prepare_app_arguments(&argc, &argv);
/* parse options */ /* parse options */
optindex = 1; optindex = 1;
while (optindex < argc) { while (optindex < argc) {
......
...@@ -1248,7 +1248,7 @@ mdct_select="fft" ...@@ -1248,7 +1248,7 @@ mdct_select="fft"
rdft_select="fft" rdft_select="fft"
# decoders / encoders / hardware accelerators # decoders / encoders / hardware accelerators
aac_decoder_select="mdct rdft sinewin" aac_decoder_select="mdct sinewin"
aac_encoder_select="mdct sinewin" aac_encoder_select="mdct sinewin"
aac_latm_decoder_select="aac_decoder aac_latm_parser" aac_latm_decoder_select="aac_decoder aac_latm_parser"
ac3_decoder_select="mdct ac3dsp ac3_parser" ac3_decoder_select="mdct ac3dsp ac3_parser"
......
...@@ -280,7 +280,7 @@ Just create an "input.avs" text file with this single line ... ...@@ -280,7 +280,7 @@ Just create an "input.avs" text file with this single line ...
@example @example
DirectShowSource("C:\path to your file\yourfile.asf") DirectShowSource("C:\path to your file\yourfile.asf")
@end example @end example
... and then feed that text file to FFmpeg: ... and then feed that text file to ffmpeg:
@example @example
ffmpeg -i input.avs ffmpeg -i input.avs
@end example @end example
...@@ -348,7 +348,7 @@ ffmpeg -f u16le -acodec pcm_s16le -ac 2 -ar 44100 -i all.a \ ...@@ -348,7 +348,7 @@ ffmpeg -f u16le -acodec pcm_s16le -ac 2 -ar 44100 -i all.a \
rm temp[12].[av] all.[av] rm temp[12].[av] all.[av]
@end example @end example
@section FFmpeg does not adhere to the -maxrate setting, some frames are bigger than maxrate/fps. @section The ffmpeg program does not respect the -maxrate setting, some frames are bigger than maxrate/fps.
Read the MPEG spec about video buffer verifier. Read the MPEG spec about video buffer verifier.
......
\input texinfo @c -*- texinfo -*- \input texinfo @c -*- texinfo -*-
@settitle FFmpeg Documentation @settitle ffmpeg Documentation
@titlepage @titlepage
@center @titlefont{FFmpeg Documentation} @center @titlefont{ffmpeg Documentation}
@end titlepage @end titlepage
@top @top
...@@ -22,17 +22,15 @@ ffmpeg [[infile options][@option{-i} @var{infile}]]... @{[outfile options] @var{ ...@@ -22,17 +22,15 @@ ffmpeg [[infile options][@option{-i} @var{infile}]]... @{[outfile options] @var{
@chapter Description @chapter Description
@c man begin DESCRIPTION @c man begin DESCRIPTION
FFmpeg is a very fast video and audio converter. It can also grab from ffmpeg is a very fast video and audio converter that can also grab from
a live audio/video source. a live audio/video source. It can also convert between arbitrary sample
rates and resize video on the fly with a high quality polyphase filter.
The command line interface is designed to be intuitive, in the sense The command line interface is designed to be intuitive, in the sense
that FFmpeg tries to figure out all parameters that can possibly be that ffmpeg tries to figure out all parameters that can possibly be
derived automatically. You usually only have to specify the target derived automatically. You usually only have to specify the target
bitrate you want. bitrate you want.
FFmpeg can also convert from any sample rate to any other, and resize
video on the fly with a high quality polyphase filter.
As a general rule, options are applied to the next specified As a general rule, options are applied to the next specified
file. Therefore, order is important, and you can have the same file. Therefore, order is important, and you can have the same
option on the command line multiple times. Each occurrence is option on the command line multiple times. Each occurrence is
...@@ -61,7 +59,7 @@ ffmpeg -r 1 -i input.m2v -r 24 output.avi ...@@ -61,7 +59,7 @@ ffmpeg -r 1 -i input.m2v -r 24 output.avi
The format option may be needed for raw input files. The format option may be needed for raw input files.
By default, FFmpeg tries to convert as losslessly as possible: It By default ffmpeg tries to convert as losslessly as possible: It
uses the same audio and video parameters for the outputs as the one uses the same audio and video parameters for the outputs as the one
specified for the inputs. specified for the inputs.
...@@ -495,7 +493,7 @@ Use 'frames' B-frames (supported for MPEG-1, MPEG-2 and MPEG-4). ...@@ -495,7 +493,7 @@ Use 'frames' B-frames (supported for MPEG-1, MPEG-2 and MPEG-4).
macroblock decision macroblock decision
@table @samp @table @samp
@item 0 @item 0
FF_MB_DECISION_SIMPLE: Use mb_cmp (cannot change it yet in FFmpeg). FF_MB_DECISION_SIMPLE: Use mb_cmp (cannot change it yet in ffmpeg).
@item 1 @item 1
FF_MB_DECISION_BITS: Choose the one which needs the fewest bits. FF_MB_DECISION_BITS: Choose the one which needs the fewest bits.
@item 2 @item 2
...@@ -877,22 +875,22 @@ It allows almost lossless encoding. ...@@ -877,22 +875,22 @@ It allows almost lossless encoding.
@section Video and Audio grabbing @section Video and Audio grabbing
FFmpeg can grab video and audio from devices given that you specify the input If you specify the input format and device then ffmpeg can grab video
format and device. and audio directly.
@example @example
ffmpeg -f oss -i /dev/dsp -f video4linux2 -i /dev/video0 /tmp/out.mpg ffmpeg -f oss -i /dev/dsp -f video4linux2 -i /dev/video0 /tmp/out.mpg
@end example @end example
Note that you must activate the right video source and channel before Note that you must activate the right video source and channel before
launching FFmpeg with any TV viewer such as xawtv launching ffmpeg with any TV viewer such as xawtv
(@url{http://linux.bytesex.org/xawtv/}) by Gerd Knorr. You also (@url{http://linux.bytesex.org/xawtv/}) by Gerd Knorr. You also
have to set the audio recording levels correctly with a have to set the audio recording levels correctly with a
standard mixer. standard mixer.
@section X11 grabbing @section X11 grabbing
FFmpeg can grab the X11 display. Grab the X11 display with ffmpeg via
@example @example
ffmpeg -f x11grab -s cif -r 25 -i :0.0 /tmp/out.mpg ffmpeg -f x11grab -s cif -r 25 -i :0.0 /tmp/out.mpg
...@@ -910,7 +908,7 @@ variable. 10 is the x-offset and 20 the y-offset for the grabbing. ...@@ -910,7 +908,7 @@ variable. 10 is the x-offset and 20 the y-offset for the grabbing.
@section Video and Audio file format conversion @section Video and Audio file format conversion
FFmpeg can use any supported file format and protocol as input: Any supported file format and protocol can serve as input to ffmpeg:
Examples: Examples:
@itemize @itemize
...@@ -930,7 +928,7 @@ It will use the files: ...@@ -930,7 +928,7 @@ It will use the files:
The Y files use twice the resolution of the U and V files. They are The Y files use twice the resolution of the U and V files. They are
raw files, without header. They can be generated by all decent video raw files, without header. They can be generated by all decent video
decoders. You must specify the size of the image with the @option{-s} option decoders. You must specify the size of the image with the @option{-s} option
if FFmpeg cannot guess it. if ffmpeg cannot guess it.
@item @item
You can input from a raw YUV420P file: You can input from a raw YUV420P file:
...@@ -1057,7 +1055,7 @@ file to which you want to add them. ...@@ -1057,7 +1055,7 @@ file to which you want to add them.
@ignore @ignore
@setfilename ffmpeg @setfilename ffmpeg
@settitle FFmpeg video converter @settitle ffmpeg video converter
@c man begin SEEALSO @c man begin SEEALSO
ffplay(1), ffprobe(1), ffserver(1) and the FFmpeg HTML documentation ffplay(1), ffprobe(1), ffserver(1) and the FFmpeg HTML documentation
......
\input texinfo @c -*- texinfo -*- \input texinfo @c -*- texinfo -*-
@settitle FFplay Documentation @settitle ffplay Documentation
@titlepage @titlepage
@center @titlefont{FFplay Documentation} @center @titlefont{ffplay Documentation}
@end titlepage @end titlepage
@top @top
......
\input texinfo @c -*- texinfo -*- \input texinfo @c -*- texinfo -*-
@settitle FFprobe Documentation @settitle ffprobe Documentation
@titlepage @titlepage
@center @titlefont{FFprobe Documentation} @center @titlefont{ffprobe Documentation}
@end titlepage @end titlepage
@top @top
...@@ -22,7 +22,7 @@ ffprobe [options] [@file{input_file}] ...@@ -22,7 +22,7 @@ ffprobe [options] [@file{input_file}]
@chapter Description @chapter Description
@c man begin DESCRIPTION @c man begin DESCRIPTION
FFprobe gathers information from multimedia streams and prints it in ffprobe gathers information from multimedia streams and prints it in
human- and machine-readable fashion. human- and machine-readable fashion.
For example it can be used to check the format of the container used For example it can be used to check the format of the container used
...@@ -33,7 +33,7 @@ If a filename is specified in input, ffprobe will try to open and ...@@ -33,7 +33,7 @@ If a filename is specified in input, ffprobe will try to open and
probe the file content. If the file cannot be opened or recognized as probe the file content. If the file cannot be opened or recognized as
a multimedia file, a positive exit code is returned. a multimedia file, a positive exit code is returned.
FFprobe may be employed both as a standalone application or in ffprobe may be employed both as a standalone application or in
combination with a textual filter, which may perform more combination with a textual filter, which may perform more
sophisticated processing, e.g. statistical processing or plotting. sophisticated processing, e.g. statistical processing or plotting.
...@@ -41,7 +41,7 @@ Options are used to list some of the formats supported by ffprobe or ...@@ -41,7 +41,7 @@ Options are used to list some of the formats supported by ffprobe or
for specifying which information to display, and for setting how for specifying which information to display, and for setting how
ffprobe will show it. ffprobe will show it.
FFprobe output is designed to be easily parsable by a textual filter, ffprobe output is designed to be easily parsable by a textual filter,
and consists of one or more sections of the form: and consists of one or more sections of the form:
@example @example
[SECTION] [SECTION]
...@@ -119,7 +119,7 @@ with name "STREAM". ...@@ -119,7 +119,7 @@ with name "STREAM".
@ignore @ignore
@setfilename ffprobe @setfilename ffprobe
@settitle FFprobe media prober @settitle ffprobe media prober
@c man begin SEEALSO @c man begin SEEALSO
ffmpeg(1), ffplay(1), ffserver(1) and the FFmpeg HTML documentation ffmpeg(1), ffplay(1), ffserver(1) and the FFmpeg HTML documentation
......
\input texinfo @c -*- texinfo -*- \input texinfo @c -*- texinfo -*-
@settitle FFserver Documentation @settitle ffserver Documentation
@titlepage @titlepage
@center @titlefont{FFserver Documentation} @center @titlefont{ffserver Documentation}
@end titlepage @end titlepage
@top @top
...@@ -22,12 +22,12 @@ ffserver [options] ...@@ -22,12 +22,12 @@ ffserver [options]
@chapter Description @chapter Description
@c man begin DESCRIPTION @c man begin DESCRIPTION
FFserver is a streaming server for both audio and video. It supports ffserver is a streaming server for both audio and video. It supports
several live feeds, streaming from files and time shifting on live feeds several live feeds, streaming from files and time shifting on live feeds
(you can seek to positions in the past on each live feed, provided you (you can seek to positions in the past on each live feed, provided you
specify a big enough feed storage in ffserver.conf). specify a big enough feed storage in ffserver.conf).
FFserver runs in daemon mode by default; that is, it puts itself in ffserver runs in daemon mode by default; that is, it puts itself in
the background and detaches from its TTY, unless it is launched in the background and detaches from its TTY, unless it is launched in
debug mode or a NoDaemon option is specified in the configuration debug mode or a NoDaemon option is specified in the configuration
file. file.
...@@ -39,7 +39,7 @@ information. ...@@ -39,7 +39,7 @@ information.
@section How does it work? @section How does it work?
FFserver receives prerecorded files or FFM streams from some ffmpeg ffserver receives prerecorded files or FFM streams from some ffmpeg
instance as input, then streams them over RTP/RTSP/HTTP. instance as input, then streams them over RTP/RTSP/HTTP.
An ffserver instance will listen on some port as specified in the An ffserver instance will listen on some port as specified in the
...@@ -57,7 +57,7 @@ file. ...@@ -57,7 +57,7 @@ file.
@section Status stream @section Status stream
FFserver supports an HTTP interface which exposes the current status ffserver supports an HTTP interface which exposes the current status
of the server. of the server.
Simply point your browser to the address of the special status stream Simply point your browser to the address of the special status stream
...@@ -249,8 +249,8 @@ For example: @samp{http://localhost:8080/test.asf?date=2002-07-26T23:05:00}. ...@@ -249,8 +249,8 @@ For example: @samp{http://localhost:8080/test.asf?date=2002-07-26T23:05:00}.
Use @file{configfile} instead of @file{/etc/ffserver.conf}. Use @file{configfile} instead of @file{/etc/ffserver.conf}.
@item -n @item -n
Enable no-launch mode. This option disables all the Launch directives Enable no-launch mode. This option disables all the Launch directives
within the various <Stream> sections. FFserver will not launch any within the various <Stream> sections. Since ffserver will not launch
ffmpeg instance, so you will have to launch them manually. any ffmpeg instances, you will have to launch them manually.
@item -d @item -d
Enable debug mode. This option increases log verbosity, directs log Enable debug mode. This option increases log verbosity, directs log
messages to stdout and causes ffserver to run in the foreground messages to stdout and causes ffserver to run in the foreground
...@@ -261,7 +261,7 @@ rather than as a daemon. ...@@ -261,7 +261,7 @@ rather than as a daemon.
@ignore @ignore
@setfilename ffserver @setfilename ffserver
@settitle FFserver video server @settitle ffserver video server
@c man begin SEEALSO @c man begin SEEALSO
......
...@@ -789,9 +789,9 @@ to configure. ...@@ -789,9 +789,9 @@ to configure.
BSD make will not build FFmpeg, you need to install and use GNU Make BSD make will not build FFmpeg, you need to install and use GNU Make
(@file{gmake}). (@file{gmake}).
@subsubsection FreeBSD @subsubsection FreeBSD, DragonFly BSD
FreeBSD will not compile out-of-the-box due to broken system headers. These systems will not compile out-of-the-box due to broken system headers.
Passing @code{--extra-cflags=-D__BSD_VISIBLE} to configure will work Passing @code{--extra-cflags=-D__BSD_VISIBLE} to configure will work
around the problem. This may have unexpected sideeffects, so use it at around the problem. This may have unexpected sideeffects, so use it at
your own risk. If you care about FreeBSD, please make an attempt at your own risk. If you care about FreeBSD, please make an attempt at
......
/* /*
* FFmpeg main * ffmpeg main
* Copyright (c) 2000-2003 Fabrice Bellard * Copyright (c) 2000-2003 Fabrice Bellard
* *
* This file is part of FFmpeg. * This file is part of FFmpeg.
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
#include "libavutil/avassert.h" #include "libavutil/avassert.h"
const char program_name[] = "FFmpeg"; const char program_name[] = "ffmpeg";
const int program_birth_year = 2000; const int program_birth_year = 2000;
/* select an input stream for an output stream */ /* select an input stream for an output stream */
......
/* /*
* FFplay : Simple Media Player based on the FFmpeg libraries * ffplay : Simple Media Player based on the FFmpeg libraries
* Copyright (c) 2003 Fabrice Bellard * Copyright (c) 2003 Fabrice Bellard
* *
* This file is part of FFmpeg. * This file is part of FFmpeg.
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
#include <unistd.h> #include <unistd.h>
#include <assert.h> #include <assert.h>
const char program_name[] = "FFplay"; const char program_name[] = "ffplay";
const int program_birth_year = 2003; const int program_birth_year = 2003;
//#define DEBUG //#define DEBUG
......
/* /*
* FFprobe : Simple Media Prober based on the FFmpeg libraries * ffprobe : Simple Media Prober based on the FFmpeg libraries
* Copyright (c) 2007-2010 Stefano Sabatini * Copyright (c) 2007-2010 Stefano Sabatini
* *
* This file is part of FFmpeg. * This file is part of FFmpeg.
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include "libavdevice/avdevice.h" #include "libavdevice/avdevice.h"
#include "cmdutils.h" #include "cmdutils.h"
const char program_name[] = "FFprobe"; const char program_name[] = "ffprobe";
const int program_birth_year = 2007; const int program_birth_year = 2007;
static int do_show_format = 0; static int do_show_format = 0;
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
#include "cmdutils.h" #include "cmdutils.h"
const char program_name[] = "FFserver"; const char program_name[] = "ffserver";
const int program_birth_year = 2000; const int program_birth_year = 2000;
static const OptionDef options[]; static const OptionDef options[];
......
...@@ -392,9 +392,9 @@ OBJS-$(CONFIG_VCR1_ENCODER) += vcr1.o ...@@ -392,9 +392,9 @@ OBJS-$(CONFIG_VCR1_ENCODER) += vcr1.o
OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o
OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdav.o OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdav.o
OBJS-$(CONFIG_VMNC_DECODER) += vmnc.o OBJS-$(CONFIG_VMNC_DECODER) += vmnc.o
OBJS-$(CONFIG_VORBIS_DECODER) += vorbis_dec.o vorbis.o \ OBJS-$(CONFIG_VORBIS_DECODER) += vorbisdec.o vorbis.o \
vorbis_data.o xiph.o vorbis_data.o xiph.o
OBJS-$(CONFIG_VORBIS_ENCODER) += vorbis_enc.o vorbis.o \ OBJS-$(CONFIG_VORBIS_ENCODER) += vorbisenc.o vorbis.o \
vorbis_data.o vorbis_data.o
OBJS-$(CONFIG_VP3_DECODER) += vp3.o vp3dsp.o OBJS-$(CONFIG_VP3_DECODER) += vp3.o vp3dsp.o
OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o vp56dsp.o \ OBJS-$(CONFIG_VP5_DECODER) += vp5.o vp56.o vp56data.o vp56dsp.o \
......
...@@ -463,6 +463,11 @@ static int decode_audio_specific_config(AACContext *ac, ...@@ -463,6 +463,11 @@ static int decode_audio_specific_config(AACContext *ac,
GetBitContext gb; GetBitContext gb;
int i; int i;
av_dlog(avctx, "extradata size %d\n", avctx->extradata_size);
for (i = 0; i < avctx->extradata_size; i++)
av_dlog(avctx, "%02x ", avctx->extradata[i]);
av_dlog(avctx, "\n");
init_get_bits(&gb, data, data_size * 8); init_get_bits(&gb, data, data_size * 8);
if ((i = ff_mpeg4audio_get_config(m4ac, data, data_size)) < 0) if ((i = ff_mpeg4audio_get_config(m4ac, data, data_size)) < 0)
...@@ -489,6 +494,10 @@ static int decode_audio_specific_config(AACContext *ac, ...@@ -489,6 +494,10 @@ static int decode_audio_specific_config(AACContext *ac,
return -1; return -1;
} }
av_dlog(avctx, "AOT %d chan config %d sampling index %d (%d) SBR %d PS %d\n",
m4ac->object_type, m4ac->chan_config, m4ac->sampling_index,
m4ac->sample_rate, m4ac->sbr, m4ac->ps);
return get_bits_count(&gb); return get_bits_count(&gb);
} }
......
...@@ -606,8 +606,10 @@ static int aac_encode_frame(AVCodecContext *avctx, ...@@ -606,8 +606,10 @@ static int aac_encode_frame(AVCodecContext *avctx,
} }
frame_bits = put_bits_count(&s->pb); frame_bits = put_bits_count(&s->pb);
if (frame_bits <= 6144 * avctx->channels - 3) if (frame_bits <= 6144 * avctx->channels - 3) {
s->psy.bitres.bits = frame_bits / avctx->channels;
break; break;
}
s->lambda *= avctx->bit_rate * 1024.0f / avctx->sample_rate / frame_bits; s->lambda *= avctx->bit_rate * 1024.0f / avctx->sample_rate / frame_bits;
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
/*********************************** /***********************************
* TODOs: * TODOs:
* thresholds linearization after their modifications for attaining given bitrate
* try other bitrate controlling mechanism (maybe use ratecontrol.c?) * try other bitrate controlling mechanism (maybe use ratecontrol.c?)
* control quality for quality-based output * control quality for quality-based output
**********************************/ **********************************/
...@@ -41,10 +40,51 @@ ...@@ -41,10 +40,51 @@
*/ */
#define PSY_3GPP_THR_SPREAD_HI 1.5f // spreading factor for low-to-hi threshold spreading (15 dB/Bark) #define PSY_3GPP_THR_SPREAD_HI 1.5f // spreading factor for low-to-hi threshold spreading (15 dB/Bark)
#define PSY_3GPP_THR_SPREAD_LOW 3.0f // spreading factor for hi-to-low threshold spreading (30 dB/Bark) #define PSY_3GPP_THR_SPREAD_LOW 3.0f // spreading factor for hi-to-low threshold spreading (30 dB/Bark)
/* spreading factor for low-to-hi energy spreading, long block, > 22kbps/channel (20dB/Bark) */
#define PSY_3GPP_EN_SPREAD_HI_L1 2.0f
/* spreading factor for low-to-hi energy spreading, long block, <= 22kbps/channel (15dB/Bark) */
#define PSY_3GPP_EN_SPREAD_HI_L2 1.5f
/* spreading factor for low-to-hi energy spreading, short block (15 dB/Bark) */
#define PSY_3GPP_EN_SPREAD_HI_S 1.5f
/* spreading factor for hi-to-low energy spreading, long block (30dB/Bark) */
#define PSY_3GPP_EN_SPREAD_LOW_L 3.0f
/* spreading factor for hi-to-low energy spreading, short block (20dB/Bark) */
#define PSY_3GPP_EN_SPREAD_LOW_S 2.0f
#define PSY_3GPP_RPEMIN 0.01f #define PSY_3GPP_RPEMIN 0.01f
#define PSY_3GPP_RPELEV 2.0f #define PSY_3GPP_RPELEV 2.0f
#define PSY_3GPP_C1 3.0f /* log2(8) */
#define PSY_3GPP_C2 1.3219281f /* log2(2.5) */
#define PSY_3GPP_C3 0.55935729f /* 1 - C2 / C1 */
#define PSY_SNR_1DB 7.9432821e-1f /* -1dB */
#define PSY_SNR_25DB 3.1622776e-3f /* -25dB */
#define PSY_3GPP_SAVE_SLOPE_L -0.46666667f
#define PSY_3GPP_SAVE_SLOPE_S -0.36363637f
#define PSY_3GPP_SAVE_ADD_L -0.84285712f
#define PSY_3GPP_SAVE_ADD_S -0.75f
#define PSY_3GPP_SPEND_SLOPE_L 0.66666669f
#define PSY_3GPP_SPEND_SLOPE_S 0.81818181f
#define PSY_3GPP_SPEND_ADD_L -0.35f
#define PSY_3GPP_SPEND_ADD_S -0.26111111f
#define PSY_3GPP_CLIP_LO_L 0.2f
#define PSY_3GPP_CLIP_LO_S 0.2f
#define PSY_3GPP_CLIP_HI_L 0.95f
#define PSY_3GPP_CLIP_HI_S 0.75f
#define PSY_3GPP_AH_THR_LONG 0.5f
#define PSY_3GPP_AH_THR_SHORT 0.63f
enum {
PSY_3GPP_AH_NONE,
PSY_3GPP_AH_INACTIVE,
PSY_3GPP_AH_ACTIVE
};
#define PSY_3GPP_BITS_TO_PE(bits) ((bits) * 1.18f)
/* LAME psy model constants */ /* LAME psy model constants */
#define PSY_LAME_FIR_LEN 21 ///< LAME psy model FIR order #define PSY_LAME_FIR_LEN 21 ///< LAME psy model FIR order
#define AAC_BLOCK_SIZE_LONG 1024 ///< long block size #define AAC_BLOCK_SIZE_LONG 1024 ///< long block size
...@@ -60,9 +100,15 @@ ...@@ -60,9 +100,15 @@
* information for single band used by 3GPP TS26.403-inspired psychoacoustic model * information for single band used by 3GPP TS26.403-inspired psychoacoustic model
*/ */
typedef struct AacPsyBand{ typedef struct AacPsyBand{
float energy; ///< band energy float energy; ///< band energy
float thr; ///< energy threshold float thr; ///< energy threshold
float thr_quiet; ///< threshold in quiet float thr_quiet; ///< threshold in quiet
float nz_lines; ///< number of non-zero spectral lines
float active_lines; ///< number of active spectral lines
float pe; ///< perceptual entropy
float pe_const; ///< constant part of the PE calculation
float norm_fac; ///< normalization factor for linearization
int avoid_holes; ///< hole avoidance flag
}AacPsyBand; }AacPsyBand;
/** /**
...@@ -97,6 +143,15 @@ typedef struct AacPsyCoeffs{ ...@@ -97,6 +143,15 @@ typedef struct AacPsyCoeffs{
* 3GPP TS26.403-inspired psychoacoustic model specific data * 3GPP TS26.403-inspired psychoacoustic model specific data
*/ */
typedef struct AacPsyContext{ typedef struct AacPsyContext{
int chan_bitrate; ///< bitrate per channel
int frame_bits; ///< average bits per frame
int fill_level; ///< bit reservoir fill level
struct {
float min; ///< minimum allowed PE for bit factor calculation
float max; ///< maximum allowed PE for bit factor calculation
float previous; ///< allowed PE of the previous frame
float correction; ///< PE correction factor
} pe;
AacPsyCoeffs psy_coef[2][64]; AacPsyCoeffs psy_coef[2][64];
AacPsyChannel *ch; AacPsyChannel *ch;
}AacPsyContext; }AacPsyContext;
...@@ -235,16 +290,33 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) { ...@@ -235,16 +290,33 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) {
AacPsyContext *pctx; AacPsyContext *pctx;
float bark; float bark;
int i, j, g, start; int i, j, g, start;
float prev, minscale, minath; float prev, minscale, minath, minsnr, pe_min;
const int chan_bitrate = ctx->avctx->bit_rate / ctx->avctx->channels;
const int bandwidth = ctx->avctx->cutoff ? ctx->avctx->cutoff : ctx->avctx->sample_rate / 2;
const float num_bark = calc_bark((float)bandwidth);
ctx->model_priv_data = av_mallocz(sizeof(AacPsyContext)); ctx->model_priv_data = av_mallocz(sizeof(AacPsyContext));
pctx = (AacPsyContext*) ctx->model_priv_data; pctx = (AacPsyContext*) ctx->model_priv_data;
pctx->chan_bitrate = chan_bitrate;
pctx->frame_bits = chan_bitrate * AAC_BLOCK_SIZE_LONG / ctx->avctx->sample_rate;
pctx->pe.min = 8.0f * AAC_BLOCK_SIZE_LONG * bandwidth / (ctx->avctx->sample_rate * 2.0f);
pctx->pe.max = 12.0f * AAC_BLOCK_SIZE_LONG * bandwidth / (ctx->avctx->sample_rate * 2.0f);
ctx->bitres.size = 6144 - pctx->frame_bits;
ctx->bitres.size -= ctx->bitres.size % 8;
pctx->fill_level = ctx->bitres.size;
minath = ath(3410, ATH_ADD); minath = ath(3410, ATH_ADD);
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++) {
AacPsyCoeffs *coeffs = pctx->psy_coef[j]; AacPsyCoeffs *coeffs = pctx->psy_coef[j];
const uint8_t *band_sizes = ctx->bands[j]; const uint8_t *band_sizes = ctx->bands[j];
float line_to_frequency = ctx->avctx->sample_rate / (j ? 256.f : 2048.0f); float line_to_frequency = ctx->avctx->sample_rate / (j ? 256.f : 2048.0f);
float avg_chan_bits = chan_bitrate / ctx->avctx->sample_rate * (j ? 128.0f : 1024.0f);
/* reference encoder uses 2.4% here instead of 60% like the spec says */
float bark_pe = 0.024f * PSY_3GPP_BITS_TO_PE(avg_chan_bits) / num_bark;
float en_spread_low = j ? PSY_3GPP_EN_SPREAD_LOW_S : PSY_3GPP_EN_SPREAD_LOW_L;
/* High energy spreading for long blocks <= 22kbps/channel and short blocks are the same. */
float en_spread_hi = (j || (chan_bitrate <= 22.0f)) ? PSY_3GPP_EN_SPREAD_HI_S : PSY_3GPP_EN_SPREAD_HI_L1;
i = 0; i = 0;
prev = 0.0; prev = 0.0;
for (g = 0; g < ctx->num_bands[j]; g++) { for (g = 0; g < ctx->num_bands[j]; g++) {
...@@ -258,6 +330,11 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) { ...@@ -258,6 +330,11 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) {
float bark_width = coeffs[g+1].barks - coeffs->barks; float bark_width = coeffs[g+1].barks - coeffs->barks;
coeff->spread_low[0] = pow(10.0, -bark_width * PSY_3GPP_THR_SPREAD_LOW); coeff->spread_low[0] = pow(10.0, -bark_width * PSY_3GPP_THR_SPREAD_LOW);
coeff->spread_hi [0] = pow(10.0, -bark_width * PSY_3GPP_THR_SPREAD_HI); coeff->spread_hi [0] = pow(10.0, -bark_width * PSY_3GPP_THR_SPREAD_HI);
coeff->spread_low[1] = pow(10.0, -bark_width * en_spread_low);
coeff->spread_hi [1] = pow(10.0, -bark_width * en_spread_hi);
pe_min = bark_pe * bark_width;
minsnr = pow(2.0f, pe_min / band_sizes[g]) - 1.5f;
coeff->min_snr = av_clipf(1.0f / minsnr, PSY_SNR_25DB, PSY_SNR_1DB);
} }
start = 0; start = 0;
for (g = 0; g < ctx->num_bands[j]; g++) { for (g = 0; g < ctx->num_bands[j]; g++) {
...@@ -385,6 +462,97 @@ static FFPsyWindowInfo psy_3gpp_window(FFPsyContext *ctx, ...@@ -385,6 +462,97 @@ static FFPsyWindowInfo psy_3gpp_window(FFPsyContext *ctx,
return wi; return wi;
} }
/* 5.6.1.2 "Calculation of Bit Demand" */
static int calc_bit_demand(AacPsyContext *ctx, float pe, int bits, int size,
int short_window)
{
const float bitsave_slope = short_window ? PSY_3GPP_SAVE_SLOPE_S : PSY_3GPP_SAVE_SLOPE_L;
const float bitsave_add = short_window ? PSY_3GPP_SAVE_ADD_S : PSY_3GPP_SAVE_ADD_L;
const float bitspend_slope = short_window ? PSY_3GPP_SPEND_SLOPE_S : PSY_3GPP_SPEND_SLOPE_L;
const float bitspend_add = short_window ? PSY_3GPP_SPEND_ADD_S : PSY_3GPP_SPEND_ADD_L;
const float clip_low = short_window ? PSY_3GPP_CLIP_LO_S : PSY_3GPP_CLIP_LO_L;
const float clip_high = short_window ? PSY_3GPP_CLIP_HI_S : PSY_3GPP_CLIP_HI_L;
float clipped_pe, bit_save, bit_spend, bit_factor, fill_level;
ctx->fill_level += ctx->frame_bits - bits;
ctx->fill_level = av_clip(ctx->fill_level, 0, size);
fill_level = av_clipf((float)ctx->fill_level / size, clip_low, clip_high);
clipped_pe = av_clipf(pe, ctx->pe.min, ctx->pe.max);
bit_save = (fill_level + bitsave_add) * bitsave_slope;
assert(bit_save <= 0.3f && bit_save >= -0.05000001f);
bit_spend = (fill_level + bitspend_add) * bitspend_slope;
assert(bit_spend <= 0.5f && bit_spend >= -0.1f);
/* The bit factor graph in the spec is obviously incorrect.
* bit_spend + ((bit_spend - bit_spend))...
* The reference encoder subtracts everything from 1, but also seems incorrect.
* 1 - bit_save + ((bit_spend + bit_save))...
* Hopefully below is correct.
*/
bit_factor = 1.0f - bit_save + ((bit_spend - bit_save) / (ctx->pe.max - ctx->pe.min)) * (clipped_pe - ctx->pe.min);
/* NOTE: The reference encoder attempts to center pe max/min around the current pe. */
ctx->pe.max = FFMAX(pe, ctx->pe.max);
ctx->pe.min = FFMIN(pe, ctx->pe.min);
return FFMIN(ctx->frame_bits * bit_factor, ctx->frame_bits + size - bits);
}
static float calc_pe_3gpp(AacPsyBand *band)
{
float pe, a;
band->pe = 0.0f;
band->pe_const = 0.0f;
band->active_lines = 0.0f;
if (band->energy > band->thr) {
a = log2f(band->energy);
pe = a - log2f(band->thr);
band->active_lines = band->nz_lines;
if (pe < PSY_3GPP_C1) {
pe = pe * PSY_3GPP_C3 + PSY_3GPP_C2;
a = a * PSY_3GPP_C3 + PSY_3GPP_C2;
band->active_lines *= PSY_3GPP_C3;
}
band->pe = pe * band->nz_lines;
band->pe_const = a * band->nz_lines;
}
return band->pe;
}
static float calc_reduction_3gpp(float a, float desired_pe, float pe,
float active_lines)
{
float thr_avg, reduction;
thr_avg = powf(2.0f, (a - pe) / (4.0f * active_lines));
reduction = powf(2.0f, (a - desired_pe) / (4.0f * active_lines)) - thr_avg;
return FFMAX(reduction, 0.0f);
}
static float calc_reduced_thr_3gpp(AacPsyBand *band, float min_snr,
float reduction)
{
float thr = band->thr;
if (band->energy > thr) {
thr = powf(thr, 0.25f) + reduction;
thr = powf(thr, 4.0f);
/* This deviates from the 3GPP spec to match the reference encoder.
* It performs min(thr_reduced, max(thr, energy/min_snr)) only for bands
* that have hole avoidance on (active or inactive). It always reduces the
* threshold of bands with hole avoidance off.
*/
if (thr > band->energy * min_snr && band->avoid_holes != PSY_3GPP_AH_NONE) {
thr = FFMAX(band->thr, band->energy * min_snr);
band->avoid_holes = PSY_3GPP_AH_ACTIVE;
}
}
return thr;
}
/** /**
* Calculate band thresholds as suggested in 3GPP TS26.403 * Calculate band thresholds as suggested in 3GPP TS26.403
*/ */
...@@ -395,37 +563,167 @@ static void psy_3gpp_analyze(FFPsyContext *ctx, int channel, ...@@ -395,37 +563,167 @@ static void psy_3gpp_analyze(FFPsyContext *ctx, int channel,
AacPsyChannel *pch = &pctx->ch[channel]; AacPsyChannel *pch = &pctx->ch[channel];
int start = 0; int start = 0;
int i, w, g; int i, w, g;
const int num_bands = ctx->num_bands[wi->num_windows == 8]; float desired_bits, desired_pe, delta_pe, reduction, spread_en[128] = {0};
const uint8_t *band_sizes = ctx->bands[wi->num_windows == 8]; float a = 0.0f, active_lines = 0.0f, norm_fac = 0.0f;
AacPsyCoeffs *coeffs = pctx->psy_coef[wi->num_windows == 8]; float pe = pctx->chan_bitrate > 32000 ? 0.0f : FFMAX(50.0f, 100.0f - pctx->chan_bitrate * 100.0f / 32000.0f);
const int num_bands = ctx->num_bands[wi->num_windows == 8];
const uint8_t *band_sizes = ctx->bands[wi->num_windows == 8];
AacPsyCoeffs *coeffs = pctx->psy_coef[wi->num_windows == 8];
const float avoid_hole_thr = wi->num_windows == 8 ? PSY_3GPP_AH_THR_SHORT : PSY_3GPP_AH_THR_LONG;
//calculate energies, initial thresholds and related values - 5.4.2 "Threshold Calculation" //calculate energies, initial thresholds and related values - 5.4.2 "Threshold Calculation"
for (w = 0; w < wi->num_windows*16; w += 16) { for (w = 0; w < wi->num_windows*16; w += 16) {
for (g = 0; g < num_bands; g++) { for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &pch->band[w+g]; AacPsyBand *band = &pch->band[w+g];
float form_factor = 0.0f;
band->energy = 0.0f; band->energy = 0.0f;
for (i = 0; i < band_sizes[g]; i++) for (i = 0; i < band_sizes[g]; i++) {
band->energy += coefs[start+i] * coefs[start+i]; band->energy += coefs[start+i] * coefs[start+i];
band->thr = band->energy * 0.001258925f; form_factor += sqrtf(fabs(coefs[start+i]));
start += band_sizes[g]; }
band->thr = band->energy * 0.001258925f;
band->nz_lines = form_factor / powf(band->energy / band_sizes[g], 0.25f);
start += band_sizes[g];
} }
} }
//modify thresholds and energies - spread, threshold in quiet, pre-echo control //modify thresholds and energies - spread, threshold in quiet, pre-echo control
for (w = 0; w < wi->num_windows*16; w += 16) { for (w = 0; w < wi->num_windows*16; w += 16) {
AacPsyBand *bands = &pch->band[w]; AacPsyBand *bands = &pch->band[w];
//5.4.2.3 "Spreading" & 5.4.3 "Spreaded Energy Calculation" //5.4.2.3 "Spreading" & 5.4.3 "Spreaded Energy Calculation"
for (g = 1; g < num_bands; g++) spread_en[0] = bands[0].energy;
bands[g].thr = FFMAX(bands[g].thr, bands[g-1].thr * coeffs[g].spread_hi[0]); for (g = 1; g < num_bands; g++) {
for (g = num_bands - 2; g >= 0; g--) bands[g].thr = FFMAX(bands[g].thr, bands[g-1].thr * coeffs[g].spread_hi[0]);
bands[g].thr = FFMAX(bands[g].thr, bands[g+1].thr * coeffs[g].spread_low[0]); spread_en[w+g] = FFMAX(bands[g].energy, spread_en[w+g-1] * coeffs[g].spread_hi[1]);
}
for (g = num_bands - 2; g >= 0; g--) {
bands[g].thr = FFMAX(bands[g].thr, bands[g+1].thr * coeffs[g].spread_low[0]);
spread_en[w+g] = FFMAX(spread_en[w+g], spread_en[w+g+1] * coeffs[g].spread_low[1]);
}
//5.4.2.4 "Threshold in quiet" //5.4.2.4 "Threshold in quiet"
for (g = 0; g < num_bands; g++) { for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &bands[g]; AacPsyBand *band = &bands[g];
band->thr_quiet = band->thr = FFMAX(band->thr, coeffs[g].ath); band->thr_quiet = band->thr = FFMAX(band->thr, coeffs[g].ath);
//5.4.2.5 "Pre-echo control" //5.4.2.5 "Pre-echo control"
if (!(wi->window_type[0] == LONG_STOP_SEQUENCE || (wi->window_type[1] == LONG_START_SEQUENCE && !w))) if (!(wi->window_type[0] == LONG_STOP_SEQUENCE || (wi->window_type[1] == LONG_START_SEQUENCE && !w)))
band->thr = FFMAX(PSY_3GPP_RPEMIN*band->thr, FFMIN(band->thr, band->thr = FFMAX(PSY_3GPP_RPEMIN*band->thr, FFMIN(band->thr,
PSY_3GPP_RPELEV*pch->prev_band[w+g].thr_quiet)); PSY_3GPP_RPELEV*pch->prev_band[w+g].thr_quiet));
/* 5.6.1.3.1 "Prepatory steps of the perceptual entropy calculation" */
pe += calc_pe_3gpp(band);
a += band->pe_const;
active_lines += band->active_lines;
/* 5.6.1.3.3 "Selection of the bands for avoidance of holes" */
if (spread_en[w+g] * avoid_hole_thr > band->energy || coeffs[g].min_snr > 1.0f)
band->avoid_holes = PSY_3GPP_AH_NONE;
else
band->avoid_holes = PSY_3GPP_AH_INACTIVE;
}
}
/* 5.6.1.3.2 "Calculation of the desired perceptual entropy" */
ctx->pe[channel] = pe;
desired_bits = calc_bit_demand(pctx, pe, ctx->bitres.bits, ctx->bitres.size, wi->num_windows == 8);
desired_pe = PSY_3GPP_BITS_TO_PE(desired_bits);
/* NOTE: PE correction is kept simple. During initial testing it had very
* little effect on the final bitrate. Probably a good idea to come
* back and do more testing later.
*/
if (ctx->bitres.bits > 0)
desired_pe *= av_clipf(pctx->pe.previous / PSY_3GPP_BITS_TO_PE(ctx->bitres.bits),
0.85f, 1.15f);
pctx->pe.previous = PSY_3GPP_BITS_TO_PE(desired_bits);
if (desired_pe < pe) {
/* 5.6.1.3.4 "First Estimation of the reduction value" */
for (w = 0; w < wi->num_windows*16; w += 16) {
reduction = calc_reduction_3gpp(a, desired_pe, pe, active_lines);
pe = 0.0f;
a = 0.0f;
active_lines = 0.0f;
for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &pch->band[w+g];
band->thr = calc_reduced_thr_3gpp(band, coeffs[g].min_snr, reduction);
/* recalculate PE */
pe += calc_pe_3gpp(band);
a += band->pe_const;
active_lines += band->active_lines;
}
}
/* 5.6.1.3.5 "Second Estimation of the reduction value" */
for (i = 0; i < 2; i++) {
float pe_no_ah = 0.0f, desired_pe_no_ah;
active_lines = a = 0.0f;
for (w = 0; w < wi->num_windows*16; w += 16) {
for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &pch->band[w+g];
if (band->avoid_holes != PSY_3GPP_AH_ACTIVE) {
pe_no_ah += band->pe;
a += band->pe_const;
active_lines += band->active_lines;
}
}
}
desired_pe_no_ah = FFMAX(desired_pe - (pe - pe_no_ah), 0.0f);
if (active_lines > 0.0f)
reduction += calc_reduction_3gpp(a, desired_pe_no_ah, pe_no_ah, active_lines);
pe = 0.0f;
for (w = 0; w < wi->num_windows*16; w += 16) {
for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &pch->band[w+g];
if (active_lines > 0.0f)
band->thr = calc_reduced_thr_3gpp(band, coeffs[g].min_snr, reduction);
pe += calc_pe_3gpp(band);
band->norm_fac = band->active_lines / band->thr;
norm_fac += band->norm_fac;
}
}
delta_pe = desired_pe - pe;
if (fabs(delta_pe) > 0.05f * desired_pe)
break;
}
if (pe < 1.15f * desired_pe) {
/* 6.6.1.3.6 "Final threshold modification by linearization" */
norm_fac = 1.0f / norm_fac;
for (w = 0; w < wi->num_windows*16; w += 16) {
for (g = 0; g < num_bands; g++) {
AacPsyBand *band = &pch->band[w+g];
if (band->active_lines > 0.5f) {
float delta_sfb_pe = band->norm_fac * norm_fac * delta_pe;
float thr = band->thr;
thr *= powf(2.0f, delta_sfb_pe / band->active_lines);
if (thr > coeffs[g].min_snr * band->energy && band->avoid_holes == PSY_3GPP_AH_INACTIVE)
thr = FFMAX(band->thr, coeffs[g].min_snr * band->energy);
band->thr = thr;
}
}
}
} else {
/* 5.6.1.3.7 "Further perceptual entropy reduction" */
g = num_bands;
while (pe > desired_pe && g--) {
for (w = 0; w < wi->num_windows*16; w+= 16) {
AacPsyBand *band = &pch->band[w+g];
if (band->avoid_holes != PSY_3GPP_AH_NONE && coeffs[g].min_snr < PSY_SNR_1DB) {
coeffs[g].min_snr = PSY_SNR_1DB;
band->thr = band->energy * PSY_SNR_1DB;
pe += band->active_lines * 1.5f - band->pe;
}
}
}
/* TODO: allow more holes (unused without mid/side) */
} }
} }
......
...@@ -1136,7 +1136,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) ...@@ -1136,7 +1136,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
switch (q->subpacket[s].cookversion) { switch (q->subpacket[s].cookversion) {
case MONO: case MONO:
if (q->nb_channels != 1) { if (q->nb_channels != 1) {
av_log_ask_for_sample(avctx, "Container channels != 1.!\n"); av_log_ask_for_sample(avctx, "Container channels != 1.\n");
return -1; return -1;
} }
av_log(avctx,AV_LOG_DEBUG,"MONO\n"); av_log(avctx,AV_LOG_DEBUG,"MONO\n");
......
...@@ -234,7 +234,7 @@ static void memset_float(float *buf, float val, int size) ...@@ -234,7 +234,7 @@ static void memset_float(float *buf, float val, int size)
* be a multiple of four. * be a multiple of four.
* @return the LPC value * @return the LPC value
* *
* @todo reuse code from vorbis_dec.c: vorbis_floor0_decode * @todo reuse code from Vorbis decoder: vorbis_floor0_decode
*/ */
static float eval_lpc_spectrum(const float *lsp, float cos_val, int order) static float eval_lpc_spectrum(const float *lsp, float cos_val, int order)
{ {
......
...@@ -316,6 +316,7 @@ OBJS+= avio.o aviobuf.o ...@@ -316,6 +316,7 @@ OBJS+= avio.o aviobuf.o
OBJS-$(CONFIG_APPLEHTTP_PROTOCOL) += applehttpproto.o OBJS-$(CONFIG_APPLEHTTP_PROTOCOL) += applehttpproto.o
OBJS-$(CONFIG_CONCAT_PROTOCOL) += concat.o OBJS-$(CONFIG_CONCAT_PROTOCOL) += concat.o
OBJS-$(CONFIG_CRYPTO_PROTOCOL) += crypto.o
OBJS-$(CONFIG_FILE_PROTOCOL) += file.o OBJS-$(CONFIG_FILE_PROTOCOL) += file.o
OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o
OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o httpauth.o OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o httpauth.o
......
...@@ -237,6 +237,7 @@ void av_register_all(void) ...@@ -237,6 +237,7 @@ void av_register_all(void)
/* protocols */ /* protocols */
REGISTER_PROTOCOL (APPLEHTTP, applehttp); REGISTER_PROTOCOL (APPLEHTTP, applehttp);
REGISTER_PROTOCOL (CONCAT, concat); REGISTER_PROTOCOL (CONCAT, concat);
REGISTER_PROTOCOL (CRYPTO, crypto);
REGISTER_PROTOCOL (FILE, file); REGISTER_PROTOCOL (FILE, file);
REGISTER_PROTOCOL (GOPHER, gopher); REGISTER_PROTOCOL (GOPHER, gopher);
REGISTER_PROTOCOL (HTTP, http); REGISTER_PROTOCOL (HTTP, http);
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#define _XOPEN_SOURCE 600 #define _XOPEN_SOURCE 600
#include "libavutil/avstring.h" #include "libavutil/avstring.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/opt.h"
#include "avformat.h" #include "avformat.h"
#include "internal.h" #include "internal.h"
#include <unistd.h> #include <unistd.h>
...@@ -47,9 +49,17 @@ ...@@ -47,9 +49,17 @@
* one anonymous toplevel variant for this, to maintain the structure. * one anonymous toplevel variant for this, to maintain the structure.
*/ */
enum KeyType {
KEY_NONE,
KEY_AES_128,
};
struct segment { struct segment {
int duration; int duration;
char url[MAX_URL_SIZE]; char url[MAX_URL_SIZE];
char key[MAX_URL_SIZE];
enum KeyType key_type;
uint8_t iv[16];
}; };
/* /*
...@@ -77,6 +87,9 @@ struct variant { ...@@ -77,6 +87,9 @@ struct variant {
int needed, cur_needed; int needed, cur_needed;
int cur_seq_no; int cur_seq_no;
int64_t last_load_time; int64_t last_load_time;
char key_url[MAX_URL_SIZE];
uint8_t key[16];
}; };
typedef struct AppleHTTPContext { typedef struct AppleHTTPContext {
...@@ -160,10 +173,35 @@ static void handle_variant_args(struct variant_info *info, const char *key, ...@@ -160,10 +173,35 @@ static void handle_variant_args(struct variant_info *info, const char *key,
} }
} }
struct key_info {
char uri[MAX_URL_SIZE];
char method[10];
char iv[35];
};
static void handle_key_args(struct key_info *info, const char *key,
int key_len, char **dest, int *dest_len)
{
if (!strncmp(key, "METHOD=", key_len)) {
*dest = info->method;
*dest_len = sizeof(info->method);
} else if (!strncmp(key, "URI=", key_len)) {
*dest = info->uri;
*dest_len = sizeof(info->uri);
} else if (!strncmp(key, "IV=", key_len)) {
*dest = info->iv;
*dest_len = sizeof(info->iv);
}
}
static int parse_playlist(AppleHTTPContext *c, const char *url, static int parse_playlist(AppleHTTPContext *c, const char *url,
struct variant *var, AVIOContext *in) struct variant *var, AVIOContext *in)
{ {
int ret = 0, duration = 0, is_segment = 0, is_variant = 0, bandwidth = 0; int ret = 0, duration = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
enum KeyType key_type = KEY_NONE;
uint8_t iv[16] = "";
int has_iv = 0;
char key[MAX_URL_SIZE];
char line[1024]; char line[1024];
const char *ptr; const char *ptr;
int close_in = 0; int close_in = 0;
...@@ -192,6 +230,19 @@ static int parse_playlist(AppleHTTPContext *c, const char *url, ...@@ -192,6 +230,19 @@ static int parse_playlist(AppleHTTPContext *c, const char *url,
ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args, ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args,
&info); &info);
bandwidth = atoi(info.bandwidth); bandwidth = atoi(info.bandwidth);
} else if (av_strstart(line, "#EXT-X-KEY:", &ptr)) {
struct key_info info = {{0}};
ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args,
&info);
key_type = KEY_NONE;
has_iv = 0;
if (!strcmp(info.method, "AES-128"))
key_type = KEY_AES_128;
if (!strncmp(info.iv, "0x", 2) || !strncmp(info.iv, "0X", 2)) {
ff_hex_to_data(iv, info.iv + 2);
has_iv = 1;
}
av_strlcpy(key, info.uri, sizeof(key));
} else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) { } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) {
if (!var) { if (!var) {
var = new_variant(c, 0, url, NULL); var = new_variant(c, 0, url, NULL);
...@@ -242,6 +293,15 @@ static int parse_playlist(AppleHTTPContext *c, const char *url, ...@@ -242,6 +293,15 @@ static int parse_playlist(AppleHTTPContext *c, const char *url,
goto fail; goto fail;
} }
seg->duration = duration; seg->duration = duration;
seg->key_type = key_type;
if (has_iv) {
memcpy(seg->iv, iv, sizeof(iv));
} else {
int seq = var->start_seq_no + var->n_segments;
memset(seg->iv, 0, sizeof(seg->iv));
AV_WB32(seg->iv + 12, seq);
}
ff_make_absolute_url(seg->key, sizeof(seg->key), url, key);
ff_make_absolute_url(seg->url, sizeof(seg->url), url, line); ff_make_absolute_url(seg->url, sizeof(seg->url), url, line);
dynarray_add(&var->segments, &var->n_segments, seg); dynarray_add(&var->segments, &var->n_segments, seg);
is_segment = 0; is_segment = 0;
...@@ -257,6 +317,50 @@ fail: ...@@ -257,6 +317,50 @@ fail:
return ret; return ret;
} }
static int open_input(struct variant *var)
{
struct segment *seg = var->segments[var->cur_seq_no - var->start_seq_no];
if (seg->key_type == KEY_NONE) {
return ffurl_open(&var->input, seg->url, AVIO_FLAG_READ);
} else if (seg->key_type == KEY_AES_128) {
char iv[33], key[33], url[MAX_URL_SIZE];
int ret;
if (strcmp(seg->key, var->key_url)) {
URLContext *uc;
if (ffurl_open(&uc, seg->key, AVIO_FLAG_READ) == 0) {
if (ffurl_read_complete(uc, var->key, sizeof(var->key))
!= sizeof(var->key)) {
av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n",
seg->key);
}
ffurl_close(uc);
} else {
av_log(NULL, AV_LOG_ERROR, "Unable to open key file %s\n",
seg->key);
}
av_strlcpy(var->key_url, seg->key, sizeof(var->key_url));
}
ff_data_to_hex(iv, seg->iv, sizeof(seg->iv), 0);
ff_data_to_hex(key, var->key, sizeof(var->key), 0);
iv[32] = key[32] = '\0';
if (strstr(seg->url, "://"))
snprintf(url, sizeof(url), "crypto+%s", seg->url);
else
snprintf(url, sizeof(url), "crypto:%s", seg->url);
if ((ret = ffurl_alloc(&var->input, url, AVIO_FLAG_READ)) < 0)
return ret;
av_set_string3(var->input->priv_data, "key", key, 0, NULL);
av_set_string3(var->input->priv_data, "iv", iv, 0, NULL);
if ((ret = ffurl_connect(var->input)) < 0) {
ffurl_close(var->input);
var->input = NULL;
return ret;
}
return 0;
}
return AVERROR(ENOSYS);
}
static int read_data(void *opaque, uint8_t *buf, int buf_size) static int read_data(void *opaque, uint8_t *buf, int buf_size)
{ {
struct variant *v = opaque; struct variant *v = opaque;
...@@ -291,9 +395,7 @@ reload: ...@@ -291,9 +395,7 @@ reload:
goto reload; goto reload;
} }
ret = ffurl_open(&v->input, ret = open_input(v);
v->segments[v->cur_seq_no - v->start_seq_no]->url,
AVIO_FLAG_READ);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
......
/*
* Decryption protocol handler
* Copyright (c) 2011 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 "avformat.h"
#include "libavutil/aes.h"
#include "libavutil/avstring.h"
#include "libavutil/opt.h"
#include "internal.h"
#include "url.h"
#define MAX_BUFFER_BLOCKS 150
#define BLOCKSIZE 16
typedef struct {
const AVClass *class;
URLContext *hd;
uint8_t inbuffer [BLOCKSIZE*MAX_BUFFER_BLOCKS],
outbuffer[BLOCKSIZE*MAX_BUFFER_BLOCKS];
uint8_t *outptr;
int indata, indata_used, outdata;
int eof;
uint8_t *key;
int keylen;
uint8_t *iv;
int ivlen;
struct AVAES *aes;
} CryptoContext;
#define OFFSET(x) offsetof(CryptoContext, x)
static const AVOption options[] = {
{"key", "AES decryption key", OFFSET(key), FF_OPT_TYPE_BINARY },
{"iv", "AES decryption initialization vector", OFFSET(iv), FF_OPT_TYPE_BINARY },
{ NULL }
};
static const AVClass crypto_class = {
"crypto", av_default_item_name, options, LIBAVUTIL_VERSION_INT
};
static int crypto_open(URLContext *h, const char *uri, int flags)
{
const char *nested_url;
int ret;
CryptoContext *c = h->priv_data;
if (!av_strstart(uri, "crypto+", &nested_url) &&
!av_strstart(uri, "crypto:", &nested_url)) {
av_log(h, AV_LOG_ERROR, "Unsupported url %s\n", uri);
ret = AVERROR(EINVAL);
goto err;
}
if (c->keylen < BLOCKSIZE || c->ivlen < BLOCKSIZE) {
av_log(h, AV_LOG_ERROR, "Key or IV not set\n");
ret = AVERROR(EINVAL);
goto err;
}
if (flags & AVIO_FLAG_WRITE) {
av_log(h, AV_LOG_ERROR, "Only decryption is supported currently\n");
ret = AVERROR(ENOSYS);
goto err;
}
if ((ret = ffurl_open(&c->hd, nested_url, AVIO_FLAG_READ)) < 0) {
av_log(h, AV_LOG_ERROR, "Unable to open input\n");
goto err;
}
c->aes = av_mallocz(av_aes_size);
if (!c->aes) {
ret = AVERROR(ENOMEM);
goto err;
}
av_aes_init(c->aes, c->key, 128, 1);
h->is_streamed = 1;
return 0;
err:
av_free(c->key);
av_free(c->iv);
return ret;
}
static int crypto_read(URLContext *h, uint8_t *buf, int size)
{
CryptoContext *c = h->priv_data;
int blocks;
retry:
if (c->outdata > 0) {
size = FFMIN(size, c->outdata);
memcpy(buf, c->outptr, size);
c->outptr += size;
c->outdata -= size;
return size;
}
// We avoid using the last block until we've found EOF,
// since we'll remove PKCS7 padding at the end. So make
// sure we've got at least 2 blocks, so we can decrypt
// at least one.
while (c->indata - c->indata_used < 2*BLOCKSIZE) {
int n = ffurl_read(c->hd, c->inbuffer + c->indata,
sizeof(c->inbuffer) - c->indata);
if (n <= 0) {
c->eof = 1;
break;
}
c->indata += n;
}
blocks = (c->indata - c->indata_used) / BLOCKSIZE;
if (!blocks)
return AVERROR_EOF;
if (!c->eof)
blocks--;
av_aes_crypt(c->aes, c->outbuffer, c->inbuffer + c->indata_used, blocks,
c->iv, 1);
c->outdata = BLOCKSIZE * blocks;
c->outptr = c->outbuffer;
c->indata_used += BLOCKSIZE * blocks;
if (c->indata_used >= sizeof(c->inbuffer)/2) {
memmove(c->inbuffer, c->inbuffer + c->indata_used,
c->indata - c->indata_used);
c->indata -= c->indata_used;
c->indata_used = 0;
}
if (c->eof) {
// Remove PKCS7 padding at the end
int padding = c->outbuffer[c->outdata - 1];
c->outdata -= padding;
}
goto retry;
}
static int crypto_close(URLContext *h)
{
CryptoContext *c = h->priv_data;
if (c->hd)
ffurl_close(c->hd);
av_free(c->aes);
av_free(c->key);
av_free(c->iv);
return 0;
}
URLProtocol ff_crypto_protocol = {
.name = "crypto",
.url_open = crypto_open,
.url_read = crypto_read,
.url_close = crypto_close,
.priv_data_size = sizeof(CryptoContext),
.priv_data_class = &crypto_class,
.flags = URL_PROTOCOL_FLAG_NESTED_SCHEME,
};
...@@ -588,7 +588,7 @@ static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom) ...@@ -588,7 +588,7 @@ static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom)
static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
{ {
c->fragment.moof_offset = avio_tell(pb) - 8; c->fragment.moof_offset = avio_tell(pb) - 8;
av_dlog(c->fc, "moof offset %llx\n", c->fragment.moof_offset); av_dlog(c->fc, "moof offset %"PRIx64"\n", c->fragment.moof_offset);
return mov_read_default(c, pb, atom); return mov_read_default(c, pb, atom);
} }
...@@ -2367,7 +2367,7 @@ static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap) ...@@ -2367,7 +2367,7 @@ static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
av_log(s, AV_LOG_ERROR, "moov atom not found\n"); av_log(s, AV_LOG_ERROR, "moov atom not found\n");
return -1; return -1;
} }
av_dlog(mov->fc, "on_parse_exit_offset=%lld\n", avio_tell(pb)); av_dlog(mov->fc, "on_parse_exit_offset=%"PRId64"\n", avio_tell(pb));
if (pb->seekable && mov->chapter_track > 0) if (pb->seekable && mov->chapter_track > 0)
mov_read_chapters(s); mov_read_chapters(s);
...@@ -2416,7 +2416,7 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -2416,7 +2416,7 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX }) < 0 || mov_read_default(mov, s->pb, (MOVAtom){ AV_RL32("root"), INT64_MAX }) < 0 ||
url_feof(s->pb)) url_feof(s->pb))
return AVERROR_EOF; return AVERROR_EOF;
av_dlog(s, "read fragments, offset 0x%llx\n", avio_tell(s->pb)); av_dlog(s, "read fragments, offset 0x%"PRIx64"\n", avio_tell(s->pb));
goto retry; goto retry;
} }
sc = st->priv_data; sc = st->priv_data;
......
...@@ -28,6 +28,34 @@ ...@@ -28,6 +28,34 @@
#include "avformat.h" #include "avformat.h"
#include "os_support.h" #include "os_support.h"
#if defined(_WIN32) && !defined(__MINGW32CE__)
#include <windows.h>
#undef open
int ff_win32_open(const char *filename_utf8, int oflag, int pmode)
{
int fd;
int num_chars;
wchar_t *filename_w;
/* convert UTF-8 to wide chars */
num_chars = MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, NULL, 0);
if (num_chars <= 0)
return -1;
filename_w = av_mallocz(sizeof(wchar_t) * num_chars);
MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, filename_w, num_chars);
fd = _wopen(filename_w, oflag, pmode);
av_freep(&filename_w);
/* filename maybe be in CP_ACP */
if (fd == -1 && !(oflag & O_CREAT))
return open(filename_utf8, oflag, pmode);
return fd;
}
#endif
#if CONFIG_NETWORK #if CONFIG_NETWORK
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
......
...@@ -45,6 +45,11 @@ static inline int is_dos_path(const char *path) ...@@ -45,6 +45,11 @@ static inline int is_dos_path(const char *path)
return 0; return 0;
} }
#if defined(_WIN32) && !defined(__MINGW32CE__)
int ff_win32_open(const char *filename, int oflag, int pmode);
#define open ff_win32_open
#endif
#if CONFIG_NETWORK #if CONFIG_NETWORK
#if !HAVE_SOCKLEN_T #if !HAVE_SOCKLEN_T
typedef int socklen_t; typedef int socklen_t;
......
...@@ -551,8 +551,8 @@ static RTPDynamicProtocolHandler ff_rdt_ ## n ## _handler = { \ ...@@ -551,8 +551,8 @@ static RTPDynamicProtocolHandler ff_rdt_ ## n ## _handler = { \
.codec_type = t, \ .codec_type = t, \
.codec_id = CODEC_ID_NONE, \ .codec_id = CODEC_ID_NONE, \
.parse_sdp_a_line = rdt_parse_sdp_line, \ .parse_sdp_a_line = rdt_parse_sdp_line, \
.open = rdt_new_context, \ .alloc = rdt_new_context, \
.close = rdt_free_context, \ .free = rdt_free_context, \
.parse_packet = rdt_parse_packet \ .parse_packet = rdt_parse_packet \
} }
......
...@@ -126,8 +126,8 @@ struct RTPDynamicProtocolHandler_s { ...@@ -126,8 +126,8 @@ struct RTPDynamicProtocolHandler_s {
int st_index, int st_index,
PayloadContext *priv_data, PayloadContext *priv_data,
const char *line); ///< Parse the a= line from the sdp field const char *line); ///< Parse the a= line from the sdp field
PayloadContext *(*open) (void); ///< allocate any data needed by the rtp parsing for this dynamic data. PayloadContext *(*alloc) (void); ///< allocate any data needed by the rtp parsing for this dynamic data.
void (*close)(PayloadContext *protocol_data); ///< free any data needed by the rtp parsing for this dynamic data. void (*free)(PayloadContext *protocol_data); ///< free any data needed by the rtp parsing for this dynamic data.
DynamicPayloadPacketHandlerProc parse_packet; ///< parse handler for this dynamic packet. DynamicPayloadPacketHandlerProc parse_packet; ///< parse handler for this dynamic packet.
struct RTPDynamicProtocolHandler_s *next; struct RTPDynamicProtocolHandler_s *next;
......
...@@ -191,8 +191,8 @@ RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler = { ...@@ -191,8 +191,8 @@ RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler = {
.codec_type = AVMEDIA_TYPE_AUDIO, .codec_type = AVMEDIA_TYPE_AUDIO,
.codec_id = CODEC_ID_AMR_NB, .codec_id = CODEC_ID_AMR_NB,
.parse_sdp_a_line = amr_parse_sdp_line, .parse_sdp_a_line = amr_parse_sdp_line,
.open = amr_new_context, .alloc = amr_new_context,
.close = amr_free_context, .free = amr_free_context,
.parse_packet = amr_handle_packet, .parse_packet = amr_handle_packet,
}; };
...@@ -201,8 +201,8 @@ RTPDynamicProtocolHandler ff_amr_wb_dynamic_handler = { ...@@ -201,8 +201,8 @@ RTPDynamicProtocolHandler ff_amr_wb_dynamic_handler = {
.codec_type = AVMEDIA_TYPE_AUDIO, .codec_type = AVMEDIA_TYPE_AUDIO,
.codec_id = CODEC_ID_AMR_WB, .codec_id = CODEC_ID_AMR_WB,
.parse_sdp_a_line = amr_parse_sdp_line, .parse_sdp_a_line = amr_parse_sdp_line,
.open = amr_new_context, .alloc = amr_new_context,
.close = amr_free_context, .free = amr_free_context,
.parse_packet = amr_handle_packet, .parse_packet = amr_handle_packet,
}; };
...@@ -286,8 +286,8 @@ RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \ ...@@ -286,8 +286,8 @@ RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \
.codec_type = t, \ .codec_type = t, \
.codec_id = CODEC_ID_NONE, \ .codec_id = CODEC_ID_NONE, \
.parse_sdp_a_line = asfrtp_parse_sdp_line, \ .parse_sdp_a_line = asfrtp_parse_sdp_line, \
.open = asfrtp_new_context, \ .alloc = asfrtp_new_context, \
.close = asfrtp_free_context, \ .free = asfrtp_free_context, \
.parse_packet = asfrtp_parse_packet, \ .parse_packet = asfrtp_parse_packet, \
} }
......
...@@ -398,7 +398,7 @@ RTPDynamicProtocolHandler ff_h264_dynamic_handler = { ...@@ -398,7 +398,7 @@ RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
.codec_type = AVMEDIA_TYPE_VIDEO, .codec_type = AVMEDIA_TYPE_VIDEO,
.codec_id = CODEC_ID_H264, .codec_id = CODEC_ID_H264,
.parse_sdp_a_line = parse_h264_sdp_line, .parse_sdp_a_line = parse_h264_sdp_line,
.open = h264_new_context, .alloc = h264_new_context,
.close = h264_free_context, .free = h264_free_context,
.parse_packet = h264_handle_packet .parse_packet = h264_handle_packet
}; };
...@@ -181,7 +181,7 @@ RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler = { ...@@ -181,7 +181,7 @@ RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler = {
.codec_type = AVMEDIA_TYPE_AUDIO, .codec_type = AVMEDIA_TYPE_AUDIO,
.codec_id = CODEC_ID_AAC, .codec_id = CODEC_ID_AAC,
.parse_sdp_a_line = latm_parse_sdp_line, .parse_sdp_a_line = latm_parse_sdp_line,
.open = latm_new_context, .alloc = latm_new_context,
.close = latm_free_context, .free = latm_free_context,
.parse_packet = latm_parse_packet .parse_packet = latm_parse_packet
}; };
...@@ -235,8 +235,8 @@ RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler = { ...@@ -235,8 +235,8 @@ RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler = {
.codec_type = AVMEDIA_TYPE_VIDEO, .codec_type = AVMEDIA_TYPE_VIDEO,
.codec_id = CODEC_ID_MPEG4, .codec_id = CODEC_ID_MPEG4,
.parse_sdp_a_line = parse_sdp_line, .parse_sdp_a_line = parse_sdp_line,
.open = NULL, .alloc = NULL,
.close = NULL, .free = NULL,
.parse_packet = NULL .parse_packet = NULL
}; };
...@@ -245,7 +245,7 @@ RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler = { ...@@ -245,7 +245,7 @@ RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler = {
.codec_type = AVMEDIA_TYPE_AUDIO, .codec_type = AVMEDIA_TYPE_AUDIO,
.codec_id = CODEC_ID_AAC, .codec_id = CODEC_ID_AAC,
.parse_sdp_a_line = parse_sdp_line, .parse_sdp_a_line = parse_sdp_line,
.open = new_context, .alloc = new_context,
.close = free_context, .free = free_context,
.parse_packet = aac_parse_packet .parse_packet = aac_parse_packet
}; };
...@@ -223,7 +223,7 @@ RTPDynamicProtocolHandler ff_qcelp_dynamic_handler = { ...@@ -223,7 +223,7 @@ RTPDynamicProtocolHandler ff_qcelp_dynamic_handler = {
.codec_type = AVMEDIA_TYPE_AUDIO, .codec_type = AVMEDIA_TYPE_AUDIO,
.codec_id = CODEC_ID_QCELP, .codec_id = CODEC_ID_QCELP,
.static_payload_id = 12, .static_payload_id = 12,
.open = qcelp_new_context, .alloc = qcelp_new_context,
.close = qcelp_free_context, .free = qcelp_free_context,
.parse_packet = qcelp_parse_packet .parse_packet = qcelp_parse_packet
}; };
...@@ -309,7 +309,7 @@ RTPDynamicProtocolHandler ff_qdm2_dynamic_handler = { ...@@ -309,7 +309,7 @@ RTPDynamicProtocolHandler ff_qdm2_dynamic_handler = {
.enc_name = "X-QDM", .enc_name = "X-QDM",
.codec_type = AVMEDIA_TYPE_AUDIO, .codec_type = AVMEDIA_TYPE_AUDIO,
.codec_id = CODEC_ID_NONE, .codec_id = CODEC_ID_NONE,
.open = qdm2_extradata_new, .alloc = qdm2_extradata_new,
.close = qdm2_extradata_free, .free = qdm2_extradata_free,
.parse_packet = qdm2_parse_packet, .parse_packet = qdm2_parse_packet,
}; };
...@@ -244,8 +244,8 @@ RTPDynamicProtocolHandler ff_ ## m ## _rtp_ ## n ## _handler = { \ ...@@ -244,8 +244,8 @@ RTPDynamicProtocolHandler ff_ ## m ## _rtp_ ## n ## _handler = { \
.enc_name = s, \ .enc_name = s, \
.codec_type = t, \ .codec_type = t, \
.codec_id = CODEC_ID_NONE, \ .codec_id = CODEC_ID_NONE, \
.open = qt_rtp_new, \ .alloc = qt_rtp_new, \
.close = qt_rtp_free, \ .free = qt_rtp_free, \
.parse_packet = qt_rtp_parse_packet, \ .parse_packet = qt_rtp_parse_packet, \
} }
......
...@@ -128,7 +128,7 @@ RTPDynamicProtocolHandler ff_svq3_dynamic_handler = { ...@@ -128,7 +128,7 @@ RTPDynamicProtocolHandler ff_svq3_dynamic_handler = {
.enc_name = "X-SV3V-ES", .enc_name = "X-SV3V-ES",
.codec_type = AVMEDIA_TYPE_VIDEO, .codec_type = AVMEDIA_TYPE_VIDEO,
.codec_id = CODEC_ID_NONE, // see if (config_packet) above .codec_id = CODEC_ID_NONE, // see if (config_packet) above
.open = svq3_extradata_new, .alloc = svq3_extradata_new,
.close = svq3_extradata_free, .free = svq3_extradata_free,
.parse_packet = svq3_parse_packet, .parse_packet = svq3_parse_packet,
}; };
...@@ -148,7 +148,7 @@ RTPDynamicProtocolHandler ff_vp8_dynamic_handler = { ...@@ -148,7 +148,7 @@ RTPDynamicProtocolHandler ff_vp8_dynamic_handler = {
.enc_name = "VP8", .enc_name = "VP8",
.codec_type = AVMEDIA_TYPE_VIDEO, .codec_type = AVMEDIA_TYPE_VIDEO,
.codec_id = CODEC_ID_VP8, .codec_id = CODEC_ID_VP8,
.open = vp8_new_context, .alloc = vp8_new_context,
.close = vp8_free_context, .free = vp8_free_context,
.parse_packet = vp8_handle_packet, .parse_packet = vp8_handle_packet,
}; };
...@@ -389,8 +389,8 @@ RTPDynamicProtocolHandler ff_theora_dynamic_handler = { ...@@ -389,8 +389,8 @@ RTPDynamicProtocolHandler ff_theora_dynamic_handler = {
.codec_type = AVMEDIA_TYPE_VIDEO, .codec_type = AVMEDIA_TYPE_VIDEO,
.codec_id = CODEC_ID_THEORA, .codec_id = CODEC_ID_THEORA,
.parse_sdp_a_line = xiph_parse_sdp_line, .parse_sdp_a_line = xiph_parse_sdp_line,
.open = xiph_new_context, .alloc = xiph_new_context,
.close = xiph_free_context, .free = xiph_free_context,
.parse_packet = xiph_handle_packet .parse_packet = xiph_handle_packet
}; };
...@@ -399,7 +399,7 @@ RTPDynamicProtocolHandler ff_vorbis_dynamic_handler = { ...@@ -399,7 +399,7 @@ RTPDynamicProtocolHandler ff_vorbis_dynamic_handler = {
.codec_type = AVMEDIA_TYPE_AUDIO, .codec_type = AVMEDIA_TYPE_AUDIO,
.codec_id = CODEC_ID_VORBIS, .codec_id = CODEC_ID_VORBIS,
.parse_sdp_a_line = xiph_parse_sdp_line, .parse_sdp_a_line = xiph_parse_sdp_line,
.open = xiph_new_context, .alloc = xiph_new_context,
.close = xiph_free_context, .free = xiph_free_context,
.parse_packet = xiph_handle_packet .parse_packet = xiph_handle_packet
}; };
...@@ -132,8 +132,8 @@ static void init_rtp_handler(RTPDynamicProtocolHandler *handler, ...@@ -132,8 +132,8 @@ static void init_rtp_handler(RTPDynamicProtocolHandler *handler,
return; return;
codec->codec_id = handler->codec_id; codec->codec_id = handler->codec_id;
rtsp_st->dynamic_handler = handler; rtsp_st->dynamic_handler = handler;
if (handler->open) if (handler->alloc)
rtsp_st->dynamic_protocol_context = handler->open(); rtsp_st->dynamic_protocol_context = handler->alloc();
} }
/* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */ /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */
...@@ -526,7 +526,7 @@ void ff_rtsp_close_streams(AVFormatContext *s) ...@@ -526,7 +526,7 @@ void ff_rtsp_close_streams(AVFormatContext *s)
rtsp_st = rt->rtsp_streams[i]; rtsp_st = rt->rtsp_streams[i];
if (rtsp_st) { if (rtsp_st) {
if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context) if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context)
rtsp_st->dynamic_handler->close( rtsp_st->dynamic_handler->free(
rtsp_st->dynamic_protocol_context); rtsp_st->dynamic_protocol_context);
av_free(rtsp_st); av_free(rtsp_st);
} }
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#define LIBAVFORMAT_VERSION_MAJOR 53 #define LIBAVFORMAT_VERSION_MAJOR 53
#define LIBAVFORMAT_VERSION_MINOR 0 #define LIBAVFORMAT_VERSION_MINOR 0
#define LIBAVFORMAT_VERSION_MICRO 1 #define LIBAVFORMAT_VERSION_MICRO 3
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \ LIBAVFORMAT_VERSION_MINOR, \
......
...@@ -29,9 +29,9 @@ ...@@ -29,9 +29,9 @@
#include "libavutil/attributes.h" #include "libavutil/attributes.h"
#define av_bswap16 av_bswap16 #define av_bswap16 av_bswap16
static av_always_inline av_const uint16_t av_bswap16(uint16_t x) static av_always_inline av_const unsigned av_bswap16(unsigned x)
{ {
__asm__("rorw $8, %0" : "+r"(x)); __asm__("rorw $8, %w0" : "+r"(x));
return x; return x;
} }
......
#!/bin/sh #!/bin/sh
sed '/^+[^+]/!s/ /TaBBaT/g' |\ sed '/^+[^+]/!s/ /TaBBaT/g' |\
expand -t `seq -s , 9 8 200` |\ expand -t $(seq -s , 9 8 200) |\
sed 's/TaBBaT/ /g' |\ sed 's/TaBBaT/ /g' |\
sed '/^+[^+]/s/ * $//' |\ sed '/^+[^+]/s/ * $//' |\
tr -d '\015' |\ tr -d '\015' |\
......
...@@ -8,9 +8,11 @@ if [ $# = 0 ]; then ...@@ -8,9 +8,11 @@ if [ $# = 0 ]; then
exit exit
fi fi
GREP=grep
EGREP=egrep
TMP=patcheck.tmp TMP=patcheck.tmp
OPT="-nH" OPT="-nH"
#FILES=`grep '^+++' $* | sed 's/+++ //g'` #FILES=$($GREP '^+++' $* | sed 's/+++ //g')
echo patCHeck 1e10.0 echo patCHeck 1e10.0
echo This tool is intended to help a human check/review patches it is very far from echo This tool is intended to help a human check/review patches it is very far from
...@@ -27,7 +29,7 @@ hiegrep(){ ...@@ -27,7 +29,7 @@ hiegrep(){
arg="$1" arg="$1"
msg="$2" msg="$2"
shift 2 shift 2
grep $OPT '^+' $* | grep -v ':+++'| egrep --color=always -- "$arg"> $TMP && printf "\n$msg\n" $GREP $OPT '^+' $* | $GREP -v ':+++'| $EGREP --color=always -- "$arg"> $TMP && printf "\n$msg\n"
cat $TMP cat $TMP
} }
...@@ -36,12 +38,12 @@ hiegrep2(){ ...@@ -36,12 +38,12 @@ hiegrep2(){
varg="$2" varg="$2"
msg="$3" msg="$3"
shift 3 shift 3
grep $OPT '^+' $* | grep -v ':+++' | egrep -v -- "$varg" | egrep --color=always -- "$arg" > $TMP && printf "\n$msg\n" $GREP $OPT '^+' $* | $GREP -v ':+++' | $EGREP -v -- "$varg" | $EGREP --color=always -- "$arg" > $TMP && printf "\n$msg\n"
cat $TMP cat $TMP
} }
hiegrep '[[:space:]]$' 'trailing whitespace' $* hiegrep '[[:space:]]$' 'trailing whitespace' $*
hiegrep "`echo x | tr 'x' '\t'`" 'tabs' $* hiegrep "$(echo x | tr 'x' '\t')" 'tabs' $*
#hiegrep ':\+$' 'Empty lines' $* #hiegrep ':\+$' 'Empty lines' $*
hiegrep ';;' 'double ;' $* hiegrep ';;' 'double ;' $*
hiegrep2 '\b_[a-zA-Z0-9_]{1,}' '__(asm|attribute)([^a-zA-Z0-9]|$)' 'reserved identifer' $* hiegrep2 '\b_[a-zA-Z0-9_]{1,}' '__(asm|attribute)([^a-zA-Z0-9]|$)' 'reserved identifer' $*
...@@ -60,7 +62,7 @@ hiegrep '\+= *1 *;' 'can be simplified to ++' $* ...@@ -60,7 +62,7 @@ hiegrep '\+= *1 *;' 'can be simplified to ++' $*
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' $* 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' $EGREP $OPT '^\+ *(const *|)static' $*| $EGREP --color=always '[^=]= *(0|NULL)[^0-9a-zA-Z]'> $TMP && printf '\nuseless 0 init\n'
cat $TMP cat $TMP
hiegrep '# *ifdef * (HAVE|CONFIG)_' 'ifdefs that should be #if' $* hiegrep '# *ifdef * (HAVE|CONFIG)_' 'ifdefs that should be #if' $*
...@@ -90,7 +92,7 @@ hiegrep2 '\.sample_fmts *= *\(' 'const' 'missing const for sample_fmts array' $* ...@@ -90,7 +92,7 @@ hiegrep2 '\.sample_fmts *= *\(' 'const' 'missing const for sample_fmts array' $*
hiegrep2 '\.supported_framerates *= *\(' 'const' 'missing const for supported_framerates array' $* hiegrep2 '\.supported_framerates *= *\(' 'const' 'missing const for supported_framerates array' $*
hiegrep2 '\.channel_layouts *= *\(' 'const' 'missing const for channel_layouts array' $* hiegrep2 '\.channel_layouts *= *\(' 'const' 'missing const for channel_layouts array' $*
#egrep $OPT '^\+.*const ' $*| grep -v 'static'> $TMP && printf '\nnon static const\n' #$EGREP $OPT '^\+.*const ' $*| $GREP -v 'static'> $TMP && printf '\nnon static const\n'
#cat $TMP #cat $TMP
hiegrep2 "$ERE_TYPES" '(static|av_|ff_|typedef|:\+[^a-zA-Z_])' 'Non static with no ff_/av_ prefix' $* hiegrep2 "$ERE_TYPES" '(static|av_|ff_|typedef|:\+[^a-zA-Z_])' 'Non static with no ff_/av_ prefix' $*
...@@ -105,58 +107,58 @@ hiegrep ':\+ *{ *$' '{ should be on the same line as the related previous state ...@@ -105,58 +107,58 @@ hiegrep ':\+ *{ *$' '{ should be on the same line as the related previous state
rm $TMP rm $TMP
for i in `grep -H '^+.*@param' $*| sed 's/^\([^:]*\):.*@param\(\[.*\]\|\) *\([a-zA-Z0-9_]*\) .*$/\1:\3/'` ; do for i in $($GREP -H '^+.*@param' $*| sed 's/^\([^:]*\):.*@param\(\[.*\]\|\) *\([a-zA-Z0-9_]*\) .*$/\1:\3/') ; do
doxpar=`echo $i | sed 's/^.*:\(.*\)$/\1/'` doxpar=$(echo $i | sed 's/^.*:\(.*\)$/\1/')
file=`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 $GREP " *$doxpar *[),]" $file | $GREP -v '@param' >/dev/null || $GREP --color=always "@param *$doxpar" $file >>$TMP
done done
if test -e $TMP ; then if test -e $TMP ; then
printf '\nmismatching doxy params\n' printf '\nmismatching doxy params\n'
cat $TMP cat $TMP
fi fi
egrep -B2 $OPT '^(\+|) *('"$ERE_TYPES"'|# *define)' $* | egrep -A2 --color=always '(:|-)\+[^/]*/(\*([^*]|$)|/([^/]|$))' > $TMP && printf "\n Non doxy comments\n" $EGREP -B2 $OPT '^(\+|) *('"$ERE_TYPES"'|# *define)' $* | $EGREP -A2 --color=always '(:|-)\+[^/]*/(\*([^*]|$)|/([^/]|$))' > $TMP && printf "\n Non doxy comments\n"
cat $TMP cat $TMP
rm $TMP rm $TMP
for i in \ for i in \
`egrep -H '^\+ *'"$ERE_TYPES" $* |\ $($EGREP -H '^\+ *'"$ERE_TYPES" $* |\
grep -v '(' | egrep -v '\Wgoto\W' |\ $GREP -v '(' | $EGREP -v '\Wgoto\W' |\
xargs -d '\n' -n 1 |\ xargs -d '\n' -n 1 |\
grep -o '[* ][* ]*[a-zA-Z][0-9a-zA-Z_]* *[,;=]' |\ $GREP -o '[* ][* ]*[a-zA-Z][0-9a-zA-Z_]* *[,;=]' |\
sed 's/.[* ]*\([a-zA-Z][0-9a-zA-Z_]*\) *[,;=]/\1/'` \ sed 's/.[* ]*\([a-zA-Z][0-9a-zA-Z_]*\) *[,;=]/\1/') \
; do ; do
echo $i | grep '^NULL$' && continue echo $i | $GREP '^NULL$' && continue
egrep $i' *(\+|-|\*|/|\||&|%|)=[^=]' $* >/dev/null || echo "possibly never written:"$i >> $TMP $EGREP $i' *(\+|-|\*|/|\||&|%|)=[^=]' $* >/dev/null || echo "possibly never written:"$i >> $TMP
egrep '(=|\(|return).*'$i'(==|[^=])*$' $* >/dev/null || echo "possibly never read :"$i >> $TMP $EGREP '(=|\(|return).*'$i'(==|[^=])*$' $* >/dev/null || echo "possibly never read :"$i >> $TMP
egrep -o $i' *((\+|-|\*|/|\||&|%|)=[^=]|\+\+|--) *(0x|)[0-9]*(;|)' $* |\ $EGREP -o $i' *((\+|-|\*|/|\||&|%|)=[^=]|\+\+|--) *(0x|)[0-9]*(;|)' $* |\
egrep -v $i' *= *(0x|)[0-9]{1,};'>/dev/null || echo "possibly constant :"$i >> $TMP $EGREP -v $i' *= *(0x|)[0-9]{1,};'>/dev/null || echo "possibly constant :"$i >> $TMP
done done
if test -e $TMP ; then if test -e $TMP ; then
printf '\npossibly unused variables\n' printf '\npossibly unused variables\n'
cat $TMP cat $TMP
fi fi
grep '^+++ .*Changelog' $* >/dev/null || printf "\nMissing changelog entry (ignore if minor change)\n" $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 $* | tr '\n' '@' | $EGREP --color=always -o '(fprintf|av_log|printf)\([^)]*\)[+ ;@]*\1' >$TMP && printf "\nMergeable calls\n"
cat $TMP | tr '@' '\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 $* | 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 $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 $* | 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 $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 $* | 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 $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 $* | 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' cat $TMP | tr '@' '\n'
# doesnt work # doesnt 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 $* | 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' #cat $TMP | tr '@' '\n'
exit exit
...@@ -164,7 +166,7 @@ exit ...@@ -164,7 +166,7 @@ exit
TODO/idea list: TODO/idea list:
for all demuxers & muxers for all demuxers & muxers
grep for "avctx->priv_data" $EGREP for "avctx->priv_data"
vertical align = vertical align =
/* and * align /* and * align
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment