diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-06-19 20:52:00 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-06-19 20:53:27 +0200 |
commit | cabbd271a5f37042291c06b9f8bd6c641fbddfde (patch) | |
tree | 110238d357631f95c4849d0d99d978a61b2a1ee7 | |
parent | 6b9446e93296ed236d497fe3f493d8956571f888 (diff) | |
parent | 4cc2920dd2c0ce4e64e709da4f78508e1ec9871e (diff) | |
download | ffmpeg-cabbd271a5f37042291c06b9f8bd6c641fbddfde.tar.gz |
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>
44 files changed, 952 insertions, 231 deletions
@@ -10,6 +10,7 @@ version next: - atempo filter - ffprobe -show_data option - RTMPT protocol support +- iLBC encoding/decoding via libilbc version 0.11: @@ -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 } |