* 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>
... | ... |
@@ -180,6 +180,7 @@ External library support: |
180 | 180 |
--enable-libfaac enable FAAC support via libfaac [no] |
181 | 181 |
--enable-libfreetype enable libfreetype [no] |
182 | 182 |
--enable-libgsm enable GSM support via libgsm [no] |
183 |
+ --enable-libilbc enable iLBC de/encoding via libilbc [no] |
|
183 | 184 |
--enable-libmodplug enable ModPlug via libmodplug [no] |
184 | 185 |
--enable-libmp3lame enable MP3 encoding via libmp3lame [no] |
185 | 186 |
--enable-libnut enable NUT (de)muxing via libnut, |
... | ... |
@@ -1051,6 +1052,7 @@ CONFIG_LIST=" |
1051 | 1051 |
libfaac |
1052 | 1052 |
libfreetype |
1053 | 1053 |
libgsm |
1054 |
+ libilbc |
|
1054 | 1055 |
libmodplug |
1055 | 1056 |
libmp3lame |
1056 | 1057 |
libnut |
... | ... |
@@ -1168,6 +1170,7 @@ HAVE_LIST=" |
1168 | 1168 |
$ARCH_EXT_LIST |
1169 | 1169 |
$HAVE_LIST_PUB |
1170 | 1170 |
$THREADS_LIST |
1171 |
+ aligned_malloc |
|
1171 | 1172 |
aligned_stack |
1172 | 1173 |
alsa_asoundlib_h |
1173 | 1174 |
altivec_h |
... | ... |
@@ -1588,6 +1591,8 @@ libgsm_decoder_deps="libgsm" |
1588 | 1588 |
libgsm_encoder_deps="libgsm" |
1589 | 1589 |
libgsm_ms_decoder_deps="libgsm" |
1590 | 1590 |
libgsm_ms_encoder_deps="libgsm" |
1591 |
+libilbc_decoder_deps="libilbc" |
|
1592 |
+libilbc_encoder_deps="libilbc" |
|
1591 | 1593 |
libmodplug_demuxer_deps="libmodplug" |
1592 | 1594 |
libmp3lame_encoder_deps="libmp3lame" |
1593 | 1595 |
libopencore_amrnb_decoder_deps="libopencore_amrnb" |
... | ... |
@@ -3144,6 +3149,7 @@ check_func ${malloc_prefix}memalign && enable memalign |
3144 | 3144 |
check_func mkstemp |
3145 | 3145 |
check_func mmap |
3146 | 3146 |
check_func ${malloc_prefix}posix_memalign && enable posix_memalign |
3147 |
+check_func_headers malloc.h _aligned_malloc && enable aligned_malloc |
|
3147 | 3148 |
check_func setrlimit |
3148 | 3149 |
check_func strerror_r |
3149 | 3150 |
check_func strptime |
... | ... |
@@ -3254,6 +3260,7 @@ enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && |
3254 | 3254 |
enabled libfaac && require2 libfaac "stdint.h faac.h" faacEncGetVersion -lfaac |
3255 | 3255 |
enabled libfreetype && require_pkg_config freetype2 "ft2build.h freetype/freetype.h" FT_Init_FreeType |
3256 | 3256 |
enabled libgsm && require libgsm gsm/gsm.h gsm_create -lgsm |
3257 |
+enabled libilbc && require libilbc ilbc.h WebRtcIlbcfix_InitDecode -lilbc |
|
3257 | 3258 |
enabled libmodplug && require libmodplug libmodplug/modplug.h ModPlug_Load -lmodplug |
3258 | 3259 |
enabled libmp3lame && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame |
3259 | 3260 |
enabled libnut && require libnut libnut.h nut_demuxer_init -lnut |
... | ... |
@@ -3522,7 +3529,7 @@ if test $target_os = "haiku"; then |
3522 | 3522 |
disable posix_memalign |
3523 | 3523 |
fi |
3524 | 3524 |
|
3525 |
-! enabled_any memalign posix_memalign && |
|
3525 |
+! enabled_any memalign posix_memalign aligned_malloc && |
|
3526 | 3526 |
enabled_any $need_memalign && enable memalign_hack |
3527 | 3527 |
|
3528 | 3528 |
# add_dep lib dep |
... | ... |
@@ -3628,6 +3635,7 @@ echo "libcelt enabled ${libcelt-no}" |
3628 | 3628 |
echo "libdc1394 support ${libdc1394-no}" |
3629 | 3629 |
echo "libfaac enabled ${libfaac-no}" |
3630 | 3630 |
echo "libgsm enabled ${libgsm-no}" |
3631 |
+echo "libilbc enabled ${libilbc-no}" |
|
3631 | 3632 |
echo "libmodplug enabled ${libmodplug-no}" |
3632 | 3633 |
echo "libmp3lame enabled ${libmp3lame-no}" |
3633 | 3634 |
echo "libnut enabled ${libnut-no}" |
... | ... |
@@ -93,6 +93,17 @@ x264 is under the GNU Public License Version 2 or later |
93 | 93 |
details), you must upgrade FFmpeg's license to GPL in order to use it. |
94 | 94 |
@end float |
95 | 95 |
|
96 |
+@section libilbc |
|
97 |
+ |
|
98 |
+iLBC is a narrowband speech codec that has been made freely available |
|
99 |
+by Google as part of the WebRTC project. libilbc is a packaging friendly |
|
100 |
+copy of the iLBC codec. Libav can make use of the libilbc library for |
|
101 |
+iLBC encoding and decoding. |
|
102 |
+ |
|
103 |
+Go to @url{https://github.com/dekkers/libilbc} and follow the instructions for |
|
104 |
+installing the library. Then pass @code{--enable-libilbc} to configure to |
|
105 |
+enable it. |
|
106 |
+ |
|
96 | 107 |
|
97 | 108 |
|
98 | 109 |
@chapter Supported File Formats, Codecs or Features |
... | ... |
@@ -191,6 +202,7 @@ library: |
191 | 191 |
@item IEC61937 encapsulation @tab X @tab X |
192 | 192 |
@item IFF @tab @tab X |
193 | 193 |
@tab Interchange File Format |
194 |
+@item iLBC @tab X @tab X |
|
194 | 195 |
@item Interplay MVE @tab @tab X |
195 | 196 |
@tab Format used in various Interplay computer games. |
196 | 197 |
@item IV8 @tab @tab X |
... | ... |
@@ -749,6 +761,8 @@ following image formats are supported: |
749 | 749 |
@item GSM Microsoft variant @tab E @tab X |
750 | 750 |
@tab encoding supported through external library libgsm |
751 | 751 |
@item IAC (Indeo Audio Coder) @tab @tab X |
752 |
+@item iLBC (Internet Low Bitrate Codec) @tab E @tab E |
|
753 |
+ @tab encoding and decoding supported through external library libilbc |
|
752 | 754 |
@item IMC (Intel Music Coder) @tab @tab X |
753 | 755 |
@item MACE (Macintosh Audio Compression/Expansion) 3:1 @tab @tab X |
754 | 756 |
@item MACE (Macintosh Audio Compression/Expansion) 6:1 @tab @tab X |
... | ... |
@@ -247,6 +247,10 @@ times to construct arbitrary AMF sequences. |
247 | 247 |
Version of the Flash plugin used to run the SWF player. The default |
248 | 248 |
is LNX 9,0,124,2. |
249 | 249 |
|
250 |
+@item rtmp_flush_interval |
|
251 |
+Number of packets flushed in the same request (RTMPT only). The default |
|
252 |
+is 10. |
|
253 |
+ |
|
250 | 254 |
@item rtmp_live |
251 | 255 |
Specify that the media is a live stream. No resuming or seeking in |
252 | 256 |
live streams is possible. The default value is @code{any}, which means the |
... | ... |
@@ -659,6 +659,8 @@ OBJS-$(CONFIG_LIBGSM_DECODER) += libgsm.o |
659 | 659 |
OBJS-$(CONFIG_LIBGSM_ENCODER) += libgsm.o |
660 | 660 |
OBJS-$(CONFIG_LIBGSM_MS_DECODER) += libgsm.o |
661 | 661 |
OBJS-$(CONFIG_LIBGSM_MS_ENCODER) += libgsm.o |
662 |
+OBJS-$(CONFIG_LIBILBC_DECODER) += libilbc.o |
|
663 |
+OBJS-$(CONFIG_LIBILBC_ENCODER) += libilbc.o |
|
662 | 664 |
OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o mpegaudiodecheader.o \ |
663 | 665 |
audio_frame_queue.o |
664 | 666 |
OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o \ |
... | ... |
@@ -410,6 +410,7 @@ void avcodec_register_all(void) |
410 | 410 |
REGISTER_ENCODER (LIBFAAC, libfaac); |
411 | 411 |
REGISTER_ENCDEC (LIBGSM, libgsm); |
412 | 412 |
REGISTER_ENCDEC (LIBGSM_MS, libgsm_ms); |
413 |
+ REGISTER_ENCDEC (LIBILBC, libilbc); |
|
413 | 414 |
REGISTER_ENCODER (LIBMP3LAME, libmp3lame); |
414 | 415 |
REGISTER_ENCDEC (LIBOPENCORE_AMRNB, libopencore_amrnb); |
415 | 416 |
REGISTER_DECODER (LIBOPENCORE_AMRWB, libopencore_amrwb); |
... | ... |
@@ -154,8 +154,6 @@ void ff_vector_fmul_window_neon(float *dst, const float *src0, |
154 | 154 |
const float *src1, const float *win, int len); |
155 | 155 |
void ff_vector_fmul_scalar_neon(float *dst, const float *src, float mul, |
156 | 156 |
int len); |
157 |
-void ff_vector_fmac_scalar_neon(float *dst, const float *src, float mul, |
|
158 |
- int len); |
|
159 | 157 |
void ff_butterflies_float_neon(float *v1, float *v2, int len); |
160 | 158 |
float ff_scalarproduct_float_neon(const float *v1, const float *v2, int len); |
161 | 159 |
void ff_vector_fmul_reverse_neon(float *dst, const float *src0, |
... | ... |
@@ -329,7 +327,6 @@ void ff_dsputil_init_neon(DSPContext *c, AVCodecContext *avctx) |
329 | 329 |
|
330 | 330 |
c->vector_fmul_window = ff_vector_fmul_window_neon; |
331 | 331 |
c->vector_fmul_scalar = ff_vector_fmul_scalar_neon; |
332 |
- c->vector_fmac_scalar = ff_vector_fmac_scalar_neon; |
|
333 | 332 |
c->butterflies_float = ff_butterflies_float_neon; |
334 | 333 |
c->scalarproduct_float = ff_scalarproduct_float_neon; |
335 | 334 |
c->vector_fmul_reverse = ff_vector_fmul_reverse_neon; |
... | ... |
@@ -682,54 +682,6 @@ NOVFP vdup.32 q8, r2 |
682 | 682 |
.unreq len |
683 | 683 |
endfunc |
684 | 684 |
|
685 |
-function ff_vector_fmac_scalar_neon, export=1 |
|
686 |
-VFP len .req r2 |
|
687 |
-VFP acc .req r3 |
|
688 |
-NOVFP len .req r3 |
|
689 |
-NOVFP acc .req r2 |
|
690 |
-VFP vdup.32 q15, d0[0] |
|
691 |
-NOVFP vdup.32 q15, r2 |
|
692 |
- bics r12, len, #15 |
|
693 |
- mov acc, r0 |
|
694 |
- beq 3f |
|
695 |
- vld1.32 {q0}, [r1,:128]! |
|
696 |
- vld1.32 {q8}, [acc,:128]! |
|
697 |
- vld1.32 {q1}, [r1,:128]! |
|
698 |
- vld1.32 {q9}, [acc,:128]! |
|
699 |
-1: vmla.f32 q8, q0, q15 |
|
700 |
- vld1.32 {q2}, [r1,:128]! |
|
701 |
- vld1.32 {q10}, [acc,:128]! |
|
702 |
- vmla.f32 q9, q1, q15 |
|
703 |
- vld1.32 {q3}, [r1,:128]! |
|
704 |
- vld1.32 {q11}, [acc,:128]! |
|
705 |
- vmla.f32 q10, q2, q15 |
|
706 |
- vst1.32 {q8}, [r0,:128]! |
|
707 |
- vmla.f32 q11, q3, q15 |
|
708 |
- vst1.32 {q9}, [r0,:128]! |
|
709 |
- subs r12, r12, #16 |
|
710 |
- beq 2f |
|
711 |
- vld1.32 {q0}, [r1,:128]! |
|
712 |
- vld1.32 {q8}, [acc,:128]! |
|
713 |
- vst1.32 {q10}, [r0,:128]! |
|
714 |
- vld1.32 {q1}, [r1,:128]! |
|
715 |
- vld1.32 {q9}, [acc,:128]! |
|
716 |
- vst1.32 {q11}, [r0,:128]! |
|
717 |
- b 1b |
|
718 |
-2: vst1.32 {q10}, [r0,:128]! |
|
719 |
- vst1.32 {q11}, [r0,:128]! |
|
720 |
- ands len, len, #15 |
|
721 |
- it eq |
|
722 |
- bxeq lr |
|
723 |
-3: vld1.32 {q0}, [r1,:128]! |
|
724 |
- vld1.32 {q8}, [acc,:128]! |
|
725 |
- vmla.f32 q8, q0, q15 |
|
726 |
- vst1.32 {q8}, [r0,:128]! |
|
727 |
- subs len, len, #4 |
|
728 |
- bgt 3b |
|
729 |
- bx lr |
|
730 |
- .unreq len |
|
731 |
-endfunc |
|
732 |
- |
|
733 | 685 |
function ff_butterflies_float_neon, export=1 |
734 | 686 |
1: vld1.32 {q0},[r0,:128] |
735 | 687 |
vld1.32 {q1},[r1,:128] |
... | ... |
@@ -407,6 +407,7 @@ enum CodecID { |
407 | 407 |
CODEC_ID_BMV_AUDIO, |
408 | 408 |
CODEC_ID_RALF, |
409 | 409 |
CODEC_ID_IAC, |
410 |
+ CODEC_ID_ILBC, |
|
410 | 411 |
CODEC_ID_FFWAVESYNTH = MKBETAG('F','F','W','S'), |
411 | 412 |
CODEC_ID_8SVX_RAW = MKBETAG('8','S','V','X'), |
412 | 413 |
CODEC_ID_SONIC = MKBETAG('S','O','N','C'), |
... | ... |
@@ -3470,6 +3471,9 @@ void av_destruct_packet(AVPacket *pkt); |
3470 | 3470 |
/** |
3471 | 3471 |
* Initialize optional fields of a packet with default values. |
3472 | 3472 |
* |
3473 |
+ * Note, this does not touch the data and size members, which have to be |
|
3474 |
+ * initialized separately. |
|
3475 |
+ * |
|
3473 | 3476 |
* @param pkt packet |
3474 | 3477 |
*/ |
3475 | 3478 |
void av_init_packet(AVPacket *pkt); |
... | ... |
@@ -27,6 +27,7 @@ |
27 | 27 |
#include <stdio.h> |
28 | 28 |
|
29 | 29 |
#include "libavutil/common.h" |
30 |
+#include "libavutil/float_dsp.h" |
|
30 | 31 |
#include "libavutil/intmath.h" |
31 | 32 |
#include "libavutil/intreadwrite.h" |
32 | 33 |
#include "libavutil/mathematics.h" |
... | ... |
@@ -384,7 +385,7 @@ typedef struct { |
384 | 384 |
int profile; |
385 | 385 |
|
386 | 386 |
int debug_flag; ///< used for suppressing repeated error messages output |
387 |
- DSPContext dsp; |
|
387 |
+ AVFloatDSPContext fdsp; |
|
388 | 388 |
FFTContext imdct; |
389 | 389 |
SynthFilterContext synth; |
390 | 390 |
DCADSPContext dcadsp; |
... | ... |
@@ -2042,8 +2043,8 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, |
2042 | 2042 |
float *back_chan = s->samples + s->channel_order_tab[s->xch_base_channel] * 256; |
2043 | 2043 |
float *lt_chan = s->samples + s->channel_order_tab[s->xch_base_channel - 2] * 256; |
2044 | 2044 |
float *rt_chan = s->samples + s->channel_order_tab[s->xch_base_channel - 1] * 256; |
2045 |
- s->dsp.vector_fmac_scalar(lt_chan, back_chan, -M_SQRT1_2, 256); |
|
2046 |
- s->dsp.vector_fmac_scalar(rt_chan, back_chan, -M_SQRT1_2, 256); |
|
2045 |
+ s->fdsp.vector_fmac_scalar(lt_chan, back_chan, -M_SQRT1_2, 256); |
|
2046 |
+ s->fdsp.vector_fmac_scalar(rt_chan, back_chan, -M_SQRT1_2, 256); |
|
2047 | 2047 |
} |
2048 | 2048 |
|
2049 | 2049 |
if (avctx->sample_fmt == AV_SAMPLE_FMT_FLT) { |
... | ... |
@@ -2085,7 +2086,7 @@ static av_cold int dca_decode_init(AVCodecContext *avctx) |
2085 | 2085 |
s->avctx = avctx; |
2086 | 2086 |
dca_init_vlcs(); |
2087 | 2087 |
|
2088 |
- ff_dsputil_init(&s->dsp, avctx); |
|
2088 |
+ avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); |
|
2089 | 2089 |
ff_mdct_init(&s->imdct, 6, 1, 1.0); |
2090 | 2090 |
ff_synth_filter_init(&s->synth); |
2091 | 2091 |
ff_dcadsp_init(&s->dcadsp); |
... | ... |
@@ -127,7 +127,7 @@ static const enum PixelFormat dirac_pix_fmt[2][3] = { |
127 | 127 |
static int parse_source_parameters(AVCodecContext *avctx, GetBitContext *gb, |
128 | 128 |
dirac_source_params *source) |
129 | 129 |
{ |
130 |
- AVRational frame_rate = (AVRational){0,0}; |
|
130 |
+ AVRational frame_rate = {0,0}; |
|
131 | 131 |
unsigned luma_depth = 8, luma_offset = 16; |
132 | 132 |
int idx; |
133 | 133 |
|
... | ... |
@@ -2509,14 +2509,6 @@ static void vector_fmul_scalar_c(float *dst, const float *src, float mul, |
2509 | 2509 |
dst[i] = src[i] * mul; |
2510 | 2510 |
} |
2511 | 2511 |
|
2512 |
-static void vector_fmac_scalar_c(float *dst, const float *src, float mul, |
|
2513 |
- int len) |
|
2514 |
-{ |
|
2515 |
- int i; |
|
2516 |
- for (i = 0; i < len; i++) |
|
2517 |
- dst[i] += src[i] * mul; |
|
2518 |
-} |
|
2519 |
- |
|
2520 | 2512 |
static void butterflies_float_c(float *av_restrict v1, float *av_restrict v2, |
2521 | 2513 |
int len) |
2522 | 2514 |
{ |
... | ... |
@@ -3060,7 +3052,6 @@ av_cold void ff_dsputil_init(DSPContext* c, AVCodecContext *avctx) |
3060 | 3060 |
c->butterflies_float = butterflies_float_c; |
3061 | 3061 |
c->butterflies_float_interleave = butterflies_float_interleave_c; |
3062 | 3062 |
c->vector_fmul_scalar = vector_fmul_scalar_c; |
3063 |
- c->vector_fmac_scalar = vector_fmac_scalar_c; |
|
3064 | 3063 |
|
3065 | 3064 |
c->shrink[0]= av_image_copy_plane; |
3066 | 3065 |
c->shrink[1]= ff_shrink22; |
... | ... |
@@ -421,17 +421,6 @@ typedef struct DSPContext { |
421 | 421 |
void (*vector_fmul_scalar)(float *dst, const float *src, float mul, |
422 | 422 |
int len); |
423 | 423 |
/** |
424 |
- * Multiply a vector of floats by a scalar float and add to |
|
425 |
- * destination vector. Source and destination vectors must |
|
426 |
- * overlap exactly or not at all. |
|
427 |
- * @param dst result vector, 16-byte aligned |
|
428 |
- * @param src input vector, 16-byte aligned |
|
429 |
- * @param mul scalar value |
|
430 |
- * @param len length of vector, multiple of 4 |
|
431 |
- */ |
|
432 |
- void (*vector_fmac_scalar)(float *dst, const float *src, float mul, |
|
433 |
- int len); |
|
434 |
- /** |
|
435 | 424 |
* Calculate the scalar product of two vectors of floats. |
436 | 425 |
* @param v1 first vector, 16-byte aligned |
437 | 426 |
* @param v2 second vector, 16-byte aligned |
438 | 427 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,209 @@ |
0 |
+/* |
|
1 |
+ * iLBC decoder/encoder stub |
|
2 |
+ * Copyright (c) 2012 Martin Storsjo |
|
3 |
+ * |
|
4 |
+ * This file is part of FFmpeg. |
|
5 |
+ * |
|
6 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
7 |
+ * modify it under the terms of the GNU Lesser General Public |
|
8 |
+ * License as published by the Free Software Foundation; either |
|
9 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
10 |
+ * |
|
11 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
12 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 |
+ * Lesser General Public License for more details. |
|
15 |
+ * |
|
16 |
+ * You should have received a copy of the GNU Lesser General Public |
|
17 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
19 |
+ */ |
|
20 |
+ |
|
21 |
+#include <ilbc.h> |
|
22 |
+ |
|
23 |
+#include "avcodec.h" |
|
24 |
+#include "libavutil/opt.h" |
|
25 |
+#include "internal.h" |
|
26 |
+ |
|
27 |
+static int get_mode(AVCodecContext *avctx) |
|
28 |
+{ |
|
29 |
+ if (avctx->block_align == 38) |
|
30 |
+ return 20; |
|
31 |
+ else if (avctx->block_align == 50) |
|
32 |
+ return 30; |
|
33 |
+ else if (avctx->bit_rate > 0) |
|
34 |
+ return avctx->bit_rate <= 14000 ? 30 : 20; |
|
35 |
+ else |
|
36 |
+ return -1; |
|
37 |
+} |
|
38 |
+ |
|
39 |
+typedef struct ILBCDecContext { |
|
40 |
+ const AVClass *class; |
|
41 |
+ AVFrame frame; |
|
42 |
+ iLBC_Dec_Inst_t decoder; |
|
43 |
+ int enhance; |
|
44 |
+} ILBCDecContext; |
|
45 |
+ |
|
46 |
+static const AVOption ilbc_dec_options[] = { |
|
47 |
+ { "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 }, |
|
48 |
+ { NULL } |
|
49 |
+}; |
|
50 |
+ |
|
51 |
+static const AVClass ilbc_dec_class = { |
|
52 |
+ "libilbc", av_default_item_name, ilbc_dec_options, LIBAVUTIL_VERSION_INT |
|
53 |
+}; |
|
54 |
+ |
|
55 |
+static av_cold int ilbc_decode_init(AVCodecContext *avctx) |
|
56 |
+{ |
|
57 |
+ ILBCDecContext *s = avctx->priv_data; |
|
58 |
+ int mode; |
|
59 |
+ |
|
60 |
+ if ((mode = get_mode(avctx)) < 0) { |
|
61 |
+ av_log(avctx, AV_LOG_ERROR, "iLBC frame mode not indicated\n"); |
|
62 |
+ return AVERROR(EINVAL); |
|
63 |
+ } |
|
64 |
+ |
|
65 |
+ WebRtcIlbcfix_InitDecode(&s->decoder, mode, s->enhance); |
|
66 |
+ avcodec_get_frame_defaults(&s->frame); |
|
67 |
+ avctx->coded_frame = &s->frame; |
|
68 |
+ |
|
69 |
+ avctx->channels = 1; |
|
70 |
+ avctx->sample_rate = 8000; |
|
71 |
+ avctx->sample_fmt = AV_SAMPLE_FMT_S16; |
|
72 |
+ |
|
73 |
+ return 0; |
|
74 |
+} |
|
75 |
+ |
|
76 |
+static int ilbc_decode_frame(AVCodecContext *avctx, void *data, |
|
77 |
+ int *got_frame_ptr, AVPacket *avpkt) |
|
78 |
+{ |
|
79 |
+ const uint8_t *buf = avpkt->data; |
|
80 |
+ int buf_size = avpkt->size; |
|
81 |
+ ILBCDecContext *s = avctx->priv_data; |
|
82 |
+ int ret; |
|
83 |
+ |
|
84 |
+ if (s->decoder.no_of_bytes > buf_size) { |
|
85 |
+ av_log(avctx, AV_LOG_ERROR, "iLBC frame too short (%u, should be %u)\n", |
|
86 |
+ buf_size, s->decoder.no_of_bytes); |
|
87 |
+ return AVERROR_INVALIDDATA; |
|
88 |
+ } |
|
89 |
+ |
|
90 |
+ s->frame.nb_samples = s->decoder.blockl; |
|
91 |
+ if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) { |
|
92 |
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
|
93 |
+ return ret; |
|
94 |
+ } |
|
95 |
+ |
|
96 |
+ WebRtcIlbcfix_DecodeImpl((WebRtc_Word16*) s->frame.data[0], |
|
97 |
+ (const WebRtc_UWord16*) buf, &s->decoder, 1); |
|
98 |
+ |
|
99 |
+ *got_frame_ptr = 1; |
|
100 |
+ *(AVFrame *)data = s->frame; |
|
101 |
+ |
|
102 |
+ return s->decoder.no_of_bytes; |
|
103 |
+} |
|
104 |
+ |
|
105 |
+AVCodec ff_libilbc_decoder = { |
|
106 |
+ .name = "libilbc", |
|
107 |
+ .type = AVMEDIA_TYPE_AUDIO, |
|
108 |
+ .id = CODEC_ID_ILBC, |
|
109 |
+ .priv_data_size = sizeof(ILBCDecContext), |
|
110 |
+ .init = ilbc_decode_init, |
|
111 |
+ .decode = ilbc_decode_frame, |
|
112 |
+ .capabilities = CODEC_CAP_DR1, |
|
113 |
+ .long_name = NULL_IF_CONFIG_SMALL("Internet Low Bitrate Codec (iLBC)"), |
|
114 |
+ .priv_class = &ilbc_dec_class, |
|
115 |
+}; |
|
116 |
+ |
|
117 |
+typedef struct ILBCEncContext { |
|
118 |
+ const AVClass *class; |
|
119 |
+ iLBC_Enc_Inst_t encoder; |
|
120 |
+ int mode; |
|
121 |
+} ILBCEncContext; |
|
122 |
+ |
|
123 |
+static const AVOption ilbc_enc_options[] = { |
|
124 |
+ { "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 }, |
|
125 |
+ { NULL } |
|
126 |
+}; |
|
127 |
+ |
|
128 |
+static const AVClass ilbc_enc_class = { |
|
129 |
+ "libilbc", av_default_item_name, ilbc_enc_options, LIBAVUTIL_VERSION_INT |
|
130 |
+}; |
|
131 |
+ |
|
132 |
+static av_cold int ilbc_encode_init(AVCodecContext *avctx) |
|
133 |
+{ |
|
134 |
+ ILBCEncContext *s = avctx->priv_data; |
|
135 |
+ int mode; |
|
136 |
+ |
|
137 |
+ if (avctx->sample_rate != 8000) { |
|
138 |
+ av_log(avctx, AV_LOG_ERROR, "Only 8000Hz sample rate supported\n"); |
|
139 |
+ return AVERROR(EINVAL); |
|
140 |
+ } |
|
141 |
+ |
|
142 |
+ if (avctx->channels != 1) { |
|
143 |
+ av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); |
|
144 |
+ return AVERROR(EINVAL); |
|
145 |
+ } |
|
146 |
+ |
|
147 |
+ if ((mode = get_mode(avctx)) > 0) |
|
148 |
+ s->mode = mode; |
|
149 |
+ else |
|
150 |
+ s->mode = s->mode != 30 ? 20 : 30; |
|
151 |
+ WebRtcIlbcfix_InitEncode(&s->encoder, s->mode); |
|
152 |
+ |
|
153 |
+ avctx->block_align = s->encoder.no_of_bytes; |
|
154 |
+ avctx->frame_size = s->encoder.blockl; |
|
155 |
+#if FF_API_OLD_ENCODE_AUDIO |
|
156 |
+ avctx->coded_frame = avcodec_alloc_frame(); |
|
157 |
+ if (!avctx->coded_frame) |
|
158 |
+ return AVERROR(ENOMEM); |
|
159 |
+#endif |
|
160 |
+ |
|
161 |
+ return 0; |
|
162 |
+} |
|
163 |
+ |
|
164 |
+static av_cold int ilbc_encode_close(AVCodecContext *avctx) |
|
165 |
+{ |
|
166 |
+#if FF_API_OLD_ENCODE_AUDIO |
|
167 |
+ av_freep(&avctx->coded_frame); |
|
168 |
+#endif |
|
169 |
+ return 0; |
|
170 |
+} |
|
171 |
+ |
|
172 |
+static int ilbc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, |
|
173 |
+ const AVFrame *frame, int *got_packet_ptr) |
|
174 |
+{ |
|
175 |
+ ILBCEncContext *s = avctx->priv_data; |
|
176 |
+ int ret; |
|
177 |
+ |
|
178 |
+ if ((ret = ff_alloc_packet(avpkt, 50))) { |
|
179 |
+ av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n"); |
|
180 |
+ return ret; |
|
181 |
+ } |
|
182 |
+ |
|
183 |
+ WebRtcIlbcfix_EncodeImpl((WebRtc_UWord16*) avpkt->data, (const WebRtc_Word16*) frame->data[0], &s->encoder); |
|
184 |
+ |
|
185 |
+ avpkt->size = s->encoder.no_of_bytes; |
|
186 |
+ *got_packet_ptr = 1; |
|
187 |
+ return 0; |
|
188 |
+} |
|
189 |
+ |
|
190 |
+static const AVCodecDefault ilbc_encode_defaults[] = { |
|
191 |
+ { "b", "0" }, |
|
192 |
+ { NULL } |
|
193 |
+}; |
|
194 |
+ |
|
195 |
+AVCodec ff_libilbc_encoder = { |
|
196 |
+ .name = "libilbc", |
|
197 |
+ .type = AVMEDIA_TYPE_AUDIO, |
|
198 |
+ .id = CODEC_ID_ILBC, |
|
199 |
+ .priv_data_size = sizeof(ILBCEncContext), |
|
200 |
+ .init = ilbc_encode_init, |
|
201 |
+ .encode2 = ilbc_encode_frame, |
|
202 |
+ .close = ilbc_encode_close, |
|
203 |
+ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, |
|
204 |
+ AV_SAMPLE_FMT_NONE }, |
|
205 |
+ .long_name = NULL_IF_CONFIG_SMALL("Internet Low Bitrate Codec (iLBC)"), |
|
206 |
+ .defaults = ilbc_encode_defaults, |
|
207 |
+ .priv_class = &ilbc_enc_class, |
|
208 |
+}; |
... | ... |
@@ -514,14 +514,6 @@ static double predict_size(Predictor *p, double q, double var) |
514 | 514 |
return p->coeff*var / (q*p->count); |
515 | 515 |
} |
516 | 516 |
|
517 |
-/* |
|
518 |
-static double predict_qp(Predictor *p, double size, double var) |
|
519 |
-{ |
|
520 |
-//printf("coeff:%f, count:%f, var:%f, size:%f//\n", p->coeff, p->count, var, size); |
|
521 |
- return p->coeff*var / (size*p->count); |
|
522 |
-} |
|
523 |
-*/ |
|
524 |
- |
|
525 | 517 |
static void update_predictor(Predictor *p, double q, double var, double size) |
526 | 518 |
{ |
527 | 519 |
double new_coeff= size*q / (var + 1); |
... | ... |
@@ -561,10 +553,6 @@ static void adaptive_quantization(MpegEncContext *s, double q){ |
561 | 561 |
int mb_y = mb_xy / s->mb_stride; |
562 | 562 |
int mb_distance; |
563 | 563 |
float mb_factor = 0.0; |
564 |
-#if 0 |
|
565 |
- if(spat_cplx < q/3) spat_cplx= q/3; //FIXME finetune |
|
566 |
- if(temp_cplx < q/3) temp_cplx= q/3; //FIXME finetune |
|
567 |
-#endif |
|
568 | 564 |
if(spat_cplx < 4) spat_cplx= 4; //FIXME finetune |
569 | 565 |
if(temp_cplx < 4) temp_cplx= 4; //FIXME finetune |
570 | 566 |
|
... | ... |
@@ -2138,6 +2138,11 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) |
2138 | 2138 |
case 29: return 288; |
2139 | 2139 |
case 37: return 480; |
2140 | 2140 |
} |
2141 |
+ } else if (id == CODEC_ID_ILBC) { |
|
2142 |
+ switch (ba) { |
|
2143 |
+ case 38: return 160; |
|
2144 |
+ case 50: return 240; |
|
2145 |
+ } |
|
2141 | 2146 |
} |
2142 | 2147 |
} |
2143 | 2148 |
|
... | ... |
@@ -32,6 +32,7 @@ |
32 | 32 |
#include "libavutil/audio_fifo.h" |
33 | 33 |
#include "libavutil/avassert.h" |
34 | 34 |
#include "libavutil/avstring.h" |
35 |
+#include "libavutil/float_dsp.h" |
|
35 | 36 |
#include "libavutil/mathematics.h" |
36 | 37 |
#include "libavutil/opt.h" |
37 | 38 |
#include "libavutil/samplefmt.h" |
... | ... |
@@ -152,6 +153,7 @@ static int frame_list_add_frame(FrameList *frame_list, int nb_samples, int64_t p |
152 | 152 |
|
153 | 153 |
typedef struct MixContext { |
154 | 154 |
const AVClass *class; /**< class for AVOptions */ |
155 |
+ AVFloatDSPContext fdsp; |
|
155 | 156 |
|
156 | 157 |
int nb_inputs; /**< number of inputs */ |
157 | 158 |
int active_inputs; /**< number of input currently active */ |
... | ... |
@@ -160,6 +162,7 @@ typedef struct MixContext { |
160 | 160 |
|
161 | 161 |
int nb_channels; /**< number of channels */ |
162 | 162 |
int sample_rate; /**< sample rate */ |
163 |
+ int planar; |
|
163 | 164 |
AVAudioFifo **fifos; /**< audio fifo for each input */ |
164 | 165 |
uint8_t *input_state; /**< current state of each input */ |
165 | 166 |
float *input_scale; /**< mixing scale factor for each input */ |
... | ... |
@@ -224,6 +227,7 @@ static int config_output(AVFilterLink *outlink) |
224 | 224 |
int i; |
225 | 225 |
char buf[64]; |
226 | 226 |
|
227 |
+ s->planar = av_sample_fmt_is_planar(outlink->format); |
|
227 | 228 |
s->sample_rate = outlink->sample_rate; |
228 | 229 |
outlink->time_base = (AVRational){ 1, outlink->sample_rate }; |
229 | 230 |
s->next_pts = AV_NOPTS_VALUE; |
... | ... |
@@ -264,14 +268,6 @@ static int config_output(AVFilterLink *outlink) |
264 | 264 |
return 0; |
265 | 265 |
} |
266 | 266 |
|
267 |
-/* TODO: move optimized version from DSPContext to libavutil */ |
|
268 |
-static void vector_fmac_scalar(float *dst, const float *src, float mul, int len) |
|
269 |
-{ |
|
270 |
- int i; |
|
271 |
- for (i = 0; i < len; i++) |
|
272 |
- dst[i] += src[i] * mul; |
|
273 |
-} |
|
274 |
- |
|
275 | 267 |
/** |
276 | 268 |
* Read samples from the input FIFOs, mix, and write to the output link. |
277 | 269 |
*/ |
... | ... |
@@ -294,11 +290,20 @@ static int output_frame(AVFilterLink *outlink, int nb_samples) |
294 | 294 |
|
295 | 295 |
for (i = 0; i < s->nb_inputs; i++) { |
296 | 296 |
if (s->input_state[i] == INPUT_ON) { |
297 |
+ int planes, plane_size, p; |
|
298 |
+ |
|
297 | 299 |
av_audio_fifo_read(s->fifos[i], (void **)in_buf->extended_data, |
298 | 300 |
nb_samples); |
299 |
- vector_fmac_scalar((float *)out_buf->extended_data[0], |
|
300 |
- (float *) in_buf->extended_data[0], |
|
301 |
- s->input_scale[i], nb_samples * s->nb_channels); |
|
301 |
+ |
|
302 |
+ planes = s->planar ? s->nb_channels : 1; |
|
303 |
+ plane_size = nb_samples * (s->planar ? 1 : s->nb_channels); |
|
304 |
+ plane_size = FFALIGN(plane_size, 16); |
|
305 |
+ |
|
306 |
+ for (p = 0; p < planes; p++) { |
|
307 |
+ s->fdsp.vector_fmac_scalar((float *)out_buf->extended_data[p], |
|
308 |
+ (float *) in_buf->extended_data[p], |
|
309 |
+ s->input_scale[i], plane_size); |
|
310 |
+ } |
|
302 | 311 |
} |
303 | 312 |
} |
304 | 313 |
avfilter_unref_buffer(in_buf); |
... | ... |
@@ -501,6 +506,8 @@ static int init(AVFilterContext *ctx, const char *args, void *opaque) |
501 | 501 |
ff_insert_inpad(ctx, i, &pad); |
502 | 502 |
} |
503 | 503 |
|
504 |
+ avpriv_float_dsp_init(&s->fdsp, 0); |
|
505 |
+ |
|
504 | 506 |
return 0; |
505 | 507 |
} |
506 | 508 |
|
... | ... |
@@ -527,6 +534,7 @@ static int query_formats(AVFilterContext *ctx) |
527 | 527 |
{ |
528 | 528 |
AVFilterFormats *formats = NULL; |
529 | 529 |
ff_add_format(&formats, AV_SAMPLE_FMT_FLT); |
530 |
+ ff_add_format(&formats, AV_SAMPLE_FMT_FLTP); |
|
530 | 531 |
ff_set_common_formats(ctx, formats); |
531 | 532 |
ff_set_common_channel_layouts(ctx, ff_all_channel_layouts()); |
532 | 533 |
ff_set_common_samplerates(ctx, ff_all_samplerates()); |
... | ... |
@@ -123,6 +123,8 @@ OBJS-$(CONFIG_ICO_DEMUXER) += icodec.o |
123 | 123 |
OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o |
124 | 124 |
OBJS-$(CONFIG_IDF_DEMUXER) += bintext.o |
125 | 125 |
OBJS-$(CONFIG_IFF_DEMUXER) += iff.o |
126 |
+OBJS-$(CONFIG_ILBC_DEMUXER) += ilbc.o |
|
127 |
+OBJS-$(CONFIG_ILBC_MUXER) += ilbc.o |
|
126 | 128 |
OBJS-$(CONFIG_IMAGE2_DEMUXER) += img2dec.o img2.o |
127 | 129 |
OBJS-$(CONFIG_IMAGE2_MUXER) += img2enc.o img2.o |
128 | 130 |
OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER) += img2dec.o img2.o |
... | ... |
@@ -281,6 +283,7 @@ OBJS-$(CONFIG_RTPDEC) += rdt.o \ |
281 | 281 |
rtpdec_h263.o \ |
282 | 282 |
rtpdec_h263_rfc2190.o \ |
283 | 283 |
rtpdec_h264.o \ |
284 |
+ rtpdec_ilbc.o \ |
|
284 | 285 |
rtpdec_latm.o \ |
285 | 286 |
rtpdec_mpeg4.o \ |
286 | 287 |
rtpdec_qcelp.o \ |
... | ... |
@@ -116,6 +116,7 @@ void av_register_all(void) |
116 | 116 |
REGISTER_DEMUXER (IDCIN, idcin); |
117 | 117 |
REGISTER_DEMUXER (IDF, idf); |
118 | 118 |
REGISTER_DEMUXER (IFF, iff); |
119 |
+ REGISTER_MUXDEMUX (ILBC, ilbc); |
|
119 | 120 |
REGISTER_MUXDEMUX (IMAGE2, image2); |
120 | 121 |
REGISTER_MUXDEMUX (IMAGE2PIPE, image2pipe); |
121 | 122 |
REGISTER_DEMUXER (INGENIENT, ingenient); |
... | ... |
@@ -759,33 +759,6 @@ static int flv_read_seek(AVFormatContext *s, int stream_index, |
759 | 759 |
return avio_seek_time(s->pb, stream_index, ts, flags); |
760 | 760 |
} |
761 | 761 |
|
762 |
-#if 0 /* don't know enough to implement this */ |
|
763 |
-static int flv_read_seek2(AVFormatContext *s, int stream_index, |
|
764 |
- int64_t min_ts, int64_t ts, int64_t max_ts, int flags) |
|
765 |
-{ |
|
766 |
- int ret = AVERROR(ENOSYS); |
|
767 |
- |
|
768 |
- if (ts - min_ts > (uint64_t)(max_ts - ts)) flags |= AVSEEK_FLAG_BACKWARD; |
|
769 |
- |
|
770 |
- if (!s->pb->seekable) { |
|
771 |
- if (stream_index < 0) { |
|
772 |
- stream_index = av_find_default_stream_index(s); |
|
773 |
- if (stream_index < 0) |
|
774 |
- return -1; |
|
775 |
- |
|
776 |
- /* timestamp for default must be expressed in AV_TIME_BASE units */ |
|
777 |
- ts = av_rescale_rnd(ts, 1000, AV_TIME_BASE, |
|
778 |
- flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); |
|
779 |
- } |
|
780 |
- ret = avio_seek_time(s->pb, stream_index, ts, flags); |
|
781 |
- } |
|
782 |
- |
|
783 |
- if (ret == AVERROR(ENOSYS)) |
|
784 |
- ret = av_seek_frame(s, stream_index, ts, flags); |
|
785 |
- return ret; |
|
786 |
-} |
|
787 |
-#endif |
|
788 |
- |
|
789 | 762 |
AVInputFormat ff_flv_demuxer = { |
790 | 763 |
.name = "flv", |
791 | 764 |
.long_name = NULL_IF_CONFIG_SMALL("FLV format"), |
... | ... |
@@ -794,9 +767,6 @@ AVInputFormat ff_flv_demuxer = { |
794 | 794 |
.read_header = flv_read_header, |
795 | 795 |
.read_packet = flv_read_packet, |
796 | 796 |
.read_seek = flv_read_seek, |
797 |
-#if 0 |
|
798 |
- .read_seek2 = flv_read_seek2, |
|
799 |
-#endif |
|
800 | 797 |
.read_close = flv_read_close, |
801 | 798 |
.extensions = "flv", |
802 | 799 |
}; |
... | ... |
@@ -308,15 +308,15 @@ static int process_line(URLContext *h, char *line, int line_count, |
308 | 308 |
strcpy(s->location, p); |
309 | 309 |
*new_location = 1; |
310 | 310 |
} else if (!av_strcasecmp (tag, "Content-Length") && s->filesize == -1) { |
311 |
- s->filesize = atoll(p); |
|
311 |
+ s->filesize = strtoll(p, NULL, 10); |
|
312 | 312 |
} else if (!av_strcasecmp (tag, "Content-Range")) { |
313 | 313 |
/* "bytes $from-$to/$document_size" */ |
314 | 314 |
const char *slash; |
315 | 315 |
if (!strncmp (p, "bytes ", 6)) { |
316 | 316 |
p += 6; |
317 |
- s->off = atoll(p); |
|
317 |
+ s->off = strtoll(p, NULL, 10); |
|
318 | 318 |
if ((slash = strchr(p, '/')) && strlen(slash) > 0) |
319 |
- s->filesize = atoll(slash+1); |
|
319 |
+ s->filesize = strtoll(slash+1, NULL, 10); |
|
320 | 320 |
} |
321 | 321 |
h->is_streamed = 0; /* we _can_ in fact seek */ |
322 | 322 |
} else if (!av_strcasecmp(tag, "Accept-Ranges") && !strncmp(p, "bytes", 5)) { |
323 | 323 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,141 @@ |
0 |
+/* |
|
1 |
+ * iLBC storage file format |
|
2 |
+ * Copyright (c) 2012 Martin Storsjo |
|
3 |
+ * |
|
4 |
+ * This file is part of FFmpeg. |
|
5 |
+ * |
|
6 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
7 |
+ * modify it under the terms of the GNU Lesser General Public |
|
8 |
+ * License as published by the Free Software Foundation; either |
|
9 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
10 |
+ * |
|
11 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
12 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 |
+ * Lesser General Public License for more details. |
|
15 |
+ * |
|
16 |
+ * You should have received a copy of the GNU Lesser General Public |
|
17 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
19 |
+ */ |
|
20 |
+ |
|
21 |
+#include "avformat.h" |
|
22 |
+#include "internal.h" |
|
23 |
+ |
|
24 |
+static const char mode20_header[] = "#!iLBC20\n"; |
|
25 |
+static const char mode30_header[] = "#!iLBC30\n"; |
|
26 |
+ |
|
27 |
+static int ilbc_write_header(AVFormatContext *s) |
|
28 |
+{ |
|
29 |
+ AVIOContext *pb = s->pb; |
|
30 |
+ AVCodecContext *enc; |
|
31 |
+ |
|
32 |
+ if (s->nb_streams != 1) { |
|
33 |
+ av_log(s, AV_LOG_ERROR, "Unsupported number of streams\n"); |
|
34 |
+ return AVERROR(EINVAL); |
|
35 |
+ } |
|
36 |
+ enc = s->streams[0]->codec; |
|
37 |
+ |
|
38 |
+ if (enc->codec_id != CODEC_ID_ILBC) { |
|
39 |
+ av_log(s, AV_LOG_ERROR, "Unsupported codec\n"); |
|
40 |
+ return AVERROR(EINVAL); |
|
41 |
+ } |
|
42 |
+ |
|
43 |
+ if (enc->block_align == 50) { |
|
44 |
+ avio_write(pb, mode30_header, sizeof(mode30_header) - 1); |
|
45 |
+ } else if (enc->block_align == 38) { |
|
46 |
+ avio_write(pb, mode20_header, sizeof(mode20_header) - 1); |
|
47 |
+ } else { |
|
48 |
+ av_log(s, AV_LOG_ERROR, "Unsupported mode\n"); |
|
49 |
+ return AVERROR(EINVAL); |
|
50 |
+ } |
|
51 |
+ avio_flush(pb); |
|
52 |
+ return 0; |
|
53 |
+} |
|
54 |
+ |
|
55 |
+static int ilbc_write_packet(AVFormatContext *s, AVPacket *pkt) |
|
56 |
+{ |
|
57 |
+ avio_write(s->pb, pkt->data, pkt->size); |
|
58 |
+ avio_flush(s->pb); |
|
59 |
+ return 0; |
|
60 |
+} |
|
61 |
+ |
|
62 |
+static int ilbc_probe(AVProbeData *p) |
|
63 |
+{ |
|
64 |
+ // Only check for "#!iLBC" which matches both formats |
|
65 |
+ if (!memcmp(p->buf, mode20_header, 6)) |
|
66 |
+ return AVPROBE_SCORE_MAX; |
|
67 |
+ else |
|
68 |
+ return 0; |
|
69 |
+} |
|
70 |
+ |
|
71 |
+static int ilbc_read_header(AVFormatContext *s) |
|
72 |
+{ |
|
73 |
+ AVIOContext *pb = s->pb; |
|
74 |
+ AVStream *st; |
|
75 |
+ uint8_t header[9]; |
|
76 |
+ |
|
77 |
+ avio_read(pb, header, 9); |
|
78 |
+ |
|
79 |
+ st = avformat_new_stream(s, NULL); |
|
80 |
+ if (!st) |
|
81 |
+ return AVERROR(ENOMEM); |
|
82 |
+ st->codec->codec_id = CODEC_ID_ILBC; |
|
83 |
+ st->codec->sample_rate = 8000; |
|
84 |
+ st->codec->channels = 1; |
|
85 |
+ st->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
|
86 |
+ st->start_time = 0; |
|
87 |
+ avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); |
|
88 |
+ if (!memcmp(header, mode20_header, sizeof(mode20_header) - 1)) { |
|
89 |
+ st->codec->block_align = 38; |
|
90 |
+ st->codec->bit_rate = 15200; |
|
91 |
+ } else if (!memcmp(header, mode30_header, sizeof(mode30_header) - 1)) { |
|
92 |
+ st->codec->block_align = 50; |
|
93 |
+ st->codec->bit_rate = 13333; |
|
94 |
+ } else { |
|
95 |
+ av_log(s, AV_LOG_ERROR, "Unrecognized iLBC file header\n"); |
|
96 |
+ return AVERROR_INVALIDDATA; |
|
97 |
+ } |
|
98 |
+ |
|
99 |
+ return 0; |
|
100 |
+} |
|
101 |
+ |
|
102 |
+static int ilbc_read_packet(AVFormatContext *s, |
|
103 |
+ AVPacket *pkt) |
|
104 |
+{ |
|
105 |
+ AVCodecContext *enc = s->streams[0]->codec; |
|
106 |
+ int ret; |
|
107 |
+ |
|
108 |
+ if ((ret = av_new_packet(pkt, enc->block_align)) < 0) |
|
109 |
+ return ret; |
|
110 |
+ |
|
111 |
+ pkt->stream_index = 0; |
|
112 |
+ pkt->pos = avio_tell(s->pb); |
|
113 |
+ pkt->duration = enc->block_align == 38 ? 160 : 240; |
|
114 |
+ if ((ret = avio_read(s->pb, pkt->data, enc->block_align)) != enc->block_align) { |
|
115 |
+ av_free_packet(pkt); |
|
116 |
+ return ret < 0 ? ret : AVERROR(EIO); |
|
117 |
+ } |
|
118 |
+ |
|
119 |
+ return 0; |
|
120 |
+} |
|
121 |
+ |
|
122 |
+AVInputFormat ff_ilbc_demuxer = { |
|
123 |
+ .name = "ilbc", |
|
124 |
+ .long_name = NULL_IF_CONFIG_SMALL("iLBC storage file format"), |
|
125 |
+ .read_probe = ilbc_probe, |
|
126 |
+ .read_header = ilbc_read_header, |
|
127 |
+ .read_packet = ilbc_read_packet, |
|
128 |
+ .flags = AVFMT_GENERIC_INDEX, |
|
129 |
+}; |
|
130 |
+ |
|
131 |
+AVOutputFormat ff_ilbc_muxer = { |
|
132 |
+ .name = "ilbc", |
|
133 |
+ .long_name = NULL_IF_CONFIG_SMALL("iLBC storage file format"), |
|
134 |
+ .mime_type = "audio/iLBC", |
|
135 |
+ .extensions = "lbc", |
|
136 |
+ .audio_codec = CODEC_ID_ILBC, |
|
137 |
+ .write_header = ilbc_write_header, |
|
138 |
+ .write_packet = ilbc_write_packet, |
|
139 |
+ .flags = AVFMT_NOTIMESTAMPS, |
|
140 |
+}; |
... | ... |
@@ -259,6 +259,7 @@ const AVCodecTag ff_codec_movaudio_tags[] = { |
259 | 259 |
{ CODEC_ID_DVAUDIO, MKTAG('v', 'd', 'v', 'a') }, |
260 | 260 |
{ CODEC_ID_DVAUDIO, MKTAG('d', 'v', 'c', 'a') }, |
261 | 261 |
{ CODEC_ID_GSM, MKTAG('a', 'g', 's', 'm') }, |
262 |
+ { CODEC_ID_ILBC, MKTAG('i', 'l', 'b', 'c') }, |
|
262 | 263 |
{ CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') }, |
263 | 264 |
{ CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') }, |
264 | 265 |
{ CODEC_ID_MP1, MKTAG('.', 'm', 'p', '1') }, |
... | ... |
@@ -1540,6 +1540,7 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) |
1540 | 1540 |
case CODEC_ID_GSM: |
1541 | 1541 |
case CODEC_ID_ADPCM_MS: |
1542 | 1542 |
case CODEC_ID_ADPCM_IMA_WAV: |
1543 |
+ case CODEC_ID_ILBC: |
|
1543 | 1544 |
st->codec->block_align = sc->bytes_per_frame; |
1544 | 1545 |
break; |
1545 | 1546 |
case CODEC_ID_ALAC: |
... | ... |
@@ -3371,7 +3371,8 @@ static int mov_write_header(AVFormatContext *s) |
3371 | 3371 |
av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i); |
3372 | 3372 |
track->audio_vbr = 1; |
3373 | 3373 |
}else if(st->codec->codec_id == CODEC_ID_ADPCM_MS || |
3374 |
- st->codec->codec_id == CODEC_ID_ADPCM_IMA_WAV){ |
|
3374 |
+ st->codec->codec_id == CODEC_ID_ADPCM_IMA_WAV || |
|
3375 |
+ st->codec->codec_id == CODEC_ID_ILBC){ |
|
3375 | 3376 |
if (!st->codec->block_align) { |
3376 | 3377 |
av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i); |
3377 | 3378 |
goto error; |
... | ... |
@@ -19,8 +19,6 @@ |
19 | 19 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | 20 |
*/ |
21 | 21 |
|
22 |
-//#define USE_SYNCPOINT_SEARCH |
|
23 |
- |
|
24 | 22 |
#include "libavutil/crc.h" |
25 | 23 |
#include "libavutil/intreadwrite.h" |
26 | 24 |
#include "libavutil/log.h" |
... | ... |
@@ -2161,92 +2159,6 @@ static int64_t mpegts_get_dts(AVFormatContext *s, int stream_index, |
2161 | 2161 |
return AV_NOPTS_VALUE; |
2162 | 2162 |
} |
2163 | 2163 |
|
2164 |
-#ifdef USE_SYNCPOINT_SEARCH |
|
2165 |
- |
|
2166 |
-static int read_seek2(AVFormatContext *s, |
|
2167 |
- int stream_index, |
|
2168 |
- int64_t min_ts, |
|
2169 |
- int64_t target_ts, |
|
2170 |
- int64_t max_ts, |
|
2171 |
- int flags) |
|
2172 |
-{ |
|
2173 |
- int64_t pos; |
|
2174 |
- |
|
2175 |
- int64_t ts_ret, ts_adj; |
|
2176 |
- int stream_index_gen_search; |
|
2177 |
- AVStream *st; |
|
2178 |
- AVParserState *backup; |
|
2179 |
- |
|
2180 |
- backup = ff_store_parser_state(s); |
|
2181 |
- |
|
2182 |
- // detect direction of seeking for search purposes |
|
2183 |
- flags |= (target_ts - min_ts > (uint64_t)(max_ts - target_ts)) ? |
|
2184 |
- AVSEEK_FLAG_BACKWARD : 0; |
|
2185 |
- |
|
2186 |
- if (flags & AVSEEK_FLAG_BYTE) { |
|
2187 |
- // use position directly, we will search starting from it |
|
2188 |
- pos = target_ts; |
|
2189 |
- } else { |
|
2190 |
- // search for some position with good timestamp match |
|
2191 |
- if (stream_index < 0) { |
|
2192 |
- stream_index_gen_search = av_find_default_stream_index(s); |
|
2193 |
- if (stream_index_gen_search < 0) { |
|
2194 |
- ff_restore_parser_state(s, backup); |
|
2195 |
- return -1; |
|
2196 |
- } |
|
2197 |
- |
|
2198 |
- st = s->streams[stream_index_gen_search]; |
|
2199 |
- // timestamp for default must be expressed in AV_TIME_BASE units |
|
2200 |
- ts_adj = av_rescale(target_ts, |
|
2201 |
- st->time_base.den, |
|
2202 |
- AV_TIME_BASE * (int64_t)st->time_base.num); |
|
2203 |
- } else { |
|
2204 |
- ts_adj = target_ts; |
|
2205 |
- stream_index_gen_search = stream_index; |
|
2206 |
- } |
|
2207 |
- pos = ff_gen_search(s, stream_index_gen_search, ts_adj, |
|
2208 |
- 0, INT64_MAX, -1, |
|
2209 |
- AV_NOPTS_VALUE, |
|
2210 |
- AV_NOPTS_VALUE, |
|
2211 |
- flags, &ts_ret, mpegts_get_pcr); |
|
2212 |
- if (pos < 0) { |
|
2213 |
- ff_restore_parser_state(s, backup); |
|
2214 |
- return -1; |
|
2215 |
- } |
|
2216 |
- } |
|
2217 |
- |
|
2218 |
- // search for actual matching keyframe/starting position for all streams |
|
2219 |
- if (ff_gen_syncpoint_search(s, stream_index, pos, |
|
2220 |
- min_ts, target_ts, max_ts, |
|
2221 |
- flags) < 0) { |
|
2222 |
- ff_restore_parser_state(s, backup); |
|
2223 |
- return -1; |
|
2224 |
- } |
|
2225 |
- |
|
2226 |
- ff_free_parser_state(s, backup); |
|
2227 |
- return 0; |
|
2228 |
-} |
|
2229 |
- |
|
2230 |
-static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags) |
|
2231 |
-{ |
|
2232 |
- int ret; |
|
2233 |
- if (flags & AVSEEK_FLAG_BACKWARD) { |
|
2234 |
- flags &= ~AVSEEK_FLAG_BACKWARD; |
|
2235 |
- ret = read_seek2(s, stream_index, INT64_MIN, target_ts, target_ts, flags); |
|
2236 |
- if (ret < 0) |
|
2237 |
- // for compatibility reasons, seek to the best-fitting timestamp |
|
2238 |
- ret = read_seek2(s, stream_index, INT64_MIN, target_ts, INT64_MAX, flags); |
|
2239 |
- } else { |
|
2240 |
- ret = read_seek2(s, stream_index, target_ts, target_ts, INT64_MAX, flags); |
|
2241 |
- if (ret < 0) |
|
2242 |
- // for compatibility reasons, seek to the best-fitting timestamp |
|
2243 |
- ret = read_seek2(s, stream_index, INT64_MIN, target_ts, INT64_MAX, flags); |
|
2244 |
- } |
|
2245 |
- return ret; |
|
2246 |
-} |
|
2247 |
- |
|
2248 |
-#endif |
|
2249 |
- |
|
2250 | 2164 |
/**************************************************************/ |
2251 | 2165 |
/* parsing functions - called from other demuxers such as RTP */ |
2252 | 2166 |
|
... | ... |
@@ -2313,9 +2225,6 @@ AVInputFormat ff_mpegts_demuxer = { |
2313 | 2313 |
.read_close = mpegts_read_close, |
2314 | 2314 |
.read_timestamp = mpegts_get_dts, |
2315 | 2315 |
.flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, |
2316 |
-#ifdef USE_SYNCPOINT_SEARCH |
|
2317 |
- .read_seek2 = read_seek2, |
|
2318 |
-#endif |
|
2319 | 2316 |
}; |
2320 | 2317 |
|
2321 | 2318 |
AVInputFormat ff_mpegtsraw_demuxer = { |
... | ... |
@@ -2327,8 +2236,5 @@ AVInputFormat ff_mpegtsraw_demuxer = { |
2327 | 2327 |
.read_close = mpegts_read_close, |
2328 | 2328 |
.read_timestamp = mpegts_get_dts, |
2329 | 2329 |
.flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, |
2330 |
-#ifdef USE_SYNCPOINT_SEARCH |
|
2331 |
- .read_seek2 = read_seek2, |
|
2332 |
-#endif |
|
2333 | 2330 |
.priv_class = &mpegtsraw_class, |
2334 | 2331 |
}; |
... | ... |
@@ -76,6 +76,7 @@ typedef struct RTMPContext { |
76 | 76 |
uint8_t* flv_data; ///< buffer with data for demuxer |
77 | 77 |
int flv_size; ///< current buffer size |
78 | 78 |
int flv_off; ///< number of bytes read from current buffer |
79 |
+ int flv_nb_packets; ///< number of flv packets published |
|
79 | 80 |
RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output) |
80 | 81 |
uint32_t client_report_size; ///< number of bytes after which client should report to server |
81 | 82 |
uint32_t bytes_read; ///< number of bytes read from server |
... | ... |
@@ -90,6 +91,7 @@ typedef struct RTMPContext { |
90 | 90 |
char* swfurl; ///< url of the swf player |
91 | 91 |
int server_bw; ///< server bandwidth |
92 | 92 |
int client_buffer_time; ///< client buffer time in ms |
93 |
+ int flush_interval; ///< number of packets flushed in the same request (RTMPT only) |
|
93 | 94 |
} RTMPContext; |
94 | 95 |
|
95 | 96 |
#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) |
1361 | 1361 |
rt->flv_size = 0; |
1362 | 1362 |
rt->flv_off = 0; |
1363 | 1363 |
rt->flv_header_bytes = 0; |
1364 |
+ rt->flv_nb_packets++; |
|
1364 | 1365 |
} |
1365 | 1366 |
} while (buf_temp - buf < size); |
1366 | 1367 |
|
1368 |
+ if (rt->flv_nb_packets < rt->flush_interval) |
|
1369 |
+ return size; |
|
1370 |
+ rt->flv_nb_packets = 0; |
|
1371 |
+ |
|
1367 | 1372 |
/* set stream into nonblocking mode */ |
1368 | 1373 |
rt->stream->flags |= AVIO_FLAG_NONBLOCK; |
1369 | 1374 |
|
... | ... |
@@ -1404,6 +1411,7 @@ static const AVOption rtmp_options[] = { |
1404 | 1404 |
{"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}, |
1405 | 1405 |
{"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, |
1406 | 1406 |
{"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}, |
1407 |
+ {"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}, |
|
1407 | 1408 |
{"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"}, |
1408 | 1409 |
{"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"}, |
1409 | 1410 |
{"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) |
68 | 68 |
ff_register_dynamic_payload_handler(&ff_h263_2000_dynamic_handler); |
69 | 69 |
ff_register_dynamic_payload_handler(&ff_h263_rfc2190_dynamic_handler); |
70 | 70 |
ff_register_dynamic_payload_handler(&ff_h264_dynamic_handler); |
71 |
+ ff_register_dynamic_payload_handler(&ff_ilbc_dynamic_handler); |
|
71 | 72 |
ff_register_dynamic_payload_handler(&ff_vorbis_dynamic_handler); |
72 | 73 |
ff_register_dynamic_payload_handler(&ff_theora_dynamic_handler); |
73 | 74 |
ff_register_dynamic_payload_handler(&ff_qdm2_dynamic_handler); |
... | ... |
@@ -45,6 +45,7 @@ extern RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler; |
45 | 45 |
extern RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler; |
46 | 46 |
extern RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler; |
47 | 47 |
extern RTPDynamicProtocolHandler ff_h264_dynamic_handler; |
48 |
+extern RTPDynamicProtocolHandler ff_ilbc_dynamic_handler; |
|
48 | 49 |
extern RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler; |
49 | 50 |
extern RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler; |
50 | 51 |
extern RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler; |
51 | 52 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,73 @@ |
0 |
+/* |
|
1 |
+ * RTP iLBC Depacketizer, RFC 3952 |
|
2 |
+ * Copyright (c) 2012 Martin Storsjo |
|
3 |
+ * |
|
4 |
+ * This file is part of FFmpeg. |
|
5 |
+ * |
|
6 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
7 |
+ * modify it under the terms of the GNU Lesser General Public |
|
8 |
+ * License as published by the Free Software Foundation; either |
|
9 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
10 |
+ * |
|
11 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
12 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 |
+ * Lesser General Public License for more details. |
|
15 |
+ * |
|
16 |
+ * You should have received a copy of the GNU Lesser General Public |
|
17 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
19 |
+ */ |
|
20 |
+ |
|
21 |
+#include "avformat.h" |
|
22 |
+#include "rtpdec_formats.h" |
|
23 |
+#include "libavutil/avstring.h" |
|
24 |
+ |
|
25 |
+static int ilbc_parse_fmtp(AVStream *stream, PayloadContext *data, |
|
26 |
+ char *attr, char *value) |
|
27 |
+{ |
|
28 |
+ if (!strcmp(attr, "mode")) { |
|
29 |
+ int mode = atoi(value); |
|
30 |
+ switch (mode) { |
|
31 |
+ case 20: |
|
32 |
+ stream->codec->block_align = 38; |
|
33 |
+ break; |
|
34 |
+ case 30: |
|
35 |
+ stream->codec->block_align = 50; |
|
36 |
+ break; |
|
37 |
+ default: |
|
38 |
+ av_log(NULL, AV_LOG_ERROR, "Unsupported iLBC mode %d\n", mode); |
|
39 |
+ return AVERROR(EINVAL); |
|
40 |
+ } |
|
41 |
+ } |
|
42 |
+ return 0; |
|
43 |
+} |
|
44 |
+ |
|
45 |
+static int ilbc_parse_sdp_line(AVFormatContext *s, int st_index, |
|
46 |
+ PayloadContext *data, const char *line) |
|
47 |
+{ |
|
48 |
+ const char *p; |
|
49 |
+ AVStream *st; |
|
50 |
+ |
|
51 |
+ if (st_index < 0) |
|
52 |
+ return 0; |
|
53 |
+ st = s->streams[st_index]; |
|
54 |
+ |
|
55 |
+ if (av_strstart(line, "fmtp:", &p)) { |
|
56 |
+ int ret = ff_parse_fmtp(st, data, p, ilbc_parse_fmtp); |
|
57 |
+ if (ret < 0) |
|
58 |
+ return ret; |
|
59 |
+ if (!st->codec->block_align) { |
|
60 |
+ av_log(s, AV_LOG_ERROR, "No iLBC mode set\n"); |
|
61 |
+ return AVERROR(EINVAL); |
|
62 |
+ } |
|
63 |
+ } |
|
64 |
+ return 0; |
|
65 |
+} |
|
66 |
+ |
|
67 |
+RTPDynamicProtocolHandler ff_ilbc_dynamic_handler = { |
|
68 |
+ .enc_name = "iLBC", |
|
69 |
+ .codec_type = AVMEDIA_TYPE_AUDIO, |
|
70 |
+ .codec_id = CODEC_ID_ILBC, |
|
71 |
+ .parse_sdp_a_line = ilbc_parse_sdp_line, |
|
72 |
+}; |
... | ... |
@@ -74,6 +74,7 @@ static int is_supported(enum CodecID id) |
74 | 74 |
case CODEC_ID_VP8: |
75 | 75 |
case CODEC_ID_ADPCM_G722: |
76 | 76 |
case CODEC_ID_ADPCM_G726: |
77 |
+ case CODEC_ID_ILBC: |
|
77 | 78 |
return 1; |
78 | 79 |
default: |
79 | 80 |
return 0; |
... | ... |
@@ -187,6 +188,16 @@ static int rtp_write_header(AVFormatContext *s1) |
187 | 187 |
* 8000, even if the sample rate is 16000. See RFC 3551. */ |
188 | 188 |
avpriv_set_pts_info(st, 32, 1, 8000); |
189 | 189 |
break; |
190 |
+ case CODEC_ID_ILBC: |
|
191 |
+ if (st->codec->block_align != 38 && st->codec->block_align != 50) { |
|
192 |
+ av_log(s1, AV_LOG_ERROR, "Incorrect iLBC block size specified\n"); |
|
193 |
+ goto fail; |
|
194 |
+ } |
|
195 |
+ if (!s->max_frames_per_packet) |
|
196 |
+ s->max_frames_per_packet = 1; |
|
197 |
+ s->max_frames_per_packet = FFMIN(s->max_frames_per_packet, |
|
198 |
+ s->max_payload_size / st->codec->block_align); |
|
199 |
+ goto defaultcase; |
|
190 | 200 |
case CODEC_ID_AMR_NB: |
191 | 201 |
case CODEC_ID_AMR_WB: |
192 | 202 |
if (!s->max_frames_per_packet) |
... | ... |
@@ -395,6 +406,36 @@ static void rtp_send_mpegts_raw(AVFormatContext *s1, |
395 | 395 |
} |
396 | 396 |
} |
397 | 397 |
|
398 |
+static int rtp_send_ilbc(AVFormatContext *s1, const uint8_t *buf, int size) |
|
399 |
+{ |
|
400 |
+ RTPMuxContext *s = s1->priv_data; |
|
401 |
+ AVStream *st = s1->streams[0]; |
|
402 |
+ int frame_duration = av_get_audio_frame_duration(st->codec, 0); |
|
403 |
+ int frame_size = st->codec->block_align; |
|
404 |
+ int frames = size / frame_size; |
|
405 |
+ |
|
406 |
+ while (frames > 0) { |
|
407 |
+ int n = FFMIN(s->max_frames_per_packet - s->num_frames, frames); |
|
408 |
+ |
|
409 |
+ if (!s->num_frames) { |
|
410 |
+ s->buf_ptr = s->buf; |
|
411 |
+ s->timestamp = s->cur_timestamp; |
|
412 |
+ } |
|
413 |
+ memcpy(s->buf_ptr, buf, n * frame_size); |
|
414 |
+ frames -= n; |
|
415 |
+ s->num_frames += n; |
|
416 |
+ s->buf_ptr += n * frame_size; |
|
417 |
+ buf += n * frame_size; |
|
418 |
+ s->cur_timestamp += n * frame_duration; |
|
419 |
+ |
|
420 |
+ if (s->num_frames == s->max_frames_per_packet) { |
|
421 |
+ ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 1); |
|
422 |
+ s->num_frames = 0; |
|
423 |
+ } |
|
424 |
+ } |
|
425 |
+ return 0; |
|
426 |
+} |
|
427 |
+ |
|
398 | 428 |
static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) |
399 | 429 |
{ |
400 | 430 |
RTPMuxContext *s = s1->priv_data; |
... | ... |
@@ -483,6 +524,9 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) |
483 | 483 |
case CODEC_ID_VP8: |
484 | 484 |
ff_rtp_send_vp8(s1, pkt->data, size); |
485 | 485 |
break; |
486 |
+ case CODEC_ID_ILBC: |
|
487 |
+ rtp_send_ilbc(s1, pkt->data, size); |
|
488 |
+ break; |
|
486 | 489 |
default: |
487 | 490 |
/* better than nothing : send the codec raw data */ |
488 | 491 |
rtp_send_raw(s1, pkt->data, size); |
... | ... |
@@ -1279,7 +1279,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, |
1279 | 1279 |
"%s/UDP;multicast", trans_pref); |
1280 | 1280 |
} |
1281 | 1281 |
if (s->oformat) { |
1282 |
- av_strlcat(transport, ";mode=receive", sizeof(transport)); |
|
1282 |
+ av_strlcat(transport, ";mode=record", sizeof(transport)); |
|
1283 | 1283 |
} else if (rt->server_type == RTSP_SERVER_REAL || |
1284 | 1284 |
rt->server_type == RTSP_SERVER_WMS) |
1285 | 1285 |
av_strlcat(transport, ";mode=play", sizeof(transport)); |
... | ... |
@@ -549,6 +549,12 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, |
549 | 549 |
c->sample_rate); |
550 | 550 |
break; |
551 | 551 |
} |
552 |
+ case CODEC_ID_ILBC: |
|
553 |
+ av_strlcatf(buff, size, "a=rtpmap:%d iLBC/%d\r\n" |
|
554 |
+ "a=fmtp:%d mode=%d\r\n", |
|
555 |
+ payload_type, c->sample_rate, |
|
556 |
+ payload_type, c->block_align == 38 ? 20 : 30); |
|
557 |
+ break; |
|
552 | 558 |
default: |
553 | 559 |
/* Nothing special to do here... */ |
554 | 560 |
break; |
... | ... |
@@ -30,7 +30,7 @@ |
30 | 30 |
#include "libavutil/avutil.h" |
31 | 31 |
|
32 | 32 |
#define LIBAVFORMAT_VERSION_MAJOR 54 |
33 |
-#define LIBAVFORMAT_VERSION_MINOR 8 |
|
33 |
+#define LIBAVFORMAT_VERSION_MINOR 9 |
|
34 | 34 |
#define LIBAVFORMAT_VERSION_MICRO 100 |
35 | 35 |
|
36 | 36 |
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ |
... | ... |
@@ -1,6 +1,7 @@ |
1 | 1 |
;****************************************************************************** |
2 | 2 |
;* x86 optimized Format Conversion Utils |
3 | 3 |
;* Copyright (c) 2008 Loren Merritt |
4 |
+;* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com> |
|
4 | 5 |
;* |
5 | 6 |
;* This file is part of Libav. |
6 | 7 |
;* |
... | ... |
@@ -21,9 +22,217 @@ |
21 | 21 |
|
22 | 22 |
%include "x86inc.asm" |
23 | 23 |
%include "x86util.asm" |
24 |
+%include "util.asm" |
|
25 |
+ |
|
26 |
+SECTION_RODATA 32 |
|
27 |
+ |
|
28 |
+pf_s32_inv_scale: times 8 dd 0x30000000 |
|
29 |
+pf_s32_scale: times 8 dd 0x4f000000 |
|
30 |
+pf_s16_inv_scale: times 4 dd 0x38000000 |
|
31 |
+pf_s16_scale: times 4 dd 0x47000000 |
|
24 | 32 |
|
25 | 33 |
SECTION_TEXT |
26 | 34 |
|
35 |
+;------------------------------------------------------------------------------ |
|
36 |
+; void ff_conv_s16_to_s32(int32_t *dst, const int16_t *src, int len); |
|
37 |
+;------------------------------------------------------------------------------ |
|
38 |
+ |
|
39 |
+INIT_XMM sse2 |
|
40 |
+cglobal conv_s16_to_s32, 3,3,3, dst, src, len |
|
41 |
+ lea lenq, [2*lend] |
|
42 |
+ lea dstq, [dstq+2*lenq] |
|
43 |
+ add srcq, lenq |
|
44 |
+ neg lenq |
|
45 |
+.loop: |
|
46 |
+ mova m2, [srcq+lenq] |
|
47 |
+ pxor m0, m0 |
|
48 |
+ pxor m1, m1 |
|
49 |
+ punpcklwd m0, m2 |
|
50 |
+ punpckhwd m1, m2 |
|
51 |
+ mova [dstq+2*lenq ], m0 |
|
52 |
+ mova [dstq+2*lenq+mmsize], m1 |
|
53 |
+ add lenq, mmsize |
|
54 |
+ jl .loop |
|
55 |
+ REP_RET |
|
56 |
+ |
|
57 |
+;------------------------------------------------------------------------------ |
|
58 |
+; void ff_conv_s16_to_flt(float *dst, const int16_t *src, int len); |
|
59 |
+;------------------------------------------------------------------------------ |
|
60 |
+ |
|
61 |
+%macro CONV_S16_TO_FLT 0 |
|
62 |
+cglobal conv_s16_to_flt, 3,3,3, dst, src, len |
|
63 |
+ lea lenq, [2*lend] |
|
64 |
+ add srcq, lenq |
|
65 |
+ lea dstq, [dstq + 2*lenq] |
|
66 |
+ neg lenq |
|
67 |
+ mova m2, [pf_s16_inv_scale] |
|
68 |
+ ALIGN 16 |
|
69 |
+.loop: |
|
70 |
+ mova m0, [srcq+lenq] |
|
71 |
+ S16_TO_S32_SX 0, 1 |
|
72 |
+ cvtdq2ps m0, m0 |
|
73 |
+ cvtdq2ps m1, m1 |
|
74 |
+ mulps m0, m2 |
|
75 |
+ mulps m1, m2 |
|
76 |
+ mova [dstq+2*lenq ], m0 |
|
77 |
+ mova [dstq+2*lenq+mmsize], m1 |
|
78 |
+ add lenq, mmsize |
|
79 |
+ jl .loop |
|
80 |
+ REP_RET |
|
81 |
+%endmacro |
|
82 |
+ |
|
83 |
+INIT_XMM sse2 |
|
84 |
+CONV_S16_TO_FLT |
|
85 |
+INIT_XMM sse4 |
|
86 |
+CONV_S16_TO_FLT |
|
87 |
+ |
|
88 |
+;------------------------------------------------------------------------------ |
|
89 |
+; void ff_conv_s32_to_s16(int16_t *dst, const int32_t *src, int len); |
|
90 |
+;------------------------------------------------------------------------------ |
|
91 |
+ |
|
92 |
+%macro CONV_S32_TO_S16 0 |
|
93 |
+cglobal conv_s32_to_s16, 3,3,4, dst, src, len |
|
94 |
+ lea lenq, [2*lend] |
|
95 |
+ lea srcq, [srcq+2*lenq] |
|
96 |
+ add dstq, lenq |
|
97 |
+ neg lenq |
|
98 |
+.loop: |
|
99 |
+ mova m0, [srcq+2*lenq ] |
|
100 |
+ mova m1, [srcq+2*lenq+ mmsize] |
|
101 |
+ mova m2, [srcq+2*lenq+2*mmsize] |
|
102 |
+ mova m3, [srcq+2*lenq+3*mmsize] |
|
103 |
+ psrad m0, 16 |
|
104 |
+ psrad m1, 16 |
|
105 |
+ psrad m2, 16 |
|
106 |
+ psrad m3, 16 |
|
107 |
+ packssdw m0, m1 |
|
108 |
+ packssdw m2, m3 |
|
109 |
+ mova [dstq+lenq ], m0 |
|
110 |
+ mova [dstq+lenq+mmsize], m2 |
|
111 |
+ add lenq, mmsize*2 |
|
112 |
+ jl .loop |
|
113 |
+%if mmsize == 8 |
|
114 |
+ emms |
|
115 |
+ RET |
|
116 |
+%else |
|
117 |
+ REP_RET |
|
118 |
+%endif |
|
119 |
+%endmacro |
|
120 |
+ |
|
121 |
+INIT_MMX mmx |
|
122 |
+CONV_S32_TO_S16 |
|
123 |
+INIT_XMM sse2 |
|
124 |
+CONV_S32_TO_S16 |
|
125 |
+ |
|
126 |
+;------------------------------------------------------------------------------ |
|
127 |
+; void ff_conv_s32_to_flt(float *dst, const int32_t *src, int len); |
|
128 |
+;------------------------------------------------------------------------------ |
|
129 |
+ |
|
130 |
+%macro CONV_S32_TO_FLT 0 |
|
131 |
+cglobal conv_s32_to_flt, 3,3,3, dst, src, len |
|
132 |
+ lea lenq, [4*lend] |
|
133 |
+ add srcq, lenq |
|
134 |
+ add dstq, lenq |
|
135 |
+ neg lenq |
|
136 |
+ mova m0, [pf_s32_inv_scale] |
|
137 |
+ ALIGN 16 |
|
138 |
+.loop: |
|
139 |
+ cvtdq2ps m1, [srcq+lenq ] |
|
140 |
+ cvtdq2ps m2, [srcq+lenq+mmsize] |
|
141 |
+ mulps m1, m1, m0 |
|
142 |
+ mulps m2, m2, m0 |
|
143 |
+ mova [dstq+lenq ], m1 |
|
144 |
+ mova [dstq+lenq+mmsize], m2 |
|
145 |
+ add lenq, mmsize*2 |
|
146 |
+ jl .loop |
|
147 |
+%if mmsize == 32 |
|
148 |
+ vzeroupper |
|
149 |
+ RET |
|
150 |
+%else |
|
151 |
+ REP_RET |
|
152 |
+%endif |
|
153 |
+%endmacro |
|
154 |
+ |
|
155 |
+INIT_XMM sse2 |
|
156 |
+CONV_S32_TO_FLT |
|
157 |
+%if HAVE_AVX |
|
158 |
+INIT_YMM avx |
|
159 |
+CONV_S32_TO_FLT |
|
160 |
+%endif |
|
161 |
+ |
|
162 |
+;------------------------------------------------------------------------------ |
|
163 |
+; void ff_conv_flt_to_s16(int16_t *dst, const float *src, int len); |
|
164 |
+;------------------------------------------------------------------------------ |
|
165 |
+ |
|
166 |
+INIT_XMM sse2 |
|
167 |
+cglobal conv_flt_to_s16, 3,3,5, dst, src, len |
|
168 |
+ lea lenq, [2*lend] |
|
169 |
+ lea srcq, [srcq+2*lenq] |
|
170 |
+ add dstq, lenq |
|
171 |
+ neg lenq |
|
172 |
+ mova m4, [pf_s16_scale] |
|
173 |
+.loop: |
|
174 |
+ mova m0, [srcq+2*lenq ] |
|
175 |
+ mova m1, [srcq+2*lenq+1*mmsize] |
|
176 |
+ mova m2, [srcq+2*lenq+2*mmsize] |
|
177 |
+ mova m3, [srcq+2*lenq+3*mmsize] |
|
178 |
+ mulps m0, m4 |
|
179 |
+ mulps m1, m4 |
|
180 |
+ mulps m2, m4 |
|
181 |
+ mulps m3, m4 |
|
182 |
+ cvtps2dq m0, m0 |
|
183 |
+ cvtps2dq m1, m1 |
|
184 |
+ cvtps2dq m2, m2 |
|
185 |
+ cvtps2dq m3, m3 |
|
186 |
+ packssdw m0, m1 |
|
187 |
+ packssdw m2, m3 |
|
188 |
+ mova [dstq+lenq ], m0 |
|
189 |
+ mova [dstq+lenq+mmsize], m2 |
|
190 |
+ add lenq, mmsize*2 |
|
191 |
+ jl .loop |
|
192 |
+ REP_RET |
|
193 |
+ |
|
194 |
+;------------------------------------------------------------------------------ |
|
195 |
+; void ff_conv_flt_to_s32(int32_t *dst, const float *src, int len); |
|
196 |
+;------------------------------------------------------------------------------ |
|
197 |
+ |
|
198 |
+%macro CONV_FLT_TO_S32 0 |
|
199 |
+cglobal conv_flt_to_s32, 3,3,5, dst, src, len |
|
200 |
+ lea lenq, [lend*4] |
|
201 |
+ add srcq, lenq |
|
202 |
+ add dstq, lenq |
|
203 |
+ neg lenq |
|
204 |
+ mova m4, [pf_s32_scale] |
|
205 |
+.loop: |
|
206 |
+ mulps m0, m4, [srcq+lenq ] |
|
207 |
+ mulps m1, m4, [srcq+lenq+1*mmsize] |
|
208 |
+ mulps m2, m4, [srcq+lenq+2*mmsize] |
|
209 |
+ mulps m3, m4, [srcq+lenq+3*mmsize] |
|
210 |
+ cvtps2dq m0, m0 |
|
211 |
+ cvtps2dq m1, m1 |
|
212 |
+ cvtps2dq m2, m2 |
|
213 |
+ cvtps2dq m3, m3 |
|
214 |
+ mova [dstq+lenq ], m0 |
|
215 |
+ mova [dstq+lenq+1*mmsize], m1 |
|
216 |
+ mova [dstq+lenq+2*mmsize], m2 |
|
217 |
+ mova [dstq+lenq+3*mmsize], m3 |
|
218 |
+ add lenq, mmsize*4 |
|
219 |
+ jl .loop |
|
220 |
+%if mmsize == 32 |
|
221 |
+ vzeroupper |
|
222 |
+ RET |
|
223 |
+%else |
|
224 |
+ REP_RET |
|
225 |
+%endif |
|
226 |
+%endmacro |
|
227 |
+ |
|
228 |
+INIT_XMM sse2 |
|
229 |
+CONV_FLT_TO_S32 |
|
230 |
+%if HAVE_AVX |
|
231 |
+INIT_YMM avx |
|
232 |
+CONV_FLT_TO_S32 |
|
233 |
+%endif |
|
234 |
+ |
|
27 | 235 |
;----------------------------------------------------------------------------- |
28 | 236 |
; void ff_conv_fltp_to_flt_6ch(float *dst, float *const *src, int len, |
29 | 237 |
; int channels); |
... | ... |
@@ -22,6 +22,22 @@ |
22 | 22 |
#include "libavutil/cpu.h" |
23 | 23 |
#include "libavresample/audio_convert.h" |
24 | 24 |
|
25 |
+extern void ff_conv_s16_to_s32_sse2(int16_t *dst, const int32_t *src, int len); |
|
26 |
+ |
|
27 |
+extern void ff_conv_s16_to_flt_sse2(float *dst, const int16_t *src, int len); |
|
28 |
+extern void ff_conv_s16_to_flt_sse4(float *dst, const int16_t *src, int len); |
|
29 |
+ |
|
30 |
+extern void ff_conv_s32_to_s16_mmx (int16_t *dst, const int32_t *src, int len); |
|
31 |
+extern void ff_conv_s32_to_s16_sse2(int16_t *dst, const int32_t *src, int len); |
|
32 |
+ |
|
33 |
+extern void ff_conv_s32_to_flt_sse2(float *dst, const int32_t *src, int len); |
|
34 |
+extern void ff_conv_s32_to_flt_avx (float *dst, const int32_t *src, int len); |
|
35 |
+ |
|
36 |
+extern void ff_conv_flt_to_s16_sse2(int16_t *dst, const float *src, int len); |
|
37 |
+ |
|
38 |
+extern void ff_conv_flt_to_s32_sse2(int32_t *dst, const float *src, int len); |
|
39 |
+extern void ff_conv_flt_to_s32_avx (int32_t *dst, const float *src, int len); |
|
40 |
+ |
|
25 | 41 |
extern void ff_conv_fltp_to_flt_6ch_mmx (float *dst, float *const *src, int len); |
26 | 42 |
extern void ff_conv_fltp_to_flt_6ch_sse4(float *dst, float *const *src, int len); |
27 | 43 |
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) |
32 | 32 |
int mm_flags = av_get_cpu_flags(); |
33 | 33 |
|
34 | 34 |
if (mm_flags & AV_CPU_FLAG_MMX && HAVE_MMX) { |
35 |
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, |
|
36 |
+ 0, 1, 8, "MMX", ff_conv_s32_to_s16_mmx); |
|
35 | 37 |
ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, |
36 | 38 |
6, 1, 4, "MMX", ff_conv_fltp_to_flt_6ch_mmx); |
37 | 39 |
} |
... | ... |
@@ -43,5 +61,31 @@ av_cold void ff_audio_convert_init_x86(AudioConvert *ac) |
43 | 43 |
ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, |
44 | 44 |
6, 16, 4, "AVX", ff_conv_fltp_to_flt_6ch_avx); |
45 | 45 |
} |
46 |
+ if (mm_flags & AV_CPU_FLAG_SSE2 && HAVE_SSE) { |
|
47 |
+ if (!(mm_flags & AV_CPU_FLAG_SSE2SLOW)) { |
|
48 |
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, |
|
49 |
+ 0, 16, 16, "SSE2", ff_conv_s32_to_s16_sse2); |
|
50 |
+ } |
|
51 |
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16, |
|
52 |
+ 0, 16, 8, "SSE2", ff_conv_s16_to_s32_sse2); |
|
53 |
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, |
|
54 |
+ 0, 16, 8, "SSE2", ff_conv_s16_to_flt_sse2); |
|
55 |
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32, |
|
56 |
+ 0, 16, 8, "SSE2", ff_conv_s32_to_flt_sse2); |
|
57 |
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT, |
|
58 |
+ 0, 16, 16, "SSE2", ff_conv_flt_to_s16_sse2); |
|
59 |
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT, |
|
60 |
+ 0, 16, 16, "SSE2", ff_conv_flt_to_s32_sse2); |
|
61 |
+ } |
|
62 |
+ if (mm_flags & AV_CPU_FLAG_SSE4 && HAVE_SSE) { |
|
63 |
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, |
|
64 |
+ 0, 16, 8, "SSE4", ff_conv_s16_to_flt_sse4); |
|
65 |
+ } |
|
66 |
+ if (mm_flags & AV_CPU_FLAG_AVX && HAVE_AVX) { |
|
67 |
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32, |
|
68 |
+ 0, 32, 16, "AVX", ff_conv_s32_to_flt_avx); |
|
69 |
+ ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT, |
|
70 |
+ 0, 32, 32, "AVX", ff_conv_flt_to_s32_avx); |
|
71 |
+ } |
|
46 | 72 |
#endif |
47 | 73 |
} |
... | ... |
@@ -26,7 +26,11 @@ |
26 | 26 |
|
27 | 27 |
void ff_vector_fmul_neon(float *dst, const float *src0, const float *src1, int len); |
28 | 28 |
|
29 |
+void ff_vector_fmac_scalar_neon(float *dst, const float *src, float mul, |
|
30 |
+ int len); |
|
31 |
+ |
|
29 | 32 |
void ff_float_dsp_init_neon(AVFloatDSPContext *fdsp) |
30 | 33 |
{ |
31 | 34 |
fdsp->vector_fmul = ff_vector_fmul_neon; |
35 |
+ fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_neon; |
|
32 | 36 |
} |
... | ... |
@@ -62,3 +62,51 @@ function ff_vector_fmul_neon, export=1 |
62 | 62 |
3: vst1.32 {d16-d19},[r0,:128]! |
63 | 63 |
bx lr |
64 | 64 |
endfunc |
65 |
+ |
|
66 |
+function ff_vector_fmac_scalar_neon, export=1 |
|
67 |
+VFP len .req r2 |
|
68 |
+VFP acc .req r3 |
|
69 |
+NOVFP len .req r3 |
|
70 |
+NOVFP acc .req r2 |
|
71 |
+VFP vdup.32 q15, d0[0] |
|
72 |
+NOVFP vdup.32 q15, r2 |
|
73 |
+ bics r12, len, #15 |
|
74 |
+ mov acc, r0 |
|
75 |
+ beq 3f |
|
76 |
+ vld1.32 {q0}, [r1,:128]! |
|
77 |
+ vld1.32 {q8}, [acc,:128]! |
|
78 |
+ vld1.32 {q1}, [r1,:128]! |
|
79 |
+ vld1.32 {q9}, [acc,:128]! |
|
80 |
+1: vmla.f32 q8, q0, q15 |
|
81 |
+ vld1.32 {q2}, [r1,:128]! |
|
82 |
+ vld1.32 {q10}, [acc,:128]! |
|
83 |
+ vmla.f32 q9, q1, q15 |
|
84 |
+ vld1.32 {q3}, [r1,:128]! |
|
85 |
+ vld1.32 {q11}, [acc,:128]! |
|
86 |
+ vmla.f32 q10, q2, q15 |
|
87 |
+ vst1.32 {q8}, [r0,:128]! |
|
88 |
+ vmla.f32 q11, q3, q15 |
|
89 |
+ vst1.32 {q9}, [r0,:128]! |
|
90 |
+ subs r12, r12, #16 |
|
91 |
+ beq 2f |
|
92 |
+ vld1.32 {q0}, [r1,:128]! |
|
93 |
+ vld1.32 {q8}, [acc,:128]! |
|
94 |
+ vst1.32 {q10}, [r0,:128]! |
|
95 |
+ vld1.32 {q1}, [r1,:128]! |
|
96 |
+ vld1.32 {q9}, [acc,:128]! |
|
97 |
+ vst1.32 {q11}, [r0,:128]! |
|
98 |
+ b 1b |
|
99 |
+2: vst1.32 {q10}, [r0,:128]! |
|
100 |
+ vst1.32 {q11}, [r0,:128]! |
|
101 |
+ ands len, len, #15 |
|
102 |
+ it eq |
|
103 |
+ bxeq lr |
|
104 |
+3: vld1.32 {q0}, [r1,:128]! |
|
105 |
+ vld1.32 {q8}, [acc,:128]! |
|
106 |
+ vmla.f32 q8, q0, q15 |
|
107 |
+ vst1.32 {q8}, [r0,:128]! |
|
108 |
+ subs len, len, #4 |
|
109 |
+ bgt 3b |
|
110 |
+ bx lr |
|
111 |
+ .unreq len |
|
112 |
+endfunc |
... | ... |
@@ -31,9 +31,18 @@ static void vector_fmul_c(float *dst, const float *src0, const float *src1, |
31 | 31 |
dst[i] = src0[i] * src1[i]; |
32 | 32 |
} |
33 | 33 |
|
34 |
+static void vector_fmac_scalar_c(float *dst, const float *src, float mul, |
|
35 |
+ int len) |
|
36 |
+{ |
|
37 |
+ int i; |
|
38 |
+ for (i = 0; i < len; i++) |
|
39 |
+ dst[i] += src[i] * mul; |
|
40 |
+} |
|
41 |
+ |
|
34 | 42 |
void avpriv_float_dsp_init(AVFloatDSPContext *fdsp, int bit_exact) |
35 | 43 |
{ |
36 | 44 |
fdsp->vector_fmul = vector_fmul_c; |
45 |
+ fdsp->vector_fmac_scalar = vector_fmac_scalar_c; |
|
37 | 46 |
|
38 | 47 |
#if ARCH_ARM |
39 | 48 |
ff_float_dsp_init_arm(fdsp); |
... | ... |
@@ -35,6 +35,22 @@ typedef struct AVFloatDSPContext { |
35 | 35 |
*/ |
36 | 36 |
void (*vector_fmul)(float *dst, const float *src0, const float *src1, |
37 | 37 |
int len); |
38 |
+ |
|
39 |
+ /** |
|
40 |
+ * Multiply a vector of floats by a scalar float and add to |
|
41 |
+ * destination vector. Source and destination vectors must |
|
42 |
+ * overlap exactly or not at all. |
|
43 |
+ * |
|
44 |
+ * @param dst result vector |
|
45 |
+ * constraints: 32-byte aligned |
|
46 |
+ * @param src input vector |
|
47 |
+ * constraints: 32-byte aligned |
|
48 |
+ * @param mul scalar value |
|
49 |
+ * @param len length of vector |
|
50 |
+ * constraints: multiple of 16 |
|
51 |
+ */ |
|
52 |
+ void (*vector_fmac_scalar)(float *dst, const float *src, float mul, |
|
53 |
+ int len); |
|
38 | 54 |
} AVFloatDSPContext; |
39 | 55 |
|
40 | 56 |
/** |
... | ... |
@@ -94,6 +94,8 @@ void *av_malloc(size_t size) |
94 | 94 |
if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation |
95 | 95 |
if (posix_memalign(&ptr,ALIGN,size)) |
96 | 96 |
ptr = NULL; |
97 |
+#elif HAVE_ALIGNED_MALLOC |
|
98 |
+ ptr = _aligned_malloc(size, ALIGN); |
|
97 | 99 |
#elif HAVE_MEMALIGN |
98 | 100 |
ptr = memalign(ALIGN,size); |
99 | 101 |
/* Why 64? |
... | ... |
@@ -145,6 +147,8 @@ void *av_realloc(void *ptr, size_t size) |
145 | 145 |
ptr= realloc((char*)ptr - diff, size + diff); |
146 | 146 |
if(ptr) ptr = (char*)ptr + diff; |
147 | 147 |
return ptr; |
148 |
+#elif HAVE_ALIGNED_MALLOC |
|
149 |
+ return _aligned_realloc(ptr, size + !size, ALIGN); |
|
148 | 150 |
#else |
149 | 151 |
return realloc(ptr, size + !size); |
150 | 152 |
#endif |
... | ... |
@@ -170,6 +174,8 @@ void av_free(void *ptr) |
170 | 170 |
#if CONFIG_MEMALIGN_HACK |
171 | 171 |
if (ptr) |
172 | 172 |
free((char*)ptr - ((char*)ptr)[-1]); |
173 |
+#elif HAVE_ALIGNED_MALLOC |
|
174 |
+ _aligned_free(ptr); |
|
173 | 175 |
#else |
174 | 176 |
free(ptr); |
175 | 177 |
#endif |
... | ... |
@@ -21,6 +21,7 @@ |
21 | 21 |
;****************************************************************************** |
22 | 22 |
|
23 | 23 |
%include "x86inc.asm" |
24 |
+%include "x86util.asm" |
|
24 | 25 |
|
25 | 26 |
SECTION .text |
26 | 27 |
|
... | ... |
@@ -55,3 +56,49 @@ VECTOR_FMUL |
55 | 55 |
INIT_YMM avx |
56 | 56 |
VECTOR_FMUL |
57 | 57 |
%endif |
58 |
+ |
|
59 |
+;------------------------------------------------------------------------------ |
|
60 |
+; void ff_vector_fmac_scalar(float *dst, const float *src, float mul, int len) |
|
61 |
+;------------------------------------------------------------------------------ |
|
62 |
+ |
|
63 |
+%macro VECTOR_FMAC_SCALAR 0 |
|
64 |
+%if UNIX64 |
|
65 |
+cglobal vector_fmac_scalar, 3,3,3, dst, src, len |
|
66 |
+%else |
|
67 |
+cglobal vector_fmac_scalar, 4,4,3, dst, src, mul, len |
|
68 |
+%endif |
|
69 |
+%if WIN64 |
|
70 |
+ SWAP 0, 2 |
|
71 |
+%endif |
|
72 |
+%if ARCH_X86_32 |
|
73 |
+ VBROADCASTSS m0, mulm |
|
74 |
+%else |
|
75 |
+ shufps xmm0, xmm0, 0 |
|
76 |
+%if cpuflag(avx) |
|
77 |
+ vinsertf128 m0, m0, xmm0, 1 |
|
78 |
+%endif |
|
79 |
+%endif |
|
80 |
+ lea lenq, [lend*4-2*mmsize] |
|
81 |
+.loop |
|
82 |
+ mulps m1, m0, [srcq+lenq ] |
|
83 |
+ mulps m2, m0, [srcq+lenq+mmsize] |
|
84 |
+ addps m1, m1, [dstq+lenq ] |
|
85 |
+ addps m2, m2, [dstq+lenq+mmsize] |
|
86 |
+ mova [dstq+lenq ], m1 |
|
87 |
+ mova [dstq+lenq+mmsize], m2 |
|
88 |
+ sub lenq, 2*mmsize |
|
89 |
+ jge .loop |
|
90 |
+%if mmsize == 32 |
|
91 |
+ vzeroupper |
|
92 |
+ RET |
|
93 |
+%else |
|
94 |
+ REP_RET |
|
95 |
+%endif |
|
96 |
+%endmacro |
|
97 |
+ |
|
98 |
+INIT_XMM sse |
|
99 |
+VECTOR_FMAC_SCALAR |
|
100 |
+%if HAVE_AVX |
|
101 |
+INIT_YMM avx |
|
102 |
+VECTOR_FMAC_SCALAR |
|
103 |
+%endif |
... | ... |
@@ -26,6 +26,11 @@ extern void ff_vector_fmul_sse(float *dst, const float *src0, const float *src1, |
26 | 26 |
extern void ff_vector_fmul_avx(float *dst, const float *src0, const float *src1, |
27 | 27 |
int len); |
28 | 28 |
|
29 |
+extern void ff_vector_fmac_scalar_sse(float *dst, const float *src, float mul, |
|
30 |
+ int len); |
|
31 |
+extern void ff_vector_fmac_scalar_avx(float *dst, const float *src, float mul, |
|
32 |
+ int len); |
|
33 |
+ |
|
29 | 34 |
void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp) |
30 | 35 |
{ |
31 | 36 |
#if HAVE_YASM |
... | ... |
@@ -33,9 +38,11 @@ void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp) |
33 | 33 |
|
34 | 34 |
if (mm_flags & AV_CPU_FLAG_SSE && HAVE_SSE) { |
35 | 35 |
fdsp->vector_fmul = ff_vector_fmul_sse; |
36 |
+ fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_sse; |
|
36 | 37 |
} |
37 | 38 |
if (mm_flags & AV_CPU_FLAG_AVX && HAVE_AVX) { |
38 | 39 |
fdsp->vector_fmul = ff_vector_fmul_avx; |
40 |
+ fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_avx; |
|
39 | 41 |
} |
40 | 42 |
#endif |
41 | 43 |
} |