diff --git a/libavformat/Makefile b/libavformat/Makefile index 7664087bbe..0d69448ad5 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -121,9 +121,9 @@ OBJS-$(CONFIG_RM_DEMUXER) += rmdec.o OBJS-$(CONFIG_RM_MUXER) += rmenc.o OBJS-$(CONFIG_ROQ_DEMUXER) += idroq.o OBJS-$(CONFIG_ROQ_MUXER) += raw.o -OBJS-$(CONFIG_RTP_MUXER) += rtp.o rtp_mpv.o rtp_aac.o +OBJS-$(CONFIG_RTP_MUXER) += rtp.o rtpenc.o rtp_mpv.o rtp_aac.o OBJS-$(CONFIG_RTSP_DEMUXER) += rtsp.o -OBJS-$(CONFIG_SDP_DEMUXER) += rtsp.o rtp.o rtpdec.o rtp_h264.o rtp_mpv.o rtp_aac.o +OBJS-$(CONFIG_SDP_DEMUXER) += rtsp.o rtp.o rtpdec.o rtp_h264.o OBJS-$(CONFIG_SEGAFILM_DEMUXER) += segafilm.o OBJS-$(CONFIG_SHORTEN_DEMUXER) += raw.o OBJS-$(CONFIG_SIFF_DEMUXER) += siff.o diff --git a/libavformat/rtp.c b/libavformat/rtp.c index 7841ef641f..ddd2ad1601 100644 --- a/libavformat/rtp.c +++ b/libavformat/rtp.c @@ -19,20 +19,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "avformat.h" -#include "mpegts.h" #include "bitstream.h" #include #include "network.h" #include "rtp_internal.h" -#include "rtp_mpv.h" -#include "rtp_aac.h" //#define DEBUG -#define RTCP_SR_SIZE 28 - /* from http://www.iana.org/assignments/rtp-parameters last updated 05 January 2005 */ AVRtpPayloadType_t AVRtpPayloadTypes[]= { @@ -225,326 +220,3 @@ enum CodecID ff_rtp_codec_id(const char *buf, enum CodecType codec_type) return CODEC_ID_NONE; } - -/* rtp output */ - -static int rtp_write_header(AVFormatContext *s1) -{ - RTPDemuxContext *s = s1->priv_data; - int payload_type, max_packet_size, n; - AVStream *st; - - if (s1->nb_streams != 1) - return -1; - st = s1->streams[0]; - - payload_type = rtp_get_payload_type(st->codec); - if (payload_type < 0) - payload_type = RTP_PT_PRIVATE; /* private payload type */ - s->payload_type = payload_type; - -// following 2 FIXMEs could be set based on the current time, there is normally no info leak, as RTP will likely be transmitted immediately - s->base_timestamp = 0; /* FIXME: was random(), what should this be? */ - s->timestamp = s->base_timestamp; - s->cur_timestamp = 0; - s->ssrc = 0; /* FIXME: was random(), what should this be? */ - s->first_packet = 1; - s->first_rtcp_ntp_time = AV_NOPTS_VALUE; - - max_packet_size = url_fget_max_packet_size(s1->pb); - if (max_packet_size <= 12) - return AVERROR(EIO); - s->max_payload_size = max_packet_size - 12; - - s->max_frames_per_packet = 0; - if (s1->max_delay) { - if (st->codec->codec_type == CODEC_TYPE_AUDIO) { - if (st->codec->frame_size == 0) { - av_log(s1, AV_LOG_ERROR, "Cannot respect max delay: frame size = 0\n"); - } else { - s->max_frames_per_packet = av_rescale_rnd(s1->max_delay, st->codec->sample_rate, AV_TIME_BASE * st->codec->frame_size, AV_ROUND_DOWN); - } - } - if (st->codec->codec_type == CODEC_TYPE_VIDEO) { - /* FIXME: We should round down here... */ - s->max_frames_per_packet = av_rescale_q(s1->max_delay, AV_TIME_BASE_Q, st->codec->time_base); - } - } - - av_set_pts_info(st, 32, 1, 90000); - switch(st->codec->codec_id) { - case CODEC_ID_MP2: - case CODEC_ID_MP3: - s->buf_ptr = s->buf + 4; - break; - case CODEC_ID_MPEG1VIDEO: - case CODEC_ID_MPEG2VIDEO: - break; - case CODEC_ID_MPEG2TS: - n = s->max_payload_size / TS_PACKET_SIZE; - if (n < 1) - n = 1; - s->max_payload_size = n * TS_PACKET_SIZE; - s->buf_ptr = s->buf; - break; - case CODEC_ID_AAC: - s->read_buf_index = 0; - default: - if (st->codec->codec_type == CODEC_TYPE_AUDIO) { - av_set_pts_info(st, 32, 1, st->codec->sample_rate); - } - s->buf_ptr = s->buf; - break; - } - - return 0; -} - -/* send an rtcp sender report packet */ -static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time) -{ - RTPDemuxContext *s = s1->priv_data; - uint32_t rtp_ts; - -#if defined(DEBUG) - printf("RTCP: %02x %"PRIx64" %x\n", s->payload_type, ntp_time, s->timestamp); -#endif - - if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE) s->first_rtcp_ntp_time = ntp_time; - s->last_rtcp_ntp_time = ntp_time; - rtp_ts = av_rescale_q(ntp_time - s->first_rtcp_ntp_time, AV_TIME_BASE_Q, - s1->streams[0]->time_base) + s->base_timestamp; - put_byte(s1->pb, (RTP_VERSION << 6)); - put_byte(s1->pb, 200); - put_be16(s1->pb, 6); /* length in words - 1 */ - put_be32(s1->pb, s->ssrc); - put_be32(s1->pb, ntp_time / 1000000); - put_be32(s1->pb, ((ntp_time % 1000000) << 32) / 1000000); - put_be32(s1->pb, rtp_ts); - put_be32(s1->pb, s->packet_count); - put_be32(s1->pb, s->octet_count); - put_flush_packet(s1->pb); -} - -/* send an rtp packet. sequence number is incremented, but the caller - must update the timestamp itself */ -void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m) -{ - RTPDemuxContext *s = s1->priv_data; - -#ifdef DEBUG - printf("rtp_send_data size=%d\n", len); -#endif - - /* build the RTP header */ - put_byte(s1->pb, (RTP_VERSION << 6)); - put_byte(s1->pb, (s->payload_type & 0x7f) | ((m & 0x01) << 7)); - put_be16(s1->pb, s->seq); - put_be32(s1->pb, s->timestamp); - put_be32(s1->pb, s->ssrc); - - put_buffer(s1->pb, buf1, len); - put_flush_packet(s1->pb); - - s->seq++; - s->octet_count += len; - s->packet_count++; -} - -/* send an integer number of samples and compute time stamp and fill - the rtp send buffer before sending. */ -static void rtp_send_samples(AVFormatContext *s1, - const uint8_t *buf1, int size, int sample_size) -{ - RTPDemuxContext *s = s1->priv_data; - int len, max_packet_size, n; - - max_packet_size = (s->max_payload_size / sample_size) * sample_size; - /* not needed, but who nows */ - if ((size % sample_size) != 0) - av_abort(); - n = 0; - while (size > 0) { - s->buf_ptr = s->buf; - len = FFMIN(max_packet_size, size); - - /* copy data */ - memcpy(s->buf_ptr, buf1, len); - s->buf_ptr += len; - buf1 += len; - size -= len; - s->timestamp = s->cur_timestamp + n / sample_size; - ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0); - n += (s->buf_ptr - s->buf); - } -} - -/* NOTE: we suppose that exactly one frame is given as argument here */ -/* XXX: test it */ -static void rtp_send_mpegaudio(AVFormatContext *s1, - const uint8_t *buf1, int size) -{ - RTPDemuxContext *s = s1->priv_data; - int len, count, max_packet_size; - - max_packet_size = s->max_payload_size; - - /* test if we must flush because not enough space */ - len = (s->buf_ptr - s->buf); - if ((len + size) > max_packet_size) { - if (len > 4) { - ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0); - s->buf_ptr = s->buf + 4; - } - } - if (s->buf_ptr == s->buf + 4) { - s->timestamp = s->cur_timestamp; - } - - /* add the packet */ - if (size > max_packet_size) { - /* big packet: fragment */ - count = 0; - while (size > 0) { - len = max_packet_size - 4; - if (len > size) - len = size; - /* build fragmented packet */ - s->buf[0] = 0; - s->buf[1] = 0; - s->buf[2] = count >> 8; - s->buf[3] = count; - memcpy(s->buf + 4, buf1, len); - ff_rtp_send_data(s1, s->buf, len + 4, 0); - size -= len; - buf1 += len; - count += len; - } - } else { - if (s->buf_ptr == s->buf + 4) { - /* no fragmentation possible */ - s->buf[0] = 0; - s->buf[1] = 0; - s->buf[2] = 0; - s->buf[3] = 0; - } - memcpy(s->buf_ptr, buf1, size); - s->buf_ptr += size; - } -} - -static void rtp_send_raw(AVFormatContext *s1, - const uint8_t *buf1, int size) -{ - RTPDemuxContext *s = s1->priv_data; - int len, max_packet_size; - - max_packet_size = s->max_payload_size; - - while (size > 0) { - len = max_packet_size; - if (len > size) - len = size; - - s->timestamp = s->cur_timestamp; - ff_rtp_send_data(s1, buf1, len, (len == size)); - - buf1 += len; - size -= len; - } -} - -/* NOTE: size is assumed to be an integer multiple of TS_PACKET_SIZE */ -static void rtp_send_mpegts_raw(AVFormatContext *s1, - const uint8_t *buf1, int size) -{ - RTPDemuxContext *s = s1->priv_data; - int len, out_len; - - while (size >= TS_PACKET_SIZE) { - len = s->max_payload_size - (s->buf_ptr - s->buf); - if (len > size) - len = size; - memcpy(s->buf_ptr, buf1, len); - buf1 += len; - size -= len; - s->buf_ptr += len; - - out_len = s->buf_ptr - s->buf; - if (out_len >= s->max_payload_size) { - ff_rtp_send_data(s1, s->buf, out_len, 0); - s->buf_ptr = s->buf; - } - } -} - -/* write an RTP packet. 'buf1' must contain a single specific frame. */ -static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) -{ - RTPDemuxContext *s = s1->priv_data; - AVStream *st = s1->streams[0]; - int rtcp_bytes; - int size= pkt->size; - uint8_t *buf1= pkt->data; - -#ifdef DEBUG - printf("%d: write len=%d\n", pkt->stream_index, size); -#endif - - /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */ - rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) / - RTCP_TX_RATIO_DEN; - if (s->first_packet || ((rtcp_bytes >= RTCP_SR_SIZE) && - (av_gettime() - s->last_rtcp_ntp_time > 5000000))) { - rtcp_send_sr(s1, av_gettime()); - s->last_octet_count = s->octet_count; - s->first_packet = 0; - } - s->cur_timestamp = s->base_timestamp + pkt->pts; - - switch(st->codec->codec_id) { - case CODEC_ID_PCM_MULAW: - case CODEC_ID_PCM_ALAW: - case CODEC_ID_PCM_U8: - case CODEC_ID_PCM_S8: - rtp_send_samples(s1, buf1, size, 1 * st->codec->channels); - break; - case CODEC_ID_PCM_U16BE: - case CODEC_ID_PCM_U16LE: - case CODEC_ID_PCM_S16BE: - case CODEC_ID_PCM_S16LE: - rtp_send_samples(s1, buf1, size, 2 * st->codec->channels); - break; - case CODEC_ID_MP2: - case CODEC_ID_MP3: - rtp_send_mpegaudio(s1, buf1, size); - break; - case CODEC_ID_MPEG1VIDEO: - case CODEC_ID_MPEG2VIDEO: - ff_rtp_send_mpegvideo(s1, buf1, size); - break; - case CODEC_ID_AAC: - ff_rtp_send_aac(s1, buf1, size); - break; - case CODEC_ID_MPEG2TS: - rtp_send_mpegts_raw(s1, buf1, size); - break; - default: - /* better than nothing : send the codec raw data */ - rtp_send_raw(s1, buf1, size); - break; - } - return 0; -} - -AVOutputFormat rtp_muxer = { - "rtp", - "RTP output format", - NULL, - NULL, - sizeof(RTPDemuxContext), - CODEC_ID_PCM_MULAW, - CODEC_ID_NONE, - rtp_write_header, - rtp_write_packet, -}; diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c new file mode 100644 index 0000000000..291d474204 --- /dev/null +++ b/libavformat/rtpenc.c @@ -0,0 +1,355 @@ +/* + * RTP output format + * Copyright (c) 2002 Fabrice Bellard. + * + * 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 "mpegts.h" +#include "bitstream.h" + +#include +#include "network.h" + +#include "rtp_internal.h" +#include "rtp_mpv.h" +#include "rtp_aac.h" + +//#define DEBUG + +#define RTCP_SR_SIZE 28 + +static int rtp_write_header(AVFormatContext *s1) +{ + RTPDemuxContext *s = s1->priv_data; + int payload_type, max_packet_size, n; + AVStream *st; + + if (s1->nb_streams != 1) + return -1; + st = s1->streams[0]; + + payload_type = rtp_get_payload_type(st->codec); + if (payload_type < 0) + payload_type = RTP_PT_PRIVATE; /* private payload type */ + s->payload_type = payload_type; + +// following 2 FIXMEs could be set based on the current time, there is normally no info leak, as RTP will likely be transmitted immediately + s->base_timestamp = 0; /* FIXME: was random(), what should this be? */ + s->timestamp = s->base_timestamp; + s->cur_timestamp = 0; + s->ssrc = 0; /* FIXME: was random(), what should this be? */ + s->first_packet = 1; + s->first_rtcp_ntp_time = AV_NOPTS_VALUE; + + max_packet_size = url_fget_max_packet_size(s1->pb); + if (max_packet_size <= 12) + return AVERROR(EIO); + s->max_payload_size = max_packet_size - 12; + + s->max_frames_per_packet = 0; + if (s1->max_delay) { + if (st->codec->codec_type == CODEC_TYPE_AUDIO) { + if (st->codec->frame_size == 0) { + av_log(s1, AV_LOG_ERROR, "Cannot respect max delay: frame size = 0\n"); + } else { + s->max_frames_per_packet = av_rescale_rnd(s1->max_delay, st->codec->sample_rate, AV_TIME_BASE * st->codec->frame_size, AV_ROUND_DOWN); + } + } + if (st->codec->codec_type == CODEC_TYPE_VIDEO) { + /* FIXME: We should round down here... */ + s->max_frames_per_packet = av_rescale_q(s1->max_delay, AV_TIME_BASE_Q, st->codec->time_base); + } + } + + av_set_pts_info(st, 32, 1, 90000); + switch(st->codec->codec_id) { + case CODEC_ID_MP2: + case CODEC_ID_MP3: + s->buf_ptr = s->buf + 4; + break; + case CODEC_ID_MPEG1VIDEO: + case CODEC_ID_MPEG2VIDEO: + break; + case CODEC_ID_MPEG2TS: + n = s->max_payload_size / TS_PACKET_SIZE; + if (n < 1) + n = 1; + s->max_payload_size = n * TS_PACKET_SIZE; + s->buf_ptr = s->buf; + break; + case CODEC_ID_AAC: + s->read_buf_index = 0; + default: + if (st->codec->codec_type == CODEC_TYPE_AUDIO) { + av_set_pts_info(st, 32, 1, st->codec->sample_rate); + } + s->buf_ptr = s->buf; + break; + } + + return 0; +} + +/* send an rtcp sender report packet */ +static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time) +{ + RTPDemuxContext *s = s1->priv_data; + uint32_t rtp_ts; + +#if defined(DEBUG) + printf("RTCP: %02x %"PRIx64" %x\n", s->payload_type, ntp_time, s->timestamp); +#endif + + if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE) s->first_rtcp_ntp_time = ntp_time; + s->last_rtcp_ntp_time = ntp_time; + rtp_ts = av_rescale_q(ntp_time - s->first_rtcp_ntp_time, AV_TIME_BASE_Q, + s1->streams[0]->time_base) + s->base_timestamp; + put_byte(s1->pb, (RTP_VERSION << 6)); + put_byte(s1->pb, 200); + put_be16(s1->pb, 6); /* length in words - 1 */ + put_be32(s1->pb, s->ssrc); + put_be32(s1->pb, ntp_time / 1000000); + put_be32(s1->pb, ((ntp_time % 1000000) << 32) / 1000000); + put_be32(s1->pb, rtp_ts); + put_be32(s1->pb, s->packet_count); + put_be32(s1->pb, s->octet_count); + put_flush_packet(s1->pb); +} + +/* send an rtp packet. sequence number is incremented, but the caller + must update the timestamp itself */ +void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m) +{ + RTPDemuxContext *s = s1->priv_data; + +#ifdef DEBUG + printf("rtp_send_data size=%d\n", len); +#endif + + /* build the RTP header */ + put_byte(s1->pb, (RTP_VERSION << 6)); + put_byte(s1->pb, (s->payload_type & 0x7f) | ((m & 0x01) << 7)); + put_be16(s1->pb, s->seq); + put_be32(s1->pb, s->timestamp); + put_be32(s1->pb, s->ssrc); + + put_buffer(s1->pb, buf1, len); + put_flush_packet(s1->pb); + + s->seq++; + s->octet_count += len; + s->packet_count++; +} + +/* send an integer number of samples and compute time stamp and fill + the rtp send buffer before sending. */ +static void rtp_send_samples(AVFormatContext *s1, + const uint8_t *buf1, int size, int sample_size) +{ + RTPDemuxContext *s = s1->priv_data; + int len, max_packet_size, n; + + max_packet_size = (s->max_payload_size / sample_size) * sample_size; + /* not needed, but who nows */ + if ((size % sample_size) != 0) + av_abort(); + n = 0; + while (size > 0) { + s->buf_ptr = s->buf; + len = FFMIN(max_packet_size, size); + + /* copy data */ + memcpy(s->buf_ptr, buf1, len); + s->buf_ptr += len; + buf1 += len; + size -= len; + s->timestamp = s->cur_timestamp + n / sample_size; + ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0); + n += (s->buf_ptr - s->buf); + } +} + +/* NOTE: we suppose that exactly one frame is given as argument here */ +/* XXX: test it */ +static void rtp_send_mpegaudio(AVFormatContext *s1, + const uint8_t *buf1, int size) +{ + RTPDemuxContext *s = s1->priv_data; + int len, count, max_packet_size; + + max_packet_size = s->max_payload_size; + + /* test if we must flush because not enough space */ + len = (s->buf_ptr - s->buf); + if ((len + size) > max_packet_size) { + if (len > 4) { + ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0); + s->buf_ptr = s->buf + 4; + } + } + if (s->buf_ptr == s->buf + 4) { + s->timestamp = s->cur_timestamp; + } + + /* add the packet */ + if (size > max_packet_size) { + /* big packet: fragment */ + count = 0; + while (size > 0) { + len = max_packet_size - 4; + if (len > size) + len = size; + /* build fragmented packet */ + s->buf[0] = 0; + s->buf[1] = 0; + s->buf[2] = count >> 8; + s->buf[3] = count; + memcpy(s->buf + 4, buf1, len); + ff_rtp_send_data(s1, s->buf, len + 4, 0); + size -= len; + buf1 += len; + count += len; + } + } else { + if (s->buf_ptr == s->buf + 4) { + /* no fragmentation possible */ + s->buf[0] = 0; + s->buf[1] = 0; + s->buf[2] = 0; + s->buf[3] = 0; + } + memcpy(s->buf_ptr, buf1, size); + s->buf_ptr += size; + } +} + +static void rtp_send_raw(AVFormatContext *s1, + const uint8_t *buf1, int size) +{ + RTPDemuxContext *s = s1->priv_data; + int len, max_packet_size; + + max_packet_size = s->max_payload_size; + + while (size > 0) { + len = max_packet_size; + if (len > size) + len = size; + + s->timestamp = s->cur_timestamp; + ff_rtp_send_data(s1, buf1, len, (len == size)); + + buf1 += len; + size -= len; + } +} + +/* NOTE: size is assumed to be an integer multiple of TS_PACKET_SIZE */ +static void rtp_send_mpegts_raw(AVFormatContext *s1, + const uint8_t *buf1, int size) +{ + RTPDemuxContext *s = s1->priv_data; + int len, out_len; + + while (size >= TS_PACKET_SIZE) { + len = s->max_payload_size - (s->buf_ptr - s->buf); + if (len > size) + len = size; + memcpy(s->buf_ptr, buf1, len); + buf1 += len; + size -= len; + s->buf_ptr += len; + + out_len = s->buf_ptr - s->buf; + if (out_len >= s->max_payload_size) { + ff_rtp_send_data(s1, s->buf, out_len, 0); + s->buf_ptr = s->buf; + } + } +} + +/* write an RTP packet. 'buf1' must contain a single specific frame. */ +static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) +{ + RTPDemuxContext *s = s1->priv_data; + AVStream *st = s1->streams[0]; + int rtcp_bytes; + int size= pkt->size; + uint8_t *buf1= pkt->data; + +#ifdef DEBUG + printf("%d: write len=%d\n", pkt->stream_index, size); +#endif + + /* XXX: mpeg pts hardcoded. RTCP send every 0.5 seconds */ + rtcp_bytes = ((s->octet_count - s->last_octet_count) * RTCP_TX_RATIO_NUM) / + RTCP_TX_RATIO_DEN; + if (s->first_packet || ((rtcp_bytes >= RTCP_SR_SIZE) && + (av_gettime() - s->last_rtcp_ntp_time > 5000000))) { + rtcp_send_sr(s1, av_gettime()); + s->last_octet_count = s->octet_count; + s->first_packet = 0; + } + s->cur_timestamp = s->base_timestamp + pkt->pts; + + switch(st->codec->codec_id) { + case CODEC_ID_PCM_MULAW: + case CODEC_ID_PCM_ALAW: + case CODEC_ID_PCM_U8: + case CODEC_ID_PCM_S8: + rtp_send_samples(s1, buf1, size, 1 * st->codec->channels); + break; + case CODEC_ID_PCM_U16BE: + case CODEC_ID_PCM_U16LE: + case CODEC_ID_PCM_S16BE: + case CODEC_ID_PCM_S16LE: + rtp_send_samples(s1, buf1, size, 2 * st->codec->channels); + break; + case CODEC_ID_MP2: + case CODEC_ID_MP3: + rtp_send_mpegaudio(s1, buf1, size); + break; + case CODEC_ID_MPEG1VIDEO: + case CODEC_ID_MPEG2VIDEO: + ff_rtp_send_mpegvideo(s1, buf1, size); + break; + case CODEC_ID_AAC: + ff_rtp_send_aac(s1, buf1, size); + break; + case CODEC_ID_MPEG2TS: + rtp_send_mpegts_raw(s1, buf1, size); + break; + default: + /* better than nothing : send the codec raw data */ + rtp_send_raw(s1, buf1, size); + break; + } + return 0; +} + +AVOutputFormat rtp_muxer = { + "rtp", + "RTP output format", + NULL, + NULL, + sizeof(RTPDemuxContext), + CODEC_ID_PCM_MULAW, + CODEC_ID_NONE, + rtp_write_header, + rtp_write_packet, +};