summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-06-19 20:52:00 +0200
committerMichael Niedermayer <michaelni@gmx.at>2012-06-19 20:53:27 +0200
commitcabbd271a5f37042291c06b9f8bd6c641fbddfde (patch)
tree110238d357631f95c4849d0d99d978a61b2a1ee7
parent6b9446e93296ed236d497fe3f493d8956571f888 (diff)
parent4cc2920dd2c0ce4e64e709da4f78508e1ec9871e (diff)
Merge remote-tracking branch 'qatar/master'
* qatar/master: (24 commits) flvdec: remove incomplete, disabled seeking code mem: add support for _aligned_malloc() as found on Windows lavc: Extend the documentation for avcodec_init_packet flvdec: remove incomplete, disabled seeking code http: replace atoll() with strtoll() mpegts: remove unused/incomplete/broken seeking code af_amix: allow float planar sample format as input af_amix: use AVFloatDSPContext.vector_fmac_scalar() float_dsp: add x86-optimized functions for vector_fmac_scalar() float_dsp: Move vector_fmac_scalar() from libavcodec to libavutil lavr: Add x86-optimized function for flt to s32 conversion lavr: Add x86-optimized function for flt to s16 conversion lavr: Add x86-optimized functions for s32 to flt conversion lavr: Add x86-optimized functions for s32 to s16 conversion lavr: Add x86-optimized functions for s16 to flt conversion lavr: Add x86-optimized function for s16 to s32 conversion rtpenc: Support packetizing iLBC rtpdec: Add a depacketizer for iLBC Implement the iLBC storage file format mov: Support muxing/demuxing iLBC ... Conflicts: Changelog configure libavcodec/avcodec.h libavcodec/dsputil.c libavcodec/version.h libavformat/movenc.c libavformat/mpegts.c libavformat/version.h libavutil/mem.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r--Changelog1
-rwxr-xr-xconfigure10
-rw-r--r--doc/general.texi14
-rw-r--r--doc/protocols.texi4
-rw-r--r--libavcodec/Makefile2
-rw-r--r--libavcodec/allcodecs.c1
-rw-r--r--libavcodec/arm/dsputil_init_neon.c3
-rw-r--r--libavcodec/arm/dsputil_neon.S48
-rw-r--r--libavcodec/avcodec.h4
-rw-r--r--libavcodec/dca.c9
-rw-r--r--libavcodec/dirac.c2
-rw-r--r--libavcodec/dsputil.c9
-rw-r--r--libavcodec/dsputil.h11
-rw-r--r--libavcodec/libilbc.c209
-rw-r--r--libavcodec/ratecontrol.c12
-rw-r--r--libavcodec/utils.c5
-rw-r--r--libavcodec/version.h2
-rw-r--r--libavfilter/af_amix.c30
-rw-r--r--libavformat/Makefile3
-rw-r--r--libavformat/allformats.c1
-rw-r--r--libavformat/flvdec.c30
-rw-r--r--libavformat/http.c6
-rw-r--r--libavformat/ilbc.c141
-rw-r--r--libavformat/isom.c1
-rw-r--r--libavformat/mov.c1
-rw-r--r--libavformat/movenc.c3
-rw-r--r--libavformat/mpegts.c94
-rw-r--r--libavformat/rtmpproto.c8
-rw-r--r--libavformat/rtpdec.c1
-rw-r--r--libavformat/rtpdec_formats.h1
-rw-r--r--libavformat/rtpdec_ilbc.c73
-rw-r--r--libavformat/rtpenc.c44
-rw-r--r--libavformat/rtsp.c2
-rw-r--r--libavformat/sdp.c6
-rw-r--r--libavformat/version.h2
-rw-r--r--libavresample/x86/audio_convert.asm209
-rw-r--r--libavresample/x86/audio_convert_init.c44
-rw-r--r--libavutil/arm/float_dsp_init_neon.c4
-rw-r--r--libavutil/arm/float_dsp_neon.S48
-rw-r--r--libavutil/float_dsp.c9
-rw-r--r--libavutil/float_dsp.h16
-rw-r--r--libavutil/mem.c6
-rw-r--r--libavutil/x86/float_dsp.asm47
-rw-r--r--libavutil/x86/float_dsp_init.c7
44 files changed, 952 insertions, 231 deletions
diff --git a/Changelog b/Changelog
index 2e92165f01..0f4168a02c 100644
--- a/Changelog
+++ b/Changelog
@@ -10,6 +10,7 @@ version next:
- atempo filter
- ffprobe -show_data option
- RTMPT protocol support
+- iLBC encoding/decoding via libilbc
version 0.11:
diff --git a/configure b/configure
index 7de8149edb..bf6a1f94a6 100755
--- a/configure
+++ b/configure
@@ -180,6 +180,7 @@ External library support:
--enable-libfaac enable FAAC support via libfaac [no]
--enable-libfreetype enable libfreetype [no]
--enable-libgsm enable GSM support via libgsm [no]
+ --enable-libilbc enable iLBC de/encoding via libilbc [no]
--enable-libmodplug enable ModPlug via libmodplug [no]
--enable-libmp3lame enable MP3 encoding via libmp3lame [no]
--enable-libnut enable NUT (de)muxing via libnut,
@@ -1051,6 +1052,7 @@ CONFIG_LIST="
libfaac
libfreetype
libgsm
+ libilbc
libmodplug
libmp3lame
libnut
@@ -1168,6 +1170,7 @@ HAVE_LIST="
$ARCH_EXT_LIST
$HAVE_LIST_PUB
$THREADS_LIST
+ aligned_malloc
aligned_stack
alsa_asoundlib_h
altivec_h
@@ -1588,6 +1591,8 @@ libgsm_decoder_deps="libgsm"
libgsm_encoder_deps="libgsm"
libgsm_ms_decoder_deps="libgsm"
libgsm_ms_encoder_deps="libgsm"
+libilbc_decoder_deps="libilbc"
+libilbc_encoder_deps="libilbc"
libmodplug_demuxer_deps="libmodplug"
libmp3lame_encoder_deps="libmp3lame"
libopencore_amrnb_decoder_deps="libopencore_amrnb"
@@ -3144,6 +3149,7 @@ check_func ${malloc_prefix}memalign && enable memalign
check_func mkstemp
check_func mmap
check_func ${malloc_prefix}posix_memalign && enable posix_memalign
+check_func_headers malloc.h _aligned_malloc && enable aligned_malloc
check_func setrlimit
check_func strerror_r
check_func strptime
@@ -3254,6 +3260,7 @@ enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 &&
enabled libfaac && require2 libfaac "stdint.h faac.h" faacEncGetVersion -lfaac
enabled libfreetype && require_pkg_config freetype2 "ft2build.h freetype/freetype.h" FT_Init_FreeType
enabled libgsm && require libgsm gsm/gsm.h gsm_create -lgsm
+enabled libilbc && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -lilbc
enabled libmodplug && require libmodplug libmodplug/modplug.h ModPlug_Load -lmodplug
enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame
enabled libnut && require libnut libnut.h nut_demuxer_init -lnut
@@ -3522,7 +3529,7 @@ if test $target_os = "haiku"; then
disable posix_memalign
fi
-! enabled_any memalign posix_memalign &&
+! enabled_any memalign posix_memalign aligned_malloc &&
enabled_any $need_memalign && enable memalign_hack
# add_dep lib dep
@@ -3628,6 +3635,7 @@ echo "libcelt enabled ${libcelt-no}"
echo "libdc1394 support ${libdc1394-no}"
echo "libfaac enabled ${libfaac-no}"
echo "libgsm enabled ${libgsm-no}"
+echo "libilbc enabled ${libilbc-no}"
echo "libmodplug enabled ${libmodplug-no}"
echo "libmp3lame enabled ${libmp3lame-no}"
echo "libnut enabled ${libnut-no}"
diff --git a/doc/general.texi b/doc/general.texi
index 12d7c68962..6981399843 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -93,6 +93,17 @@ x264 is under the GNU Public License Version 2 or later
details), you must upgrade FFmpeg's license to GPL in order to use it.
@end float
+@section libilbc
+
+iLBC is a narrowband speech codec that has been made freely available
+by Google as part of the WebRTC project. libilbc is a packaging friendly
+copy of the iLBC codec. Libav can make use of the libilbc library for
+iLBC encoding and decoding.
+
+Go to @url{https://github.com/dekkers/libilbc} and follow the instructions for
+installing the library. Then pass @code{--enable-libilbc} to configure to
+enable it.
+
@chapter Supported File Formats, Codecs or Features
@@ -191,6 +202,7 @@ library:
@item IEC61937 encapsulation @tab X @tab X
@item IFF @tab @tab X
@tab Interchange File Format
+@item iLBC @tab X @tab X
@item Interplay MVE @tab @tab X
@tab Format used in various Interplay computer games.
@item IV8 @tab @tab X
@@ -749,6 +761,8 @@ following image formats are supported:
@item GSM Microsoft variant @tab E @tab X
@tab encoding supported through external library libgsm
@item IAC (Indeo Audio Coder) @tab @tab X
+@item iLBC (Internet Low Bitrate Codec) @tab E @tab E
+ @tab encoding and decoding supported through external library libilbc
@item IMC (Intel Music Coder) @tab @tab X
@item MACE (Macintosh Audio Compression/Expansion) 3:1 @tab @tab X
@item MACE (Macintosh Audio Compression/Expansion) 6:1 @tab @tab X
diff --git a/doc/protocols.texi b/doc/protocols.texi
index a157d344d5..a335fa7d21 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -247,6 +247,10 @@ times to construct arbitrary AMF sequences.
Version of the Flash plugin used to run the SWF player. The default
is LNX 9,0,124,2.
+@item rtmp_flush_interval
+Number of packets flushed in the same request (RTMPT only). The default
+is 10.
+
@item rtmp_live
Specify that the media is a live stream. No resuming or seeking in
live streams is possible. The default value is @code{any}, which means the
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 851fe1db74..1eeba3a8cd 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -659,6 +659,8 @@ OBJS-$(CONFIG_LIBGSM_DECODER) += libgsm.o
OBJS-$(CONFIG_LIBGSM_ENCODER) += libgsm.o
OBJS-$(CONFIG_LIBGSM_MS_DECODER) += libgsm.o
OBJS-$(CONFIG_LIBGSM_MS_ENCODER) += libgsm.o
+OBJS-$(CONFIG_LIBILBC_DECODER) += libilbc.o
+OBJS-$(CONFIG_LIBILBC_ENCODER) += libilbc.o
OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o mpegaudiodecheader.o \
audio_frame_queue.o
OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o \
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 4067537403..e4af0d8d79 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -410,6 +410,7 @@ void avcodec_register_all(void)
REGISTER_ENCODER (LIBFAAC, libfaac);
REGISTER_ENCDEC (LIBGSM, libgsm);
REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms);
+ REGISTER_ENCDEC (LIBILBC, libilbc);
REGISTER_ENCODER (LIBMP3LAME, libmp3lame);
REGISTER_ENCDEC (LIBOPENCORE_AMRNB, libopencore_amrnb);
REGISTER_DECODER (LIBOPENCORE_AMRWB, libopencore_amrwb);
diff --git a/libavcodec/arm/dsputil_init_neon.c b/libavcodec/arm/dsputil_init_neon.c
index 46b22a412c..ef5a8df85f 100644
--- a/libavcodec/arm/dsputil_init_neon.c
+++ b/libavcodec/arm/dsputil_init_neon.c
@@ -154,8 +154,6 @@ void ff_vector_fmul_window_neon(float *dst, const float *src0,
const float *src1, const float *win, int len);
void ff_vector_fmul_scalar_neon(float *dst, const float *src, float mul,
int len);
-void ff_vector_fmac_scalar_neon(float *dst, const float *src, float mul,
- int len);
void ff_butterflies_float_neon(float *v1, float *v2, int len);
float ff_scalarproduct_float_neon(const float *v1, const float *v2, int len);
void ff_vector_fmul_reverse_neon(float *dst, const float *src0,
@@ -329,7 +327,6 @@ void ff_dsputil_init_neon(DSPContext *c, AVCodecContext *avctx)
c->vector_fmul_window = ff_vector_fmul_window_neon;
c->vector_fmul_scalar = ff_vector_fmul_scalar_neon;
- c->vector_fmac_scalar = ff_vector_fmac_scalar_neon;
c->butterflies_float = ff_butterflies_float_neon;
c->scalarproduct_float = ff_scalarproduct_float_neon;
c->vector_fmul_reverse = ff_vector_fmul_reverse_neon;
diff --git a/libavcodec/arm/dsputil_neon.S b/libavcodec/arm/dsputil_neon.S
index 7ddd76a153..66b3f17d3d 100644
--- a/libavcodec/arm/dsputil_neon.S
+++ b/libavcodec/arm/dsputil_neon.S
@@ -682,54 +682,6 @@ NOVFP vdup.32 q8, r2
.unreq len
endfunc
-function ff_vector_fmac_scalar_neon, export=1
-VFP len .req r2
-VFP acc .req r3
-NOVFP len .req r3
-NOVFP acc .req r2
-VFP vdup.32 q15, d0[0]
-NOVFP vdup.32 q15, r2
- bics r12, len, #15
- mov acc, r0
- beq 3f
- vld1.32 {q0}, [r1,:128]!
- vld1.32 {q8}, [acc,:128]!
- vld1.32 {q1}, [r1,:128]!
- vld1.32 {q9}, [acc,:128]!
-1: vmla.f32 q8, q0, q15
- vld1.32 {q2}, [r1,:128]!
- vld1.32 {q10}, [acc,:128]!
- vmla.f32 q9, q1, q15
- vld1.32 {q3}, [r1,:128]!
- vld1.32 {q11}, [acc,:128]!
- vmla.f32 q10, q2, q15
- vst1.32 {q8}, [r0,:128]!
- vmla.f32 q11, q3, q15
- vst1.32 {q9}, [r0,:128]!
- subs r12, r12, #16
- beq 2f
- vld1.32 {q0}, [r1,:128]!
- vld1.32 {q8}, [acc,:128]!
- vst1.32 {q10}, [r0,:128]!
- vld1.32 {q1}, [r1,:128]!
- vld1.32 {q9}, [acc,:128]!
- vst1.32 {q11}, [r0,:128]!
- b 1b
-2: vst1.32 {q10}, [r0,:128]!
- vst1.32 {q11}, [r0,:128]!
- ands len, len, #15
- it eq
- bxeq lr
-3: vld1.32 {q0}, [r1,:128]!
- vld1.32 {q8}, [acc,:128]!
- vmla.f32 q8, q0, q15
- vst1.32 {q8}, [r0,:128]!
- subs len, len, #4
- bgt 3b
- bx lr
- .unreq len
-endfunc
-
function ff_butterflies_float_neon, export=1
1: vld1.32 {q0},[r0,:128]
vld1.32 {q1},[r1,:128]
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 43931da831..b3c2991069 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -407,6 +407,7 @@ enum CodecID {
CODEC_ID_BMV_AUDIO,
CODEC_ID_RALF,
CODEC_ID_IAC,
+ CODEC_ID_ILBC,
CODEC_ID_FFWAVESYNTH = MKBETAG('F','F','W','S'),
CODEC_ID_8SVX_RAW = MKBETAG('8','S','V','X'),
CODEC_ID_SONIC = MKBETAG('S','O','N','C'),
@@ -3470,6 +3471,9 @@ void av_destruct_packet(AVPacket *pkt);
/**
* Initialize optional fields of a packet with default values.
*
+ * Note, this does not touch the data and size members, which have to be
+ * initialized separately.
+ *
* @param pkt packet
*/
void av_init_packet(AVPacket *pkt);
diff --git a/libavcodec/dca.c b/libavcodec/dca.c
index f40440c1ca..76b258bf05 100644
--- a/libavcodec/dca.c
+++ b/libavcodec/dca.c
@@ -27,6 +27,7 @@
#include <stdio.h>
#include "libavutil/common.h"
+#include "libavutil/float_dsp.h"
#include "libavutil/intmath.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mathematics.h"
@@ -384,7 +385,7 @@ typedef struct {
int profile;
int debug_flag; ///< used for suppressing repeated error messages output
- DSPContext dsp;
+ AVFloatDSPContext fdsp;
FFTContext imdct;
SynthFilterContext synth;
DCADSPContext dcadsp;
@@ -2042,8 +2043,8 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
float *back_chan = s->samples + s->channel_order_tab[s->xch_base_channel] * 256;
float *lt_chan = s->samples + s->channel_order_tab[s->xch_base_channel - 2] * 256;
float *rt_chan = s->samples + s->channel_order_tab[s->xch_base_channel - 1] * 256;
- s->dsp.vector_fmac_scalar(lt_chan, back_chan, -M_SQRT1_2, 256);
- s->dsp.vector_fmac_scalar(rt_chan, back_chan, -M_SQRT1_2, 256);
+ s->fdsp.vector_fmac_scalar(lt_chan, back_chan, -M_SQRT1_2, 256);
+ s->fdsp.vector_fmac_scalar(rt_chan, back_chan, -M_SQRT1_2, 256);
}
if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT) {
@@ -2085,7 +2086,7 @@ static av_cold int dca_decode_init(AVCodecContext *avctx)
s->avctx = avctx;
dca_init_vlcs();
- ff_dsputil_init(&s->dsp, avctx);
+ avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
ff_mdct_init(&s->imdct, 6, 1, 1.0);
ff_synth_filter_init(&s->synth);
ff_dcadsp_init(&s->dcadsp);
diff --git a/libavcodec/dirac.c b/libavcodec/dirac.c
index 3ff33f6554..57074bcc8c 100644
--- a/libavcodec/dirac.c
+++ b/libavcodec/dirac.c
@@ -127,7 +127,7 @@ static const enum PixelFormat dirac_pix_fmt[2][3] = {
static int parse_source_parameters(AVCodecContext *avctx, GetBitContext *gb,
dirac_source_params *source)
{
- AVRational frame_rate = (AVRational){0,0};
+ AVRational frame_rate = {0,0};
unsigned luma_depth = 8, luma_offset = 16;
int idx;
diff --git a/libavcodec/dsputil.c b/libavcodec/dsputil.c
index 81521ea376..442b9005f8 100644
--- a/libavcodec/dsputil.c
+++ b/libavcodec/dsputil.c
@@ -2509,14 +2509,6 @@ static void vector_fmul_scalar_c(float *dst, const float *src, float mul,
dst[i] = src[i] * mul;
}
-static void vector_fmac_scalar_c(float *dst, const float *src, float mul,
- int len)
-{
- int i;
- for (i = 0; i < len; i++)
- dst[i] += src[i] * mul;
-}
-
static void butterflies_float_c(float *av_restrict v1, float *av_restrict v2,
int len)
{
@@ -3060,7 +3052,6 @@ av_cold void ff_dsputil_init(DSPContext* c, AVCodecContext *avctx)
c->butterflies_float = butterflies_float_c;
c->butterflies_float_interleave = butterflies_float_interleave_c;
c->vector_fmul_scalar = vector_fmul_scalar_c;
- c->vector_fmac_scalar = vector_fmac_scalar_c;
c->shrink[0]= av_image_copy_plane;
c->shrink[1]= ff_shrink22;
diff --git a/libavcodec/dsputil.h b/libavcodec/dsputil.h
index 67dd269fd4..e1aefe1eb6 100644
--- a/libavcodec/dsputil.h
+++ b/libavcodec/dsputil.h
@@ -421,17 +421,6 @@ typedef struct DSPContext {
void (*vector_fmul_scalar)(float *dst, const float *src, float mul,
int len);
/**
- * Multiply a vector of floats by a scalar float and add to
- * destination vector. Source and destination vectors must
- * overlap exactly or not at all.
- * @param dst result vector, 16-byte aligned
- * @param src input vector, 16-byte aligned
- * @param mul scalar value
- * @param len length of vector, multiple of 4
- */
- void (*vector_fmac_scalar)(float *dst, const float *src, float mul,
- int len);
- /**
* Calculate the scalar product of two vectors of floats.
* @param v1 first vector, 16-byte aligned
* @param v2 second vector, 16-byte aligned
diff --git a/libavcodec/libilbc.c b/libavcodec/libilbc.c
new file mode 100644
index 0000000000..0893c6c794
--- /dev/null
+++ b/libavcodec/libilbc.c
@@ -0,0 +1,209 @@
+/*
+ * iLBC decoder/encoder stub
+ * Copyright (c) 2012 Martin Storsjo
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <ilbc.h>
+
+#include "avcodec.h"
+#include "libavutil/opt.h"
+#include "internal.h"
+
+static int get_mode(AVCodecContext *avctx)
+{
+ if (avctx->block_align == 38)
+ return 20;
+ else if (avctx->block_align == 50)
+ return 30;
+ else if (avctx->bit_rate > 0)
+ return avctx->bit_rate <= 14000 ? 30 : 20;
+ else
+ return -1;
+}
+
+typedef struct ILBCDecContext {
+ const AVClass *class;
+ AVFrame frame;
+ iLBC_Dec_Inst_t decoder;
+ int enhance;
+} ILBCDecContext;
+
+static const AVOption ilbc_dec_options[] = {
+ { "enhance", "Enhance the decoded audio (adds delay)", offsetof(ILBCDecContext, enhance), AV_OPT_TYPE_INT, { 0 }, 0, 1, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM },
+ { NULL }
+};
+
+static const AVClass ilbc_dec_class = {
+ "libilbc", av_default_item_name, ilbc_dec_options, LIBAVUTIL_VERSION_INT
+};
+
+static av_cold int ilbc_decode_init(AVCodecContext *avctx)
+{
+ ILBCDecContext *s = avctx->priv_data;
+ int mode;
+
+ if ((mode = get_mode(avctx)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "iLBC frame mode not indicated\n");
+ return AVERROR(EINVAL);
+ }
+
+ WebRtcIlbcfix_InitDecode(&s->decoder, mode, s->enhance);
+ avcodec_get_frame_defaults(&s->frame);
+ avctx->coded_frame = &s->frame;
+
+ avctx->channels = 1;
+ avctx->sample_rate = 8000;
+ avctx->sample_fmt = AV_SAMPLE_FMT_S16;
+
+ return 0;
+}
+
+static int ilbc_decode_frame(AVCodecContext *avctx, void *data,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
+ const uint8_t *buf = avpkt->data;
+ int buf_size = avpkt->size;
+ ILBCDecContext *s = avctx->priv_data;
+ int ret;
+
+ if (s->decoder.no_of_bytes > buf_size) {
+ av_log(avctx, AV_LOG_ERROR, "iLBC frame too short (%u, should be %u)\n",
+ buf_size, s->decoder.no_of_bytes);
+ return AVERROR_INVALIDDATA;
+ }
+
+ s->frame.nb_samples = s->decoder.blockl;
+ if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return ret;
+ }
+
+ WebRtcIlbcfix_DecodeImpl((WebRtc_Word16*) s->frame.data[0],
+ (const WebRtc_UWord16*) buf, &s->decoder, 1);
+
+ *got_frame_ptr = 1;
+ *(AVFrame *)data = s->frame;
+
+ return s->decoder.no_of_bytes;
+}
+
+AVCodec ff_libilbc_decoder = {
+ .name = "libilbc",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .id = CODEC_ID_ILBC,
+ .priv_data_size = sizeof(ILBCDecContext),
+ .init = ilbc_decode_init,
+ .decode = ilbc_decode_frame,
+ .capabilities = CODEC_CAP_DR1,
+ .long_name = NULL_IF_CONFIG_SMALL("Internet Low Bitrate Codec (iLBC)"),
+ .priv_class = &ilbc_dec_class,
+};
+
+typedef struct ILBCEncContext {
+ const AVClass *class;
+ iLBC_Enc_Inst_t encoder;
+ int mode;
+} ILBCEncContext;
+
+static const AVOption ilbc_enc_options[] = {
+ { "mode", "iLBC mode (20 or 30 ms frames)", offsetof(ILBCEncContext, mode), AV_OPT_TYPE_INT, { 20 }, 20, 30, AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
+ { NULL }
+};
+
+static const AVClass ilbc_enc_class = {
+ "libilbc", av_default_item_name, ilbc_enc_options, LIBAVUTIL_VERSION_INT
+};
+
+static av_cold int ilbc_encode_init(AVCodecContext *avctx)
+{
+ ILBCEncContext *s = avctx->priv_data;
+ int mode;
+
+ if (avctx->sample_rate != 8000) {
+ av_log(avctx, AV_LOG_ERROR, "Only 8000Hz sample rate supported\n");
+ return AVERROR(EINVAL);
+ }
+
+ if (avctx->channels != 1) {
+ av_log(avctx, AV_LOG_ERROR, "Only mono supported\n");
+ return AVERROR(EINVAL);
+ }
+
+ if ((mode = get_mode(avctx)) > 0)
+ s->mode = mode;
+ else
+ s->mode = s->mode != 30 ? 20 : 30;
+ WebRtcIlbcfix_InitEncode(&s->encoder, s->mode);
+
+ avctx->block_align = s->encoder.no_of_bytes;
+ avctx->frame_size = s->encoder.blockl;
+#if FF_API_OLD_ENCODE_AUDIO
+ avctx->coded_frame = avcodec_alloc_frame();
+ if (!avctx->coded_frame)
+ return AVERROR(ENOMEM);
+#endif
+
+ return 0;
+}
+
+static av_cold int ilbc_encode_close(AVCodecContext *avctx)
+{
+#if FF_API_OLD_ENCODE_AUDIO
+ av_freep(&avctx->coded_frame);
+#endif
+ return 0;
+}
+
+static int ilbc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+ const AVFrame *frame, int *got_packet_ptr)
+{
+ ILBCEncContext *s = avctx->priv_data;
+ int ret;
+
+ if ((ret = ff_alloc_packet(avpkt, 50))) {
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+ return ret;
+ }
+
+ WebRtcIlbcfix_EncodeImpl((WebRtc_UWord16*) avpkt->data, (const WebRtc_Word16*) frame->data[0], &s->encoder);
+
+ avpkt->size = s->encoder.no_of_bytes;
+ *got_packet_ptr = 1;
+ return 0;
+}
+
+static const AVCodecDefault ilbc_encode_defaults[] = {
+ { "b", "0" },
+ { NULL }
+};
+
+AVCodec ff_libilbc_encoder = {
+ .name = "libilbc",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .id = CODEC_ID_ILBC,
+ .priv_data_size = sizeof(ILBCEncContext),
+ .init = ilbc_encode_init,
+ .encode2 = ilbc_encode_frame,
+ .close = ilbc_encode_close,
+ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
+ AV_SAMPLE_FMT_NONE },
+ .long_name = NULL_IF_CONFIG_SMALL("Internet Low Bitrate Codec (iLBC)"),
+ .defaults = ilbc_encode_defaults,
+ .priv_class = &ilbc_enc_class,
+};
diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c
index 9223dce2da..c4624f9e3c 100644
--- a/libavcodec/ratecontrol.c
+++ b/libavcodec/ratecontrol.c
@@ -514,14 +514,6 @@ static double predict_size(Predictor *p, double q, double var)
return p->coeff*var / (q*p->count);
}
-/*
-static double predict_qp(Predictor *p, double size, double var)
-{
-//printf("coeff:%f, count:%f, var:%f, size:%f//\n", p->coeff, p->count, var, size);
- return p->coeff*var / (size*p->count);
-}
-*/
-
static void update_predictor(Predictor *p, double q, double var, double size)
{
double new_coeff= size*q / (var + 1);
@@ -561,10 +553,6 @@ static void adaptive_quantization(MpegEncContext *s, double q){
int mb_y = mb_xy / s->mb_stride;
int mb_distance;
float mb_factor = 0.0;
-#if 0
- if(spat_cplx < q/3) spat_cplx= q/3; //FIXME finetune
- if(temp_cplx < q/3) temp_cplx= q/3; //FIXME finetune
-#endif
if(spat_cplx < 4) spat_cplx= 4; //FIXME finetune
if(temp_cplx < 4) temp_cplx= 4; //FIXME finetune
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 315dc57da4..e3a4e93883 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -2138,6 +2138,11 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
case 29: return 288;
case 37: return 480;
}
+ } else if (id == CODEC_ID_ILBC) {
+ switch (ba) {
+ case 38: return 160;
+ case 50: return 240;
+ }
}
}
diff --git a/libavcodec/version.h b/libavcodec/version.h
index b3644ba24c..2c3a941067 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -27,7 +27,7 @@
*/
#define LIBAVCODEC_VERSION_MAJOR 54
-#define LIBAVCODEC_VERSION_MINOR 25
+#define LIBAVCODEC_VERSION_MINOR 26
#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
diff --git a/libavfilter/af_amix.c b/libavfilter/af_amix.c
index 81586981be..dcfa5e4f94 100644
--- a/libavfilter/af_amix.c
+++ b/libavfilter/af_amix.c
@@ -32,6 +32,7 @@
#include "libavutil/audio_fifo.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
+#include "libavutil/float_dsp.h"
#include "libavutil/mathematics.h"
#include "libavutil/opt.h"
#include "libavutil/samplefmt.h"
@@ -152,6 +153,7 @@ static int frame_list_add_frame(FrameList *frame_list, int nb_samples, int64_t p
typedef struct MixContext {
const AVClass *class; /**< class for AVOptions */
+ AVFloatDSPContext fdsp;
int nb_inputs; /**< number of inputs */
int active_inputs; /**< number of input currently active */
@@ -160,6 +162,7 @@ typedef struct MixContext {
int nb_channels; /**< number of channels */
int sample_rate; /**< sample rate */
+ int planar;
AVAudioFifo **fifos; /**< audio fifo for each input */
uint8_t *input_state; /**< current state of each input */
float *input_scale; /**< mixing scale factor for each input */
@@ -224,6 +227,7 @@ static int config_output(AVFilterLink *outlink)
int i;
char buf[64];
+ s->planar = av_sample_fmt_is_planar(outlink->format);
s->sample_rate = outlink->sample_rate;
outlink->time_base = (AVRational){ 1, outlink->sample_rate };
s->next_pts = AV_NOPTS_VALUE;
@@ -264,14 +268,6 @@ static int config_output(AVFilterLink *outlink)
return 0;
}
-/* TODO: move optimized version from DSPContext to libavutil */
-static void vector_fmac_scalar(float *dst, const float *src, float mul, int len)
-{
- int i;
- for (i = 0; i < len; i++)
- dst[i] += src[i] * mul;
-}
-
/**
* Read samples from the input FIFOs, mix, and write to the output link.
*/
@@ -294,11 +290,20 @@ static int output_frame(AVFilterLink *outlink, int nb_samples)
for (i = 0; i < s->nb_inputs; i++) {
if (s->input_state[i] == INPUT_ON) {
+ int planes, plane_size, p;
+
av_audio_fifo_read(s->fifos[i], (void **)in_buf->extended_data,
nb_samples);
- vector_fmac_scalar((float *)out_buf->extended_data[0],
- (float *) in_buf->extended_data[0],
- s->input_scale[i], nb_samples * s->nb_channels);
+
+ planes = s->planar ? s->nb_channels : 1;
+ plane_size = nb_samples * (s->planar ? 1 : s->nb_channels);
+ plane_size = FFALIGN(plane_size, 16);
+
+ for (p = 0; p < planes; p++) {
+ s->fdsp.vector_fmac_scalar((float *)out_buf->extended_data[p],
+ (float *) in_buf->extended_data[p],
+ s->input_scale[i], plane_size);
+ }
}
}
avfilter_unref_buffer(in_buf);
@@ -501,6 +506,8 @@ static int init(AVFilterContext *ctx, const char *args, void *opaque)
ff_insert_inpad(ctx, i, &pad);
}
+ avpriv_float_dsp_init(&s->fdsp, 0);
+
return 0;
}
@@ -527,6 +534,7 @@ static int query_formats(AVFilterContext *ctx)
{
AVFilterFormats *formats = NULL;
ff_add_format(&formats, AV_SAMPLE_FMT_FLT);
+ ff_add_format(&formats, AV_SAMPLE_FMT_FLTP);
ff_set_common_formats(ctx, formats);
ff_set_common_channel_layouts(ctx, ff_all_channel_layouts());
ff_set_common_samplerates(ctx, ff_all_samplerates());
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 3dca060994..f38b8a575c 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -123,6 +123,8 @@ OBJS-$(CONFIG_ICO_DEMUXER) += icodec.o
OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o
OBJS-$(CONFIG_IDF_DEMUXER) += bintext.o
OBJS-$(CONFIG_IFF_DEMUXER) += iff.o
+OBJS-$(CONFIG_ILBC_DEMUXER) += ilbc.o
+OBJS-$(CONFIG_ILBC_MUXER) += ilbc.o
OBJS-$(CONFIG_IMAGE2_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE2_MUXER) += img2enc.o img2.o
OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER) += img2dec.o img2.o
@@ -281,6 +283,7 @@ OBJS-$(CONFIG_RTPDEC) += rdt.o \
rtpdec_h263.o \
rtpdec_h263_rfc2190.o \
rtpdec_h264.o \
+ rtpdec_ilbc.o \
rtpdec_latm.o \
rtpdec_mpeg4.o \
rtpdec_qcelp.o \
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index ed9227e5b6..b5738e4d97 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -116,6 +116,7 @@ void av_register_all(void)
REGISTER_DEMUXER (IDCIN, idcin);
REGISTER_DEMUXER (IDF, idf);
REGISTER_DEMUXER (IFF, iff);
+ REGISTER_MUXDEMUX (ILBC, ilbc);
REGISTER_MUXDEMUX (IMAGE2, image2);
REGISTER_MUXDEMUX (IMAGE2PIPE, image2pipe);
REGISTER_DEMUXER (INGENIENT, ingenient);
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index aa016ee4de..31f306872f 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -759,33 +759,6 @@ static int flv_read_seek(AVFormatContext *s, int stream_index,
return avio_seek_time(s->pb, stream_index, ts, flags);
}
-#if 0 /* don't know enough to implement this */
-static int flv_read_seek2(AVFormatContext *s, int stream_index,
- int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
-{
- int ret = AVERROR(ENOSYS);
-
- if (ts - min_ts > (uint64_t)(max_ts - ts)) flags |= AVSEEK_FLAG_BACKWARD;
-
- if (!s->pb->seekable) {
- if (stream_index < 0) {
- stream_index = av_find_default_stream_index(s);
- if (stream_index < 0)
- return -1;
-
- /* timestamp for default must be expressed in AV_TIME_BASE units */
- ts = av_rescale_rnd(ts, 1000, AV_TIME_BASE,
- flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP);
- }
- ret = avio_seek_time(s->pb, stream_index, ts, flags);
- }
-
- if (ret == AVERROR(ENOSYS))
- ret = av_seek_frame(s, stream_index, ts, flags);
- return ret;
-}
-#endif
-
AVInputFormat ff_flv_demuxer = {
.name = "flv",
.long_name = NULL_IF_CONFIG_SMALL("FLV format"),
@@ -794,9 +767,6 @@ AVInputFormat ff_flv_demuxer = {
.read_header = flv_read_header,
.read_packet = flv_read_packet,
.read_seek = flv_read_seek,
-#if 0
- .read_seek2 = flv_read_seek2,
-#endif
.read_close = flv_read_close,
.extensions = "flv",
};
diff --git a/libavformat/http.c b/libavformat/http.c
index fb4a83ad0e..96a7eeda0a 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -308,15 +308,15 @@ static int process_line(URLContext *h, char *line, int line_count,
strcpy(s->location, p);
*new_location = 1;
} else if (!av_strcasecmp (tag, "Content-Length") && s->filesize == -1) {
- s->filesize = atoll(p);
+ s->filesize = strtoll(p, NULL, 10);
} else if (!av_strcasecmp (tag, "Content-Range")) {
/* "bytes $from-$to/$document_size" */
const char *slash;
if (!strncmp (p, "bytes ", 6)) {
p += 6;
- s->off = atoll(p);
+ s->off = strtoll(p, NULL, 10);
if ((slash = strchr(p, '/')) && strlen(slash) > 0)
- s->filesize = atoll(slash+1);
+ s->filesize = strtoll(slash+1, NULL, 10);
}
h->is_streamed = 0; /* we _can_ in fact seek */
} else if (!av_strcasecmp(tag, "Accept-Ranges") && !strncmp(p, "bytes", 5)) {
diff --git a/libavformat/ilbc.c b/libavformat/ilbc.c
new file mode 100644
index 0000000000..d4f4583545
--- /dev/null
+++ b/libavformat/ilbc.c
@@ -0,0 +1,141 @@
+/*
+ * iLBC storage file format
+ * Copyright (c) 2012 Martin Storsjo
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avformat.h"
+#include "internal.h"
+
+static const char mode20_header[] = "#!iLBC20\n";
+static const char mode30_header[] = "#!iLBC30\n";
+
+static int ilbc_write_header(AVFormatContext *s)
+{
+ AVIOContext *pb = s->pb;
+ AVCodecContext *enc;
+
+ if (s->nb_streams != 1) {
+ av_log(s, AV_LOG_ERROR, "Unsupported number of streams\n");
+ return AVERROR(EINVAL);
+ }
+ enc = s->streams[0]->codec;
+
+ if (enc->codec_id != CODEC_ID_ILBC) {
+ av_log(s, AV_LOG_ERROR, "Unsupported codec\n");
+ return AVERROR(EINVAL);
+ }
+
+ if (enc->block_align == 50) {
+ avio_write(pb, mode30_header, sizeof(mode30_header) - 1);
+ } else if (enc->block_align == 38) {
+ avio_write(pb, mode20_header, sizeof(mode20_header) - 1);
+ } else {
+ av_log(s, AV_LOG_ERROR, "Unsupported mode\n");
+ return AVERROR(EINVAL);
+ }
+ avio_flush(pb);
+ return 0;
+}
+
+static int ilbc_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ avio_write(s->pb, pkt->data, pkt->size);
+ avio_flush(s->pb);
+ return 0;
+}
+
+static int ilbc_probe(AVProbeData *p)
+{
+ // Only check for "#!iLBC" which matches both formats
+ if (!memcmp(p->buf, mode20_header, 6))
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static int ilbc_read_header(AVFormatContext *s)
+{
+ AVIOContext *pb = s->pb;
+ AVStream *st;
+ uint8_t header[9];
+
+ avio_read(pb, header, 9);
+
+ st = avformat_new_stream(s, NULL);
+ if (!st)
+ return AVERROR(ENOMEM);
+ st->codec->codec_id = CODEC_ID_ILBC;
+ st->codec->sample_rate = 8000;
+ st->codec->channels = 1;
+ st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+ st->start_time = 0;
+ avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+ if (!memcmp(header, mode20_header, sizeof(mode20_header) - 1)) {
+ st->codec->block_align = 38;
+ st->codec->bit_rate = 15200;
+ } else if (!memcmp(header, mode30_header, sizeof(mode30_header) - 1)) {
+ st->codec->block_align = 50;
+ st->codec->bit_rate = 13333;
+ } else {
+ av_log(s, AV_LOG_ERROR, "Unrecognized iLBC file header\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ return 0;
+}
+
+static int ilbc_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ AVCodecContext *enc = s->streams[0]->codec;
+ int ret;
+
+ if ((ret = av_new_packet(pkt, enc->block_align)) < 0)
+ return ret;
+
+ pkt->stream_index = 0;
+ pkt->pos = avio_tell(s->pb);
+ pkt->duration = enc->block_align == 38 ? 160 : 240;
+ if ((ret = avio_read(s->pb, pkt->data, enc->block_align)) != enc->block_align) {
+ av_free_packet(pkt);
+ return ret < 0 ? ret : AVERROR(EIO);
+ }
+
+ return 0;
+}
+
+AVInputFormat ff_ilbc_demuxer = {
+ .name = "ilbc",
+ .long_name = NULL_IF_CONFIG_SMALL("iLBC storage file format"),
+ .read_probe = ilbc_probe,
+ .read_header = ilbc_read_header,
+ .read_packet = ilbc_read_packet,
+ .flags = AVFMT_GENERIC_INDEX,
+};
+
+AVOutputFormat ff_ilbc_muxer = {
+ .name = "ilbc",
+ .long_name = NULL_IF_CONFIG_SMALL("iLBC storage file format"),
+ .mime_type = "audio/iLBC",
+ .extensions = "lbc",
+ .audio_codec = CODEC_ID_ILBC,
+ .write_header = ilbc_write_header,
+ .write_packet = ilbc_write_packet,
+ .flags = AVFMT_NOTIMESTAMPS,
+};
diff --git a/libavformat/isom.c b/libavformat/isom.c
index e4575033e2..0ddbb813ec 100644
--- a/libavformat/isom.c
+++ b/libavformat/isom.c
@@ -259,6 +259,7 @@ const AVCodecTag ff_codec_movaudio_tags[] = {
{ CODEC_ID_DVAUDIO, MKTAG('v', 'd', 'v', 'a') },
{ CODEC_ID_DVAUDIO, MKTAG('d', 'v', 'c', 'a') },
{ CODEC_ID_GSM, MKTAG('a', 'g', 's', 'm') },
+ { CODEC_ID_ILBC, MKTAG('i', 'l', 'b', 'c') },
{ CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') },
{ CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') },
{ CODEC_ID_MP1, MKTAG('.', 'm', 'p', '1') },
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 9548f215f3..3aab48ffff 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -1540,6 +1540,7 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
case CODEC_ID_GSM:
case CODEC_ID_ADPCM_MS:
case CODEC_ID_ADPCM_IMA_WAV:
+ case CODEC_ID_ILBC:
st->codec->block_align = sc->bytes_per_frame;
break;
case CODEC_ID_ALAC:
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index d5eb25bcc2..89072d5ded 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -3371,7 +3371,8 @@ static int mov_write_header(AVFormatContext *s)
av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
track->audio_vbr = 1;
}else if(st->codec->codec_id == CODEC_ID_ADPCM_MS ||
- st->codec->codec_id == CODEC_ID_ADPCM_IMA_WAV){
+ st->codec->codec_id == CODEC_ID_ADPCM_IMA_WAV ||
+ st->codec->codec_id == CODEC_ID_ILBC){
if (!st->codec->block_align) {
av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
goto error;
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 3acca0230c..3a5ed696c8 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -19,8 +19,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-//#define USE_SYNCPOINT_SEARCH
-
#include "libavutil/crc.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/log.h"
@@ -2161,92 +2159,6 @@ static int64_t mpegts_get_dts(AVFormatContext *s, int stream_index,
return AV_NOPTS_VALUE;
}
-#ifdef USE_SYNCPOINT_SEARCH
-
-static int read_seek2(AVFormatContext *s,
- int stream_index,
- int64_t min_ts,
- int64_t target_ts,
- int64_t max_ts,
- int flags)
-{
- int64_t pos;
-
- int64_t ts_ret, ts_adj;
- int stream_index_gen_search;
- AVStream *st;
- AVParserState *backup;
-
- backup = ff_store_parser_state(s);
-
- // detect direction of seeking for search purposes
- flags |= (target_ts - min_ts > (uint64_t)(max_ts - target_ts)) ?
- AVSEEK_FLAG_BACKWARD : 0;
-
- if (flags & AVSEEK_FLAG_BYTE) {
- // use position directly, we will search starting from it
- pos = target_ts;
- } else {
- // search for some position with good timestamp match
- if (stream_index < 0) {
- stream_index_gen_search = av_find_default_stream_index(s);
- if (stream_index_gen_search < 0) {
- ff_restore_parser_state(s, backup);
- return -1;
- }
-
- st = s->streams[stream_index_gen_search];
- // timestamp for default must be expressed in AV_TIME_BASE units
- ts_adj = av_rescale(target_ts,
- st->time_base.den,
- AV_TIME_BASE * (int64_t)st->time_base.num);
- } else {
- ts_adj = target_ts;
- stream_index_gen_search = stream_index;
- }
- pos = ff_gen_search(s, stream_index_gen_search, ts_adj,
- 0, INT64_MAX, -1,
- AV_NOPTS_VALUE,
- AV_NOPTS_VALUE,
- flags, &ts_ret, mpegts_get_pcr);
- if (pos < 0) {
- ff_restore_parser_state(s, backup);
- return -1;
- }
- }
-
- // search for actual matching keyframe/starting position for all streams
- if (ff_gen_syncpoint_search(s, stream_index, pos,
- min_ts, target_ts, max_ts,
- flags) < 0) {
- ff_restore_parser_state(s, backup);
- return -1;
- }
-
- ff_free_parser_state(s, backup);
- return 0;
-}
-
-static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags)
-{
- int ret;
- if (flags & AVSEEK_FLAG_BACKWARD) {
- flags &= ~AVSEEK_FLAG_BACKWARD;
- ret = read_seek2(s, stream_index, INT64_MIN, target_ts, target_ts, flags);
- if (ret < 0)
- // for compatibility reasons, seek to the best-fitting timestamp
- ret = read_seek2(s, stream_index, INT64_MIN, target_ts, INT64_MAX, flags);
- } else {
- ret = read_seek2(s, stream_index, target_ts, target_ts, INT64_MAX, flags);
- if (ret < 0)
- // for compatibility reasons, seek to the best-fitting timestamp
- ret = read_seek2(s, stream_index, INT64_MIN, target_ts, INT64_MAX, flags);
- }
- return ret;
-}
-
-#endif
-
/**************************************************************/
/* parsing functions - called from other demuxers such as RTP */
@@ -2313,9 +2225,6 @@ AVInputFormat ff_mpegts_demuxer = {
.read_close = mpegts_read_close,
.read_timestamp = mpegts_get_dts,
.flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT,
-#ifdef USE_SYNCPOINT_SEARCH
- .read_seek2 = read_seek2,
-#endif
};
AVInputFormat ff_mpegtsraw_demuxer = {
@@ -2327,8 +2236,5 @@ AVInputFormat ff_mpegtsraw_demuxer = {
.read_close = mpegts_read_close,
.read_timestamp = mpegts_get_dts,
.flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT,
-#ifdef USE_SYNCPOINT_SEARCH
- .read_seek2 = read_seek2,
-#endif
.priv_class = &mpegtsraw_class,
};
diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
index 07ec62cc43..4bdda4d097 100644
--- a/libavformat/rtmpproto.c
+++ b/libavformat/rtmpproto.c
@@ -76,6 +76,7 @@ typedef struct RTMPContext {
uint8_t* flv_data; ///< buffer with data for demuxer
int flv_size; ///< current buffer size
int flv_off; ///< number of bytes read from current buffer
+ int flv_nb_packets; ///< number of flv packets published
RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
uint32_t client_report_size; ///< number of bytes after which client should report to server
uint32_t bytes_read; ///< number of bytes read from server
@@ -90,6 +91,7 @@ typedef struct RTMPContext {
char* swfurl; ///< url of the swf player
int server_bw; ///< server bandwidth
int client_buffer_time; ///< client buffer time in ms
+ int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
} RTMPContext;
#define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
@@ -1361,9 +1363,14 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
rt->flv_size = 0;
rt->flv_off = 0;
rt->flv_header_bytes = 0;
+ rt->flv_nb_packets++;
}
} while (buf_temp - buf < size);
+ if (rt->flv_nb_packets < rt->flush_interval)
+ return size;
+ rt->flv_nb_packets = 0;
+
/* set stream into nonblocking mode */
rt->stream->flags |= AVIO_FLAG_NONBLOCK;
@@ -1404,6 +1411,7 @@ static const AVOption rtmp_options[] = {
{"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {3000}, 0, INT_MAX, DEC|ENC},
{"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
{"rtmp_flashver", "Version of the Flash plugin used to run the SWF player.", OFFSET(flashver), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
+ {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {10}, 0, INT_MAX, ENC},
{"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
{"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"},
{"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"},
diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c
index b7240a2d51..3a272e33c7 100644
--- a/libavformat/rtpdec.c
+++ b/libavformat/rtpdec.c
@@ -68,6 +68,7 @@ void av_register_rtp_dynamic_payload_handlers(void)
ff_register_dynamic_payload_handler(&ff_h263_2000_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_h263_rfc2190_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_h264_dynamic_handler);
+ ff_register_dynamic_payload_handler(&ff_ilbc_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_vorbis_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_theora_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_qdm2_dynamic_handler);
diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h
index 73ffe1f49e..a0c61a84b9 100644
--- a/libavformat/rtpdec_formats.h
+++ b/libavformat/rtpdec_formats.h
@@ -45,6 +45,7 @@ extern RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler;
extern RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler;
extern RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler;
extern RTPDynamicProtocolHandler ff_h264_dynamic_handler;
+extern RTPDynamicProtocolHandler ff_ilbc_dynamic_handler;
extern RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler;
extern RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler;
extern RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler;
diff --git a/libavformat/rtpdec_ilbc.c b/libavformat/rtpdec_ilbc.c
new file mode 100644
index 0000000000..247c779bfc
--- /dev/null
+++ b/libavformat/rtpdec_ilbc.c
@@ -0,0 +1,73 @@
+/*
+ * RTP iLBC Depacketizer, RFC 3952
+ * Copyright (c) 2012 Martin Storsjo
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avformat.h"
+#include "rtpdec_formats.h"
+#include "libavutil/avstring.h"
+
+static int ilbc_parse_fmtp(AVStream *stream, PayloadContext *data,
+ char *attr, char *value)
+{
+ if (!strcmp(attr, "mode")) {
+ int mode = atoi(value);
+ switch (mode) {
+ case 20:
+ stream->codec->block_align = 38;
+ break;
+ case 30:
+ stream->codec->block_align = 50;
+ break;
+ default:
+ av_log(NULL, AV_LOG_ERROR, "Unsupported iLBC mode %d\n", mode);
+ return AVERROR(EINVAL);
+ }
+ }
+ return 0;
+}
+
+static int ilbc_parse_sdp_line(AVFormatContext *s, int st_index,
+ PayloadContext *data, const char *line)
+{
+ const char *p;
+ AVStream *st;
+
+ if (st_index < 0)
+ return 0;
+ st = s->streams[st_index];
+
+ if (av_strstart(line, "fmtp:", &p)) {
+ int ret = ff_parse_fmtp(st, data, p, ilbc_parse_fmtp);
+ if (ret < 0)
+ return ret;
+ if (!st->codec->block_align) {
+ av_log(s, AV_LOG_ERROR, "No iLBC mode set\n");
+ return AVERROR(EINVAL);
+ }
+ }
+ return 0;
+}
+
+RTPDynamicProtocolHandler ff_ilbc_dynamic_handler = {
+ .enc_name = "iLBC",
+ .codec_type = AVMEDIA_TYPE_AUDIO,
+ .codec_id = CODEC_ID_ILBC,
+ .parse_sdp_a_line = ilbc_parse_sdp_line,
+};
diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c
index e16e610820..f7e2cf0630 100644
--- a/libavformat/rtpenc.c
+++ b/libavformat/rtpenc.c
@@ -74,6 +74,7 @@ static int is_supported(enum CodecID id)
case CODEC_ID_VP8:
case CODEC_ID_ADPCM_G722:
case CODEC_ID_ADPCM_G726:
+ case CODEC_ID_ILBC:
return 1;
default:
return 0;
@@ -187,6 +188,16 @@ static int rtp_write_header(AVFormatContext *s1)
* 8000, even if the sample rate is 16000. See RFC 3551. */
avpriv_set_pts_info(st, 32, 1, 8000);
break;
+ case CODEC_ID_ILBC:
+ if (st->codec->block_align != 38 && st->codec->block_align != 50) {
+ av_log(s1, AV_LOG_ERROR, "Incorrect iLBC block size specified\n");
+ goto fail;
+ }
+ if (!s->max_frames_per_packet)
+ s->max_frames_per_packet = 1;
+ s->max_frames_per_packet = FFMIN(s->max_frames_per_packet,
+ s->max_payload_size / st->codec->block_align);
+ goto defaultcase;
case CODEC_ID_AMR_NB:
case CODEC_ID_AMR_WB:
if (!s->max_frames_per_packet)
@@ -395,6 +406,36 @@ static void rtp_send_mpegts_raw(AVFormatContext *s1,
}
}
+static int rtp_send_ilbc(AVFormatContext *s1, const uint8_t *buf, int size)
+{
+ RTPMuxContext *s = s1->priv_data;
+ AVStream *st = s1->streams[0];
+ int frame_duration = av_get_audio_frame_duration(st->codec, 0);
+ int frame_size = st->codec->block_align;
+ int frames = size / frame_size;
+
+ while (frames > 0) {
+ int n = FFMIN(s->max_frames_per_packet - s->num_frames, frames);
+
+ if (!s->num_frames) {
+ s->buf_ptr = s->buf;
+ s->timestamp = s->cur_timestamp;
+ }
+ memcpy(s->buf_ptr, buf, n * frame_size);
+ frames -= n;
+ s->num_frames += n;
+ s->buf_ptr += n * frame_size;
+ buf += n * frame_size;
+ s->cur_timestamp += n * frame_duration;
+
+ if (s->num_frames == s->max_frames_per_packet) {
+ ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 1);
+ s->num_frames = 0;
+ }
+ }
+ return 0;
+}
+
static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
{
RTPMuxContext *s = s1->priv_data;
@@ -483,6 +524,9 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
case CODEC_ID_VP8:
ff_rtp_send_vp8(s1, pkt->data, size);
break;
+ case CODEC_ID_ILBC:
+ rtp_send_ilbc(s1, pkt->data, size);
+ break;
default:
/* better than nothing : send the codec raw data */
rtp_send_raw(s1, pkt->data, size);
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 891afc92a4..68ca247b00 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -1279,7 +1279,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
"%s/UDP;multicast", trans_pref);
}
if (s->oformat) {
- av_strlcat(transport, ";mode=receive", sizeof(transport));
+ av_strlcat(transport, ";mode=record", sizeof(transport));
} else if (rt->server_type == RTSP_SERVER_REAL ||
rt->server_type == RTSP_SERVER_WMS)
av_strlcat(transport, ";mode=play", sizeof(transport));
diff --git a/libavformat/sdp.c b/libavformat/sdp.c
index 5d5e9515f7..352dea0335 100644
--- a/libavformat/sdp.c
+++ b/libavformat/sdp.c
@@ -549,6 +549,12 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
c->sample_rate);
break;
}
+ case CODEC_ID_ILBC:
+ av_strlcatf(buff, size, "a=rtpmap:%d iLBC/%d\r\n"
+ "a=fmtp:%d mode=%d\r\n",
+ payload_type, c->sample_rate,
+ payload_type, c->block_align == 38 ? 20 : 30);
+ break;
default:
/* Nothing special to do here... */
break;
diff --git a/libavformat/version.h b/libavformat/version.h
index 0b1bff2764..3b61ea34fc 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -30,7 +30,7 @@
#include "libavutil/avutil.h"
#define LIBAVFORMAT_VERSION_MAJOR 54
-#define LIBAVFORMAT_VERSION_MINOR 8
+#define LIBAVFORMAT_VERSION_MINOR 9
#define LIBAVFORMAT_VERSION_MICRO 100
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
diff --git a/libavresample/x86/audio_convert.asm b/libavresample/x86/audio_convert.asm
index ba59f3314f..7b3cc223c7 100644
--- a/libavresample/x86/audio_convert.asm
+++ b/libavresample/x86/audio_convert.asm
@@ -1,6 +1,7 @@
;******************************************************************************
;* x86 optimized Format Conversion Utils
;* Copyright (c) 2008 Loren Merritt
+;* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
;*
;* This file is part of Libav.
;*
@@ -21,9 +22,217 @@
%include "x86inc.asm"
%include "x86util.asm"
+%include "util.asm"
+
+SECTION_RODATA 32
+
+pf_s32_inv_scale: times 8 dd 0x30000000
+pf_s32_scale: times 8 dd 0x4f000000
+pf_s16_inv_scale: times 4 dd 0x38000000
+pf_s16_scale: times 4 dd 0x47000000
SECTION_TEXT
+;------------------------------------------------------------------------------
+; void ff_conv_s16_to_s32(int32_t *dst, const int16_t *src, int len);
+;------------------------------------------------------------------------------
+
+INIT_XMM sse2
+cglobal conv_s16_to_s32, 3,3,3, dst, src, len
+ lea lenq, [2*lend]
+ lea dstq, [dstq+2*lenq]
+ add srcq, lenq
+ neg lenq
+.loop:
+ mova m2, [srcq+lenq]
+ pxor m0, m0
+ pxor m1, m1
+ punpcklwd m0, m2
+ punpckhwd m1, m2
+ mova [dstq+2*lenq ], m0
+ mova [dstq+2*lenq+mmsize], m1
+ add lenq, mmsize
+ jl .loop
+ REP_RET
+
+;------------------------------------------------------------------------------
+; void ff_conv_s16_to_flt(float *dst, const int16_t *src, int len);
+;------------------------------------------------------------------------------
+
+%macro CONV_S16_TO_FLT 0
+cglobal conv_s16_to_flt, 3,3,3, dst, src, len
+ lea lenq, [2*lend]
+ add srcq, lenq
+ lea dstq, [dstq + 2*lenq]
+ neg lenq
+ mova m2, [pf_s16_inv_scale]
+ ALIGN 16
+.loop:
+ mova m0, [srcq+lenq]
+ S16_TO_S32_SX 0, 1
+ cvtdq2ps m0, m0
+ cvtdq2ps m1, m1
+ mulps m0, m2
+ mulps m1, m2
+ mova [dstq+2*lenq ], m0
+ mova [dstq+2*lenq+mmsize], m1
+ add lenq, mmsize
+ jl .loop
+ REP_RET
+%endmacro
+
+INIT_XMM sse2
+CONV_S16_TO_FLT
+INIT_XMM sse4
+CONV_S16_TO_FLT
+
+;------------------------------------------------------------------------------
+; void ff_conv_s32_to_s16(int16_t *dst, const int32_t *src, int len);
+;------------------------------------------------------------------------------
+
+%macro CONV_S32_TO_S16 0
+cglobal conv_s32_to_s16, 3,3,4, dst, src, len
+ lea lenq, [2*lend]
+ lea srcq, [srcq+2*lenq]
+ add dstq, lenq
+ neg lenq
+.loop:
+ mova m0, [srcq+2*lenq ]
+ mova m1, [srcq+2*lenq+ mmsize]
+ mova m2, [srcq+2*lenq+2*mmsize]
+ mova m3, [srcq+2*lenq+3*mmsize]
+ psrad m0, 16
+ psrad m1, 16
+ psrad m2, 16
+ psrad m3, 16
+ packssdw m0, m1
+ packssdw m2, m3
+ mova [dstq+lenq ], m0
+ mova [dstq+lenq+mmsize], m2
+ add lenq, mmsize*2
+ jl .loop
+%if mmsize == 8
+ emms
+ RET
+%else
+ REP_RET
+%endif
+%endmacro
+
+INIT_MMX mmx
+CONV_S32_TO_S16
+INIT_XMM sse2
+CONV_S32_TO_S16
+
+;------------------------------------------------------------------------------
+; void ff_conv_s32_to_flt(float *dst, const int32_t *src, int len);
+;------------------------------------------------------------------------------
+
+%macro CONV_S32_TO_FLT 0
+cglobal conv_s32_to_flt, 3,3,3, dst, src, len
+ lea lenq, [4*lend]
+ add srcq, lenq
+ add dstq, lenq
+ neg lenq
+ mova m0, [pf_s32_inv_scale]
+ ALIGN 16
+.loop:
+ cvtdq2ps m1, [srcq+lenq ]
+ cvtdq2ps m2, [srcq+lenq+mmsize]
+ mulps m1, m1, m0
+ mulps m2, m2, m0
+ mova [dstq+lenq ], m1
+ mova [dstq+lenq+mmsize], m2
+ add lenq, mmsize*2
+ jl .loop
+%if mmsize == 32
+ vzeroupper
+ RET
+%else
+ REP_RET
+%endif
+%endmacro
+
+INIT_XMM sse2
+CONV_S32_TO_FLT
+%if HAVE_AVX
+INIT_YMM avx
+CONV_S32_TO_FLT
+%endif
+
+;------------------------------------------------------------------------------
+; void ff_conv_flt_to_s16(int16_t *dst, const float *src, int len);
+;------------------------------------------------------------------------------
+
+INIT_XMM sse2
+cglobal conv_flt_to_s16, 3,3,5, dst, src, len
+ lea lenq, [2*lend]
+ lea srcq, [srcq+2*lenq]
+ add dstq, lenq
+ neg lenq
+ mova m4, [pf_s16_scale]
+.loop:
+ mova m0, [srcq+2*lenq ]
+ mova m1, [srcq+2*lenq+1*mmsize]
+ mova m2, [srcq+2*lenq+2*mmsize]
+ mova m3, [srcq+2*lenq+3*mmsize]
+ mulps m0, m4
+ mulps m1, m4
+ mulps m2, m4
+ mulps m3, m4
+ cvtps2dq m0, m0
+ cvtps2dq m1, m1
+ cvtps2dq m2, m2
+ cvtps2dq m3, m3
+ packssdw m0, m1
+ packssdw m2, m3
+ mova [dstq+lenq ], m0
+ mova [dstq+lenq+mmsize], m2
+ add lenq, mmsize*2
+ jl .loop
+ REP_RET
+
+;------------------------------------------------------------------------------
+; void ff_conv_flt_to_s32(int32_t *dst, const float *src, int len);
+;------------------------------------------------------------------------------
+
+%macro CONV_FLT_TO_S32 0
+cglobal conv_flt_to_s32, 3,3,5, dst, src, len
+ lea lenq, [lend*4]
+ add srcq, lenq
+ add dstq, lenq
+ neg lenq
+ mova m4, [pf_s32_scale]
+.loop:
+ mulps m0, m4, [srcq+lenq ]
+ mulps m1, m4, [srcq+lenq+1*mmsize]
+ mulps m2, m4, [srcq+lenq+2*mmsize]
+ mulps m3, m4, [srcq+lenq+3*mmsize]
+ cvtps2dq m0, m0
+ cvtps2dq m1, m1
+ cvtps2dq m2, m2
+ cvtps2dq m3, m3
+ mova [dstq+lenq ], m0
+ mova [dstq+lenq+1*mmsize], m1
+ mova [dstq+lenq+2*mmsize], m2
+ mova [dstq+lenq+3*mmsize], m3
+ add lenq, mmsize*4
+ jl .loop
+%if mmsize == 32
+ vzeroupper
+ RET
+%else
+ REP_RET
+%endif
+%endmacro
+
+INIT_XMM sse2
+CONV_FLT_TO_S32
+%if HAVE_AVX
+INIT_YMM avx
+CONV_FLT_TO_S32
+%endif
+
;-----------------------------------------------------------------------------
; void ff_conv_fltp_to_flt_6ch(float *dst, float *const *src, int len,
; int channels);
diff --git a/libavresample/x86/audio_convert_init.c b/libavresample/x86/audio_convert_init.c
index 206aede751..f41d974445 100644
--- a/libavresample/x86/audio_convert_init.c
+++ b/libavresample/x86/audio_convert_init.c
@@ -22,6 +22,22 @@
#include "libavutil/cpu.h"
#include "libavresample/audio_convert.h"
+extern void ff_conv_s16_to_s32_sse2(int16_t *dst, const int32_t *src, int len);
+
+extern void ff_conv_s16_to_flt_sse2(float *dst, const int16_t *src, int len);
+extern void ff_conv_s16_to_flt_sse4(float *dst, const int16_t *src, int len);
+
+extern void ff_conv_s32_to_s16_mmx (int16_t *dst, const int32_t *src, int len);
+extern void ff_conv_s32_to_s16_sse2(int16_t *dst, const int32_t *src, int len);
+
+extern void ff_conv_s32_to_flt_sse2(float *dst, const int32_t *src, int len);
+extern void ff_conv_s32_to_flt_avx (float *dst, const int32_t *src, int len);
+
+extern void ff_conv_flt_to_s16_sse2(int16_t *dst, const float *src, int len);
+
+extern void ff_conv_flt_to_s32_sse2(int32_t *dst, const float *src, int len);
+extern void ff_conv_flt_to_s32_avx (int32_t *dst, const float *src, int len);
+
extern void ff_conv_fltp_to_flt_6ch_mmx (float *dst, float *const *src, int len);
extern void ff_conv_fltp_to_flt_6ch_sse4(float *dst, float *const *src, int len);
extern void ff_conv_fltp_to_flt_6ch_avx (float *dst, float *const *src, int len);
@@ -32,6 +48,8 @@ av_cold void ff_audio_convert_init_x86(AudioConvert *ac)
int mm_flags = av_get_cpu_flags();
if (mm_flags & AV_CPU_FLAG_MMX && HAVE_MMX) {
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32,
+ 0, 1, 8, "MMX", ff_conv_s32_to_s16_mmx);
ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
6, 1, 4, "MMX", ff_conv_fltp_to_flt_6ch_mmx);
}
@@ -43,5 +61,31 @@ av_cold void ff_audio_convert_init_x86(AudioConvert *ac)
ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
6, 16, 4, "AVX", ff_conv_fltp_to_flt_6ch_avx);
}
+ if (mm_flags & AV_CPU_FLAG_SSE2 && HAVE_SSE) {
+ if (!(mm_flags & AV_CPU_FLAG_SSE2SLOW)) {
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32,
+ 0, 16, 16, "SSE2", ff_conv_s32_to_s16_sse2);
+ }
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16,
+ 0, 16, 8, "SSE2", ff_conv_s16_to_s32_sse2);
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16,
+ 0, 16, 8, "SSE2", ff_conv_s16_to_flt_sse2);
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32,
+ 0, 16, 8, "SSE2", ff_conv_s32_to_flt_sse2);
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT,
+ 0, 16, 16, "SSE2", ff_conv_flt_to_s16_sse2);
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT,
+ 0, 16, 16, "SSE2", ff_conv_flt_to_s32_sse2);
+ }
+ if (mm_flags & AV_CPU_FLAG_SSE4 && HAVE_SSE) {
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16,
+ 0, 16, 8, "SSE4", ff_conv_s16_to_flt_sse4);
+ }
+ if (mm_flags & AV_CPU_FLAG_AVX && HAVE_AVX) {
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32,
+ 0, 32, 16, "AVX", ff_conv_s32_to_flt_avx);
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT,
+ 0, 32, 32, "AVX", ff_conv_flt_to_s32_avx);
+ }
#endif
}
diff --git a/libavutil/arm/float_dsp_init_neon.c b/libavutil/arm/float_dsp_init_neon.c
index fa6d0d7d15..3ca0288b31 100644
--- a/libavutil/arm/float_dsp_init_neon.c
+++ b/libavutil/arm/float_dsp_init_neon.c
@@ -26,7 +26,11 @@
void ff_vector_fmul_neon(float *dst, const float *src0, const float *src1, int len);
+void ff_vector_fmac_scalar_neon(float *dst, const float *src, float mul,
+ int len);
+
void ff_float_dsp_init_neon(AVFloatDSPContext *fdsp)
{
fdsp->vector_fmul = ff_vector_fmul_neon;
+ fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_neon;
}
diff --git a/libavutil/arm/float_dsp_neon.S b/libavutil/arm/float_dsp_neon.S
index d66fa09424..03b164388f 100644
--- a/libavutil/arm/float_dsp_neon.S
+++ b/libavutil/arm/float_dsp_neon.S
@@ -62,3 +62,51 @@ function ff_vector_fmul_neon, export=1
3: vst1.32 {d16-d19},[r0,:128]!
bx lr
endfunc
+
+function ff_vector_fmac_scalar_neon, export=1
+VFP len .req r2
+VFP acc .req r3
+NOVFP len .req r3
+NOVFP acc .req r2
+VFP vdup.32 q15, d0[0]
+NOVFP vdup.32 q15, r2
+ bics r12, len, #15
+ mov acc, r0
+ beq 3f
+ vld1.32 {q0}, [r1,:128]!
+ vld1.32 {q8}, [acc,:128]!
+ vld1.32 {q1}, [r1,:128]!
+ vld1.32 {q9}, [acc,:128]!
+1: vmla.f32 q8, q0, q15
+ vld1.32 {q2}, [r1,:128]!
+ vld1.32 {q10}, [acc,:128]!
+ vmla.f32 q9, q1, q15
+ vld1.32 {q3}, [r1,:128]!
+ vld1.32 {q11}, [acc,:128]!
+ vmla.f32 q10, q2, q15
+ vst1.32 {q8}, [r0,:128]!
+ vmla.f32 q11, q3, q15
+ vst1.32 {q9}, [r0,:128]!
+ subs r12, r12, #16
+ beq 2f
+ vld1.32 {q0}, [r1,:128]!
+ vld1.32 {q8}, [acc,:128]!
+ vst1.32 {q10}, [r0,:128]!
+ vld1.32 {q1}, [r1,:128]!
+ vld1.32 {q9}, [acc,:128]!
+ vst1.32 {q11}, [r0,:128]!
+ b 1b
+2: vst1.32 {q10}, [r0,:128]!
+ vst1.32 {q11}, [r0,:128]!
+ ands len, len, #15
+ it eq
+ bxeq lr
+3: vld1.32 {q0}, [r1,:128]!
+ vld1.32 {q8}, [acc,:128]!
+ vmla.f32 q8, q0, q15
+ vst1.32 {q8}, [r0,:128]!
+ subs len, len, #4
+ bgt 3b
+ bx lr
+ .unreq len
+endfunc
diff --git a/libavutil/float_dsp.c b/libavutil/float_dsp.c
index 87cfd88268..f5a8360c86 100644
--- a/libavutil/float_dsp.c
+++ b/libavutil/float_dsp.c
@@ -31,9 +31,18 @@ static void vector_fmul_c(float *dst, const float *src0, const float *src1,
dst[i] = src0[i] * src1[i];
}
+static void vector_fmac_scalar_c(float *dst, const float *src, float mul,
+ int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ dst[i] += src[i] * mul;
+}
+
void avpriv_float_dsp_init(AVFloatDSPContext *fdsp, int bit_exact)
{
fdsp->vector_fmul = vector_fmul_c;
+ fdsp->vector_fmac_scalar = vector_fmac_scalar_c;
#if ARCH_ARM
ff_float_dsp_init_arm(fdsp);
diff --git a/libavutil/float_dsp.h b/libavutil/float_dsp.h
index 02c4ab7bde..735eb34c36 100644
--- a/libavutil/float_dsp.h
+++ b/libavutil/float_dsp.h
@@ -35,6 +35,22 @@ typedef struct AVFloatDSPContext {
*/
void (*vector_fmul)(float *dst, const float *src0, const float *src1,
int len);
+
+ /**
+ * Multiply a vector of floats by a scalar float and add to
+ * destination vector. Source and destination vectors must
+ * overlap exactly or not at all.
+ *
+ * @param dst result vector
+ * constraints: 32-byte aligned
+ * @param src input vector
+ * constraints: 32-byte aligned
+ * @param mul scalar value
+ * @param len length of vector
+ * constraints: multiple of 16
+ */
+ void (*vector_fmac_scalar)(float *dst, const float *src, float mul,
+ int len);
} AVFloatDSPContext;
/**
diff --git a/libavutil/mem.c b/libavutil/mem.c
index de22ad8db8..385ace0702 100644
--- a/libavutil/mem.c
+++ b/libavutil/mem.c
@@ -94,6 +94,8 @@ void *av_malloc(size_t size)
if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
if (posix_memalign(&ptr,ALIGN,size))
ptr = NULL;
+#elif HAVE_ALIGNED_MALLOC
+ ptr = _aligned_malloc(size, ALIGN);
#elif HAVE_MEMALIGN
ptr = memalign(ALIGN,size);
/* Why 64?
@@ -145,6 +147,8 @@ void *av_realloc(void *ptr, size_t size)
ptr= realloc((char*)ptr - diff, size + diff);
if(ptr) ptr = (char*)ptr + diff;
return ptr;
+#elif HAVE_ALIGNED_MALLOC
+ return _aligned_realloc(ptr, size + !size, ALIGN);
#else
return realloc(ptr, size + !size);
#endif
@@ -170,6 +174,8 @@ void av_free(void *ptr)
#if CONFIG_MEMALIGN_HACK
if (ptr)
free((char*)ptr - ((char*)ptr)[-1]);
+#elif HAVE_ALIGNED_MALLOC
+ _aligned_free(ptr);
#else
free(ptr);
#endif
diff --git a/libavutil/x86/float_dsp.asm b/libavutil/x86/float_dsp.asm
index 6ed716c026..f68e0bfe2d 100644
--- a/libavutil/x86/float_dsp.asm
+++ b/libavutil/x86/float_dsp.asm
@@ -21,6 +21,7 @@
;******************************************************************************
%include "x86inc.asm"
+%include "x86util.asm"
SECTION .text
@@ -55,3 +56,49 @@ VECTOR_FMUL
INIT_YMM avx
VECTOR_FMUL
%endif
+
+;------------------------------------------------------------------------------
+; void ff_vector_fmac_scalar(float *dst, const float *src, float mul, int len)
+;------------------------------------------------------------------------------
+
+%macro VECTOR_FMAC_SCALAR 0
+%if UNIX64
+cglobal vector_fmac_scalar, 3,3,3, dst, src, len
+%else
+cglobal vector_fmac_scalar, 4,4,3, dst, src, mul, len
+%endif
+%if WIN64
+ SWAP 0, 2
+%endif
+%if ARCH_X86_32
+ VBROADCASTSS m0, mulm
+%else
+ shufps xmm0, xmm0, 0
+%if cpuflag(avx)
+ vinsertf128 m0, m0, xmm0, 1
+%endif
+%endif
+ lea lenq, [lend*4-2*mmsize]
+.loop
+ mulps m1, m0, [srcq+lenq ]
+ mulps m2, m0, [srcq+lenq+mmsize]
+ addps m1, m1, [dstq+lenq ]
+ addps m2, m2, [dstq+lenq+mmsize]
+ mova [dstq+lenq ], m1
+ mova [dstq+lenq+mmsize], m2
+ sub lenq, 2*mmsize
+ jge .loop
+%if mmsize == 32
+ vzeroupper
+ RET
+%else
+ REP_RET
+%endif
+%endmacro
+
+INIT_XMM sse
+VECTOR_FMAC_SCALAR
+%if HAVE_AVX
+INIT_YMM avx
+VECTOR_FMAC_SCALAR
+%endif
diff --git a/libavutil/x86/float_dsp_init.c b/libavutil/x86/float_dsp_init.c
index 8f6980cbc2..3e05b9d4ca 100644
--- a/libavutil/x86/float_dsp_init.c
+++ b/libavutil/x86/float_dsp_init.c
@@ -26,6 +26,11 @@ extern void ff_vector_fmul_sse(float *dst, const float *src0, const float *src1,
extern void ff_vector_fmul_avx(float *dst, const float *src0, const float *src1,
int len);
+extern void ff_vector_fmac_scalar_sse(float *dst, const float *src, float mul,
+ int len);
+extern void ff_vector_fmac_scalar_avx(float *dst, const float *src, float mul,
+ int len);
+
void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp)
{
#if HAVE_YASM
@@ -33,9 +38,11 @@ void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp)
if (mm_flags & AV_CPU_FLAG_SSE && HAVE_SSE) {
fdsp->vector_fmul = ff_vector_fmul_sse;
+ fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_sse;
}
if (mm_flags & AV_CPU_FLAG_AVX && HAVE_AVX) {
fdsp->vector_fmul = ff_vector_fmul_avx;
+ fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_avx;
}
#endif
}