rtp.o \
rtpdec.o \
rtpdec_amr.o \
+ rtpdec_asf.o \
rtpdec_h263.o \
- rtp_asf.o \
- rtp_h264.o \
- rtp_vorbis.o
+ rtpdec_h264.o \
+ rtpdec_vorbis.o
OBJS-$(CONFIG_SEGAFILM_DEMUXER) += segafilm.o
OBJS-$(CONFIG_SHORTEN_DEMUXER) += raw.o id3v2.o
OBJS-$(CONFIG_SIFF_DEMUXER) += siff.o
+++ /dev/null
-/*
- * Microsoft RTP/ASF support.
- * Copyright (c) 2008 Ronald S. Bultje
- *
- * 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
- */
-
-/**
- * @file libavformat/rtp_asf.c
- * @brief Microsoft RTP/ASF support
- * @author Ronald S. Bultje <rbultje@ronald.bitfreak.net>
- */
-
-#include <libavutil/base64.h>
-#include <libavutil/avstring.h>
-#include <libavutil/intreadwrite.h>
-#include "rtp.h"
-#include "rtp_asf.h"
-#include "rtsp.h"
-#include "asf.h"
-
-/**
- * From MSDN 2.2.1.4, we learn that ASF data packets over RTP should not
- * contain any padding. Unfortunately, the header min/max_pktsize are not
- * updated (thus making min_pktsize invalid). Here, we "fix" these faulty
- * min_pktsize values in the ASF file header.
- * @return 0 on success, <0 on failure (currently -1).
- */
-static int rtp_asf_fix_header(uint8_t *buf, int len)
-{
- uint8_t *p = buf, *end = buf + len;
-
- if (len < sizeof(ff_asf_guid) * 2 + 22 ||
- memcmp(p, ff_asf_header, sizeof(ff_asf_guid))) {
- return -1;
- }
- p += sizeof(ff_asf_guid) + 14;
- do {
- uint64_t chunksize = AV_RL64(p + sizeof(ff_asf_guid));
- if (memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) {
- if (chunksize > end - p)
- return -1;
- p += chunksize;
- continue;
- }
-
- /* skip most of the file header, to min_pktsize */
- p += 6 * 8 + 3 * 4 + sizeof(ff_asf_guid) * 2;
- if (p + 8 <= end && AV_RL32(p) == AV_RL32(p + 4)) {
- /* and set that to zero */
- AV_WL32(p, 0);
- return 0;
- }
- break;
- } while (end - p >= sizeof(ff_asf_guid) + 8);
-
- return -1;
-}
-
-/**
- * The following code is basically a buffered ByteIOContext,
- * with the added benefit of returning -EAGAIN (instead of 0)
- * on packet boundaries, such that the ASF demuxer can return
- * safely and resume business at the next packet.
- */
-static int packetizer_read(void *opaque, uint8_t *buf, int buf_size)
-{
- return AVERROR(EAGAIN);
-}
-
-static void init_packetizer(ByteIOContext *pb, uint8_t *buf, int len)
-{
- init_put_byte(pb, buf, len, 0, NULL, packetizer_read, NULL, NULL);
-
- /* this "fills" the buffer with its current content */
- pb->pos = len;
- pb->buf_end = buf + len;
-}
-
-void ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p)
-{
- if (av_strstart(p, "pgmpu:data:application/vnd.ms.wms-hdr.asfv1;base64,", &p)) {
- ByteIOContext pb;
- RTSPState *rt = s->priv_data;
- int len = strlen(p) * 6 / 8;
- char *buf = av_mallocz(len);
- av_base64_decode(buf, p, len);
-
- if (rtp_asf_fix_header(buf, len) < 0)
- av_log(s, AV_LOG_ERROR,
- "Failed to fix invalid RTSP-MS/ASF min_pktsize\n");
- init_packetizer(&pb, buf, len);
- if (rt->asf_ctx) {
- av_close_input_stream(rt->asf_ctx);
- rt->asf_ctx = NULL;
- }
- av_open_input_stream(&rt->asf_ctx, &pb, "", &asf_demuxer, NULL);
- rt->asf_pb_pos = url_ftell(&pb);
- av_free(buf);
- rt->asf_ctx->pb = NULL;
- }
-}
-
-static int asfrtp_parse_sdp_line(AVFormatContext *s, int stream_index,
- PayloadContext *asf, const char *line)
-{
- if (av_strstart(line, "stream:", &line)) {
- RTSPState *rt = s->priv_data;
-
- s->streams[stream_index]->id = strtol(line, NULL, 10);
-
- if (rt->asf_ctx) {
- int i;
-
- for (i = 0; i < rt->asf_ctx->nb_streams; i++) {
- if (s->streams[stream_index]->id == rt->asf_ctx->streams[i]->id) {
- *s->streams[stream_index]->codec =
- *rt->asf_ctx->streams[i]->codec;
- rt->asf_ctx->streams[i]->codec->extradata_size = 0;
- rt->asf_ctx->streams[i]->codec->extradata = NULL;
- av_set_pts_info(s->streams[stream_index], 32, 1, 1000);
- }
- }
- }
- }
-
- return 0;
-}
-
-struct PayloadContext {
- ByteIOContext *pktbuf, pb;
- char *buf;
-};
-
-/**
- * @return 0 when a packet was written into /p pkt, and no more data is left;
- * 1 when a packet was written into /p pkt, and more packets might be left;
- * <0 when not enough data was provided to return a full packet, or on error.
- */
-static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf,
- AVStream *st, AVPacket *pkt,
- uint32_t *timestamp,
- const uint8_t *buf, int len, int flags)
-{
- ByteIOContext *pb = &asf->pb;
- int res, mflags, len_off;
- RTSPState *rt = s->priv_data;
-
- if (!rt->asf_ctx)
- return -1;
-
- if (len > 0) {
- int off, out_len;
-
- if (len < 4)
- return -1;
-
- init_put_byte(pb, buf, len, 0, NULL, NULL, NULL, NULL);
- mflags = get_byte(pb);
- if (mflags & 0x80)
- flags |= RTP_FLAG_KEY;
- len_off = get_be24(pb);
- if (mflags & 0x20) /**< relative timestamp */
- url_fskip(pb, 4);
- if (mflags & 0x10) /**< has duration */
- url_fskip(pb, 4);
- if (mflags & 0x8) /**< has location ID */
- url_fskip(pb, 4);
- off = url_ftell(pb);
-
- av_freep(&asf->buf);
- if (!(mflags & 0x40)) {
- /**
- * If 0x40 is not set, the len_off field specifies an offset of this
- * packet's payload data in the complete (reassembled) ASF packet.
- * This is used to spread one ASF packet over multiple RTP packets.
- */
- if (asf->pktbuf && len_off != url_ftell(asf->pktbuf)) {
- uint8_t *p;
- url_close_dyn_buf(asf->pktbuf, &p);
- asf->pktbuf = NULL;
- av_free(p);
- }
- if (!len_off && !asf->pktbuf &&
- (res = url_open_dyn_buf(&asf->pktbuf)) < 0)
- return res;
- if (!asf->pktbuf)
- return AVERROR(EIO);
-
- put_buffer(asf->pktbuf, buf + off, len - off);
- if (!(flags & RTP_FLAG_MARKER))
- return -1;
- out_len = url_close_dyn_buf(asf->pktbuf, &asf->buf);
- asf->pktbuf = NULL;
- } else {
- /**
- * If 0x40 is set, the len_off field specifies the length of the
- * next ASF packet that can be read from this payload data alone.
- * This is commonly the same as the payload size, but could be
- * less in case of packet splitting (i.e. multiple ASF packets in
- * one RTP packet).
- */
- if (len_off != len) {
- av_log_missing_feature(s,
- "RTSP-MS packet splitting", 1);
- return -1;
- }
- asf->buf = av_malloc(len - off);
- out_len = len - off;
- memcpy(asf->buf, buf + off, len - off);
- }
-
- init_packetizer(pb, asf->buf, out_len);
- pb->pos += rt->asf_pb_pos;
- pb->eof_reached = 0;
- rt->asf_ctx->pb = pb;
- }
-
- for (;;) {
- int i;
-
- res = av_read_packet(rt->asf_ctx, pkt);
- rt->asf_pb_pos = url_ftell(pb);
- if (res != 0)
- break;
- for (i = 0; i < s->nb_streams; i++) {
- if (s->streams[i]->id == rt->asf_ctx->streams[pkt->stream_index]->id) {
- pkt->stream_index = i;
- return 1; // FIXME: return 0 if last packet
- }
- }
- av_free_packet(pkt);
- }
-
- return res == 1 ? -1 : res;
-}
-
-static PayloadContext *asfrtp_new_context(void)
-{
- return av_mallocz(sizeof(PayloadContext));
-}
-
-static void asfrtp_free_context(PayloadContext *asf)
-{
- if (asf->pktbuf) {
- uint8_t *p = NULL;
- url_close_dyn_buf(asf->pktbuf, &p);
- asf->pktbuf = NULL;
- av_free(p);
- }
- av_freep(&asf->buf);
- av_free(asf);
-}
-
-#define RTP_ASF_HANDLER(n, s, t) \
-RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \
- .enc_name = s, \
- .codec_type = t, \
- .codec_id = CODEC_ID_NONE, \
- .parse_sdp_a_line = asfrtp_parse_sdp_line, \
- .open = asfrtp_new_context, \
- .close = asfrtp_free_context, \
- .parse_packet = asfrtp_parse_packet, \
-};
-
-RTP_ASF_HANDLER(asf_pfv, "x-asf-pf", CODEC_TYPE_VIDEO);
-RTP_ASF_HANDLER(asf_pfa, "x-asf-pf", CODEC_TYPE_AUDIO);
+++ /dev/null
-/*
- * Microsoft RTP/ASF support.
- * Copyright (c) 2008 Ronald S. Bultje
- *
- * 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
- */
-
-#ifndef AVFORMAT_RTP_ASF_H
-#define AVFORMAT_RTP_ASF_H
-
-#include "avformat.h"
-#include "rtpdec.h"
-
-/**
- * Parse a Windows Media Server-specific SDP line
- *
- * @param s RTSP demux context
- * @param line the SDP line to be parsed
- */
-void ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p);
-
-/**
- * Handlers for the x-asf-pf payloads (the payload ID for RTP/ASF).
- * Defined and implemented in rtp_asf.c, registered in rtpdec.c.
- */
-extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfv_handler,
- ff_ms_rtp_asf_pfa_handler;
-
-#endif /* AVFORMAT_RTP_ASF_H */
+++ /dev/null
-/*
- * RTP H264 Protocol (RFC3984)
- * Copyright (c) 2006 Ryan Martell
- *
- * 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
- */
-
-/**
-* @file libavformat/rtp_h264.c
- * @brief H.264 / RTP Code (RFC3984)
- * @author Ryan Martell <rdm4@martellventures.com>
- *
- * @note Notes:
- * Notes:
- * This currently supports packetization mode:
- * Single Nal Unit Mode (0), or
- * Non-Interleaved Mode (1). It currently does not support
- * Interleaved Mode (2). (This requires implementing STAP-B, MTAP16, MTAP24, FU-B packet types)
- *
- * @note TODO:
- * 1) RTCP sender reports for udp streams are required..
- *
- */
-
-#include "libavutil/base64.h"
-#include "libavutil/avstring.h"
-#include "libavcodec/get_bits.h"
-#include "avformat.h"
-#include "mpegts.h"
-
-#include <unistd.h>
-#include "network.h"
-#include <assert.h>
-
-#include "rtpdec.h"
-#include "rtp_h264.h"
-
-/**
- RTP/H264 specific private data.
-*/
-struct PayloadContext {
- unsigned long cookie; ///< sanity check, to make sure we get the pointer we're expecting.
-
- //sdp setup parameters
- uint8_t profile_idc; ///< from the sdp setup parameters.
- uint8_t profile_iop; ///< from the sdp setup parameters.
- uint8_t level_idc; ///< from the sdp setup parameters.
- int packetization_mode; ///< from the sdp setup parameters.
-#ifdef DEBUG
- int packet_types_received[32];
-#endif
-};
-
-#define MAGIC_COOKIE (0xdeadbeef) ///< Cookie for the extradata; to verify we are what we think we are, and that we haven't been freed.
-#define DEAD_COOKIE (0xdeaddead) ///< Cookie for the extradata; once it is freed.
-
-/* ---------------- private code */
-static void sdp_parse_fmtp_config_h264(AVStream * stream,
- PayloadContext * h264_data,
- char *attr, char *value)
-{
- AVCodecContext *codec = stream->codec;
- assert(codec->codec_id == CODEC_ID_H264);
- assert(h264_data != NULL);
-
- if (!strcmp(attr, "packetization-mode")) {
- av_log(codec, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value));
- h264_data->packetization_mode = atoi(value);
- /*
- Packetization Mode:
- 0 or not present: Single NAL mode (Only nals from 1-23 are allowed)
- 1: Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed.
- 2: Interleaved Mode: 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A), and 29 (FU-B) are allowed.
- */
- if (h264_data->packetization_mode > 1)
- av_log(codec, AV_LOG_ERROR,
- "Interleaved RTP mode is not supported yet.");
- } else if (!strcmp(attr, "profile-level-id")) {
- if (strlen(value) == 6) {
- char buffer[3];
- // 6 characters=3 bytes, in hex.
- uint8_t profile_idc;
- uint8_t profile_iop;
- uint8_t level_idc;
-
- buffer[0] = value[0]; buffer[1] = value[1]; buffer[2] = '\0';
- profile_idc = strtol(buffer, NULL, 16);
- buffer[0] = value[2]; buffer[1] = value[3];
- profile_iop = strtol(buffer, NULL, 16);
- buffer[0] = value[4]; buffer[1] = value[5];
- level_idc = strtol(buffer, NULL, 16);
-
- // set the parameters...
- av_log(codec, AV_LOG_DEBUG,
- "RTP Profile IDC: %x Profile IOP: %x Level: %x\n",
- profile_idc, profile_iop, level_idc);
- h264_data->profile_idc = profile_idc;
- h264_data->profile_iop = profile_iop;
- h264_data->level_idc = level_idc;
- }
- } else if (!strcmp(attr, "sprop-parameter-sets")) {
- uint8_t start_sequence[]= { 0, 0, 1 };
- codec->extradata_size= 0;
- codec->extradata= NULL;
-
- while (*value) {
- char base64packet[1024];
- uint8_t decoded_packet[1024];
- uint32_t packet_size;
- char *dst = base64packet;
-
- while (*value && *value != ','
- && (dst - base64packet) < sizeof(base64packet) - 1) {
- *dst++ = *value++;
- }
- *dst++ = '\0';
-
- if (*value == ',')
- value++;
-
- packet_size= av_base64_decode(decoded_packet, base64packet, sizeof(decoded_packet));
- if (packet_size) {
- uint8_t *dest= av_malloc(packet_size+sizeof(start_sequence)+codec->extradata_size);
- if(dest)
- {
- if(codec->extradata_size)
- {
- // av_realloc?
- memcpy(dest, codec->extradata, codec->extradata_size);
- av_free(codec->extradata);
- }
-
- memcpy(dest+codec->extradata_size, start_sequence, sizeof(start_sequence));
- memcpy(dest+codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size);
-
- codec->extradata= dest;
- codec->extradata_size+= sizeof(start_sequence)+packet_size;
- } else {
- av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!");
- }
- }
- }
- av_log(codec, AV_LOG_DEBUG, "Extradata set to %p (size: %d)!", codec->extradata, codec->extradata_size);
- }
-}
-
-// return 0 on packet, no more left, 1 on packet, 1 on partial packet...
-static int h264_handle_packet(AVFormatContext *ctx,
- PayloadContext *data,
- AVStream *st,
- AVPacket * pkt,
- uint32_t * timestamp,
- const uint8_t * buf,
- int len, int flags)
-{
- uint8_t nal = buf[0];
- uint8_t type = (nal & 0x1f);
- int result= 0;
- uint8_t start_sequence[]= {0, 0, 1};
-
-#ifdef DEBUG
- assert(data);
- assert(data->cookie == MAGIC_COOKIE);
-#endif
- assert(buf);
-
- if (type >= 1 && type <= 23)
- type = 1; // simplify the case. (these are all the nal types used internally by the h264 codec)
- switch (type) {
- case 0: // undefined;
- result= -1;
- break;
-
- case 1:
- av_new_packet(pkt, len+sizeof(start_sequence));
- memcpy(pkt->data, start_sequence, sizeof(start_sequence));
- memcpy(pkt->data+sizeof(start_sequence), buf, len);
-#ifdef DEBUG
- data->packet_types_received[nal & 0x1f]++;
-#endif
- break;
-
- case 24: // STAP-A (one packet, multiple nals)
- // consume the STAP-A NAL
- buf++;
- len--;
- // first we are going to figure out the total size....
- {
- int pass= 0;
- int total_length= 0;
- uint8_t *dst= NULL;
-
- for(pass= 0; pass<2; pass++) {
- const uint8_t *src= buf;
- int src_len= len;
-
- do {
- uint16_t nal_size = AV_RB16(src); // this going to be a problem if unaligned (can it be?)
-
- // consume the length of the aggregate...
- src += 2;
- src_len -= 2;
-
- if (nal_size <= src_len) {
- if(pass==0) {
- // counting...
- total_length+= sizeof(start_sequence)+nal_size;
- } else {
- // copying
- assert(dst);
- memcpy(dst, start_sequence, sizeof(start_sequence));
- dst+= sizeof(start_sequence);
- memcpy(dst, src, nal_size);
-#ifdef DEBUG
- data->packet_types_received[*src & 0x1f]++;
-#endif
- dst+= nal_size;
- }
- } else {
- av_log(ctx, AV_LOG_ERROR,
- "nal size exceeds length: %d %d\n", nal_size, src_len);
- }
-
- // eat what we handled...
- src += nal_size;
- src_len -= nal_size;
-
- if (src_len < 0)
- av_log(ctx, AV_LOG_ERROR,
- "Consumed more bytes than we got! (%d)\n", src_len);
- } while (src_len > 2); // because there could be rtp padding..
-
- if(pass==0) {
- // now we know the total size of the packet (with the start sequences added)
- av_new_packet(pkt, total_length);
- dst= pkt->data;
- } else {
- assert(dst-pkt->data==total_length);
- }
- }
- }
- break;
-
- case 25: // STAP-B
- case 26: // MTAP-16
- case 27: // MTAP-24
- case 29: // FU-B
- av_log(ctx, AV_LOG_ERROR,
- "Unhandled type (%d) (See RFC for implementation details\n",
- type);
- result= -1;
- break;
-
- case 28: // FU-A (fragmented nal)
- buf++;
- len--; // skip the fu_indicator
- {
- // these are the same as above, we just redo them here for clarity...
- uint8_t fu_indicator = nal;
- uint8_t fu_header = *buf; // read the fu_header.
- uint8_t start_bit = fu_header >> 7;
-// uint8_t end_bit = (fu_header & 0x40) >> 6;
- uint8_t nal_type = (fu_header & 0x1f);
- uint8_t reconstructed_nal;
-
- // reconstruct this packet's true nal; only the data follows..
- reconstructed_nal = fu_indicator & (0xe0); // the original nal forbidden bit and NRI are stored in this packet's nal;
- reconstructed_nal |= nal_type;
-
- // skip the fu_header...
- buf++;
- len--;
-
-#ifdef DEBUG
- if (start_bit)
- data->packet_types_received[nal_type]++;
-#endif
- if(start_bit) {
- // copy in the start sequence, and the reconstructed nal....
- av_new_packet(pkt, sizeof(start_sequence)+sizeof(nal)+len);
- memcpy(pkt->data, start_sequence, sizeof(start_sequence));
- pkt->data[sizeof(start_sequence)]= reconstructed_nal;
- memcpy(pkt->data+sizeof(start_sequence)+sizeof(nal), buf, len);
- } else {
- av_new_packet(pkt, len);
- memcpy(pkt->data, buf, len);
- }
- }
- break;
-
- case 30: // undefined
- case 31: // undefined
- default:
- av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)", type);
- result= -1;
- break;
- }
-
- pkt->stream_index = st->index;
-
- return result;
-}
-
-/* ---------------- public code */
-static PayloadContext *h264_new_context(void)
-{
- PayloadContext *data =
- av_mallocz(sizeof(PayloadContext) +
- FF_INPUT_BUFFER_PADDING_SIZE);
-
- if (data) {
- data->cookie = MAGIC_COOKIE;
- }
-
- return data;
-}
-
-static void h264_free_context(PayloadContext *data)
-{
-#ifdef DEBUG
- int ii;
-
- for (ii = 0; ii < 32; ii++) {
- if (data->packet_types_received[ii])
- av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
- data->packet_types_received[ii], ii);
- }
-#endif
-
- assert(data);
- assert(data->cookie == MAGIC_COOKIE);
-
- // avoid stale pointers (assert)
- data->cookie = DEAD_COOKIE;
-
- // and clear out this...
- av_free(data);
-}
-
-static int parse_h264_sdp_line(AVFormatContext *s, int st_index,
- PayloadContext *h264_data, const char *line)
-{
- AVStream *stream = s->streams[st_index];
- AVCodecContext *codec = stream->codec;
- const char *p = line;
-
- assert(h264_data->cookie == MAGIC_COOKIE);
-
- if (av_strstart(p, "framesize:", &p)) {
- char buf1[50];
- char *dst = buf1;
-
- // remove the protocol identifier..
- while (*p && *p == ' ') p++; // strip spaces.
- while (*p && *p != ' ') p++; // eat protocol identifier
- while (*p && *p == ' ') p++; // strip trailing spaces.
- while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1) {
- *dst++ = *p++;
- }
- *dst = '\0';
-
- // a='framesize:96 320-240'
- // set our parameters..
- codec->width = atoi(buf1);
- codec->height = atoi(p + 1); // skip the -
- codec->pix_fmt = PIX_FMT_YUV420P;
- } else if (av_strstart(p, "fmtp:", &p)) {
- char attr[256];
- char value[4096];
-
- // remove the protocol identifier..
- while (*p && *p == ' ') p++; // strip spaces.
- while (*p && *p != ' ') p++; // eat protocol identifier
- while (*p && *p == ' ') p++; // strip trailing spaces.
-
- /* loop on each attribute */
- while (ff_rtsp_next_attr_and_value
- (&p, attr, sizeof(attr), value, sizeof(value))) {
- /* grab the codec extra_data from the config parameter of the fmtp line */
- sdp_parse_fmtp_config_h264(stream, h264_data, attr, value);
- }
- } else if (av_strstart(p, "cliprect:", &p)) {
- // could use this if we wanted.
- }
-
- av_set_pts_info(stream, 33, 1, 90000); // 33 should be right, because the pts is 64 bit? (done elsewhere; this is a one time thing)
-
- return 0; // keep processing it the normal way...
-}
-
-/**
-This is the structure for expanding on the dynamic rtp protocols (makes everything static. yay!)
-*/
-RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
- .enc_name = "H264",
- .codec_type = CODEC_TYPE_VIDEO,
- .codec_id = CODEC_ID_H264,
- .parse_sdp_a_line = parse_h264_sdp_line,
- .open = h264_new_context,
- .close = h264_free_context,
- .parse_packet = h264_handle_packet
-};
+++ /dev/null
-/*
- * RTP H264 Protocol (RFC3984)
- * Copyright (c) 2006 Ryan Martell
- *
- * 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
- */
-
-#ifndef AVFORMAT_RTP_H264_H
-#define AVFORMAT_RTP_H264_H
-
-#include "rtpdec.h"
-
-extern RTPDynamicProtocolHandler ff_h264_dynamic_handler;
-
-#endif /* AVFORMAT_RTP_H264_H */
+++ /dev/null
-/*
- * RTP Vorbis Protocol (RFC5215)
- * Copyright (c) 2009 Colin McQuillan
- *
- * 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
- */
-
-/**
- * @file libavformat/rtp_vorbis.c
- * @brief Vorbis / RTP Code (RFC 5215)
- * @author Colin McQuillan <m.niloc@gmail.com>
- */
-
-#include "libavutil/base64.h"
-#include "libavutil/avstring.h"
-#include "libavcodec/bytestream.h"
-
-#include <assert.h>
-
-#include "rtpdec.h"
-#include "rtp_vorbis.h"
-
-/**
- * RTP/Vorbis specific private data.
- */
-struct PayloadContext {
- unsigned ident; ///< 24-bit stream configuration identifier
-};
-
-/**
- * Length encoding described in RFC5215 section 3.1.1.
- */
-static int get_base128(const uint8_t ** buf, const uint8_t * buf_end)
-{
- int n = 0;
- for (; *buf < buf_end; ++*buf) {
- n <<= 7;
- n += **buf & 0x7f;
- if (!(**buf & 0x80)) {
- ++*buf;
- return n;
- }
- }
- return 0;
-}
-
-/**
- * Out-of-band headers, described in RFC 5251 section 3.2.1
- */
-static unsigned int
-parse_packed_headers(const uint8_t * packed_headers,
- const uint8_t * packed_headers_end,
- AVCodecContext * codec, PayloadContext * vorbis_data)
-{
- unsigned num_packed, num_headers, length, length1, length2;
- uint8_t *ptr;
-
- num_packed = bytestream_get_be32(&packed_headers);
- vorbis_data->ident = bytestream_get_be24(&packed_headers);
- length = bytestream_get_be16(&packed_headers);
- num_headers = get_base128(&packed_headers, packed_headers_end);
- length1 = get_base128(&packed_headers, packed_headers_end);
- length2 = get_base128(&packed_headers, packed_headers_end);
-
- if (num_packed != 1 || num_headers > 3) {
- av_log(codec, AV_LOG_ERROR,
- "Unimplemented number of headers: %d packed headers, %d headers\n",
- num_packed, num_headers);
- return AVERROR_PATCHWELCOME;
- }
-
- if (packed_headers_end - packed_headers != length ||
- length1 > length || length2 > length - length1) {
- av_log(codec, AV_LOG_ERROR,
- "Bad packed header lengths (%d,%d,%d,%d)\n", length1,
- length2, packed_headers_end - packed_headers, length);
- return AVERROR_INVALIDDATA;
- }
-
- ptr = codec->extradata = av_mallocz(length + length / 255 + 64);
- if (!ptr) {
- av_log(codec, AV_LOG_ERROR, "Out of memory");
- return AVERROR_NOMEM;
- }
- *ptr++ = 2;
- ptr += av_xiphlacing(ptr, length1);
- ptr += av_xiphlacing(ptr, length2);
- memcpy(ptr, packed_headers, length);
- ptr += length;
- codec->extradata_size = ptr - codec->extradata;
-
- return 0;
-}
-
-int
-ff_vorbis_parse_fmtp_config(AVCodecContext * codec,
- void *vorbis_data, char *attr, char *value)
-{
- int result = 0;
- assert(codec->codec_id == CODEC_ID_VORBIS);
- assert(vorbis_data);
-
- // The configuration value is a base64 encoded packed header
- if (!strcmp(attr, "configuration")) {
- uint8_t *decoded_packet = NULL;
- int packet_size;
- size_t decoded_alloc = strlen(value) / 4 * 3 + 4;
-
- if (decoded_alloc <= INT_MAX) {
- decoded_packet = av_malloc(decoded_alloc);
- if (decoded_packet) {
- packet_size =
- av_base64_decode(decoded_packet, value, decoded_alloc);
-
- result = parse_packed_headers
- (decoded_packet, decoded_packet + packet_size, codec,
- vorbis_data);
- } else {
- av_log(codec, AV_LOG_ERROR,
- "Out of memory while decoding SDP configuration.\n");
- result = AVERROR_NOMEM;
- }
- } else {
- av_log(codec, AV_LOG_ERROR, "Packet too large\n");
- result = AVERROR_INVALIDDATA;
- }
- av_free(decoded_packet);
- }
- return result;
-}
-
-static PayloadContext *vorbis_new_context(void)
-{
- return av_mallocz(sizeof(PayloadContext));
-}
-
-static void vorbis_free_context(PayloadContext * data)
-{
- av_free(data);
-}
-
-/**
- * Handle payload as described in RFC 5215 section 2.2
- */
-static int
-vorbis_handle_packet(AVFormatContext * ctx,
- PayloadContext * data,
- AVStream * st,
- AVPacket * pkt,
- uint32_t * timestamp,
- const uint8_t * buf, int len, int flags)
-{
- int ident, fragmented, vdt, num_pkts, pkt_len;
-
- if (len < 6) {
- av_log(ctx, AV_LOG_ERROR, "Invalid %d byte packet\n", len);
- return AVERROR_INVALIDDATA;
- }
-
- ident = AV_RB24(buf);
- fragmented = buf[3] >> 6;
- vdt = (buf[3] >> 4) & 3;
- num_pkts = buf[3] & 7;
- pkt_len = AV_RB16(buf + 4);
-
- if (pkt_len > len - 6) {
- av_log(ctx, AV_LOG_ERROR,
- "Invalid packet length %d in %d byte packet\n", pkt_len,
- len);
- return AVERROR_INVALIDDATA;
- }
-
- if (ident != data->ident) {
- av_log(ctx, AV_LOG_ERROR,
- "Unimplemented Vorbis SDP configuration change detected\n");
- return AVERROR_PATCHWELCOME;
- }
-
- if (fragmented != 0 || vdt != 0 || num_pkts != 1) {
- av_log(ctx, AV_LOG_ERROR,
- "Unimplemented RTP Vorbis packet settings (%d,%d,%d)\n",
- fragmented, vdt, num_pkts);
- return AVERROR_PATCHWELCOME;
- }
-
- if (av_new_packet(pkt, pkt_len)) {
- av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
- return AVERROR_NOMEM;
- }
-
- memcpy(pkt->data, buf + 6, pkt_len);
- pkt->stream_index = st->index;
- return 0;
-}
-
-RTPDynamicProtocolHandler ff_vorbis_dynamic_handler = {
- .enc_name = "vorbis",
- .codec_type = CODEC_TYPE_AUDIO,
- .codec_id = CODEC_ID_VORBIS,
- .parse_sdp_a_line = NULL,
- .open = vorbis_new_context,
- .close = vorbis_free_context,
- .parse_packet = vorbis_handle_packet
-};
+++ /dev/null
-/*
- * RTP Vorbis Protocol (RFC 5215)
- * Copyright (c) 2009 Colin McQuillan
- *
- * 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
- */
-
-#ifndef AVFORMAT_RTP_VORBIS_H
-#define AVFORMAT_RTP_VORBIS_H
-
-#include "libavcodec/avcodec.h"
-#include "rtpdec.h"
-
-/**
- * Handle a Vorbis-specific FMTP parameter
- *
- * @param codec The context of the codec
- * @param ctx Private Vorbis RTP context
- * @param attr Format-specific parameter name
- * @param value Format-specific paremeter value
- */
-int
-ff_vorbis_parse_fmtp_config(AVCodecContext * codec,
- void *ctx, char *attr, char *value);
-
-/**
- * Vorbis RTP callbacks.
- */
-extern RTPDynamicProtocolHandler ff_vorbis_dynamic_handler;
-
-#endif /* AVFORMAT_RTP_VORBIS_H */
#include "network.h"
#include "rtpdec.h"
-#include "rtp_asf.h"
-#include "rtp_h264.h"
-#include "rtp_vorbis.h"
#include "rtpdec_amr.h"
+#include "rtpdec_asf.h"
#include "rtpdec_h263.h"
+#include "rtpdec_h264.h"
+#include "rtpdec_vorbis.h"
//#define DEBUG
--- /dev/null
+/*
+ * Microsoft RTP/ASF support.
+ * Copyright (c) 2008 Ronald S. Bultje
+ *
+ * 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
+ */
+
+/**
+ * @file libavformat/rtpdec_asf.c
+ * @brief Microsoft RTP/ASF support
+ * @author Ronald S. Bultje <rbultje@ronald.bitfreak.net>
+ */
+
+#include <libavutil/base64.h>
+#include <libavutil/avstring.h>
+#include <libavutil/intreadwrite.h>
+#include "rtp.h"
+#include "rtpdec_asf.h"
+#include "rtsp.h"
+#include "asf.h"
+
+/**
+ * From MSDN 2.2.1.4, we learn that ASF data packets over RTP should not
+ * contain any padding. Unfortunately, the header min/max_pktsize are not
+ * updated (thus making min_pktsize invalid). Here, we "fix" these faulty
+ * min_pktsize values in the ASF file header.
+ * @return 0 on success, <0 on failure (currently -1).
+ */
+static int rtp_asf_fix_header(uint8_t *buf, int len)
+{
+ uint8_t *p = buf, *end = buf + len;
+
+ if (len < sizeof(ff_asf_guid) * 2 + 22 ||
+ memcmp(p, ff_asf_header, sizeof(ff_asf_guid))) {
+ return -1;
+ }
+ p += sizeof(ff_asf_guid) + 14;
+ do {
+ uint64_t chunksize = AV_RL64(p + sizeof(ff_asf_guid));
+ if (memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) {
+ if (chunksize > end - p)
+ return -1;
+ p += chunksize;
+ continue;
+ }
+
+ /* skip most of the file header, to min_pktsize */
+ p += 6 * 8 + 3 * 4 + sizeof(ff_asf_guid) * 2;
+ if (p + 8 <= end && AV_RL32(p) == AV_RL32(p + 4)) {
+ /* and set that to zero */
+ AV_WL32(p, 0);
+ return 0;
+ }
+ break;
+ } while (end - p >= sizeof(ff_asf_guid) + 8);
+
+ return -1;
+}
+
+/**
+ * The following code is basically a buffered ByteIOContext,
+ * with the added benefit of returning -EAGAIN (instead of 0)
+ * on packet boundaries, such that the ASF demuxer can return
+ * safely and resume business at the next packet.
+ */
+static int packetizer_read(void *opaque, uint8_t *buf, int buf_size)
+{
+ return AVERROR(EAGAIN);
+}
+
+static void init_packetizer(ByteIOContext *pb, uint8_t *buf, int len)
+{
+ init_put_byte(pb, buf, len, 0, NULL, packetizer_read, NULL, NULL);
+
+ /* this "fills" the buffer with its current content */
+ pb->pos = len;
+ pb->buf_end = buf + len;
+}
+
+void ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p)
+{
+ if (av_strstart(p, "pgmpu:data:application/vnd.ms.wms-hdr.asfv1;base64,", &p)) {
+ ByteIOContext pb;
+ RTSPState *rt = s->priv_data;
+ int len = strlen(p) * 6 / 8;
+ char *buf = av_mallocz(len);
+ av_base64_decode(buf, p, len);
+
+ if (rtp_asf_fix_header(buf, len) < 0)
+ av_log(s, AV_LOG_ERROR,
+ "Failed to fix invalid RTSP-MS/ASF min_pktsize\n");
+ init_packetizer(&pb, buf, len);
+ if (rt->asf_ctx) {
+ av_close_input_stream(rt->asf_ctx);
+ rt->asf_ctx = NULL;
+ }
+ av_open_input_stream(&rt->asf_ctx, &pb, "", &asf_demuxer, NULL);
+ rt->asf_pb_pos = url_ftell(&pb);
+ av_free(buf);
+ rt->asf_ctx->pb = NULL;
+ }
+}
+
+static int asfrtp_parse_sdp_line(AVFormatContext *s, int stream_index,
+ PayloadContext *asf, const char *line)
+{
+ if (av_strstart(line, "stream:", &line)) {
+ RTSPState *rt = s->priv_data;
+
+ s->streams[stream_index]->id = strtol(line, NULL, 10);
+
+ if (rt->asf_ctx) {
+ int i;
+
+ for (i = 0; i < rt->asf_ctx->nb_streams; i++) {
+ if (s->streams[stream_index]->id == rt->asf_ctx->streams[i]->id) {
+ *s->streams[stream_index]->codec =
+ *rt->asf_ctx->streams[i]->codec;
+ rt->asf_ctx->streams[i]->codec->extradata_size = 0;
+ rt->asf_ctx->streams[i]->codec->extradata = NULL;
+ av_set_pts_info(s->streams[stream_index], 32, 1, 1000);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+struct PayloadContext {
+ ByteIOContext *pktbuf, pb;
+ char *buf;
+};
+
+/**
+ * @return 0 when a packet was written into /p pkt, and no more data is left;
+ * 1 when a packet was written into /p pkt, and more packets might be left;
+ * <0 when not enough data was provided to return a full packet, or on error.
+ */
+static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf,
+ AVStream *st, AVPacket *pkt,
+ uint32_t *timestamp,
+ const uint8_t *buf, int len, int flags)
+{
+ ByteIOContext *pb = &asf->pb;
+ int res, mflags, len_off;
+ RTSPState *rt = s->priv_data;
+
+ if (!rt->asf_ctx)
+ return -1;
+
+ if (len > 0) {
+ int off, out_len;
+
+ if (len < 4)
+ return -1;
+
+ init_put_byte(pb, buf, len, 0, NULL, NULL, NULL, NULL);
+ mflags = get_byte(pb);
+ if (mflags & 0x80)
+ flags |= RTP_FLAG_KEY;
+ len_off = get_be24(pb);
+ if (mflags & 0x20) /**< relative timestamp */
+ url_fskip(pb, 4);
+ if (mflags & 0x10) /**< has duration */
+ url_fskip(pb, 4);
+ if (mflags & 0x8) /**< has location ID */
+ url_fskip(pb, 4);
+ off = url_ftell(pb);
+
+ av_freep(&asf->buf);
+ if (!(mflags & 0x40)) {
+ /**
+ * If 0x40 is not set, the len_off field specifies an offset of this
+ * packet's payload data in the complete (reassembled) ASF packet.
+ * This is used to spread one ASF packet over multiple RTP packets.
+ */
+ if (asf->pktbuf && len_off != url_ftell(asf->pktbuf)) {
+ uint8_t *p;
+ url_close_dyn_buf(asf->pktbuf, &p);
+ asf->pktbuf = NULL;
+ av_free(p);
+ }
+ if (!len_off && !asf->pktbuf &&
+ (res = url_open_dyn_buf(&asf->pktbuf)) < 0)
+ return res;
+ if (!asf->pktbuf)
+ return AVERROR(EIO);
+
+ put_buffer(asf->pktbuf, buf + off, len - off);
+ if (!(flags & RTP_FLAG_MARKER))
+ return -1;
+ out_len = url_close_dyn_buf(asf->pktbuf, &asf->buf);
+ asf->pktbuf = NULL;
+ } else {
+ /**
+ * If 0x40 is set, the len_off field specifies the length of the
+ * next ASF packet that can be read from this payload data alone.
+ * This is commonly the same as the payload size, but could be
+ * less in case of packet splitting (i.e. multiple ASF packets in
+ * one RTP packet).
+ */
+ if (len_off != len) {
+ av_log_missing_feature(s,
+ "RTSP-MS packet splitting", 1);
+ return -1;
+ }
+ asf->buf = av_malloc(len - off);
+ out_len = len - off;
+ memcpy(asf->buf, buf + off, len - off);
+ }
+
+ init_packetizer(pb, asf->buf, out_len);
+ pb->pos += rt->asf_pb_pos;
+ pb->eof_reached = 0;
+ rt->asf_ctx->pb = pb;
+ }
+
+ for (;;) {
+ int i;
+
+ res = av_read_packet(rt->asf_ctx, pkt);
+ rt->asf_pb_pos = url_ftell(pb);
+ if (res != 0)
+ break;
+ for (i = 0; i < s->nb_streams; i++) {
+ if (s->streams[i]->id == rt->asf_ctx->streams[pkt->stream_index]->id) {
+ pkt->stream_index = i;
+ return 1; // FIXME: return 0 if last packet
+ }
+ }
+ av_free_packet(pkt);
+ }
+
+ return res == 1 ? -1 : res;
+}
+
+static PayloadContext *asfrtp_new_context(void)
+{
+ return av_mallocz(sizeof(PayloadContext));
+}
+
+static void asfrtp_free_context(PayloadContext *asf)
+{
+ if (asf->pktbuf) {
+ uint8_t *p = NULL;
+ url_close_dyn_buf(asf->pktbuf, &p);
+ asf->pktbuf = NULL;
+ av_free(p);
+ }
+ av_freep(&asf->buf);
+ av_free(asf);
+}
+
+#define RTP_ASF_HANDLER(n, s, t) \
+RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \
+ .enc_name = s, \
+ .codec_type = t, \
+ .codec_id = CODEC_ID_NONE, \
+ .parse_sdp_a_line = asfrtp_parse_sdp_line, \
+ .open = asfrtp_new_context, \
+ .close = asfrtp_free_context, \
+ .parse_packet = asfrtp_parse_packet, \
+};
+
+RTP_ASF_HANDLER(asf_pfv, "x-asf-pf", CODEC_TYPE_VIDEO);
+RTP_ASF_HANDLER(asf_pfa, "x-asf-pf", CODEC_TYPE_AUDIO);
--- /dev/null
+/*
+ * Microsoft RTP/ASF support.
+ * Copyright (c) 2008 Ronald S. Bultje
+ *
+ * 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
+ */
+
+#ifndef AVFORMAT_RTPDEC_ASF_H
+#define AVFORMAT_RTPDEC_ASF_H
+
+#include "avformat.h"
+#include "rtpdec.h"
+
+/**
+ * Parse a Windows Media Server-specific SDP line
+ *
+ * @param s RTSP demux context
+ * @param line the SDP line to be parsed
+ */
+void ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p);
+
+/**
+ * Handlers for the x-asf-pf payloads (the payload ID for RTP/ASF).
+ * Defined and implemented in rtp_asf.c, registered in rtpdec.c.
+ */
+extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfv_handler,
+ ff_ms_rtp_asf_pfa_handler;
+
+#endif /* AVFORMAT_RTPDEC_ASF_H */
--- /dev/null
+/*
+ * RTP H264 Protocol (RFC3984)
+ * Copyright (c) 2006 Ryan Martell
+ *
+ * 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
+ */
+
+/**
+* @file libavformat/rtpdec_h264.c
+ * @brief H.264 / RTP Code (RFC3984)
+ * @author Ryan Martell <rdm4@martellventures.com>
+ *
+ * @note Notes:
+ * Notes:
+ * This currently supports packetization mode:
+ * Single Nal Unit Mode (0), or
+ * Non-Interleaved Mode (1). It currently does not support
+ * Interleaved Mode (2). (This requires implementing STAP-B, MTAP16, MTAP24, FU-B packet types)
+ *
+ * @note TODO:
+ * 1) RTCP sender reports for udp streams are required..
+ *
+ */
+
+#include "libavutil/base64.h"
+#include "libavutil/avstring.h"
+#include "libavcodec/get_bits.h"
+#include "avformat.h"
+#include "mpegts.h"
+
+#include <unistd.h>
+#include "network.h"
+#include <assert.h>
+
+#include "rtpdec.h"
+#include "rtpdec_h264.h"
+
+/**
+ RTP/H264 specific private data.
+*/
+struct PayloadContext {
+ unsigned long cookie; ///< sanity check, to make sure we get the pointer we're expecting.
+
+ //sdp setup parameters
+ uint8_t profile_idc; ///< from the sdp setup parameters.
+ uint8_t profile_iop; ///< from the sdp setup parameters.
+ uint8_t level_idc; ///< from the sdp setup parameters.
+ int packetization_mode; ///< from the sdp setup parameters.
+#ifdef DEBUG
+ int packet_types_received[32];
+#endif
+};
+
+#define MAGIC_COOKIE (0xdeadbeef) ///< Cookie for the extradata; to verify we are what we think we are, and that we haven't been freed.
+#define DEAD_COOKIE (0xdeaddead) ///< Cookie for the extradata; once it is freed.
+
+/* ---------------- private code */
+static void sdp_parse_fmtp_config_h264(AVStream * stream,
+ PayloadContext * h264_data,
+ char *attr, char *value)
+{
+ AVCodecContext *codec = stream->codec;
+ assert(codec->codec_id == CODEC_ID_H264);
+ assert(h264_data != NULL);
+
+ if (!strcmp(attr, "packetization-mode")) {
+ av_log(codec, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value));
+ h264_data->packetization_mode = atoi(value);
+ /*
+ Packetization Mode:
+ 0 or not present: Single NAL mode (Only nals from 1-23 are allowed)
+ 1: Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed.
+ 2: Interleaved Mode: 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A), and 29 (FU-B) are allowed.
+ */
+ if (h264_data->packetization_mode > 1)
+ av_log(codec, AV_LOG_ERROR,
+ "Interleaved RTP mode is not supported yet.");
+ } else if (!strcmp(attr, "profile-level-id")) {
+ if (strlen(value) == 6) {
+ char buffer[3];
+ // 6 characters=3 bytes, in hex.
+ uint8_t profile_idc;
+ uint8_t profile_iop;
+ uint8_t level_idc;
+
+ buffer[0] = value[0]; buffer[1] = value[1]; buffer[2] = '\0';
+ profile_idc = strtol(buffer, NULL, 16);
+ buffer[0] = value[2]; buffer[1] = value[3];
+ profile_iop = strtol(buffer, NULL, 16);
+ buffer[0] = value[4]; buffer[1] = value[5];
+ level_idc = strtol(buffer, NULL, 16);
+
+ // set the parameters...
+ av_log(codec, AV_LOG_DEBUG,
+ "RTP Profile IDC: %x Profile IOP: %x Level: %x\n",
+ profile_idc, profile_iop, level_idc);
+ h264_data->profile_idc = profile_idc;
+ h264_data->profile_iop = profile_iop;
+ h264_data->level_idc = level_idc;
+ }
+ } else if (!strcmp(attr, "sprop-parameter-sets")) {
+ uint8_t start_sequence[]= { 0, 0, 1 };
+ codec->extradata_size= 0;
+ codec->extradata= NULL;
+
+ while (*value) {
+ char base64packet[1024];
+ uint8_t decoded_packet[1024];
+ uint32_t packet_size;
+ char *dst = base64packet;
+
+ while (*value && *value != ','
+ && (dst - base64packet) < sizeof(base64packet) - 1) {
+ *dst++ = *value++;
+ }
+ *dst++ = '\0';
+
+ if (*value == ',')
+ value++;
+
+ packet_size= av_base64_decode(decoded_packet, base64packet, sizeof(decoded_packet));
+ if (packet_size) {
+ uint8_t *dest= av_malloc(packet_size+sizeof(start_sequence)+codec->extradata_size);
+ if(dest)
+ {
+ if(codec->extradata_size)
+ {
+ // av_realloc?
+ memcpy(dest, codec->extradata, codec->extradata_size);
+ av_free(codec->extradata);
+ }
+
+ memcpy(dest+codec->extradata_size, start_sequence, sizeof(start_sequence));
+ memcpy(dest+codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size);
+
+ codec->extradata= dest;
+ codec->extradata_size+= sizeof(start_sequence)+packet_size;
+ } else {
+ av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!");
+ }
+ }
+ }
+ av_log(codec, AV_LOG_DEBUG, "Extradata set to %p (size: %d)!", codec->extradata, codec->extradata_size);
+ }
+}
+
+// return 0 on packet, no more left, 1 on packet, 1 on partial packet...
+static int h264_handle_packet(AVFormatContext *ctx,
+ PayloadContext *data,
+ AVStream *st,
+ AVPacket * pkt,
+ uint32_t * timestamp,
+ const uint8_t * buf,
+ int len, int flags)
+{
+ uint8_t nal = buf[0];
+ uint8_t type = (nal & 0x1f);
+ int result= 0;
+ uint8_t start_sequence[]= {0, 0, 1};
+
+#ifdef DEBUG
+ assert(data);
+ assert(data->cookie == MAGIC_COOKIE);
+#endif
+ assert(buf);
+
+ if (type >= 1 && type <= 23)
+ type = 1; // simplify the case. (these are all the nal types used internally by the h264 codec)
+ switch (type) {
+ case 0: // undefined;
+ result= -1;
+ break;
+
+ case 1:
+ av_new_packet(pkt, len+sizeof(start_sequence));
+ memcpy(pkt->data, start_sequence, sizeof(start_sequence));
+ memcpy(pkt->data+sizeof(start_sequence), buf, len);
+#ifdef DEBUG
+ data->packet_types_received[nal & 0x1f]++;
+#endif
+ break;
+
+ case 24: // STAP-A (one packet, multiple nals)
+ // consume the STAP-A NAL
+ buf++;
+ len--;
+ // first we are going to figure out the total size....
+ {
+ int pass= 0;
+ int total_length= 0;
+ uint8_t *dst= NULL;
+
+ for(pass= 0; pass<2; pass++) {
+ const uint8_t *src= buf;
+ int src_len= len;
+
+ do {
+ uint16_t nal_size = AV_RB16(src); // this going to be a problem if unaligned (can it be?)
+
+ // consume the length of the aggregate...
+ src += 2;
+ src_len -= 2;
+
+ if (nal_size <= src_len) {
+ if(pass==0) {
+ // counting...
+ total_length+= sizeof(start_sequence)+nal_size;
+ } else {
+ // copying
+ assert(dst);
+ memcpy(dst, start_sequence, sizeof(start_sequence));
+ dst+= sizeof(start_sequence);
+ memcpy(dst, src, nal_size);
+#ifdef DEBUG
+ data->packet_types_received[*src & 0x1f]++;
+#endif
+ dst+= nal_size;
+ }
+ } else {
+ av_log(ctx, AV_LOG_ERROR,
+ "nal size exceeds length: %d %d\n", nal_size, src_len);
+ }
+
+ // eat what we handled...
+ src += nal_size;
+ src_len -= nal_size;
+
+ if (src_len < 0)
+ av_log(ctx, AV_LOG_ERROR,
+ "Consumed more bytes than we got! (%d)\n", src_len);
+ } while (src_len > 2); // because there could be rtp padding..
+
+ if(pass==0) {
+ // now we know the total size of the packet (with the start sequences added)
+ av_new_packet(pkt, total_length);
+ dst= pkt->data;
+ } else {
+ assert(dst-pkt->data==total_length);
+ }
+ }
+ }
+ break;
+
+ case 25: // STAP-B
+ case 26: // MTAP-16
+ case 27: // MTAP-24
+ case 29: // FU-B
+ av_log(ctx, AV_LOG_ERROR,
+ "Unhandled type (%d) (See RFC for implementation details\n",
+ type);
+ result= -1;
+ break;
+
+ case 28: // FU-A (fragmented nal)
+ buf++;
+ len--; // skip the fu_indicator
+ {
+ // these are the same as above, we just redo them here for clarity...
+ uint8_t fu_indicator = nal;
+ uint8_t fu_header = *buf; // read the fu_header.
+ uint8_t start_bit = fu_header >> 7;
+// uint8_t end_bit = (fu_header & 0x40) >> 6;
+ uint8_t nal_type = (fu_header & 0x1f);
+ uint8_t reconstructed_nal;
+
+ // reconstruct this packet's true nal; only the data follows..
+ reconstructed_nal = fu_indicator & (0xe0); // the original nal forbidden bit and NRI are stored in this packet's nal;
+ reconstructed_nal |= nal_type;
+
+ // skip the fu_header...
+ buf++;
+ len--;
+
+#ifdef DEBUG
+ if (start_bit)
+ data->packet_types_received[nal_type]++;
+#endif
+ if(start_bit) {
+ // copy in the start sequence, and the reconstructed nal....
+ av_new_packet(pkt, sizeof(start_sequence)+sizeof(nal)+len);
+ memcpy(pkt->data, start_sequence, sizeof(start_sequence));
+ pkt->data[sizeof(start_sequence)]= reconstructed_nal;
+ memcpy(pkt->data+sizeof(start_sequence)+sizeof(nal), buf, len);
+ } else {
+ av_new_packet(pkt, len);
+ memcpy(pkt->data, buf, len);
+ }
+ }
+ break;
+
+ case 30: // undefined
+ case 31: // undefined
+ default:
+ av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)", type);
+ result= -1;
+ break;
+ }
+
+ pkt->stream_index = st->index;
+
+ return result;
+}
+
+/* ---------------- public code */
+static PayloadContext *h264_new_context(void)
+{
+ PayloadContext *data =
+ av_mallocz(sizeof(PayloadContext) +
+ FF_INPUT_BUFFER_PADDING_SIZE);
+
+ if (data) {
+ data->cookie = MAGIC_COOKIE;
+ }
+
+ return data;
+}
+
+static void h264_free_context(PayloadContext *data)
+{
+#ifdef DEBUG
+ int ii;
+
+ for (ii = 0; ii < 32; ii++) {
+ if (data->packet_types_received[ii])
+ av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
+ data->packet_types_received[ii], ii);
+ }
+#endif
+
+ assert(data);
+ assert(data->cookie == MAGIC_COOKIE);
+
+ // avoid stale pointers (assert)
+ data->cookie = DEAD_COOKIE;
+
+ // and clear out this...
+ av_free(data);
+}
+
+static int parse_h264_sdp_line(AVFormatContext *s, int st_index,
+ PayloadContext *h264_data, const char *line)
+{
+ AVStream *stream = s->streams[st_index];
+ AVCodecContext *codec = stream->codec;
+ const char *p = line;
+
+ assert(h264_data->cookie == MAGIC_COOKIE);
+
+ if (av_strstart(p, "framesize:", &p)) {
+ char buf1[50];
+ char *dst = buf1;
+
+ // remove the protocol identifier..
+ while (*p && *p == ' ') p++; // strip spaces.
+ while (*p && *p != ' ') p++; // eat protocol identifier
+ while (*p && *p == ' ') p++; // strip trailing spaces.
+ while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1) {
+ *dst++ = *p++;
+ }
+ *dst = '\0';
+
+ // a='framesize:96 320-240'
+ // set our parameters..
+ codec->width = atoi(buf1);
+ codec->height = atoi(p + 1); // skip the -
+ codec->pix_fmt = PIX_FMT_YUV420P;
+ } else if (av_strstart(p, "fmtp:", &p)) {
+ char attr[256];
+ char value[4096];
+
+ // remove the protocol identifier..
+ while (*p && *p == ' ') p++; // strip spaces.
+ while (*p && *p != ' ') p++; // eat protocol identifier
+ while (*p && *p == ' ') p++; // strip trailing spaces.
+
+ /* loop on each attribute */
+ while (ff_rtsp_next_attr_and_value
+ (&p, attr, sizeof(attr), value, sizeof(value))) {
+ /* grab the codec extra_data from the config parameter of the fmtp line */
+ sdp_parse_fmtp_config_h264(stream, h264_data, attr, value);
+ }
+ } else if (av_strstart(p, "cliprect:", &p)) {
+ // could use this if we wanted.
+ }
+
+ av_set_pts_info(stream, 33, 1, 90000); // 33 should be right, because the pts is 64 bit? (done elsewhere; this is a one time thing)
+
+ return 0; // keep processing it the normal way...
+}
+
+/**
+This is the structure for expanding on the dynamic rtp protocols (makes everything static. yay!)
+*/
+RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
+ .enc_name = "H264",
+ .codec_type = CODEC_TYPE_VIDEO,
+ .codec_id = CODEC_ID_H264,
+ .parse_sdp_a_line = parse_h264_sdp_line,
+ .open = h264_new_context,
+ .close = h264_free_context,
+ .parse_packet = h264_handle_packet
+};
--- /dev/null
+/*
+ * RTP H264 Protocol (RFC3984)
+ * Copyright (c) 2006 Ryan Martell
+ *
+ * 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
+ */
+
+#ifndef AVFORMAT_RTPDEC_H264_H
+#define AVFORMAT_RTPDEC_H264_H
+
+#include "rtpdec.h"
+
+extern RTPDynamicProtocolHandler ff_h264_dynamic_handler;
+
+#endif /* AVFORMAT_RTPDEC_H264_H */
--- /dev/null
+/*
+ * RTP Vorbis Protocol (RFC5215)
+ * Copyright (c) 2009 Colin McQuillan
+ *
+ * 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
+ */
+
+/**
+ * @file libavformat/rtpdec_vorbis.c
+ * @brief Vorbis / RTP Code (RFC 5215)
+ * @author Colin McQuillan <m.niloc@gmail.com>
+ */
+
+#include "libavutil/base64.h"
+#include "libavutil/avstring.h"
+#include "libavcodec/bytestream.h"
+
+#include <assert.h>
+
+#include "rtpdec.h"
+#include "rtpdec_vorbis.h"
+
+/**
+ * RTP/Vorbis specific private data.
+ */
+struct PayloadContext {
+ unsigned ident; ///< 24-bit stream configuration identifier
+};
+
+/**
+ * Length encoding described in RFC5215 section 3.1.1.
+ */
+static int get_base128(const uint8_t ** buf, const uint8_t * buf_end)
+{
+ int n = 0;
+ for (; *buf < buf_end; ++*buf) {
+ n <<= 7;
+ n += **buf & 0x7f;
+ if (!(**buf & 0x80)) {
+ ++*buf;
+ return n;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Out-of-band headers, described in RFC 5251 section 3.2.1
+ */
+static unsigned int
+parse_packed_headers(const uint8_t * packed_headers,
+ const uint8_t * packed_headers_end,
+ AVCodecContext * codec, PayloadContext * vorbis_data)
+{
+ unsigned num_packed, num_headers, length, length1, length2;
+ uint8_t *ptr;
+
+ num_packed = bytestream_get_be32(&packed_headers);
+ vorbis_data->ident = bytestream_get_be24(&packed_headers);
+ length = bytestream_get_be16(&packed_headers);
+ num_headers = get_base128(&packed_headers, packed_headers_end);
+ length1 = get_base128(&packed_headers, packed_headers_end);
+ length2 = get_base128(&packed_headers, packed_headers_end);
+
+ if (num_packed != 1 || num_headers > 3) {
+ av_log(codec, AV_LOG_ERROR,
+ "Unimplemented number of headers: %d packed headers, %d headers\n",
+ num_packed, num_headers);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ if (packed_headers_end - packed_headers != length ||
+ length1 > length || length2 > length - length1) {
+ av_log(codec, AV_LOG_ERROR,
+ "Bad packed header lengths (%d,%d,%d,%d)\n", length1,
+ length2, packed_headers_end - packed_headers, length);
+ return AVERROR_INVALIDDATA;
+ }
+
+ ptr = codec->extradata = av_mallocz(length + length / 255 + 64);
+ if (!ptr) {
+ av_log(codec, AV_LOG_ERROR, "Out of memory");
+ return AVERROR_NOMEM;
+ }
+ *ptr++ = 2;
+ ptr += av_xiphlacing(ptr, length1);
+ ptr += av_xiphlacing(ptr, length2);
+ memcpy(ptr, packed_headers, length);
+ ptr += length;
+ codec->extradata_size = ptr - codec->extradata;
+
+ return 0;
+}
+
+int
+ff_vorbis_parse_fmtp_config(AVCodecContext * codec,
+ void *vorbis_data, char *attr, char *value)
+{
+ int result = 0;
+ assert(codec->codec_id == CODEC_ID_VORBIS);
+ assert(vorbis_data);
+
+ // The configuration value is a base64 encoded packed header
+ if (!strcmp(attr, "configuration")) {
+ uint8_t *decoded_packet = NULL;
+ int packet_size;
+ size_t decoded_alloc = strlen(value) / 4 * 3 + 4;
+
+ if (decoded_alloc <= INT_MAX) {
+ decoded_packet = av_malloc(decoded_alloc);
+ if (decoded_packet) {
+ packet_size =
+ av_base64_decode(decoded_packet, value, decoded_alloc);
+
+ result = parse_packed_headers
+ (decoded_packet, decoded_packet + packet_size, codec,
+ vorbis_data);
+ } else {
+ av_log(codec, AV_LOG_ERROR,
+ "Out of memory while decoding SDP configuration.\n");
+ result = AVERROR_NOMEM;
+ }
+ } else {
+ av_log(codec, AV_LOG_ERROR, "Packet too large\n");
+ result = AVERROR_INVALIDDATA;
+ }
+ av_free(decoded_packet);
+ }
+ return result;
+}
+
+static PayloadContext *vorbis_new_context(void)
+{
+ return av_mallocz(sizeof(PayloadContext));
+}
+
+static void vorbis_free_context(PayloadContext * data)
+{
+ av_free(data);
+}
+
+/**
+ * Handle payload as described in RFC 5215 section 2.2
+ */
+static int
+vorbis_handle_packet(AVFormatContext * ctx,
+ PayloadContext * data,
+ AVStream * st,
+ AVPacket * pkt,
+ uint32_t * timestamp,
+ const uint8_t * buf, int len, int flags)
+{
+ int ident, fragmented, vdt, num_pkts, pkt_len;
+
+ if (len < 6) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid %d byte packet\n", len);
+ return AVERROR_INVALIDDATA;
+ }
+
+ ident = AV_RB24(buf);
+ fragmented = buf[3] >> 6;
+ vdt = (buf[3] >> 4) & 3;
+ num_pkts = buf[3] & 7;
+ pkt_len = AV_RB16(buf + 4);
+
+ if (pkt_len > len - 6) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Invalid packet length %d in %d byte packet\n", pkt_len,
+ len);
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (ident != data->ident) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Unimplemented Vorbis SDP configuration change detected\n");
+ return AVERROR_PATCHWELCOME;
+ }
+
+ if (fragmented != 0 || vdt != 0 || num_pkts != 1) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Unimplemented RTP Vorbis packet settings (%d,%d,%d)\n",
+ fragmented, vdt, num_pkts);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ if (av_new_packet(pkt, pkt_len)) {
+ av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
+ return AVERROR_NOMEM;
+ }
+
+ memcpy(pkt->data, buf + 6, pkt_len);
+ pkt->stream_index = st->index;
+ return 0;
+}
+
+RTPDynamicProtocolHandler ff_vorbis_dynamic_handler = {
+ .enc_name = "vorbis",
+ .codec_type = CODEC_TYPE_AUDIO,
+ .codec_id = CODEC_ID_VORBIS,
+ .parse_sdp_a_line = NULL,
+ .open = vorbis_new_context,
+ .close = vorbis_free_context,
+ .parse_packet = vorbis_handle_packet
+};
--- /dev/null
+/*
+ * RTP Vorbis Protocol (RFC 5215)
+ * Copyright (c) 2009 Colin McQuillan
+ *
+ * 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
+ */
+
+#ifndef AVFORMAT_RTPDEC_VORBIS_H
+#define AVFORMAT_RTPDEC_VORBIS_H
+
+#include "libavcodec/avcodec.h"
+#include "rtpdec.h"
+
+/**
+ * Handle a Vorbis-specific FMTP parameter
+ *
+ * @param codec The context of the codec
+ * @param ctx Private Vorbis RTP context
+ * @param attr Format-specific parameter name
+ * @param value Format-specific paremeter value
+ */
+int
+ff_vorbis_parse_fmtp_config(AVCodecContext * codec,
+ void *ctx, char *attr, char *value);
+
+/**
+ * Vorbis RTP callbacks.
+ */
+extern RTPDynamicProtocolHandler ff_vorbis_dynamic_handler;
+
+#endif /* AVFORMAT_RTPDEC_VORBIS_H */
#include "rtpdec.h"
#include "rdt.h"
-#include "rtp_asf.h"
-#include "rtp_vorbis.h"
+#include "rtpdec_asf.h"
+#include "rtpdec_vorbis.h"
//#define DEBUG
//#define DEBUG_RTP_TCP