* 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>tags/n1.0
| @@ -10,6 +10,7 @@ version next: | |||||
| - atempo filter | - atempo filter | ||||
| - ffprobe -show_data option | - ffprobe -show_data option | ||||
| - RTMPT protocol support | - RTMPT protocol support | ||||
| - iLBC encoding/decoding via libilbc | |||||
| version 0.11: | version 0.11: | ||||
| @@ -180,6 +180,7 @@ External library support: | |||||
| --enable-libfaac enable FAAC support via libfaac [no] | --enable-libfaac enable FAAC support via libfaac [no] | ||||
| --enable-libfreetype enable libfreetype [no] | --enable-libfreetype enable libfreetype [no] | ||||
| --enable-libgsm enable GSM support via libgsm [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-libmodplug enable ModPlug via libmodplug [no] | ||||
| --enable-libmp3lame enable MP3 encoding via libmp3lame [no] | --enable-libmp3lame enable MP3 encoding via libmp3lame [no] | ||||
| --enable-libnut enable NUT (de)muxing via libnut, | --enable-libnut enable NUT (de)muxing via libnut, | ||||
| @@ -1051,6 +1052,7 @@ CONFIG_LIST=" | |||||
| libfaac | libfaac | ||||
| libfreetype | libfreetype | ||||
| libgsm | libgsm | ||||
| libilbc | |||||
| libmodplug | libmodplug | ||||
| libmp3lame | libmp3lame | ||||
| libnut | libnut | ||||
| @@ -1168,6 +1170,7 @@ HAVE_LIST=" | |||||
| $ARCH_EXT_LIST | $ARCH_EXT_LIST | ||||
| $HAVE_LIST_PUB | $HAVE_LIST_PUB | ||||
| $THREADS_LIST | $THREADS_LIST | ||||
| aligned_malloc | |||||
| aligned_stack | aligned_stack | ||||
| alsa_asoundlib_h | alsa_asoundlib_h | ||||
| altivec_h | altivec_h | ||||
| @@ -1588,6 +1591,8 @@ libgsm_decoder_deps="libgsm" | |||||
| libgsm_encoder_deps="libgsm" | libgsm_encoder_deps="libgsm" | ||||
| libgsm_ms_decoder_deps="libgsm" | libgsm_ms_decoder_deps="libgsm" | ||||
| libgsm_ms_encoder_deps="libgsm" | libgsm_ms_encoder_deps="libgsm" | ||||
| libilbc_decoder_deps="libilbc" | |||||
| libilbc_encoder_deps="libilbc" | |||||
| libmodplug_demuxer_deps="libmodplug" | libmodplug_demuxer_deps="libmodplug" | ||||
| libmp3lame_encoder_deps="libmp3lame" | libmp3lame_encoder_deps="libmp3lame" | ||||
| libopencore_amrnb_decoder_deps="libopencore_amrnb" | libopencore_amrnb_decoder_deps="libopencore_amrnb" | ||||
| @@ -3144,6 +3149,7 @@ check_func ${malloc_prefix}memalign && enable memalign | |||||
| check_func mkstemp | check_func mkstemp | ||||
| check_func mmap | check_func mmap | ||||
| check_func ${malloc_prefix}posix_memalign && enable posix_memalign | check_func ${malloc_prefix}posix_memalign && enable posix_memalign | ||||
| check_func_headers malloc.h _aligned_malloc && enable aligned_malloc | |||||
| check_func setrlimit | check_func setrlimit | ||||
| check_func strerror_r | check_func strerror_r | ||||
| check_func strptime | 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 libfaac && require2 libfaac "stdint.h faac.h" faacEncGetVersion -lfaac | ||||
| enabled libfreetype && require_pkg_config freetype2 "ft2build.h freetype/freetype.h" FT_Init_FreeType | 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 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 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 libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame | ||||
| enabled libnut && require libnut libnut.h nut_demuxer_init -lnut | enabled libnut && require libnut libnut.h nut_demuxer_init -lnut | ||||
| @@ -3522,7 +3529,7 @@ if test $target_os = "haiku"; then | |||||
| disable posix_memalign | disable posix_memalign | ||||
| fi | fi | ||||
| ! enabled_any memalign posix_memalign && | |||||
| ! enabled_any memalign posix_memalign aligned_malloc && | |||||
| enabled_any $need_memalign && enable memalign_hack | enabled_any $need_memalign && enable memalign_hack | ||||
| # add_dep lib dep | # add_dep lib dep | ||||
| @@ -3628,6 +3635,7 @@ echo "libcelt enabled ${libcelt-no}" | |||||
| echo "libdc1394 support ${libdc1394-no}" | echo "libdc1394 support ${libdc1394-no}" | ||||
| echo "libfaac enabled ${libfaac-no}" | echo "libfaac enabled ${libfaac-no}" | ||||
| echo "libgsm enabled ${libgsm-no}" | echo "libgsm enabled ${libgsm-no}" | ||||
| echo "libilbc enabled ${libilbc-no}" | |||||
| echo "libmodplug enabled ${libmodplug-no}" | echo "libmodplug enabled ${libmodplug-no}" | ||||
| echo "libmp3lame enabled ${libmp3lame-no}" | echo "libmp3lame enabled ${libmp3lame-no}" | ||||
| echo "libnut enabled ${libnut-no}" | echo "libnut enabled ${libnut-no}" | ||||
| @@ -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. | details), you must upgrade FFmpeg's license to GPL in order to use it. | ||||
| @end float | @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 | @chapter Supported File Formats, Codecs or Features | ||||
| @@ -191,6 +202,7 @@ library: | |||||
| @item IEC61937 encapsulation @tab X @tab X | @item IEC61937 encapsulation @tab X @tab X | ||||
| @item IFF @tab @tab X | @item IFF @tab @tab X | ||||
| @tab Interchange File Format | @tab Interchange File Format | ||||
| @item iLBC @tab X @tab X | |||||
| @item Interplay MVE @tab @tab X | @item Interplay MVE @tab @tab X | ||||
| @tab Format used in various Interplay computer games. | @tab Format used in various Interplay computer games. | ||||
| @item IV8 @tab @tab X | @item IV8 @tab @tab X | ||||
| @@ -749,6 +761,8 @@ following image formats are supported: | |||||
| @item GSM Microsoft variant @tab E @tab X | @item GSM Microsoft variant @tab E @tab X | ||||
| @tab encoding supported through external library libgsm | @tab encoding supported through external library libgsm | ||||
| @item IAC (Indeo Audio Coder) @tab @tab X | @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 IMC (Intel Music Coder) @tab @tab X | ||||
| @item MACE (Macintosh Audio Compression/Expansion) 3:1 @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 | @item MACE (Macintosh Audio Compression/Expansion) 6:1 @tab @tab X | ||||
| @@ -247,6 +247,10 @@ times to construct arbitrary AMF sequences. | |||||
| Version of the Flash plugin used to run the SWF player. The default | Version of the Flash plugin used to run the SWF player. The default | ||||
| is LNX 9,0,124,2. | 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 | @item rtmp_live | ||||
| Specify that the media is a live stream. No resuming or seeking in | 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 | live streams is possible. The default value is @code{any}, which means the | ||||
| @@ -659,6 +659,8 @@ OBJS-$(CONFIG_LIBGSM_DECODER) += libgsm.o | |||||
| OBJS-$(CONFIG_LIBGSM_ENCODER) += libgsm.o | OBJS-$(CONFIG_LIBGSM_ENCODER) += libgsm.o | ||||
| OBJS-$(CONFIG_LIBGSM_MS_DECODER) += libgsm.o | OBJS-$(CONFIG_LIBGSM_MS_DECODER) += libgsm.o | ||||
| OBJS-$(CONFIG_LIBGSM_MS_ENCODER) += 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 \ | OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o mpegaudiodecheader.o \ | ||||
| audio_frame_queue.o | audio_frame_queue.o | ||||
| OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o \ | OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o \ | ||||
| @@ -410,6 +410,7 @@ void avcodec_register_all(void) | |||||
| REGISTER_ENCODER (LIBFAAC, libfaac); | REGISTER_ENCODER (LIBFAAC, libfaac); | ||||
| REGISTER_ENCDEC (LIBGSM, libgsm); | REGISTER_ENCDEC (LIBGSM, libgsm); | ||||
| REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms); | REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms); | ||||
| REGISTER_ENCDEC (LIBILBC, libilbc); | |||||
| REGISTER_ENCODER (LIBMP3LAME, libmp3lame); | REGISTER_ENCODER (LIBMP3LAME, libmp3lame); | ||||
| REGISTER_ENCDEC (LIBOPENCORE_AMRNB, libopencore_amrnb); | REGISTER_ENCDEC (LIBOPENCORE_AMRNB, libopencore_amrnb); | ||||
| REGISTER_DECODER (LIBOPENCORE_AMRWB, libopencore_amrwb); | REGISTER_DECODER (LIBOPENCORE_AMRWB, libopencore_amrwb); | ||||
| @@ -154,8 +154,6 @@ void ff_vector_fmul_window_neon(float *dst, const float *src0, | |||||
| const float *src1, const float *win, int len); | const float *src1, const float *win, int len); | ||||
| void ff_vector_fmul_scalar_neon(float *dst, const float *src, float mul, | void ff_vector_fmul_scalar_neon(float *dst, const float *src, float mul, | ||||
| int len); | 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); | void ff_butterflies_float_neon(float *v1, float *v2, int len); | ||||
| float ff_scalarproduct_float_neon(const float *v1, const 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, | 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_window = ff_vector_fmul_window_neon; | ||||
| c->vector_fmul_scalar = ff_vector_fmul_scalar_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->butterflies_float = ff_butterflies_float_neon; | ||||
| c->scalarproduct_float = ff_scalarproduct_float_neon; | c->scalarproduct_float = ff_scalarproduct_float_neon; | ||||
| c->vector_fmul_reverse = ff_vector_fmul_reverse_neon; | c->vector_fmul_reverse = ff_vector_fmul_reverse_neon; | ||||
| @@ -682,54 +682,6 @@ NOVFP vdup.32 q8, r2 | |||||
| .unreq len | .unreq len | ||||
| endfunc | 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 | function ff_butterflies_float_neon, export=1 | ||||
| 1: vld1.32 {q0},[r0,:128] | 1: vld1.32 {q0},[r0,:128] | ||||
| vld1.32 {q1},[r1,:128] | vld1.32 {q1},[r1,:128] | ||||
| @@ -407,6 +407,7 @@ enum CodecID { | |||||
| CODEC_ID_BMV_AUDIO, | CODEC_ID_BMV_AUDIO, | ||||
| CODEC_ID_RALF, | CODEC_ID_RALF, | ||||
| CODEC_ID_IAC, | CODEC_ID_IAC, | ||||
| CODEC_ID_ILBC, | |||||
| CODEC_ID_FFWAVESYNTH = MKBETAG('F','F','W','S'), | CODEC_ID_FFWAVESYNTH = MKBETAG('F','F','W','S'), | ||||
| CODEC_ID_8SVX_RAW = MKBETAG('8','S','V','X'), | CODEC_ID_8SVX_RAW = MKBETAG('8','S','V','X'), | ||||
| CODEC_ID_SONIC = MKBETAG('S','O','N','C'), | 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. | * 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 | * @param pkt packet | ||||
| */ | */ | ||||
| void av_init_packet(AVPacket *pkt); | void av_init_packet(AVPacket *pkt); | ||||
| @@ -27,6 +27,7 @@ | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include "libavutil/common.h" | #include "libavutil/common.h" | ||||
| #include "libavutil/float_dsp.h" | |||||
| #include "libavutil/intmath.h" | #include "libavutil/intmath.h" | ||||
| #include "libavutil/intreadwrite.h" | #include "libavutil/intreadwrite.h" | ||||
| #include "libavutil/mathematics.h" | #include "libavutil/mathematics.h" | ||||
| @@ -384,7 +385,7 @@ typedef struct { | |||||
| int profile; | int profile; | ||||
| int debug_flag; ///< used for suppressing repeated error messages output | int debug_flag; ///< used for suppressing repeated error messages output | ||||
| DSPContext dsp; | |||||
| AVFloatDSPContext fdsp; | |||||
| FFTContext imdct; | FFTContext imdct; | ||||
| SynthFilterContext synth; | SynthFilterContext synth; | ||||
| DCADSPContext dcadsp; | 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 *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 *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; | 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) { | if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT) { | ||||
| @@ -2085,7 +2086,7 @@ static av_cold int dca_decode_init(AVCodecContext *avctx) | |||||
| s->avctx = avctx; | s->avctx = avctx; | ||||
| dca_init_vlcs(); | 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_mdct_init(&s->imdct, 6, 1, 1.0); | ||||
| ff_synth_filter_init(&s->synth); | ff_synth_filter_init(&s->synth); | ||||
| ff_dcadsp_init(&s->dcadsp); | ff_dcadsp_init(&s->dcadsp); | ||||
| @@ -127,7 +127,7 @@ static const enum PixelFormat dirac_pix_fmt[2][3] = { | |||||
| static int parse_source_parameters(AVCodecContext *avctx, GetBitContext *gb, | static int parse_source_parameters(AVCodecContext *avctx, GetBitContext *gb, | ||||
| dirac_source_params *source) | dirac_source_params *source) | ||||
| { | { | ||||
| AVRational frame_rate = (AVRational){0,0}; | |||||
| AVRational frame_rate = {0,0}; | |||||
| unsigned luma_depth = 8, luma_offset = 16; | unsigned luma_depth = 8, luma_offset = 16; | ||||
| int idx; | int idx; | ||||
| @@ -2509,14 +2509,6 @@ static void vector_fmul_scalar_c(float *dst, const float *src, float mul, | |||||
| dst[i] = src[i] * 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, | static void butterflies_float_c(float *av_restrict v1, float *av_restrict v2, | ||||
| int len) | 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 = butterflies_float_c; | ||||
| c->butterflies_float_interleave = butterflies_float_interleave_c; | c->butterflies_float_interleave = butterflies_float_interleave_c; | ||||
| c->vector_fmul_scalar = vector_fmul_scalar_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[0]= av_image_copy_plane; | ||||
| c->shrink[1]= ff_shrink22; | c->shrink[1]= ff_shrink22; | ||||
| @@ -420,17 +420,6 @@ typedef struct DSPContext { | |||||
| */ | */ | ||||
| void (*vector_fmul_scalar)(float *dst, const float *src, float mul, | void (*vector_fmul_scalar)(float *dst, const float *src, float mul, | ||||
| int len); | 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. | * Calculate the scalar product of two vectors of floats. | ||||
| * @param v1 first vector, 16-byte aligned | * @param v1 first vector, 16-byte aligned | ||||
| @@ -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, | |||||
| }; | |||||
| @@ -514,14 +514,6 @@ static double predict_size(Predictor *p, double q, double var) | |||||
| return p->coeff*var / (q*p->count); | 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) | static void update_predictor(Predictor *p, double q, double var, double size) | ||||
| { | { | ||||
| double new_coeff= size*q / (var + 1); | 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_y = mb_xy / s->mb_stride; | ||||
| int mb_distance; | int mb_distance; | ||||
| float mb_factor = 0.0; | 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(spat_cplx < 4) spat_cplx= 4; //FIXME finetune | ||||
| if(temp_cplx < 4) temp_cplx= 4; //FIXME finetune | if(temp_cplx < 4) temp_cplx= 4; //FIXME finetune | ||||
| @@ -2138,6 +2138,11 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) | |||||
| case 29: return 288; | case 29: return 288; | ||||
| case 37: return 480; | case 37: return 480; | ||||
| } | } | ||||
| } else if (id == CODEC_ID_ILBC) { | |||||
| switch (ba) { | |||||
| case 38: return 160; | |||||
| case 50: return 240; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -27,7 +27,7 @@ | |||||
| */ | */ | ||||
| #define LIBAVCODEC_VERSION_MAJOR 54 | #define LIBAVCODEC_VERSION_MAJOR 54 | ||||
| #define LIBAVCODEC_VERSION_MINOR 25 | |||||
| #define LIBAVCODEC_VERSION_MINOR 26 | |||||
| #define LIBAVCODEC_VERSION_MICRO 100 | #define LIBAVCODEC_VERSION_MICRO 100 | ||||
| #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | ||||
| @@ -32,6 +32,7 @@ | |||||
| #include "libavutil/audio_fifo.h" | #include "libavutil/audio_fifo.h" | ||||
| #include "libavutil/avassert.h" | #include "libavutil/avassert.h" | ||||
| #include "libavutil/avstring.h" | #include "libavutil/avstring.h" | ||||
| #include "libavutil/float_dsp.h" | |||||
| #include "libavutil/mathematics.h" | #include "libavutil/mathematics.h" | ||||
| #include "libavutil/opt.h" | #include "libavutil/opt.h" | ||||
| #include "libavutil/samplefmt.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 { | typedef struct MixContext { | ||||
| const AVClass *class; /**< class for AVOptions */ | const AVClass *class; /**< class for AVOptions */ | ||||
| AVFloatDSPContext fdsp; | |||||
| int nb_inputs; /**< number of inputs */ | int nb_inputs; /**< number of inputs */ | ||||
| int active_inputs; /**< number of input currently active */ | int active_inputs; /**< number of input currently active */ | ||||
| @@ -160,6 +162,7 @@ typedef struct MixContext { | |||||
| int nb_channels; /**< number of channels */ | int nb_channels; /**< number of channels */ | ||||
| int sample_rate; /**< sample rate */ | int sample_rate; /**< sample rate */ | ||||
| int planar; | |||||
| AVAudioFifo **fifos; /**< audio fifo for each input */ | AVAudioFifo **fifos; /**< audio fifo for each input */ | ||||
| uint8_t *input_state; /**< current state of each input */ | uint8_t *input_state; /**< current state of each input */ | ||||
| float *input_scale; /**< mixing scale factor for each input */ | float *input_scale; /**< mixing scale factor for each input */ | ||||
| @@ -224,6 +227,7 @@ static int config_output(AVFilterLink *outlink) | |||||
| int i; | int i; | ||||
| char buf[64]; | char buf[64]; | ||||
| s->planar = av_sample_fmt_is_planar(outlink->format); | |||||
| s->sample_rate = outlink->sample_rate; | s->sample_rate = outlink->sample_rate; | ||||
| outlink->time_base = (AVRational){ 1, outlink->sample_rate }; | outlink->time_base = (AVRational){ 1, outlink->sample_rate }; | ||||
| s->next_pts = AV_NOPTS_VALUE; | s->next_pts = AV_NOPTS_VALUE; | ||||
| @@ -264,14 +268,6 @@ static int config_output(AVFilterLink *outlink) | |||||
| return 0; | 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. | * 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++) { | for (i = 0; i < s->nb_inputs; i++) { | ||||
| if (s->input_state[i] == INPUT_ON) { | if (s->input_state[i] == INPUT_ON) { | ||||
| int planes, plane_size, p; | |||||
| av_audio_fifo_read(s->fifos[i], (void **)in_buf->extended_data, | av_audio_fifo_read(s->fifos[i], (void **)in_buf->extended_data, | ||||
| nb_samples); | 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); | 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); | ff_insert_inpad(ctx, i, &pad); | ||||
| } | } | ||||
| avpriv_float_dsp_init(&s->fdsp, 0); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -527,6 +534,7 @@ static int query_formats(AVFilterContext *ctx) | |||||
| { | { | ||||
| AVFilterFormats *formats = NULL; | AVFilterFormats *formats = NULL; | ||||
| ff_add_format(&formats, AV_SAMPLE_FMT_FLT); | 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_formats(ctx, formats); | ||||
| ff_set_common_channel_layouts(ctx, ff_all_channel_layouts()); | ff_set_common_channel_layouts(ctx, ff_all_channel_layouts()); | ||||
| ff_set_common_samplerates(ctx, ff_all_samplerates()); | ff_set_common_samplerates(ctx, ff_all_samplerates()); | ||||
| @@ -123,6 +123,8 @@ OBJS-$(CONFIG_ICO_DEMUXER) += icodec.o | |||||
| OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o | OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o | ||||
| OBJS-$(CONFIG_IDF_DEMUXER) += bintext.o | OBJS-$(CONFIG_IDF_DEMUXER) += bintext.o | ||||
| OBJS-$(CONFIG_IFF_DEMUXER) += iff.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_DEMUXER) += img2dec.o img2.o | ||||
| OBJS-$(CONFIG_IMAGE2_MUXER) += img2enc.o img2.o | OBJS-$(CONFIG_IMAGE2_MUXER) += img2enc.o img2.o | ||||
| OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER) += img2dec.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.o \ | ||||
| rtpdec_h263_rfc2190.o \ | rtpdec_h263_rfc2190.o \ | ||||
| rtpdec_h264.o \ | rtpdec_h264.o \ | ||||
| rtpdec_ilbc.o \ | |||||
| rtpdec_latm.o \ | rtpdec_latm.o \ | ||||
| rtpdec_mpeg4.o \ | rtpdec_mpeg4.o \ | ||||
| rtpdec_qcelp.o \ | rtpdec_qcelp.o \ | ||||
| @@ -116,6 +116,7 @@ void av_register_all(void) | |||||
| REGISTER_DEMUXER (IDCIN, idcin); | REGISTER_DEMUXER (IDCIN, idcin); | ||||
| REGISTER_DEMUXER (IDF, idf); | REGISTER_DEMUXER (IDF, idf); | ||||
| REGISTER_DEMUXER (IFF, iff); | REGISTER_DEMUXER (IFF, iff); | ||||
| REGISTER_MUXDEMUX (ILBC, ilbc); | |||||
| REGISTER_MUXDEMUX (IMAGE2, image2); | REGISTER_MUXDEMUX (IMAGE2, image2); | ||||
| REGISTER_MUXDEMUX (IMAGE2PIPE, image2pipe); | REGISTER_MUXDEMUX (IMAGE2PIPE, image2pipe); | ||||
| REGISTER_DEMUXER (INGENIENT, ingenient); | REGISTER_DEMUXER (INGENIENT, ingenient); | ||||
| @@ -759,33 +759,6 @@ static int flv_read_seek(AVFormatContext *s, int stream_index, | |||||
| return avio_seek_time(s->pb, stream_index, ts, flags); | 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 = { | AVInputFormat ff_flv_demuxer = { | ||||
| .name = "flv", | .name = "flv", | ||||
| .long_name = NULL_IF_CONFIG_SMALL("FLV format"), | .long_name = NULL_IF_CONFIG_SMALL("FLV format"), | ||||
| @@ -794,9 +767,6 @@ AVInputFormat ff_flv_demuxer = { | |||||
| .read_header = flv_read_header, | .read_header = flv_read_header, | ||||
| .read_packet = flv_read_packet, | .read_packet = flv_read_packet, | ||||
| .read_seek = flv_read_seek, | .read_seek = flv_read_seek, | ||||
| #if 0 | |||||
| .read_seek2 = flv_read_seek2, | |||||
| #endif | |||||
| .read_close = flv_read_close, | .read_close = flv_read_close, | ||||
| .extensions = "flv", | .extensions = "flv", | ||||
| }; | }; | ||||
| @@ -308,15 +308,15 @@ static int process_line(URLContext *h, char *line, int line_count, | |||||
| strcpy(s->location, p); | strcpy(s->location, p); | ||||
| *new_location = 1; | *new_location = 1; | ||||
| } else if (!av_strcasecmp (tag, "Content-Length") && s->filesize == -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")) { | } else if (!av_strcasecmp (tag, "Content-Range")) { | ||||
| /* "bytes $from-$to/$document_size" */ | /* "bytes $from-$to/$document_size" */ | ||||
| const char *slash; | const char *slash; | ||||
| if (!strncmp (p, "bytes ", 6)) { | if (!strncmp (p, "bytes ", 6)) { | ||||
| p += 6; | p += 6; | ||||
| s->off = atoll(p); | |||||
| s->off = strtoll(p, NULL, 10); | |||||
| if ((slash = strchr(p, '/')) && strlen(slash) > 0) | 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 */ | h->is_streamed = 0; /* we _can_ in fact seek */ | ||||
| } else if (!av_strcasecmp(tag, "Accept-Ranges") && !strncmp(p, "bytes", 5)) { | } else if (!av_strcasecmp(tag, "Accept-Ranges") && !strncmp(p, "bytes", 5)) { | ||||
| @@ -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, | |||||
| }; | |||||
| @@ -259,6 +259,7 @@ const AVCodecTag ff_codec_movaudio_tags[] = { | |||||
| { CODEC_ID_DVAUDIO, MKTAG('v', 'd', 'v', 'a') }, | { CODEC_ID_DVAUDIO, MKTAG('v', 'd', 'v', 'a') }, | ||||
| { CODEC_ID_DVAUDIO, MKTAG('d', 'v', 'c', 'a') }, | { CODEC_ID_DVAUDIO, MKTAG('d', 'v', 'c', 'a') }, | ||||
| { CODEC_ID_GSM, MKTAG('a', 'g', 's', 'm') }, | { 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_MACE3, MKTAG('M', 'A', 'C', '3') }, | ||||
| { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') }, | { CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') }, | ||||
| { CODEC_ID_MP1, MKTAG('.', 'm', 'p', '1') }, | { CODEC_ID_MP1, MKTAG('.', 'm', 'p', '1') }, | ||||
| @@ -1540,6 +1540,7 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) | |||||
| case CODEC_ID_GSM: | case CODEC_ID_GSM: | ||||
| case CODEC_ID_ADPCM_MS: | case CODEC_ID_ADPCM_MS: | ||||
| case CODEC_ID_ADPCM_IMA_WAV: | case CODEC_ID_ADPCM_IMA_WAV: | ||||
| case CODEC_ID_ILBC: | |||||
| st->codec->block_align = sc->bytes_per_frame; | st->codec->block_align = sc->bytes_per_frame; | ||||
| break; | break; | ||||
| case CODEC_ID_ALAC: | case CODEC_ID_ALAC: | ||||
| @@ -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); | av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i); | ||||
| track->audio_vbr = 1; | track->audio_vbr = 1; | ||||
| }else if(st->codec->codec_id == CODEC_ID_ADPCM_MS || | }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) { | if (!st->codec->block_align) { | ||||
| av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i); | av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i); | ||||
| goto error; | goto error; | ||||
| @@ -19,8 +19,6 @@ | |||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
| */ | */ | ||||
| //#define USE_SYNCPOINT_SEARCH | |||||
| #include "libavutil/crc.h" | #include "libavutil/crc.h" | ||||
| #include "libavutil/intreadwrite.h" | #include "libavutil/intreadwrite.h" | ||||
| #include "libavutil/log.h" | #include "libavutil/log.h" | ||||
| @@ -2161,92 +2159,6 @@ static int64_t mpegts_get_dts(AVFormatContext *s, int stream_index, | |||||
| return AV_NOPTS_VALUE; | 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 */ | /* parsing functions - called from other demuxers such as RTP */ | ||||
| @@ -2313,9 +2225,6 @@ AVInputFormat ff_mpegts_demuxer = { | |||||
| .read_close = mpegts_read_close, | .read_close = mpegts_read_close, | ||||
| .read_timestamp = mpegts_get_dts, | .read_timestamp = mpegts_get_dts, | ||||
| .flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, | .flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, | ||||
| #ifdef USE_SYNCPOINT_SEARCH | |||||
| .read_seek2 = read_seek2, | |||||
| #endif | |||||
| }; | }; | ||||
| AVInputFormat ff_mpegtsraw_demuxer = { | AVInputFormat ff_mpegtsraw_demuxer = { | ||||
| @@ -2327,8 +2236,5 @@ AVInputFormat ff_mpegtsraw_demuxer = { | |||||
| .read_close = mpegts_read_close, | .read_close = mpegts_read_close, | ||||
| .read_timestamp = mpegts_get_dts, | .read_timestamp = mpegts_get_dts, | ||||
| .flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, | .flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, | ||||
| #ifdef USE_SYNCPOINT_SEARCH | |||||
| .read_seek2 = read_seek2, | |||||
| #endif | |||||
| .priv_class = &mpegtsraw_class, | .priv_class = &mpegtsraw_class, | ||||
| }; | }; | ||||
| @@ -76,6 +76,7 @@ typedef struct RTMPContext { | |||||
| uint8_t* flv_data; ///< buffer with data for demuxer | uint8_t* flv_data; ///< buffer with data for demuxer | ||||
| int flv_size; ///< current buffer size | int flv_size; ///< current buffer size | ||||
| int flv_off; ///< number of bytes read from current buffer | 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) | 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 client_report_size; ///< number of bytes after which client should report to server | ||||
| uint32_t bytes_read; ///< number of bytes read from 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 | char* swfurl; ///< url of the swf player | ||||
| int server_bw; ///< server bandwidth | int server_bw; ///< server bandwidth | ||||
| int client_buffer_time; ///< client buffer time in ms | int client_buffer_time; ///< client buffer time in ms | ||||
| int flush_interval; ///< number of packets flushed in the same request (RTMPT only) | |||||
| } RTMPContext; | } RTMPContext; | ||||
| #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing | #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_size = 0; | ||||
| rt->flv_off = 0; | rt->flv_off = 0; | ||||
| rt->flv_header_bytes = 0; | rt->flv_header_bytes = 0; | ||||
| rt->flv_nb_packets++; | |||||
| } | } | ||||
| } while (buf_temp - buf < size); | } 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 */ | /* set stream into nonblocking mode */ | ||||
| rt->stream->flags |= AVIO_FLAG_NONBLOCK; | 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_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_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_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"}, | {"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"}, | {"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"}, | {"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"}, | ||||
| @@ -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_2000_dynamic_handler); | ||||
| ff_register_dynamic_payload_handler(&ff_h263_rfc2190_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_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_vorbis_dynamic_handler); | ||||
| ff_register_dynamic_payload_handler(&ff_theora_dynamic_handler); | ff_register_dynamic_payload_handler(&ff_theora_dynamic_handler); | ||||
| ff_register_dynamic_payload_handler(&ff_qdm2_dynamic_handler); | ff_register_dynamic_payload_handler(&ff_qdm2_dynamic_handler); | ||||
| @@ -45,6 +45,7 @@ extern RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler; | |||||
| extern RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler; | extern RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler; | ||||
| extern RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler; | extern RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler; | ||||
| extern RTPDynamicProtocolHandler ff_h264_dynamic_handler; | extern RTPDynamicProtocolHandler ff_h264_dynamic_handler; | ||||
| extern RTPDynamicProtocolHandler ff_ilbc_dynamic_handler; | |||||
| extern RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler; | extern RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler; | ||||
| extern RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler; | extern RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler; | ||||
| extern RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler; | extern RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler; | ||||
| @@ -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, | |||||
| }; | |||||
| @@ -74,6 +74,7 @@ static int is_supported(enum CodecID id) | |||||
| case CODEC_ID_VP8: | case CODEC_ID_VP8: | ||||
| case CODEC_ID_ADPCM_G722: | case CODEC_ID_ADPCM_G722: | ||||
| case CODEC_ID_ADPCM_G726: | case CODEC_ID_ADPCM_G726: | ||||
| case CODEC_ID_ILBC: | |||||
| return 1; | return 1; | ||||
| default: | default: | ||||
| return 0; | return 0; | ||||
| @@ -187,6 +188,16 @@ static int rtp_write_header(AVFormatContext *s1) | |||||
| * 8000, even if the sample rate is 16000. See RFC 3551. */ | * 8000, even if the sample rate is 16000. See RFC 3551. */ | ||||
| avpriv_set_pts_info(st, 32, 1, 8000); | avpriv_set_pts_info(st, 32, 1, 8000); | ||||
| break; | 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_NB: | ||||
| case CODEC_ID_AMR_WB: | case CODEC_ID_AMR_WB: | ||||
| if (!s->max_frames_per_packet) | 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) | static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) | ||||
| { | { | ||||
| RTPMuxContext *s = s1->priv_data; | RTPMuxContext *s = s1->priv_data; | ||||
| @@ -483,6 +524,9 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) | |||||
| case CODEC_ID_VP8: | case CODEC_ID_VP8: | ||||
| ff_rtp_send_vp8(s1, pkt->data, size); | ff_rtp_send_vp8(s1, pkt->data, size); | ||||
| break; | break; | ||||
| case CODEC_ID_ILBC: | |||||
| rtp_send_ilbc(s1, pkt->data, size); | |||||
| break; | |||||
| default: | default: | ||||
| /* better than nothing : send the codec raw data */ | /* better than nothing : send the codec raw data */ | ||||
| rtp_send_raw(s1, pkt->data, size); | rtp_send_raw(s1, pkt->data, size); | ||||
| @@ -1279,7 +1279,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, | |||||
| "%s/UDP;multicast", trans_pref); | "%s/UDP;multicast", trans_pref); | ||||
| } | } | ||||
| if (s->oformat) { | 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 || | } else if (rt->server_type == RTSP_SERVER_REAL || | ||||
| rt->server_type == RTSP_SERVER_WMS) | rt->server_type == RTSP_SERVER_WMS) | ||||
| av_strlcat(transport, ";mode=play", sizeof(transport)); | av_strlcat(transport, ";mode=play", sizeof(transport)); | ||||
| @@ -549,6 +549,12 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, | |||||
| c->sample_rate); | c->sample_rate); | ||||
| break; | 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: | default: | ||||
| /* Nothing special to do here... */ | /* Nothing special to do here... */ | ||||
| break; | break; | ||||
| @@ -30,7 +30,7 @@ | |||||
| #include "libavutil/avutil.h" | #include "libavutil/avutil.h" | ||||
| #define LIBAVFORMAT_VERSION_MAJOR 54 | #define LIBAVFORMAT_VERSION_MAJOR 54 | ||||
| #define LIBAVFORMAT_VERSION_MINOR 8 | |||||
| #define LIBAVFORMAT_VERSION_MINOR 9 | |||||
| #define LIBAVFORMAT_VERSION_MICRO 100 | #define LIBAVFORMAT_VERSION_MICRO 100 | ||||
| #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | ||||
| @@ -1,6 +1,7 @@ | |||||
| ;****************************************************************************** | ;****************************************************************************** | ||||
| ;* x86 optimized Format Conversion Utils | ;* x86 optimized Format Conversion Utils | ||||
| ;* Copyright (c) 2008 Loren Merritt | ;* Copyright (c) 2008 Loren Merritt | ||||
| ;* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com> | |||||
| ;* | ;* | ||||
| ;* This file is part of Libav. | ;* This file is part of Libav. | ||||
| ;* | ;* | ||||
| @@ -21,9 +22,217 @@ | |||||
| %include "x86inc.asm" | %include "x86inc.asm" | ||||
| %include "x86util.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 | 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, | ; void ff_conv_fltp_to_flt_6ch(float *dst, float *const *src, int len, | ||||
| ; int channels); | ; int channels); | ||||
| @@ -22,6 +22,22 @@ | |||||
| #include "libavutil/cpu.h" | #include "libavutil/cpu.h" | ||||
| #include "libavresample/audio_convert.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_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_sse4(float *dst, float *const *src, int len); | ||||
| extern void ff_conv_fltp_to_flt_6ch_avx (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(); | int mm_flags = av_get_cpu_flags(); | ||||
| if (mm_flags & AV_CPU_FLAG_MMX && HAVE_MMX) { | 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, | 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); | 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, | 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); | 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 | #endif | ||||
| } | } | ||||
| @@ -26,7 +26,11 @@ | |||||
| void ff_vector_fmul_neon(float *dst, const float *src0, const float *src1, int len); | 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) | void ff_float_dsp_init_neon(AVFloatDSPContext *fdsp) | ||||
| { | { | ||||
| fdsp->vector_fmul = ff_vector_fmul_neon; | fdsp->vector_fmul = ff_vector_fmul_neon; | ||||
| fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_neon; | |||||
| } | } | ||||
| @@ -62,3 +62,51 @@ function ff_vector_fmul_neon, export=1 | |||||
| 3: vst1.32 {d16-d19},[r0,:128]! | 3: vst1.32 {d16-d19},[r0,:128]! | ||||
| bx lr | bx lr | ||||
| endfunc | 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 | |||||
| @@ -31,9 +31,18 @@ static void vector_fmul_c(float *dst, const float *src0, const float *src1, | |||||
| dst[i] = src0[i] * src1[i]; | 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) | void avpriv_float_dsp_init(AVFloatDSPContext *fdsp, int bit_exact) | ||||
| { | { | ||||
| fdsp->vector_fmul = vector_fmul_c; | fdsp->vector_fmul = vector_fmul_c; | ||||
| fdsp->vector_fmac_scalar = vector_fmac_scalar_c; | |||||
| #if ARCH_ARM | #if ARCH_ARM | ||||
| ff_float_dsp_init_arm(fdsp); | ff_float_dsp_init_arm(fdsp); | ||||
| @@ -35,6 +35,22 @@ typedef struct AVFloatDSPContext { | |||||
| */ | */ | ||||
| void (*vector_fmul)(float *dst, const float *src0, const float *src1, | void (*vector_fmul)(float *dst, const float *src0, const float *src1, | ||||
| int len); | 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; | } AVFloatDSPContext; | ||||
| /** | /** | ||||
| @@ -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 (size) //OS X on SDK 10.6 has a broken posix_memalign implementation | ||||
| if (posix_memalign(&ptr,ALIGN,size)) | if (posix_memalign(&ptr,ALIGN,size)) | ||||
| ptr = NULL; | ptr = NULL; | ||||
| #elif HAVE_ALIGNED_MALLOC | |||||
| ptr = _aligned_malloc(size, ALIGN); | |||||
| #elif HAVE_MEMALIGN | #elif HAVE_MEMALIGN | ||||
| ptr = memalign(ALIGN,size); | ptr = memalign(ALIGN,size); | ||||
| /* Why 64? | /* Why 64? | ||||
| @@ -145,6 +147,8 @@ void *av_realloc(void *ptr, size_t size) | |||||
| ptr= realloc((char*)ptr - diff, size + diff); | ptr= realloc((char*)ptr - diff, size + diff); | ||||
| if(ptr) ptr = (char*)ptr + diff; | if(ptr) ptr = (char*)ptr + diff; | ||||
| return ptr; | return ptr; | ||||
| #elif HAVE_ALIGNED_MALLOC | |||||
| return _aligned_realloc(ptr, size + !size, ALIGN); | |||||
| #else | #else | ||||
| return realloc(ptr, size + !size); | return realloc(ptr, size + !size); | ||||
| #endif | #endif | ||||
| @@ -170,6 +174,8 @@ void av_free(void *ptr) | |||||
| #if CONFIG_MEMALIGN_HACK | #if CONFIG_MEMALIGN_HACK | ||||
| if (ptr) | if (ptr) | ||||
| free((char*)ptr - ((char*)ptr)[-1]); | free((char*)ptr - ((char*)ptr)[-1]); | ||||
| #elif HAVE_ALIGNED_MALLOC | |||||
| _aligned_free(ptr); | |||||
| #else | #else | ||||
| free(ptr); | free(ptr); | ||||
| #endif | #endif | ||||
| @@ -21,6 +21,7 @@ | |||||
| ;****************************************************************************** | ;****************************************************************************** | ||||
| %include "x86inc.asm" | %include "x86inc.asm" | ||||
| %include "x86util.asm" | |||||
| SECTION .text | SECTION .text | ||||
| @@ -55,3 +56,49 @@ VECTOR_FMUL | |||||
| INIT_YMM avx | INIT_YMM avx | ||||
| VECTOR_FMUL | VECTOR_FMUL | ||||
| %endif | %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 | |||||
| @@ -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, | extern void ff_vector_fmul_avx(float *dst, const float *src0, const float *src1, | ||||
| int len); | 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) | void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp) | ||||
| { | { | ||||
| #if HAVE_YASM | #if HAVE_YASM | ||||
| @@ -33,9 +38,11 @@ void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp) | |||||
| if (mm_flags & AV_CPU_FLAG_SSE && HAVE_SSE) { | if (mm_flags & AV_CPU_FLAG_SSE && HAVE_SSE) { | ||||
| fdsp->vector_fmul = ff_vector_fmul_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) { | if (mm_flags & AV_CPU_FLAG_AVX && HAVE_AVX) { | ||||
| fdsp->vector_fmul = ff_vector_fmul_avx; | fdsp->vector_fmul = ff_vector_fmul_avx; | ||||
| fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_avx; | |||||
| } | } | ||||
| #endif | #endif | ||||
| } | } | ||||