mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-26 19:01:44 +02:00
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: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
commit
7b376b398a
63
cmdutils.c
63
cmdutils.c
@ -153,6 +153,66 @@ static const OptionDef* find_option(const OptionDef *po, const char *name){
|
||||
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_arg_function)(const char*))
|
||||
{
|
||||
@ -160,6 +220,9 @@ void parse_options(int argc, char **argv, const OptionDef *options,
|
||||
int optindex, handleoptions=1;
|
||||
const OptionDef *po;
|
||||
|
||||
/* perform system-dependent conversions for arguments list */
|
||||
prepare_app_arguments(&argc, &argv);
|
||||
|
||||
/* parse options */
|
||||
optindex = 1;
|
||||
while (optindex < argc) {
|
||||
|
2
configure
vendored
2
configure
vendored
@ -1248,7 +1248,7 @@ mdct_select="fft"
|
||||
rdft_select="fft"
|
||||
|
||||
# decoders / encoders / hardware accelerators
|
||||
aac_decoder_select="mdct rdft sinewin"
|
||||
aac_decoder_select="mdct sinewin"
|
||||
aac_encoder_select="mdct sinewin"
|
||||
aac_latm_decoder_select="aac_decoder aac_latm_parser"
|
||||
ac3_decoder_select="mdct ac3dsp ac3_parser"
|
||||
|
@ -280,7 +280,7 @@ Just create an "input.avs" text file with this single line ...
|
||||
@example
|
||||
DirectShowSource("C:\path to your file\yourfile.asf")
|
||||
@end example
|
||||
... and then feed that text file to FFmpeg:
|
||||
... and then feed that text file to ffmpeg:
|
||||
@example
|
||||
ffmpeg -i input.avs
|
||||
@end example
|
||||
@ -348,7 +348,7 @@ ffmpeg -f u16le -acodec pcm_s16le -ac 2 -ar 44100 -i all.a \
|
||||
rm temp[12].[av] all.[av]
|
||||
@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.
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
\input texinfo @c -*- texinfo -*-
|
||||
|
||||
@settitle FFmpeg Documentation
|
||||
@settitle ffmpeg Documentation
|
||||
@titlepage
|
||||
@center @titlefont{FFmpeg Documentation}
|
||||
@center @titlefont{ffmpeg Documentation}
|
||||
@end titlepage
|
||||
|
||||
@top
|
||||
@ -22,17 +22,15 @@ ffmpeg [[infile options][@option{-i} @var{infile}]]... @{[outfile options] @var{
|
||||
@chapter Description
|
||||
@c man begin DESCRIPTION
|
||||
|
||||
FFmpeg is a very fast video and audio converter. It can also grab from
|
||||
a live audio/video source.
|
||||
ffmpeg is a very fast video and audio converter that can also grab from
|
||||
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
|
||||
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
|
||||
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
|
||||
file. Therefore, order is important, and you can have the same
|
||||
option on the command line multiple times. Each occurrence is
|
||||
@ -61,7 +59,7 @@ ffmpeg -r 1 -i input.m2v -r 24 output.avi
|
||||
|
||||
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
|
||||
specified for the inputs.
|
||||
|
||||
@ -495,7 +493,7 @@ Use 'frames' B-frames (supported for MPEG-1, MPEG-2 and MPEG-4).
|
||||
macroblock decision
|
||||
@table @samp
|
||||
@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
|
||||
FF_MB_DECISION_BITS: Choose the one which needs the fewest bits.
|
||||
@item 2
|
||||
@ -877,22 +875,22 @@ It allows almost lossless encoding.
|
||||
|
||||
@section Video and Audio grabbing
|
||||
|
||||
FFmpeg can grab video and audio from devices given that you specify the input
|
||||
format and device.
|
||||
If you specify the input format and device then ffmpeg can grab video
|
||||
and audio directly.
|
||||
|
||||
@example
|
||||
ffmpeg -f oss -i /dev/dsp -f video4linux2 -i /dev/video0 /tmp/out.mpg
|
||||
@end example
|
||||
|
||||
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
|
||||
have to set the audio recording levels correctly with a
|
||||
standard mixer.
|
||||
|
||||
@section X11 grabbing
|
||||
|
||||
FFmpeg can grab the X11 display.
|
||||
Grab the X11 display with ffmpeg via
|
||||
|
||||
@example
|
||||
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.
|
||||
|
||||
@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:
|
||||
@itemize
|
||||
@ -930,7 +928,7 @@ It will use the files:
|
||||
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
|
||||
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
|
||||
You can input from a raw YUV420P file:
|
||||
@ -1057,7 +1055,7 @@ file to which you want to add them.
|
||||
@ignore
|
||||
|
||||
@setfilename ffmpeg
|
||||
@settitle FFmpeg video converter
|
||||
@settitle ffmpeg video converter
|
||||
|
||||
@c man begin SEEALSO
|
||||
ffplay(1), ffprobe(1), ffserver(1) and the FFmpeg HTML documentation
|
||||
|
@ -1,8 +1,8 @@
|
||||
\input texinfo @c -*- texinfo -*-
|
||||
|
||||
@settitle FFplay Documentation
|
||||
@settitle ffplay Documentation
|
||||
@titlepage
|
||||
@center @titlefont{FFplay Documentation}
|
||||
@center @titlefont{ffplay Documentation}
|
||||
@end titlepage
|
||||
|
||||
@top
|
||||
|
@ -1,8 +1,8 @@
|
||||
\input texinfo @c -*- texinfo -*-
|
||||
|
||||
@settitle FFprobe Documentation
|
||||
@settitle ffprobe Documentation
|
||||
@titlepage
|
||||
@center @titlefont{FFprobe Documentation}
|
||||
@center @titlefont{ffprobe Documentation}
|
||||
@end titlepage
|
||||
|
||||
@top
|
||||
@ -22,7 +22,7 @@ ffprobe [options] [@file{input_file}]
|
||||
@chapter 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.
|
||||
|
||||
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
|
||||
probe the file content. If the file cannot be opened or recognized as
|
||||
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
|
||||
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
|
||||
for specifying which information to display, and for setting how
|
||||
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:
|
||||
@example
|
||||
[SECTION]
|
||||
@ -119,7 +119,7 @@ with name "STREAM".
|
||||
@ignore
|
||||
|
||||
@setfilename ffprobe
|
||||
@settitle FFprobe media prober
|
||||
@settitle ffprobe media prober
|
||||
|
||||
@c man begin SEEALSO
|
||||
ffmpeg(1), ffplay(1), ffserver(1) and the FFmpeg HTML documentation
|
||||
|
@ -1,8 +1,8 @@
|
||||
\input texinfo @c -*- texinfo -*-
|
||||
|
||||
@settitle FFserver Documentation
|
||||
@settitle ffserver Documentation
|
||||
@titlepage
|
||||
@center @titlefont{FFserver Documentation}
|
||||
@center @titlefont{ffserver Documentation}
|
||||
@end titlepage
|
||||
|
||||
@top
|
||||
@ -22,12 +22,12 @@ ffserver [options]
|
||||
@chapter 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
|
||||
(you can seek to positions in the past on each live feed, provided you
|
||||
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
|
||||
debug mode or a NoDaemon option is specified in the configuration
|
||||
file.
|
||||
@ -39,7 +39,7 @@ information.
|
||||
|
||||
@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.
|
||||
|
||||
An ffserver instance will listen on some port as specified in the
|
||||
@ -57,7 +57,7 @@ file.
|
||||
|
||||
@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.
|
||||
|
||||
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}.
|
||||
Use @file{configfile} instead of @file{/etc/ffserver.conf}.
|
||||
@item -n
|
||||
Enable no-launch mode. This option disables all the Launch directives
|
||||
within the various <Stream> sections. FFserver will not launch any
|
||||
ffmpeg instance, so you will have to launch them manually.
|
||||
within the various <Stream> sections. Since ffserver will not launch
|
||||
any ffmpeg instances, you will have to launch them manually.
|
||||
@item -d
|
||||
Enable debug mode. This option increases log verbosity, directs log
|
||||
messages to stdout and causes ffserver to run in the foreground
|
||||
@ -261,7 +261,7 @@ rather than as a daemon.
|
||||
@ignore
|
||||
|
||||
@setfilename ffserver
|
||||
@settitle FFserver video server
|
||||
@settitle ffserver video server
|
||||
|
||||
@c man begin SEEALSO
|
||||
|
||||
|
@ -789,9 +789,9 @@ to configure.
|
||||
BSD make will not build FFmpeg, you need to install and use GNU Make
|
||||
(@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
|
||||
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
|
||||
|
4
ffmpeg.c
4
ffmpeg.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* FFmpeg main
|
||||
* ffmpeg main
|
||||
* Copyright (c) 2000-2003 Fabrice Bellard
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
@ -85,7 +85,7 @@
|
||||
|
||||
#include "libavutil/avassert.h"
|
||||
|
||||
const char program_name[] = "FFmpeg";
|
||||
const char program_name[] = "ffmpeg";
|
||||
const int program_birth_year = 2000;
|
||||
|
||||
/* select an input stream for an output stream */
|
||||
|
4
ffplay.c
4
ffplay.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* FFplay : Simple Media Player based on the FFmpeg libraries
|
||||
* ffplay : Simple Media Player based on the FFmpeg libraries
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
@ -56,7 +56,7 @@
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
const char program_name[] = "FFplay";
|
||||
const char program_name[] = "ffplay";
|
||||
const int program_birth_year = 2003;
|
||||
|
||||
//#define DEBUG
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* FFprobe : Simple Media Prober based on the FFmpeg libraries
|
||||
* ffprobe : Simple Media Prober based on the FFmpeg libraries
|
||||
* Copyright (c) 2007-2010 Stefano Sabatini
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
@ -28,7 +28,7 @@
|
||||
#include "libavdevice/avdevice.h"
|
||||
#include "cmdutils.h"
|
||||
|
||||
const char program_name[] = "FFprobe";
|
||||
const char program_name[] = "ffprobe";
|
||||
const int program_birth_year = 2007;
|
||||
|
||||
static int do_show_format = 0;
|
||||
|
@ -59,7 +59,7 @@
|
||||
|
||||
#include "cmdutils.h"
|
||||
|
||||
const char program_name[] = "FFserver";
|
||||
const char program_name[] = "ffserver";
|
||||
const int program_birth_year = 2000;
|
||||
|
||||
static const OptionDef options[];
|
||||
|
@ -392,9 +392,9 @@ OBJS-$(CONFIG_VCR1_ENCODER) += vcr1.o
|
||||
OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o
|
||||
OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdav.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
|
||||
OBJS-$(CONFIG_VORBIS_ENCODER) += vorbis_enc.o vorbis.o \
|
||||
OBJS-$(CONFIG_VORBIS_ENCODER) += vorbisenc.o vorbis.o \
|
||||
vorbis_data.o
|
||||
OBJS-$(CONFIG_VP3_DECODER) += vp3.o vp3dsp.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,
|
||||
GetBitContext gb;
|
||||
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);
|
||||
|
||||
if ((i = ff_mpeg4audio_get_config(m4ac, data, data_size)) < 0)
|
||||
@ -489,6 +494,10 @@ static int decode_audio_specific_config(AACContext *ac,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -606,8 +606,10 @@ static int aac_encode_frame(AVCodecContext *avctx,
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
s->lambda *= avctx->bit_rate * 1024.0f / avctx->sample_rate / frame_bits;
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
|
||||
/***********************************
|
||||
* TODOs:
|
||||
* thresholds linearization after their modifications for attaining given bitrate
|
||||
* try other bitrate controlling mechanism (maybe use ratecontrol.c?)
|
||||
* control quality for quality-based output
|
||||
**********************************/
|
||||
@ -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_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_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 */
|
||||
#define PSY_LAME_FIR_LEN 21 ///< LAME psy model FIR order
|
||||
#define AAC_BLOCK_SIZE_LONG 1024 ///< long block size
|
||||
@ -60,9 +100,15 @@
|
||||
* information for single band used by 3GPP TS26.403-inspired psychoacoustic model
|
||||
*/
|
||||
typedef struct AacPsyBand{
|
||||
float energy; ///< band energy
|
||||
float thr; ///< energy threshold
|
||||
float thr_quiet; ///< threshold in quiet
|
||||
float energy; ///< band energy
|
||||
float thr; ///< energy threshold
|
||||
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;
|
||||
|
||||
/**
|
||||
@ -97,6 +143,15 @@ typedef struct AacPsyCoeffs{
|
||||
* 3GPP TS26.403-inspired psychoacoustic model specific data
|
||||
*/
|
||||
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];
|
||||
AacPsyChannel *ch;
|
||||
}AacPsyContext;
|
||||
@ -235,16 +290,33 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) {
|
||||
AacPsyContext *pctx;
|
||||
float bark;
|
||||
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));
|
||||
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);
|
||||
for (j = 0; j < 2; j++) {
|
||||
AacPsyCoeffs *coeffs = pctx->psy_coef[j];
|
||||
const uint8_t *band_sizes = ctx->bands[j];
|
||||
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;
|
||||
prev = 0.0;
|
||||
for (g = 0; g < ctx->num_bands[j]; g++) {
|
||||
@ -258,6 +330,11 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) {
|
||||
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_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;
|
||||
for (g = 0; g < ctx->num_bands[j]; g++) {
|
||||
@ -385,6 +462,97 @@ static FFPsyWindowInfo psy_3gpp_window(FFPsyContext *ctx,
|
||||
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
|
||||
*/
|
||||
@ -395,37 +563,167 @@ static void psy_3gpp_analyze(FFPsyContext *ctx, int channel,
|
||||
AacPsyChannel *pch = &pctx->ch[channel];
|
||||
int start = 0;
|
||||
int i, w, g;
|
||||
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];
|
||||
float desired_bits, desired_pe, delta_pe, reduction, spread_en[128] = {0};
|
||||
float a = 0.0f, active_lines = 0.0f, norm_fac = 0.0f;
|
||||
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"
|
||||
for (w = 0; w < wi->num_windows*16; w += 16) {
|
||||
for (g = 0; g < num_bands; g++) {
|
||||
AacPsyBand *band = &pch->band[w+g];
|
||||
|
||||
float form_factor = 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->thr = band->energy * 0.001258925f;
|
||||
start += band_sizes[g];
|
||||
form_factor += sqrtf(fabs(coefs[start+i]));
|
||||
}
|
||||
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
|
||||
for (w = 0; w < wi->num_windows*16; w += 16) {
|
||||
AacPsyBand *bands = &pch->band[w];
|
||||
|
||||
//5.4.2.3 "Spreading" & 5.4.3 "Spreaded Energy Calculation"
|
||||
for (g = 1; g < num_bands; g++)
|
||||
bands[g].thr = FFMAX(bands[g].thr, bands[g-1].thr * coeffs[g].spread_hi[0]);
|
||||
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[0] = bands[0].energy;
|
||||
for (g = 1; g < num_bands; g++) {
|
||||
bands[g].thr = FFMAX(bands[g].thr, bands[g-1].thr * coeffs[g].spread_hi[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"
|
||||
for (g = 0; g < num_bands; g++) {
|
||||
AacPsyBand *band = &bands[g];
|
||||
|
||||
band->thr_quiet = band->thr = FFMAX(band->thr, coeffs[g].ath);
|
||||
//5.4.2.5 "Pre-echo control"
|
||||
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,
|
||||
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)
|
||||
switch (q->subpacket[s].cookversion) {
|
||||
case MONO:
|
||||
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;
|
||||
}
|
||||
av_log(avctx,AV_LOG_DEBUG,"MONO\n");
|
||||
|
@ -234,7 +234,7 @@ static void memset_float(float *buf, float val, int size)
|
||||
* be a multiple of four.
|
||||
* @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)
|
||||
{
|
||||
|
@ -316,6 +316,7 @@ OBJS+= avio.o aviobuf.o
|
||||
|
||||
OBJS-$(CONFIG_APPLEHTTP_PROTOCOL) += applehttpproto.o
|
||||
OBJS-$(CONFIG_CONCAT_PROTOCOL) += concat.o
|
||||
OBJS-$(CONFIG_CRYPTO_PROTOCOL) += crypto.o
|
||||
OBJS-$(CONFIG_FILE_PROTOCOL) += file.o
|
||||
OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o
|
||||
OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o httpauth.o
|
||||
|
@ -237,6 +237,7 @@ void av_register_all(void)
|
||||
/* protocols */
|
||||
REGISTER_PROTOCOL (APPLEHTTP, applehttp);
|
||||
REGISTER_PROTOCOL (CONCAT, concat);
|
||||
REGISTER_PROTOCOL (CRYPTO, crypto);
|
||||
REGISTER_PROTOCOL (FILE, file);
|
||||
REGISTER_PROTOCOL (GOPHER, gopher);
|
||||
REGISTER_PROTOCOL (HTTP, http);
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#define _XOPEN_SOURCE 600
|
||||
#include "libavutil/avstring.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "avformat.h"
|
||||
#include "internal.h"
|
||||
#include <unistd.h>
|
||||
@ -47,9 +49,17 @@
|
||||
* one anonymous toplevel variant for this, to maintain the structure.
|
||||
*/
|
||||
|
||||
enum KeyType {
|
||||
KEY_NONE,
|
||||
KEY_AES_128,
|
||||
};
|
||||
|
||||
struct segment {
|
||||
int duration;
|
||||
char url[MAX_URL_SIZE];
|
||||
char key[MAX_URL_SIZE];
|
||||
enum KeyType key_type;
|
||||
uint8_t iv[16];
|
||||
};
|
||||
|
||||
/*
|
||||
@ -77,6 +87,9 @@ struct variant {
|
||||
int needed, cur_needed;
|
||||
int cur_seq_no;
|
||||
int64_t last_load_time;
|
||||
|
||||
char key_url[MAX_URL_SIZE];
|
||||
uint8_t key[16];
|
||||
};
|
||||
|
||||
typedef struct AppleHTTPContext {
|
||||
@ -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,
|
||||
struct variant *var, AVIOContext *in)
|
||||
{
|
||||
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];
|
||||
const char *ptr;
|
||||
int close_in = 0;
|
||||
@ -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,
|
||||
&info);
|
||||
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)) {
|
||||
if (!var) {
|
||||
var = new_variant(c, 0, url, NULL);
|
||||
@ -242,6 +293,15 @@ static int parse_playlist(AppleHTTPContext *c, const char *url,
|
||||
goto fail;
|
||||
}
|
||||
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);
|
||||
dynarray_add(&var->segments, &var->n_segments, seg);
|
||||
is_segment = 0;
|
||||
@ -257,6 +317,50 @@ fail:
|
||||
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)
|
||||
{
|
||||
struct variant *v = opaque;
|
||||
@ -291,9 +395,7 @@ reload:
|
||||
goto reload;
|
||||
}
|
||||
|
||||
ret = ffurl_open(&v->input,
|
||||
v->segments[v->cur_seq_no - v->start_seq_no]->url,
|
||||
AVIO_FLAG_READ);
|
||||
ret = open_input(v);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
170
libavformat/crypto.c
Normal file
170
libavformat/crypto.c
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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)
|
||||
static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -2367,7 +2367,7 @@ static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
|
||||
av_log(s, AV_LOG_ERROR, "moov atom not found\n");
|
||||
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)
|
||||
mov_read_chapters(s);
|
||||
@ -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 ||
|
||||
url_feof(s->pb))
|
||||
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;
|
||||
}
|
||||
sc = st->priv_data;
|
||||
|
@ -28,6 +28,34 @@
|
||||
#include "avformat.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
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
@ -45,6 +45,11 @@ static inline int is_dos_path(const char *path)
|
||||
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 !HAVE_SOCKLEN_T
|
||||
typedef int socklen_t;
|
||||
|
@ -551,8 +551,8 @@ static RTPDynamicProtocolHandler ff_rdt_ ## n ## _handler = { \
|
||||
.codec_type = t, \
|
||||
.codec_id = CODEC_ID_NONE, \
|
||||
.parse_sdp_a_line = rdt_parse_sdp_line, \
|
||||
.open = rdt_new_context, \
|
||||
.close = rdt_free_context, \
|
||||
.alloc = rdt_new_context, \
|
||||
.free = rdt_free_context, \
|
||||
.parse_packet = rdt_parse_packet \
|
||||
}
|
||||
|
||||
|
@ -126,8 +126,8 @@ struct RTPDynamicProtocolHandler_s {
|
||||
int st_index,
|
||||
PayloadContext *priv_data,
|
||||
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.
|
||||
void (*close)(PayloadContext *protocol_data); ///< free 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 (*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.
|
||||
|
||||
struct RTPDynamicProtocolHandler_s *next;
|
||||
|
@ -191,8 +191,8 @@ RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler = {
|
||||
.codec_type = AVMEDIA_TYPE_AUDIO,
|
||||
.codec_id = CODEC_ID_AMR_NB,
|
||||
.parse_sdp_a_line = amr_parse_sdp_line,
|
||||
.open = amr_new_context,
|
||||
.close = amr_free_context,
|
||||
.alloc = amr_new_context,
|
||||
.free = amr_free_context,
|
||||
.parse_packet = amr_handle_packet,
|
||||
};
|
||||
|
||||
@ -201,8 +201,8 @@ RTPDynamicProtocolHandler ff_amr_wb_dynamic_handler = {
|
||||
.codec_type = AVMEDIA_TYPE_AUDIO,
|
||||
.codec_id = CODEC_ID_AMR_WB,
|
||||
.parse_sdp_a_line = amr_parse_sdp_line,
|
||||
.open = amr_new_context,
|
||||
.close = amr_free_context,
|
||||
.alloc = amr_new_context,
|
||||
.free = amr_free_context,
|
||||
.parse_packet = amr_handle_packet,
|
||||
};
|
||||
|
||||
|
@ -286,8 +286,8 @@ RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \
|
||||
.codec_type = t, \
|
||||
.codec_id = CODEC_ID_NONE, \
|
||||
.parse_sdp_a_line = asfrtp_parse_sdp_line, \
|
||||
.open = asfrtp_new_context, \
|
||||
.close = asfrtp_free_context, \
|
||||
.alloc = asfrtp_new_context, \
|
||||
.free = asfrtp_free_context, \
|
||||
.parse_packet = asfrtp_parse_packet, \
|
||||
}
|
||||
|
||||
|
@ -398,7 +398,7 @@ RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
|
||||
.codec_type = AVMEDIA_TYPE_VIDEO,
|
||||
.codec_id = CODEC_ID_H264,
|
||||
.parse_sdp_a_line = parse_h264_sdp_line,
|
||||
.open = h264_new_context,
|
||||
.close = h264_free_context,
|
||||
.alloc = h264_new_context,
|
||||
.free = h264_free_context,
|
||||
.parse_packet = h264_handle_packet
|
||||
};
|
||||
|
@ -181,7 +181,7 @@ RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler = {
|
||||
.codec_type = AVMEDIA_TYPE_AUDIO,
|
||||
.codec_id = CODEC_ID_AAC,
|
||||
.parse_sdp_a_line = latm_parse_sdp_line,
|
||||
.open = latm_new_context,
|
||||
.close = latm_free_context,
|
||||
.alloc = latm_new_context,
|
||||
.free = latm_free_context,
|
||||
.parse_packet = latm_parse_packet
|
||||
};
|
||||
|
@ -235,8 +235,8 @@ RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler = {
|
||||
.codec_type = AVMEDIA_TYPE_VIDEO,
|
||||
.codec_id = CODEC_ID_MPEG4,
|
||||
.parse_sdp_a_line = parse_sdp_line,
|
||||
.open = NULL,
|
||||
.close = NULL,
|
||||
.alloc = NULL,
|
||||
.free = NULL,
|
||||
.parse_packet = NULL
|
||||
};
|
||||
|
||||
@ -245,7 +245,7 @@ RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler = {
|
||||
.codec_type = AVMEDIA_TYPE_AUDIO,
|
||||
.codec_id = CODEC_ID_AAC,
|
||||
.parse_sdp_a_line = parse_sdp_line,
|
||||
.open = new_context,
|
||||
.close = free_context,
|
||||
.alloc = new_context,
|
||||
.free = free_context,
|
||||
.parse_packet = aac_parse_packet
|
||||
};
|
||||
|
@ -223,7 +223,7 @@ RTPDynamicProtocolHandler ff_qcelp_dynamic_handler = {
|
||||
.codec_type = AVMEDIA_TYPE_AUDIO,
|
||||
.codec_id = CODEC_ID_QCELP,
|
||||
.static_payload_id = 12,
|
||||
.open = qcelp_new_context,
|
||||
.close = qcelp_free_context,
|
||||
.alloc = qcelp_new_context,
|
||||
.free = qcelp_free_context,
|
||||
.parse_packet = qcelp_parse_packet
|
||||
};
|
||||
|
@ -309,7 +309,7 @@ RTPDynamicProtocolHandler ff_qdm2_dynamic_handler = {
|
||||
.enc_name = "X-QDM",
|
||||
.codec_type = AVMEDIA_TYPE_AUDIO,
|
||||
.codec_id = CODEC_ID_NONE,
|
||||
.open = qdm2_extradata_new,
|
||||
.close = qdm2_extradata_free,
|
||||
.alloc = qdm2_extradata_new,
|
||||
.free = qdm2_extradata_free,
|
||||
.parse_packet = qdm2_parse_packet,
|
||||
};
|
||||
|
@ -244,8 +244,8 @@ RTPDynamicProtocolHandler ff_ ## m ## _rtp_ ## n ## _handler = { \
|
||||
.enc_name = s, \
|
||||
.codec_type = t, \
|
||||
.codec_id = CODEC_ID_NONE, \
|
||||
.open = qt_rtp_new, \
|
||||
.close = qt_rtp_free, \
|
||||
.alloc = qt_rtp_new, \
|
||||
.free = qt_rtp_free, \
|
||||
.parse_packet = qt_rtp_parse_packet, \
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ RTPDynamicProtocolHandler ff_svq3_dynamic_handler = {
|
||||
.enc_name = "X-SV3V-ES",
|
||||
.codec_type = AVMEDIA_TYPE_VIDEO,
|
||||
.codec_id = CODEC_ID_NONE, // see if (config_packet) above
|
||||
.open = svq3_extradata_new,
|
||||
.close = svq3_extradata_free,
|
||||
.alloc = svq3_extradata_new,
|
||||
.free = svq3_extradata_free,
|
||||
.parse_packet = svq3_parse_packet,
|
||||
};
|
||||
|
@ -148,7 +148,7 @@ RTPDynamicProtocolHandler ff_vp8_dynamic_handler = {
|
||||
.enc_name = "VP8",
|
||||
.codec_type = AVMEDIA_TYPE_VIDEO,
|
||||
.codec_id = CODEC_ID_VP8,
|
||||
.open = vp8_new_context,
|
||||
.close = vp8_free_context,
|
||||
.alloc = vp8_new_context,
|
||||
.free = vp8_free_context,
|
||||
.parse_packet = vp8_handle_packet,
|
||||
};
|
||||
|
@ -389,8 +389,8 @@ RTPDynamicProtocolHandler ff_theora_dynamic_handler = {
|
||||
.codec_type = AVMEDIA_TYPE_VIDEO,
|
||||
.codec_id = CODEC_ID_THEORA,
|
||||
.parse_sdp_a_line = xiph_parse_sdp_line,
|
||||
.open = xiph_new_context,
|
||||
.close = xiph_free_context,
|
||||
.alloc = xiph_new_context,
|
||||
.free = xiph_free_context,
|
||||
.parse_packet = xiph_handle_packet
|
||||
};
|
||||
|
||||
@ -399,7 +399,7 @@ RTPDynamicProtocolHandler ff_vorbis_dynamic_handler = {
|
||||
.codec_type = AVMEDIA_TYPE_AUDIO,
|
||||
.codec_id = CODEC_ID_VORBIS,
|
||||
.parse_sdp_a_line = xiph_parse_sdp_line,
|
||||
.open = xiph_new_context,
|
||||
.close = xiph_free_context,
|
||||
.alloc = xiph_new_context,
|
||||
.free = xiph_free_context,
|
||||
.parse_packet = xiph_handle_packet
|
||||
};
|
||||
|
@ -132,8 +132,8 @@ static void init_rtp_handler(RTPDynamicProtocolHandler *handler,
|
||||
return;
|
||||
codec->codec_id = handler->codec_id;
|
||||
rtsp_st->dynamic_handler = handler;
|
||||
if (handler->open)
|
||||
rtsp_st->dynamic_protocol_context = handler->open();
|
||||
if (handler->alloc)
|
||||
rtsp_st->dynamic_protocol_context = handler->alloc();
|
||||
}
|
||||
|
||||
/* parse the rtpmap description: <codec_name>/<clock_rate>[/<other params>] */
|
||||
@ -526,7 +526,7 @@ void ff_rtsp_close_streams(AVFormatContext *s)
|
||||
rtsp_st = rt->rtsp_streams[i];
|
||||
if (rtsp_st) {
|
||||
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);
|
||||
av_free(rtsp_st);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
#define LIBAVFORMAT_VERSION_MAJOR 53
|
||||
#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, \
|
||||
LIBAVFORMAT_VERSION_MINOR, \
|
||||
|
@ -29,9 +29,9 @@
|
||||
#include "libavutil/attributes.h"
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
sed '/^+[^+]/!s/ /TaBBaT/g' |\
|
||||
expand -t `seq -s , 9 8 200` |\
|
||||
expand -t $(seq -s , 9 8 200) |\
|
||||
sed 's/TaBBaT/ /g' |\
|
||||
sed '/^+[^+]/s/ * $//' |\
|
||||
tr -d '\015' |\
|
||||
|
@ -8,9 +8,11 @@ if [ $# = 0 ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
GREP=grep
|
||||
EGREP=egrep
|
||||
TMP=patcheck.tmp
|
||||
OPT="-nH"
|
||||
#FILES=`grep '^+++' $* | sed 's/+++ //g'`
|
||||
#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
|
||||
@ -27,7 +29,7 @@ hiegrep(){
|
||||
arg="$1"
|
||||
msg="$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
|
||||
}
|
||||
|
||||
@ -36,12 +38,12 @@ hiegrep2(){
|
||||
varg="$2"
|
||||
msg="$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
|
||||
}
|
||||
|
||||
hiegrep '[[:space:]]$' 'trailing whitespace' $*
|
||||
hiegrep "`echo x | tr 'x' '\t'`" 'tabs' $*
|
||||
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' $*
|
||||
@ -60,7 +62,7 @@ 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'
|
||||
$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' $*
|
||||
|
||||
@ -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 '\.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
|
||||
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
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"
|
||||
$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' |\
|
||||
$($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/'` \
|
||||
$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
|
||||
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"
|
||||
$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 $* | 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 $* | 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 $* | 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 $* | 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'
|
||||
|
||||
|
||||
# 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'
|
||||
|
||||
exit
|
||||
@ -164,7 +166,7 @@ exit
|
||||
TODO/idea list:
|
||||
|
||||
for all demuxers & muxers
|
||||
grep for "avctx->priv_data"
|
||||
$EGREP for "avctx->priv_data"
|
||||
|
||||
vertical align =
|
||||
/* and * align
|
||||
|
Loading…
Reference in New Issue
Block a user