summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-06-19 20:52:00 +0200
committerMichael Niedermayer <michaelni@gmx.at>2012-06-19 20:53:27 +0200
commitcabbd271a5f37042291c06b9f8bd6c641fbddfde (patch)
tree110238d357631f95c4849d0d99d978a61b2a1ee7 /libavformat
parent6b9446e93296ed236d497fe3f493d8956571f888 (diff)
parent4cc2920dd2c0ce4e64e709da4f78508e1ec9871e (diff)
Merge remote-tracking branch 'qatar/master'
* qatar/master: (24 commits) flvdec: remove incomplete, disabled seeking code mem: add support for _aligned_malloc() as found on Windows lavc: Extend the documentation for avcodec_init_packet flvdec: remove incomplete, disabled seeking code http: replace atoll() with strtoll() mpegts: remove unused/incomplete/broken seeking code af_amix: allow float planar sample format as input af_amix: use AVFloatDSPContext.vector_fmac_scalar() float_dsp: add x86-optimized functions for vector_fmac_scalar() float_dsp: Move vector_fmac_scalar() from libavcodec to libavutil lavr: Add x86-optimized function for flt to s32 conversion lavr: Add x86-optimized function for flt to s16 conversion lavr: Add x86-optimized functions for s32 to flt conversion lavr: Add x86-optimized functions for s32 to s16 conversion lavr: Add x86-optimized functions for s16 to flt conversion lavr: Add x86-optimized function for s16 to s32 conversion rtpenc: Support packetizing iLBC rtpdec: Add a depacketizer for iLBC Implement the iLBC storage file format mov: Support muxing/demuxing iLBC ... Conflicts: Changelog configure libavcodec/avcodec.h libavcodec/dsputil.c libavcodec/version.h libavformat/movenc.c libavformat/mpegts.c libavformat/version.h libavutil/mem.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/Makefile3
-rw-r--r--libavformat/allformats.c1
-rw-r--r--libavformat/flvdec.c30
-rw-r--r--libavformat/http.c6
-rw-r--r--libavformat/ilbc.c141
-rw-r--r--libavformat/isom.c1
-rw-r--r--libavformat/mov.c1
-rw-r--r--libavformat/movenc.c3
-rw-r--r--libavformat/mpegts.c94
-rw-r--r--libavformat/rtmpproto.c8
-rw-r--r--libavformat/rtpdec.c1
-rw-r--r--libavformat/rtpdec_formats.h1
-rw-r--r--libavformat/rtpdec_ilbc.c73
-rw-r--r--libavformat/rtpenc.c44
-rw-r--r--libavformat/rtsp.c2
-rw-r--r--libavformat/sdp.c6
-rw-r--r--libavformat/version.h2
17 files changed, 287 insertions, 130 deletions
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 3dca060994..f38b8a575c 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -123,6 +123,8 @@ OBJS-$(CONFIG_ICO_DEMUXER) += icodec.o
OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o
OBJS-$(CONFIG_IDF_DEMUXER) += bintext.o
OBJS-$(CONFIG_IFF_DEMUXER) += iff.o
+OBJS-$(CONFIG_ILBC_DEMUXER) += ilbc.o
+OBJS-$(CONFIG_ILBC_MUXER) += ilbc.o
OBJS-$(CONFIG_IMAGE2_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE2_MUXER) += img2enc.o img2.o
OBJS-$(CONFIG_IMAGE2PIPE_DEMUXER) += img2dec.o img2.o
@@ -281,6 +283,7 @@ OBJS-$(CONFIG_RTPDEC) += rdt.o \
rtpdec_h263.o \
rtpdec_h263_rfc2190.o \
rtpdec_h264.o \
+ rtpdec_ilbc.o \
rtpdec_latm.o \
rtpdec_mpeg4.o \
rtpdec_qcelp.o \
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index ed9227e5b6..b5738e4d97 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -116,6 +116,7 @@ void av_register_all(void)
REGISTER_DEMUXER (IDCIN, idcin);
REGISTER_DEMUXER (IDF, idf);
REGISTER_DEMUXER (IFF, iff);
+ REGISTER_MUXDEMUX (ILBC, ilbc);
REGISTER_MUXDEMUX (IMAGE2, image2);
REGISTER_MUXDEMUX (IMAGE2PIPE, image2pipe);
REGISTER_DEMUXER (INGENIENT, ingenient);
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index aa016ee4de..31f306872f 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -759,33 +759,6 @@ static int flv_read_seek(AVFormatContext *s, int stream_index,
return avio_seek_time(s->pb, stream_index, ts, flags);
}
-#if 0 /* don't know enough to implement this */
-static int flv_read_seek2(AVFormatContext *s, int stream_index,
- int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
-{
- int ret = AVERROR(ENOSYS);
-
- if (ts - min_ts > (uint64_t)(max_ts - ts)) flags |= AVSEEK_FLAG_BACKWARD;
-
- if (!s->pb->seekable) {
- if (stream_index < 0) {
- stream_index = av_find_default_stream_index(s);
- if (stream_index < 0)
- return -1;
-
- /* timestamp for default must be expressed in AV_TIME_BASE units */
- ts = av_rescale_rnd(ts, 1000, AV_TIME_BASE,
- flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP);
- }
- ret = avio_seek_time(s->pb, stream_index, ts, flags);
- }
-
- if (ret == AVERROR(ENOSYS))
- ret = av_seek_frame(s, stream_index, ts, flags);
- return ret;
-}
-#endif
-
AVInputFormat ff_flv_demuxer = {
.name = "flv",
.long_name = NULL_IF_CONFIG_SMALL("FLV format"),
@@ -794,9 +767,6 @@ AVInputFormat ff_flv_demuxer = {
.read_header = flv_read_header,
.read_packet = flv_read_packet,
.read_seek = flv_read_seek,
-#if 0
- .read_seek2 = flv_read_seek2,
-#endif
.read_close = flv_read_close,
.extensions = "flv",
};
diff --git a/libavformat/http.c b/libavformat/http.c
index fb4a83ad0e..96a7eeda0a 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -308,15 +308,15 @@ static int process_line(URLContext *h, char *line, int line_count,
strcpy(s->location, p);
*new_location = 1;
} else if (!av_strcasecmp (tag, "Content-Length") && s->filesize == -1) {
- s->filesize = atoll(p);
+ s->filesize = strtoll(p, NULL, 10);
} else if (!av_strcasecmp (tag, "Content-Range")) {
/* "bytes $from-$to/$document_size" */
const char *slash;
if (!strncmp (p, "bytes ", 6)) {
p += 6;
- s->off = atoll(p);
+ s->off = strtoll(p, NULL, 10);
if ((slash = strchr(p, '/')) && strlen(slash) > 0)
- s->filesize = atoll(slash+1);
+ s->filesize = strtoll(slash+1, NULL, 10);
}
h->is_streamed = 0; /* we _can_ in fact seek */
} else if (!av_strcasecmp(tag, "Accept-Ranges") && !strncmp(p, "bytes", 5)) {
diff --git a/libavformat/ilbc.c b/libavformat/ilbc.c
new file mode 100644
index 0000000000..d4f4583545
--- /dev/null
+++ b/libavformat/ilbc.c
@@ -0,0 +1,141 @@
+/*
+ * iLBC storage file format
+ * Copyright (c) 2012 Martin Storsjo
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avformat.h"
+#include "internal.h"
+
+static const char mode20_header[] = "#!iLBC20\n";
+static const char mode30_header[] = "#!iLBC30\n";
+
+static int ilbc_write_header(AVFormatContext *s)
+{
+ AVIOContext *pb = s->pb;
+ AVCodecContext *enc;
+
+ if (s->nb_streams != 1) {
+ av_log(s, AV_LOG_ERROR, "Unsupported number of streams\n");
+ return AVERROR(EINVAL);
+ }
+ enc = s->streams[0]->codec;
+
+ if (enc->codec_id != CODEC_ID_ILBC) {
+ av_log(s, AV_LOG_ERROR, "Unsupported codec\n");
+ return AVERROR(EINVAL);
+ }
+
+ if (enc->block_align == 50) {
+ avio_write(pb, mode30_header, sizeof(mode30_header) - 1);
+ } else if (enc->block_align == 38) {
+ avio_write(pb, mode20_header, sizeof(mode20_header) - 1);
+ } else {
+ av_log(s, AV_LOG_ERROR, "Unsupported mode\n");
+ return AVERROR(EINVAL);
+ }
+ avio_flush(pb);
+ return 0;
+}
+
+static int ilbc_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ avio_write(s->pb, pkt->data, pkt->size);
+ avio_flush(s->pb);
+ return 0;
+}
+
+static int ilbc_probe(AVProbeData *p)
+{
+ // Only check for "#!iLBC" which matches both formats
+ if (!memcmp(p->buf, mode20_header, 6))
+ return AVPROBE_SCORE_MAX;
+ else
+ return 0;
+}
+
+static int ilbc_read_header(AVFormatContext *s)
+{
+ AVIOContext *pb = s->pb;
+ AVStream *st;
+ uint8_t header[9];
+
+ avio_read(pb, header, 9);
+
+ st = avformat_new_stream(s, NULL);
+ if (!st)
+ return AVERROR(ENOMEM);
+ st->codec->codec_id = CODEC_ID_ILBC;
+ st->codec->sample_rate = 8000;
+ st->codec->channels = 1;
+ st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+ st->start_time = 0;
+ avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+ if (!memcmp(header, mode20_header, sizeof(mode20_header) - 1)) {
+ st->codec->block_align = 38;
+ st->codec->bit_rate = 15200;
+ } else if (!memcmp(header, mode30_header, sizeof(mode30_header) - 1)) {
+ st->codec->block_align = 50;
+ st->codec->bit_rate = 13333;
+ } else {
+ av_log(s, AV_LOG_ERROR, "Unrecognized iLBC file header\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ return 0;
+}
+
+static int ilbc_read_packet(AVFormatContext *s,
+ AVPacket *pkt)
+{
+ AVCodecContext *enc = s->streams[0]->codec;
+ int ret;
+
+ if ((ret = av_new_packet(pkt, enc->block_align)) < 0)
+ return ret;
+
+ pkt->stream_index = 0;
+ pkt->pos = avio_tell(s->pb);
+ pkt->duration = enc->block_align == 38 ? 160 : 240;
+ if ((ret = avio_read(s->pb, pkt->data, enc->block_align)) != enc->block_align) {
+ av_free_packet(pkt);
+ return ret < 0 ? ret : AVERROR(EIO);
+ }
+
+ return 0;
+}
+
+AVInputFormat ff_ilbc_demuxer = {
+ .name = "ilbc",
+ .long_name = NULL_IF_CONFIG_SMALL("iLBC storage file format"),
+ .read_probe = ilbc_probe,
+ .read_header = ilbc_read_header,
+ .read_packet = ilbc_read_packet,
+ .flags = AVFMT_GENERIC_INDEX,
+};
+
+AVOutputFormat ff_ilbc_muxer = {
+ .name = "ilbc",
+ .long_name = NULL_IF_CONFIG_SMALL("iLBC storage file format"),
+ .mime_type = "audio/iLBC",
+ .extensions = "lbc",
+ .audio_codec = CODEC_ID_ILBC,
+ .write_header = ilbc_write_header,
+ .write_packet = ilbc_write_packet,
+ .flags = AVFMT_NOTIMESTAMPS,
+};
diff --git a/libavformat/isom.c b/libavformat/isom.c
index e4575033e2..0ddbb813ec 100644
--- a/libavformat/isom.c
+++ b/libavformat/isom.c
@@ -259,6 +259,7 @@ const AVCodecTag ff_codec_movaudio_tags[] = {
{ CODEC_ID_DVAUDIO, MKTAG('v', 'd', 'v', 'a') },
{ CODEC_ID_DVAUDIO, MKTAG('d', 'v', 'c', 'a') },
{ CODEC_ID_GSM, MKTAG('a', 'g', 's', 'm') },
+ { CODEC_ID_ILBC, MKTAG('i', 'l', 'b', 'c') },
{ CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') },
{ CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') },
{ CODEC_ID_MP1, MKTAG('.', 'm', 'p', '1') },
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 9548f215f3..3aab48ffff 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -1540,6 +1540,7 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
case CODEC_ID_GSM:
case CODEC_ID_ADPCM_MS:
case CODEC_ID_ADPCM_IMA_WAV:
+ case CODEC_ID_ILBC:
st->codec->block_align = sc->bytes_per_frame;
break;
case CODEC_ID_ALAC:
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index d5eb25bcc2..89072d5ded 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -3371,7 +3371,8 @@ static int mov_write_header(AVFormatContext *s)
av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
track->audio_vbr = 1;
}else if(st->codec->codec_id == CODEC_ID_ADPCM_MS ||
- st->codec->codec_id == CODEC_ID_ADPCM_IMA_WAV){
+ st->codec->codec_id == CODEC_ID_ADPCM_IMA_WAV ||
+ st->codec->codec_id == CODEC_ID_ILBC){
if (!st->codec->block_align) {
av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
goto error;
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 3acca0230c..3a5ed696c8 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -19,8 +19,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-//#define USE_SYNCPOINT_SEARCH
-
#include "libavutil/crc.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/log.h"
@@ -2161,92 +2159,6 @@ static int64_t mpegts_get_dts(AVFormatContext *s, int stream_index,
return AV_NOPTS_VALUE;
}
-#ifdef USE_SYNCPOINT_SEARCH
-
-static int read_seek2(AVFormatContext *s,
- int stream_index,
- int64_t min_ts,
- int64_t target_ts,
- int64_t max_ts,
- int flags)
-{
- int64_t pos;
-
- int64_t ts_ret, ts_adj;
- int stream_index_gen_search;
- AVStream *st;
- AVParserState *backup;
-
- backup = ff_store_parser_state(s);
-
- // detect direction of seeking for search purposes
- flags |= (target_ts - min_ts > (uint64_t)(max_ts - target_ts)) ?
- AVSEEK_FLAG_BACKWARD : 0;
-
- if (flags & AVSEEK_FLAG_BYTE) {
- // use position directly, we will search starting from it
- pos = target_ts;
- } else {
- // search for some position with good timestamp match
- if (stream_index < 0) {
- stream_index_gen_search = av_find_default_stream_index(s);
- if (stream_index_gen_search < 0) {
- ff_restore_parser_state(s, backup);
- return -1;
- }
-
- st = s->streams[stream_index_gen_search];
- // timestamp for default must be expressed in AV_TIME_BASE units
- ts_adj = av_rescale(target_ts,
- st->time_base.den,
- AV_TIME_BASE * (int64_t)st->time_base.num);
- } else {
- ts_adj = target_ts;
- stream_index_gen_search = stream_index;
- }
- pos = ff_gen_search(s, stream_index_gen_search, ts_adj,
- 0, INT64_MAX, -1,
- AV_NOPTS_VALUE,
- AV_NOPTS_VALUE,
- flags, &ts_ret, mpegts_get_pcr);
- if (pos < 0) {
- ff_restore_parser_state(s, backup);
- return -1;
- }
- }
-
- // search for actual matching keyframe/starting position for all streams
- if (ff_gen_syncpoint_search(s, stream_index, pos,
- min_ts, target_ts, max_ts,
- flags) < 0) {
- ff_restore_parser_state(s, backup);
- return -1;
- }
-
- ff_free_parser_state(s, backup);
- return 0;
-}
-
-static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags)
-{
- int ret;
- if (flags & AVSEEK_FLAG_BACKWARD) {
- flags &= ~AVSEEK_FLAG_BACKWARD;
- ret = read_seek2(s, stream_index, INT64_MIN, target_ts, target_ts, flags);
- if (ret < 0)
- // for compatibility reasons, seek to the best-fitting timestamp
- ret = read_seek2(s, stream_index, INT64_MIN, target_ts, INT64_MAX, flags);
- } else {
- ret = read_seek2(s, stream_index, target_ts, target_ts, INT64_MAX, flags);
- if (ret < 0)
- // for compatibility reasons, seek to the best-fitting timestamp
- ret = read_seek2(s, stream_index, INT64_MIN, target_ts, INT64_MAX, flags);
- }
- return ret;
-}
-
-#endif
-
/**************************************************************/
/* parsing functions - called from other demuxers such as RTP */
@@ -2313,9 +2225,6 @@ AVInputFormat ff_mpegts_demuxer = {
.read_close = mpegts_read_close,
.read_timestamp = mpegts_get_dts,
.flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT,
-#ifdef USE_SYNCPOINT_SEARCH
- .read_seek2 = read_seek2,
-#endif
};
AVInputFormat ff_mpegtsraw_demuxer = {
@@ -2327,8 +2236,5 @@ AVInputFormat ff_mpegtsraw_demuxer = {
.read_close = mpegts_read_close,
.read_timestamp = mpegts_get_dts,
.flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT,
-#ifdef USE_SYNCPOINT_SEARCH
- .read_seek2 = read_seek2,
-#endif
.priv_class = &mpegtsraw_class,
};
diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
index 07ec62cc43..4bdda4d097 100644
--- a/libavformat/rtmpproto.c
+++ b/libavformat/rtmpproto.c
@@ -76,6 +76,7 @@ typedef struct RTMPContext {
uint8_t* flv_data; ///< buffer with data for demuxer
int flv_size; ///< current buffer size
int flv_off; ///< number of bytes read from current buffer
+ int flv_nb_packets; ///< number of flv packets published
RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
uint32_t client_report_size; ///< number of bytes after which client should report to server
uint32_t bytes_read; ///< number of bytes read from server
@@ -90,6 +91,7 @@ typedef struct RTMPContext {
char* swfurl; ///< url of the swf player
int server_bw; ///< server bandwidth
int client_buffer_time; ///< client buffer time in ms
+ int flush_interval; ///< number of packets flushed in the same request (RTMPT only)
} RTMPContext;
#define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
@@ -1361,9 +1363,14 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
rt->flv_size = 0;
rt->flv_off = 0;
rt->flv_header_bytes = 0;
+ rt->flv_nb_packets++;
}
} while (buf_temp - buf < size);
+ if (rt->flv_nb_packets < rt->flush_interval)
+ return size;
+ rt->flv_nb_packets = 0;
+
/* set stream into nonblocking mode */
rt->stream->flags |= AVIO_FLAG_NONBLOCK;
@@ -1404,6 +1411,7 @@ static const AVOption rtmp_options[] = {
{"rtmp_buffer", "Set buffer time in milliseconds. The default is 3000.", OFFSET(client_buffer_time), AV_OPT_TYPE_INT, {3000}, 0, INT_MAX, DEC|ENC},
{"rtmp_conn", "Append arbitrary AMF data to the Connect message", OFFSET(conn), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
{"rtmp_flashver", "Version of the Flash plugin used to run the SWF player.", OFFSET(flashver), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
+ {"rtmp_flush_interval", "Number of packets flushed in the same request (RTMPT only).", OFFSET(flush_interval), AV_OPT_TYPE_INT, {10}, 0, INT_MAX, ENC},
{"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
{"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"},
{"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"},
diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c
index b7240a2d51..3a272e33c7 100644
--- a/libavformat/rtpdec.c
+++ b/libavformat/rtpdec.c
@@ -68,6 +68,7 @@ void av_register_rtp_dynamic_payload_handlers(void)
ff_register_dynamic_payload_handler(&ff_h263_2000_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_h263_rfc2190_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_h264_dynamic_handler);
+ ff_register_dynamic_payload_handler(&ff_ilbc_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_vorbis_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_theora_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_qdm2_dynamic_handler);
diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h
index 73ffe1f49e..a0c61a84b9 100644
--- a/libavformat/rtpdec_formats.h
+++ b/libavformat/rtpdec_formats.h
@@ -45,6 +45,7 @@ extern RTPDynamicProtocolHandler ff_h263_1998_dynamic_handler;
extern RTPDynamicProtocolHandler ff_h263_2000_dynamic_handler;
extern RTPDynamicProtocolHandler ff_h263_rfc2190_dynamic_handler;
extern RTPDynamicProtocolHandler ff_h264_dynamic_handler;
+extern RTPDynamicProtocolHandler ff_ilbc_dynamic_handler;
extern RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler;
extern RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler;
extern RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler;
diff --git a/libavformat/rtpdec_ilbc.c b/libavformat/rtpdec_ilbc.c
new file mode 100644
index 0000000000..247c779bfc
--- /dev/null
+++ b/libavformat/rtpdec_ilbc.c
@@ -0,0 +1,73 @@
+/*
+ * RTP iLBC Depacketizer, RFC 3952
+ * Copyright (c) 2012 Martin Storsjo
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avformat.h"
+#include "rtpdec_formats.h"
+#include "libavutil/avstring.h"
+
+static int ilbc_parse_fmtp(AVStream *stream, PayloadContext *data,
+ char *attr, char *value)
+{
+ if (!strcmp(attr, "mode")) {
+ int mode = atoi(value);
+ switch (mode) {
+ case 20:
+ stream->codec->block_align = 38;
+ break;
+ case 30:
+ stream->codec->block_align = 50;
+ break;
+ default:
+ av_log(NULL, AV_LOG_ERROR, "Unsupported iLBC mode %d\n", mode);
+ return AVERROR(EINVAL);
+ }
+ }
+ return 0;
+}
+
+static int ilbc_parse_sdp_line(AVFormatContext *s, int st_index,
+ PayloadContext *data, const char *line)
+{
+ const char *p;
+ AVStream *st;
+
+ if (st_index < 0)
+ return 0;
+ st = s->streams[st_index];
+
+ if (av_strstart(line, "fmtp:", &p)) {
+ int ret = ff_parse_fmtp(st, data, p, ilbc_parse_fmtp);
+ if (ret < 0)
+ return ret;
+ if (!st->codec->block_align) {
+ av_log(s, AV_LOG_ERROR, "No iLBC mode set\n");
+ return AVERROR(EINVAL);
+ }
+ }
+ return 0;
+}
+
+RTPDynamicProtocolHandler ff_ilbc_dynamic_handler = {
+ .enc_name = "iLBC",
+ .codec_type = AVMEDIA_TYPE_AUDIO,
+ .codec_id = CODEC_ID_ILBC,
+ .parse_sdp_a_line = ilbc_parse_sdp_line,
+};
diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c
index e16e610820..f7e2cf0630 100644
--- a/libavformat/rtpenc.c
+++ b/libavformat/rtpenc.c
@@ -74,6 +74,7 @@ static int is_supported(enum CodecID id)
case CODEC_ID_VP8:
case CODEC_ID_ADPCM_G722:
case CODEC_ID_ADPCM_G726:
+ case CODEC_ID_ILBC:
return 1;
default:
return 0;
@@ -187,6 +188,16 @@ static int rtp_write_header(AVFormatContext *s1)
* 8000, even if the sample rate is 16000. See RFC 3551. */
avpriv_set_pts_info(st, 32, 1, 8000);
break;
+ case CODEC_ID_ILBC:
+ if (st->codec->block_align != 38 && st->codec->block_align != 50) {
+ av_log(s1, AV_LOG_ERROR, "Incorrect iLBC block size specified\n");
+ goto fail;
+ }
+ if (!s->max_frames_per_packet)
+ s->max_frames_per_packet = 1;
+ s->max_frames_per_packet = FFMIN(s->max_frames_per_packet,
+ s->max_payload_size / st->codec->block_align);
+ goto defaultcase;
case CODEC_ID_AMR_NB:
case CODEC_ID_AMR_WB:
if (!s->max_frames_per_packet)
@@ -395,6 +406,36 @@ static void rtp_send_mpegts_raw(AVFormatContext *s1,
}
}
+static int rtp_send_ilbc(AVFormatContext *s1, const uint8_t *buf, int size)
+{
+ RTPMuxContext *s = s1->priv_data;
+ AVStream *st = s1->streams[0];
+ int frame_duration = av_get_audio_frame_duration(st->codec, 0);
+ int frame_size = st->codec->block_align;
+ int frames = size / frame_size;
+
+ while (frames > 0) {
+ int n = FFMIN(s->max_frames_per_packet - s->num_frames, frames);
+
+ if (!s->num_frames) {
+ s->buf_ptr = s->buf;
+ s->timestamp = s->cur_timestamp;
+ }
+ memcpy(s->buf_ptr, buf, n * frame_size);
+ frames -= n;
+ s->num_frames += n;
+ s->buf_ptr += n * frame_size;
+ buf += n * frame_size;
+ s->cur_timestamp += n * frame_duration;
+
+ if (s->num_frames == s->max_frames_per_packet) {
+ ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 1);
+ s->num_frames = 0;
+ }
+ }
+ return 0;
+}
+
static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
{
RTPMuxContext *s = s1->priv_data;
@@ -483,6 +524,9 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
case CODEC_ID_VP8:
ff_rtp_send_vp8(s1, pkt->data, size);
break;
+ case CODEC_ID_ILBC:
+ rtp_send_ilbc(s1, pkt->data, size);
+ break;
default:
/* better than nothing : send the codec raw data */
rtp_send_raw(s1, pkt->data, size);
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 891afc92a4..68ca247b00 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -1279,7 +1279,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
"%s/UDP;multicast", trans_pref);
}
if (s->oformat) {
- av_strlcat(transport, ";mode=receive", sizeof(transport));
+ av_strlcat(transport, ";mode=record", sizeof(transport));
} else if (rt->server_type == RTSP_SERVER_REAL ||
rt->server_type == RTSP_SERVER_WMS)
av_strlcat(transport, ";mode=play", sizeof(transport));
diff --git a/libavformat/sdp.c b/libavformat/sdp.c
index 5d5e9515f7..352dea0335 100644
--- a/libavformat/sdp.c
+++ b/libavformat/sdp.c
@@ -549,6 +549,12 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
c->sample_rate);
break;
}
+ case CODEC_ID_ILBC:
+ av_strlcatf(buff, size, "a=rtpmap:%d iLBC/%d\r\n"
+ "a=fmtp:%d mode=%d\r\n",
+ payload_type, c->sample_rate,
+ payload_type, c->block_align == 38 ? 20 : 30);
+ break;
default:
/* Nothing special to do here... */
break;
diff --git a/libavformat/version.h b/libavformat/version.h
index 0b1bff2764..3b61ea34fc 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -30,7 +30,7 @@
#include "libavutil/avutil.h"
#define LIBAVFORMAT_VERSION_MAJOR 54
-#define LIBAVFORMAT_VERSION_MINOR 8
+#define LIBAVFORMAT_VERSION_MINOR 9
#define LIBAVFORMAT_VERSION_MICRO 100
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \