Revision f65919af

View differences:

libavformat/Makefile
216 216
                                            rtp.o         \
217 217
                                            rtpdec.o      \
218 218
                                            rtpdec_amr.o  \
219
                                            rtpdec_asf.o  \
219 220
                                            rtpdec_h263.o \
220
                                            rtp_asf.o     \
221
                                            rtp_h264.o    \
222
                                            rtp_vorbis.o
221
                                            rtpdec_h264.o \
222
                                            rtpdec_vorbis.o
223 223
OBJS-$(CONFIG_SEGAFILM_DEMUXER)          += segafilm.o
224 224
OBJS-$(CONFIG_SHORTEN_DEMUXER)           += raw.o id3v2.o
225 225
OBJS-$(CONFIG_SIFF_DEMUXER)              += siff.o
libavformat/rtp_asf.c
1
/*
2
 * Microsoft RTP/ASF support.
3
 * Copyright (c) 2008 Ronald S. Bultje
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

  
22
/**
23
 * @file libavformat/rtp_asf.c
24
 * @brief Microsoft RTP/ASF support
25
 * @author Ronald S. Bultje <rbultje@ronald.bitfreak.net>
26
 */
27

  
28
#include <libavutil/base64.h>
29
#include <libavutil/avstring.h>
30
#include <libavutil/intreadwrite.h>
31
#include "rtp.h"
32
#include "rtp_asf.h"
33
#include "rtsp.h"
34
#include "asf.h"
35

  
36
/**
37
 * From MSDN 2.2.1.4, we learn that ASF data packets over RTP should not
38
 * contain any padding. Unfortunately, the header min/max_pktsize are not
39
 * updated (thus making min_pktsize invalid). Here, we "fix" these faulty
40
 * min_pktsize values in the ASF file header.
41
 * @return 0 on success, <0 on failure (currently -1).
42
 */
43
static int rtp_asf_fix_header(uint8_t *buf, int len)
44
{
45
    uint8_t *p = buf, *end = buf + len;
46

  
47
    if (len < sizeof(ff_asf_guid) * 2 + 22 ||
48
        memcmp(p, ff_asf_header, sizeof(ff_asf_guid))) {
49
        return -1;
50
    }
51
    p += sizeof(ff_asf_guid) + 14;
52
    do {
53
        uint64_t chunksize = AV_RL64(p + sizeof(ff_asf_guid));
54
        if (memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) {
55
            if (chunksize > end - p)
56
                return -1;
57
            p += chunksize;
58
            continue;
59
        }
60

  
61
        /* skip most of the file header, to min_pktsize */
62
        p += 6 * 8 + 3 * 4 + sizeof(ff_asf_guid) * 2;
63
        if (p + 8 <= end && AV_RL32(p) == AV_RL32(p + 4)) {
64
            /* and set that to zero */
65
            AV_WL32(p, 0);
66
            return 0;
67
        }
68
        break;
69
    } while (end - p >= sizeof(ff_asf_guid) + 8);
70

  
71
    return -1;
72
}
73

  
74
/**
75
 * The following code is basically a buffered ByteIOContext,
76
 * with the added benefit of returning -EAGAIN (instead of 0)
77
 * on packet boundaries, such that the ASF demuxer can return
78
 * safely and resume business at the next packet.
79
 */
80
static int packetizer_read(void *opaque, uint8_t *buf, int buf_size)
81
{
82
    return AVERROR(EAGAIN);
83
}
84

  
85
static void init_packetizer(ByteIOContext *pb, uint8_t *buf, int len)
86
{
87
    init_put_byte(pb, buf, len, 0, NULL, packetizer_read, NULL, NULL);
88

  
89
    /* this "fills" the buffer with its current content */
90
    pb->pos     = len;
91
    pb->buf_end = buf + len;
92
}
93

  
94
void ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p)
95
{
96
    if (av_strstart(p, "pgmpu:data:application/vnd.ms.wms-hdr.asfv1;base64,", &p)) {
97
        ByteIOContext pb;
98
        RTSPState *rt = s->priv_data;
99
        int len = strlen(p) * 6 / 8;
100
        char *buf = av_mallocz(len);
101
        av_base64_decode(buf, p, len);
102

  
103
        if (rtp_asf_fix_header(buf, len) < 0)
104
            av_log(s, AV_LOG_ERROR,
105
                   "Failed to fix invalid RTSP-MS/ASF min_pktsize\n");
106
        init_packetizer(&pb, buf, len);
107
        if (rt->asf_ctx) {
108
            av_close_input_stream(rt->asf_ctx);
109
            rt->asf_ctx = NULL;
110
        }
111
        av_open_input_stream(&rt->asf_ctx, &pb, "", &asf_demuxer, NULL);
112
        rt->asf_pb_pos = url_ftell(&pb);
113
        av_free(buf);
114
        rt->asf_ctx->pb = NULL;
115
    }
116
}
117

  
118
static int asfrtp_parse_sdp_line(AVFormatContext *s, int stream_index,
119
                                 PayloadContext *asf, const char *line)
120
{
121
    if (av_strstart(line, "stream:", &line)) {
122
        RTSPState *rt = s->priv_data;
123

  
124
        s->streams[stream_index]->id = strtol(line, NULL, 10);
125

  
126
        if (rt->asf_ctx) {
127
            int i;
128

  
129
            for (i = 0; i < rt->asf_ctx->nb_streams; i++) {
130
                if (s->streams[stream_index]->id == rt->asf_ctx->streams[i]->id) {
131
                    *s->streams[stream_index]->codec =
132
                        *rt->asf_ctx->streams[i]->codec;
133
                    rt->asf_ctx->streams[i]->codec->extradata_size = 0;
134
                    rt->asf_ctx->streams[i]->codec->extradata = NULL;
135
                    av_set_pts_info(s->streams[stream_index], 32, 1, 1000);
136
                }
137
           }
138
        }
139
    }
140

  
141
    return 0;
142
}
143

  
144
struct PayloadContext {
145
    ByteIOContext *pktbuf, pb;
146
    char *buf;
147
};
148

  
149
/**
150
 * @return 0 when a packet was written into /p pkt, and no more data is left;
151
 *         1 when a packet was written into /p pkt, and more packets might be left;
152
 *        <0 when not enough data was provided to return a full packet, or on error.
153
 */
154
static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf,
155
                               AVStream *st, AVPacket *pkt,
156
                               uint32_t *timestamp,
157
                               const uint8_t *buf, int len, int flags)
158
{
159
    ByteIOContext *pb = &asf->pb;
160
    int res, mflags, len_off;
161
    RTSPState *rt = s->priv_data;
162

  
163
    if (!rt->asf_ctx)
164
        return -1;
165

  
166
    if (len > 0) {
167
        int off, out_len;
168

  
169
        if (len < 4)
170
            return -1;
171

  
172
        init_put_byte(pb, buf, len, 0, NULL, NULL, NULL, NULL);
173
        mflags = get_byte(pb);
174
        if (mflags & 0x80)
175
            flags |= RTP_FLAG_KEY;
176
        len_off = get_be24(pb);
177
        if (mflags & 0x20)   /**< relative timestamp */
178
            url_fskip(pb, 4);
179
        if (mflags & 0x10)   /**< has duration */
180
            url_fskip(pb, 4);
181
        if (mflags & 0x8)    /**< has location ID */
182
            url_fskip(pb, 4);
183
        off = url_ftell(pb);
184

  
185
        av_freep(&asf->buf);
186
        if (!(mflags & 0x40)) {
187
            /**
188
             * If 0x40 is not set, the len_off field specifies an offset of this
189
             * packet's payload data in the complete (reassembled) ASF packet.
190
             * This is used to spread one ASF packet over multiple RTP packets.
191
             */
192
            if (asf->pktbuf && len_off != url_ftell(asf->pktbuf)) {
193
                uint8_t *p;
194
                url_close_dyn_buf(asf->pktbuf, &p);
195
                asf->pktbuf = NULL;
196
                av_free(p);
197
            }
198
            if (!len_off && !asf->pktbuf &&
199
                (res = url_open_dyn_buf(&asf->pktbuf)) < 0)
200
                return res;
201
            if (!asf->pktbuf)
202
                return AVERROR(EIO);
203

  
204
            put_buffer(asf->pktbuf, buf + off, len - off);
205
            if (!(flags & RTP_FLAG_MARKER))
206
                return -1;
207
            out_len     = url_close_dyn_buf(asf->pktbuf, &asf->buf);
208
            asf->pktbuf = NULL;
209
        } else {
210
            /**
211
             * If 0x40 is set, the len_off field specifies the length of the
212
             * next ASF packet that can be read from this payload data alone.
213
             * This is commonly the same as the payload size, but could be
214
             * less in case of packet splitting (i.e. multiple ASF packets in
215
             * one RTP packet).
216
             */
217
            if (len_off != len) {
218
                av_log_missing_feature(s,
219
                    "RTSP-MS packet splitting", 1);
220
                return -1;
221
            }
222
            asf->buf = av_malloc(len - off);
223
            out_len  = len - off;
224
            memcpy(asf->buf, buf + off, len - off);
225
        }
226

  
227
        init_packetizer(pb, asf->buf, out_len);
228
        pb->pos += rt->asf_pb_pos;
229
        pb->eof_reached = 0;
230
        rt->asf_ctx->pb = pb;
231
    }
232

  
233
    for (;;) {
234
        int i;
235

  
236
        res = av_read_packet(rt->asf_ctx, pkt);
237
        rt->asf_pb_pos = url_ftell(pb);
238
        if (res != 0)
239
            break;
240
        for (i = 0; i < s->nb_streams; i++) {
241
            if (s->streams[i]->id == rt->asf_ctx->streams[pkt->stream_index]->id) {
242
                pkt->stream_index = i;
243
                return 1; // FIXME: return 0 if last packet
244
            }
245
        }
246
        av_free_packet(pkt);
247
    }
248

  
249
    return res == 1 ? -1 : res;
250
}
251

  
252
static PayloadContext *asfrtp_new_context(void)
253
{
254
    return av_mallocz(sizeof(PayloadContext));
255
}
256

  
257
static void asfrtp_free_context(PayloadContext *asf)
258
{
259
    if (asf->pktbuf) {
260
        uint8_t *p = NULL;
261
        url_close_dyn_buf(asf->pktbuf, &p);
262
        asf->pktbuf = NULL;
263
        av_free(p);
264
    }
265
    av_freep(&asf->buf);
266
    av_free(asf);
267
}
268

  
269
#define RTP_ASF_HANDLER(n, s, t) \
270
RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \
271
    .enc_name         = s, \
272
    .codec_type       = t, \
273
    .codec_id         = CODEC_ID_NONE, \
274
    .parse_sdp_a_line = asfrtp_parse_sdp_line, \
275
    .open             = asfrtp_new_context, \
276
    .close            = asfrtp_free_context, \
277
    .parse_packet     = asfrtp_parse_packet,   \
278
};
279

  
280
RTP_ASF_HANDLER(asf_pfv, "x-asf-pf",  CODEC_TYPE_VIDEO);
281
RTP_ASF_HANDLER(asf_pfa, "x-asf-pf",  CODEC_TYPE_AUDIO);
libavformat/rtp_asf.h
1
/*
2
 * Microsoft RTP/ASF support.
3
 * Copyright (c) 2008 Ronald S. Bultje
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

  
22
#ifndef AVFORMAT_RTP_ASF_H
23
#define AVFORMAT_RTP_ASF_H
24

  
25
#include "avformat.h"
26
#include "rtpdec.h"
27

  
28
/**
29
 * Parse a Windows Media Server-specific SDP line
30
 *
31
 * @param s RTSP demux context
32
 * @param line the SDP line to be parsed
33
 */
34
void ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p);
35

  
36
/**
37
 * Handlers for the x-asf-pf payloads (the payload ID for RTP/ASF).
38
 * Defined and implemented in rtp_asf.c, registered in rtpdec.c.
39
 */
40
extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfv_handler,
41
                                 ff_ms_rtp_asf_pfa_handler;
42

  
43
#endif /* AVFORMAT_RTP_ASF_H */
libavformat/rtp_h264.c
1
/*
2
 * RTP H264 Protocol (RFC3984)
3
 * Copyright (c) 2006 Ryan Martell
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

  
22
/**
23
* @file libavformat/rtp_h264.c
24
 * @brief H.264 / RTP Code (RFC3984)
25
 * @author Ryan Martell <rdm4@martellventures.com>
26
 *
27
 * @note Notes:
28
 * Notes:
29
 * This currently supports packetization mode:
30
 * Single Nal Unit Mode (0), or
31
 * Non-Interleaved Mode (1).  It currently does not support
32
 * Interleaved Mode (2). (This requires implementing STAP-B, MTAP16, MTAP24, FU-B packet types)
33
 *
34
 * @note TODO:
35
 * 1) RTCP sender reports for udp streams are required..
36
 *
37
 */
38

  
39
#include "libavutil/base64.h"
40
#include "libavutil/avstring.h"
41
#include "libavcodec/get_bits.h"
42
#include "avformat.h"
43
#include "mpegts.h"
44

  
45
#include <unistd.h>
46
#include "network.h"
47
#include <assert.h>
48

  
49
#include "rtpdec.h"
50
#include "rtp_h264.h"
51

  
52
/**
53
    RTP/H264 specific private data.
54
*/
55
struct PayloadContext {
56
    unsigned long cookie;       ///< sanity check, to make sure we get the pointer we're expecting.
57

  
58
    //sdp setup parameters
59
    uint8_t profile_idc;        ///< from the sdp setup parameters.
60
    uint8_t profile_iop;        ///< from the sdp setup parameters.
61
    uint8_t level_idc;          ///< from the sdp setup parameters.
62
    int packetization_mode;     ///< from the sdp setup parameters.
63
#ifdef DEBUG
64
    int packet_types_received[32];
65
#endif
66
};
67

  
68
#define MAGIC_COOKIE (0xdeadbeef)       ///< Cookie for the extradata; to verify we are what we think we are, and that we haven't been freed.
69
#define DEAD_COOKIE (0xdeaddead)        ///< Cookie for the extradata; once it is freed.
70

  
71
/* ---------------- private code */
72
static void sdp_parse_fmtp_config_h264(AVStream * stream,
73
                                       PayloadContext * h264_data,
74
                                       char *attr, char *value)
75
{
76
    AVCodecContext *codec = stream->codec;
77
    assert(codec->codec_id == CODEC_ID_H264);
78
    assert(h264_data != NULL);
79

  
80
    if (!strcmp(attr, "packetization-mode")) {
81
        av_log(codec, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value));
82
        h264_data->packetization_mode = atoi(value);
83
        /*
84
           Packetization Mode:
85
           0 or not present: Single NAL mode (Only nals from 1-23 are allowed)
86
           1: Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed.
87
           2: Interleaved Mode: 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A), and 29 (FU-B) are allowed.
88
         */
89
        if (h264_data->packetization_mode > 1)
90
            av_log(codec, AV_LOG_ERROR,
91
                   "Interleaved RTP mode is not supported yet.");
92
    } else if (!strcmp(attr, "profile-level-id")) {
93
        if (strlen(value) == 6) {
94
            char buffer[3];
95
            // 6 characters=3 bytes, in hex.
96
            uint8_t profile_idc;
97
            uint8_t profile_iop;
98
            uint8_t level_idc;
99

  
100
            buffer[0] = value[0]; buffer[1] = value[1]; buffer[2] = '\0';
101
            profile_idc = strtol(buffer, NULL, 16);
102
            buffer[0] = value[2]; buffer[1] = value[3];
103
            profile_iop = strtol(buffer, NULL, 16);
104
            buffer[0] = value[4]; buffer[1] = value[5];
105
            level_idc = strtol(buffer, NULL, 16);
106

  
107
            // set the parameters...
108
            av_log(codec, AV_LOG_DEBUG,
109
                   "RTP Profile IDC: %x Profile IOP: %x Level: %x\n",
110
                   profile_idc, profile_iop, level_idc);
111
            h264_data->profile_idc = profile_idc;
112
            h264_data->profile_iop = profile_iop;
113
            h264_data->level_idc = level_idc;
114
        }
115
    } else  if (!strcmp(attr, "sprop-parameter-sets")) {
116
        uint8_t start_sequence[]= { 0, 0, 1 };
117
        codec->extradata_size= 0;
118
        codec->extradata= NULL;
119

  
120
        while (*value) {
121
            char base64packet[1024];
122
            uint8_t decoded_packet[1024];
123
            uint32_t packet_size;
124
            char *dst = base64packet;
125

  
126
            while (*value && *value != ','
127
                   && (dst - base64packet) < sizeof(base64packet) - 1) {
128
                *dst++ = *value++;
129
            }
130
            *dst++ = '\0';
131

  
132
            if (*value == ',')
133
                value++;
134

  
135
            packet_size= av_base64_decode(decoded_packet, base64packet, sizeof(decoded_packet));
136
            if (packet_size) {
137
                uint8_t *dest= av_malloc(packet_size+sizeof(start_sequence)+codec->extradata_size);
138
                if(dest)
139
                {
140
                    if(codec->extradata_size)
141
                    {
142
                        // av_realloc?
143
                        memcpy(dest, codec->extradata, codec->extradata_size);
144
                        av_free(codec->extradata);
145
                    }
146

  
147
                    memcpy(dest+codec->extradata_size, start_sequence, sizeof(start_sequence));
148
                    memcpy(dest+codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size);
149

  
150
                    codec->extradata= dest;
151
                    codec->extradata_size+= sizeof(start_sequence)+packet_size;
152
                } else {
153
                    av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!");
154
                }
155
            }
156
        }
157
        av_log(codec, AV_LOG_DEBUG, "Extradata set to %p (size: %d)!", codec->extradata, codec->extradata_size);
158
    }
159
}
160

  
161
// return 0 on packet, no more left, 1 on packet, 1 on partial packet...
162
static int h264_handle_packet(AVFormatContext *ctx,
163
                              PayloadContext *data,
164
                              AVStream *st,
165
                              AVPacket * pkt,
166
                              uint32_t * timestamp,
167
                              const uint8_t * buf,
168
                              int len, int flags)
169
{
170
    uint8_t nal = buf[0];
171
    uint8_t type = (nal & 0x1f);
172
    int result= 0;
173
    uint8_t start_sequence[]= {0, 0, 1};
174

  
175
#ifdef DEBUG
176
    assert(data);
177
    assert(data->cookie == MAGIC_COOKIE);
178
#endif
179
    assert(buf);
180

  
181
    if (type >= 1 && type <= 23)
182
        type = 1;              // simplify the case. (these are all the nal types used internally by the h264 codec)
183
    switch (type) {
184
    case 0:                    // undefined;
185
        result= -1;
186
        break;
187

  
188
    case 1:
189
        av_new_packet(pkt, len+sizeof(start_sequence));
190
        memcpy(pkt->data, start_sequence, sizeof(start_sequence));
191
        memcpy(pkt->data+sizeof(start_sequence), buf, len);
192
#ifdef DEBUG
193
        data->packet_types_received[nal & 0x1f]++;
194
#endif
195
        break;
196

  
197
    case 24:                   // STAP-A (one packet, multiple nals)
198
        // consume the STAP-A NAL
199
        buf++;
200
        len--;
201
        // first we are going to figure out the total size....
202
        {
203
            int pass= 0;
204
            int total_length= 0;
205
            uint8_t *dst= NULL;
206

  
207
            for(pass= 0; pass<2; pass++) {
208
                const uint8_t *src= buf;
209
                int src_len= len;
210

  
211
                do {
212
                    uint16_t nal_size = AV_RB16(src); // this going to be a problem if unaligned (can it be?)
213

  
214
                    // consume the length of the aggregate...
215
                    src += 2;
216
                    src_len -= 2;
217

  
218
                    if (nal_size <= src_len) {
219
                        if(pass==0) {
220
                            // counting...
221
                            total_length+= sizeof(start_sequence)+nal_size;
222
                        } else {
223
                            // copying
224
                            assert(dst);
225
                            memcpy(dst, start_sequence, sizeof(start_sequence));
226
                            dst+= sizeof(start_sequence);
227
                            memcpy(dst, src, nal_size);
228
#ifdef DEBUG
229
                            data->packet_types_received[*src & 0x1f]++;
230
#endif
231
                            dst+= nal_size;
232
                        }
233
                    } else {
234
                        av_log(ctx, AV_LOG_ERROR,
235
                               "nal size exceeds length: %d %d\n", nal_size, src_len);
236
                    }
237

  
238
                    // eat what we handled...
239
                    src += nal_size;
240
                    src_len -= nal_size;
241

  
242
                    if (src_len < 0)
243
                        av_log(ctx, AV_LOG_ERROR,
244
                               "Consumed more bytes than we got! (%d)\n", src_len);
245
                } while (src_len > 2);      // because there could be rtp padding..
246

  
247
                if(pass==0) {
248
                    // now we know the total size of the packet (with the start sequences added)
249
                    av_new_packet(pkt, total_length);
250
                    dst= pkt->data;
251
                } else {
252
                    assert(dst-pkt->data==total_length);
253
                }
254
            }
255
        }
256
        break;
257

  
258
    case 25:                   // STAP-B
259
    case 26:                   // MTAP-16
260
    case 27:                   // MTAP-24
261
    case 29:                   // FU-B
262
        av_log(ctx, AV_LOG_ERROR,
263
               "Unhandled type (%d) (See RFC for implementation details\n",
264
               type);
265
        result= -1;
266
        break;
267

  
268
    case 28:                   // FU-A (fragmented nal)
269
        buf++;
270
        len--;                  // skip the fu_indicator
271
        {
272
            // these are the same as above, we just redo them here for clarity...
273
            uint8_t fu_indicator = nal;
274
            uint8_t fu_header = *buf;   // read the fu_header.
275
            uint8_t start_bit = fu_header >> 7;
276
//            uint8_t end_bit = (fu_header & 0x40) >> 6;
277
            uint8_t nal_type = (fu_header & 0x1f);
278
            uint8_t reconstructed_nal;
279

  
280
            // reconstruct this packet's true nal; only the data follows..
281
            reconstructed_nal = fu_indicator & (0xe0);  // the original nal forbidden bit and NRI are stored in this packet's nal;
282
            reconstructed_nal |= nal_type;
283

  
284
            // skip the fu_header...
285
            buf++;
286
            len--;
287

  
288
#ifdef DEBUG
289
            if (start_bit)
290
                data->packet_types_received[nal_type]++;
291
#endif
292
            if(start_bit) {
293
                // copy in the start sequence, and the reconstructed nal....
294
                av_new_packet(pkt, sizeof(start_sequence)+sizeof(nal)+len);
295
                memcpy(pkt->data, start_sequence, sizeof(start_sequence));
296
                pkt->data[sizeof(start_sequence)]= reconstructed_nal;
297
                memcpy(pkt->data+sizeof(start_sequence)+sizeof(nal), buf, len);
298
            } else {
299
                av_new_packet(pkt, len);
300
                memcpy(pkt->data, buf, len);
301
            }
302
        }
303
        break;
304

  
305
    case 30:                   // undefined
306
    case 31:                   // undefined
307
    default:
308
        av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)", type);
309
        result= -1;
310
        break;
311
    }
312

  
313
    pkt->stream_index = st->index;
314

  
315
    return result;
316
}
317

  
318
/* ---------------- public code */
319
static PayloadContext *h264_new_context(void)
320
{
321
    PayloadContext *data =
322
        av_mallocz(sizeof(PayloadContext) +
323
                   FF_INPUT_BUFFER_PADDING_SIZE);
324

  
325
    if (data) {
326
        data->cookie = MAGIC_COOKIE;
327
    }
328

  
329
    return data;
330
}
331

  
332
static void h264_free_context(PayloadContext *data)
333
{
334
#ifdef DEBUG
335
    int ii;
336

  
337
    for (ii = 0; ii < 32; ii++) {
338
        if (data->packet_types_received[ii])
339
            av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
340
                   data->packet_types_received[ii], ii);
341
    }
342
#endif
343

  
344
    assert(data);
345
    assert(data->cookie == MAGIC_COOKIE);
346

  
347
    // avoid stale pointers (assert)
348
    data->cookie = DEAD_COOKIE;
349

  
350
    // and clear out this...
351
    av_free(data);
352
}
353

  
354
static int parse_h264_sdp_line(AVFormatContext *s, int st_index,
355
                               PayloadContext *h264_data, const char *line)
356
{
357
    AVStream *stream = s->streams[st_index];
358
    AVCodecContext *codec = stream->codec;
359
    const char *p = line;
360

  
361
    assert(h264_data->cookie == MAGIC_COOKIE);
362

  
363
    if (av_strstart(p, "framesize:", &p)) {
364
        char buf1[50];
365
        char *dst = buf1;
366

  
367
        // remove the protocol identifier..
368
        while (*p && *p == ' ') p++; // strip spaces.
369
        while (*p && *p != ' ') p++; // eat protocol identifier
370
        while (*p && *p == ' ') p++; // strip trailing spaces.
371
        while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1) {
372
            *dst++ = *p++;
373
        }
374
        *dst = '\0';
375

  
376
        // a='framesize:96 320-240'
377
        // set our parameters..
378
        codec->width = atoi(buf1);
379
        codec->height = atoi(p + 1); // skip the -
380
        codec->pix_fmt = PIX_FMT_YUV420P;
381
    } else if (av_strstart(p, "fmtp:", &p)) {
382
        char attr[256];
383
        char value[4096];
384

  
385
        // remove the protocol identifier..
386
        while (*p && *p == ' ') p++; // strip spaces.
387
        while (*p && *p != ' ') p++; // eat protocol identifier
388
        while (*p && *p == ' ') p++; // strip trailing spaces.
389

  
390
        /* loop on each attribute */
391
        while (ff_rtsp_next_attr_and_value
392
               (&p, attr, sizeof(attr), value, sizeof(value))) {
393
            /* grab the codec extra_data from the config parameter of the fmtp line */
394
            sdp_parse_fmtp_config_h264(stream, h264_data, attr, value);
395
        }
396
    } else if (av_strstart(p, "cliprect:", &p)) {
397
        // could use this if we wanted.
398
    }
399

  
400
    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)
401

  
402
    return 0;                   // keep processing it the normal way...
403
}
404

  
405
/**
406
This is the structure for expanding on the dynamic rtp protocols (makes everything static. yay!)
407
*/
408
RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
409
    .enc_name         = "H264",
410
    .codec_type       = CODEC_TYPE_VIDEO,
411
    .codec_id         = CODEC_ID_H264,
412
    .parse_sdp_a_line = parse_h264_sdp_line,
413
    .open             = h264_new_context,
414
    .close            = h264_free_context,
415
    .parse_packet     = h264_handle_packet
416
};
libavformat/rtp_h264.h
1
/*
2
 * RTP H264 Protocol (RFC3984)
3
 * Copyright (c) 2006 Ryan Martell
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

  
22
#ifndef AVFORMAT_RTP_H264_H
23
#define AVFORMAT_RTP_H264_H
24

  
25
#include "rtpdec.h"
26

  
27
extern RTPDynamicProtocolHandler ff_h264_dynamic_handler;
28

  
29
#endif /* AVFORMAT_RTP_H264_H */
libavformat/rtp_vorbis.c
1
/*
2
 * RTP Vorbis Protocol (RFC5215)
3
 * Copyright (c) 2009 Colin McQuillan
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

  
22
/**
23
 * @file libavformat/rtp_vorbis.c
24
 * @brief Vorbis / RTP Code (RFC 5215)
25
 * @author Colin McQuillan <m.niloc@gmail.com>
26
 */
27

  
28
#include "libavutil/base64.h"
29
#include "libavutil/avstring.h"
30
#include "libavcodec/bytestream.h"
31

  
32
#include <assert.h>
33

  
34
#include "rtpdec.h"
35
#include "rtp_vorbis.h"
36

  
37
/**
38
 * RTP/Vorbis specific private data.
39
 */
40
struct PayloadContext {
41
    unsigned ident;             ///< 24-bit stream configuration identifier
42
};
43

  
44
/**
45
 * Length encoding described in RFC5215 section 3.1.1.
46
 */
47
static int get_base128(const uint8_t ** buf, const uint8_t * buf_end)
48
{
49
    int n = 0;
50
    for (; *buf < buf_end; ++*buf) {
51
        n <<= 7;
52
        n += **buf & 0x7f;
53
        if (!(**buf & 0x80)) {
54
            ++*buf;
55
            return n;
56
        }
57
    }
58
    return 0;
59
}
60

  
61
/**
62
 * Out-of-band headers, described in RFC 5251 section 3.2.1
63
 */
64
static unsigned int
65
parse_packed_headers(const uint8_t * packed_headers,
66
                     const uint8_t * packed_headers_end,
67
                     AVCodecContext * codec, PayloadContext * vorbis_data)
68
{
69
    unsigned num_packed, num_headers, length, length1, length2;
70
    uint8_t *ptr;
71

  
72
    num_packed         = bytestream_get_be32(&packed_headers);
73
    vorbis_data->ident = bytestream_get_be24(&packed_headers);
74
    length             = bytestream_get_be16(&packed_headers);
75
    num_headers        = get_base128(&packed_headers, packed_headers_end);
76
    length1            = get_base128(&packed_headers, packed_headers_end);
77
    length2            = get_base128(&packed_headers, packed_headers_end);
78

  
79
    if (num_packed != 1 || num_headers > 3) {
80
        av_log(codec, AV_LOG_ERROR,
81
               "Unimplemented number of headers: %d packed headers, %d headers\n",
82
               num_packed, num_headers);
83
        return AVERROR_PATCHWELCOME;
84
    }
85

  
86
    if (packed_headers_end - packed_headers != length ||
87
        length1 > length || length2 > length - length1) {
88
        av_log(codec, AV_LOG_ERROR,
89
               "Bad packed header lengths (%d,%d,%d,%d)\n", length1,
90
               length2, packed_headers_end - packed_headers, length);
91
        return AVERROR_INVALIDDATA;
92
    }
93

  
94
    ptr = codec->extradata = av_mallocz(length + length / 255 + 64);
95
    if (!ptr) {
96
        av_log(codec, AV_LOG_ERROR, "Out of memory");
97
        return AVERROR_NOMEM;
98
    }
99
    *ptr++ = 2;
100
    ptr += av_xiphlacing(ptr, length1);
101
    ptr += av_xiphlacing(ptr, length2);
102
    memcpy(ptr, packed_headers, length);
103
    ptr += length;
104
    codec->extradata_size = ptr - codec->extradata;
105

  
106
    return 0;
107
}
108

  
109
int
110
ff_vorbis_parse_fmtp_config(AVCodecContext * codec,
111
                            void *vorbis_data, char *attr, char *value)
112
{
113
    int result = 0;
114
    assert(codec->codec_id == CODEC_ID_VORBIS);
115
    assert(vorbis_data);
116

  
117
    // The configuration value is a base64 encoded packed header
118
    if (!strcmp(attr, "configuration")) {
119
        uint8_t *decoded_packet = NULL;
120
        int packet_size;
121
        size_t decoded_alloc = strlen(value) / 4 * 3 + 4;
122

  
123
        if (decoded_alloc <= INT_MAX) {
124
            decoded_packet = av_malloc(decoded_alloc);
125
            if (decoded_packet) {
126
                packet_size =
127
                    av_base64_decode(decoded_packet, value, decoded_alloc);
128

  
129
                result = parse_packed_headers
130
                    (decoded_packet, decoded_packet + packet_size, codec,
131
                     vorbis_data);
132
            } else {
133
                av_log(codec, AV_LOG_ERROR,
134
                       "Out of memory while decoding SDP configuration.\n");
135
                result = AVERROR_NOMEM;
136
            }
137
        } else {
138
            av_log(codec, AV_LOG_ERROR, "Packet too large\n");
139
            result = AVERROR_INVALIDDATA;
140
        }
141
        av_free(decoded_packet);
142
    }
143
    return result;
144
}
145

  
146
static PayloadContext *vorbis_new_context(void)
147
{
148
    return av_mallocz(sizeof(PayloadContext));
149
}
150

  
151
static void vorbis_free_context(PayloadContext * data)
152
{
153
    av_free(data);
154
}
155

  
156
/**
157
 * Handle payload as described in RFC 5215 section 2.2
158
 */
159
static int
160
vorbis_handle_packet(AVFormatContext * ctx,
161
                     PayloadContext * data,
162
                     AVStream * st,
163
                     AVPacket * pkt,
164
                     uint32_t * timestamp,
165
                     const uint8_t * buf, int len, int flags)
166
{
167
    int ident, fragmented, vdt, num_pkts, pkt_len;
168

  
169
    if (len < 6) {
170
        av_log(ctx, AV_LOG_ERROR, "Invalid %d byte packet\n", len);
171
        return AVERROR_INVALIDDATA;
172
    }
173

  
174
    ident = AV_RB24(buf);
175
    fragmented = buf[3] >> 6;
176
    vdt = (buf[3] >> 4) & 3;
177
    num_pkts = buf[3] & 7;
178
    pkt_len = AV_RB16(buf + 4);
179

  
180
    if (pkt_len > len - 6) {
181
        av_log(ctx, AV_LOG_ERROR,
182
               "Invalid packet length %d in %d byte packet\n", pkt_len,
183
               len);
184
        return AVERROR_INVALIDDATA;
185
    }
186

  
187
    if (ident != data->ident) {
188
        av_log(ctx, AV_LOG_ERROR,
189
               "Unimplemented Vorbis SDP configuration change detected\n");
190
        return AVERROR_PATCHWELCOME;
191
    }
192

  
193
    if (fragmented != 0 || vdt != 0 || num_pkts != 1) {
194
        av_log(ctx, AV_LOG_ERROR,
195
               "Unimplemented RTP Vorbis packet settings (%d,%d,%d)\n",
196
               fragmented, vdt, num_pkts);
197
        return AVERROR_PATCHWELCOME;
198
    }
199

  
200
    if (av_new_packet(pkt, pkt_len)) {
201
        av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
202
        return AVERROR_NOMEM;
203
    }
204

  
205
    memcpy(pkt->data, buf + 6, pkt_len);
206
    pkt->stream_index = st->index;
207
    return 0;
208
}
209

  
210
RTPDynamicProtocolHandler ff_vorbis_dynamic_handler = {
211
    .enc_name         = "vorbis",
212
    .codec_type       = CODEC_TYPE_AUDIO,
213
    .codec_id         = CODEC_ID_VORBIS,
214
    .parse_sdp_a_line = NULL,
215
    .open             = vorbis_new_context,
216
    .close            = vorbis_free_context,
217
    .parse_packet     = vorbis_handle_packet
218
};
libavformat/rtp_vorbis.h
1
/*
2
 * RTP Vorbis Protocol (RFC 5215)
3
 * Copyright (c) 2009 Colin McQuillan
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

  
22
#ifndef AVFORMAT_RTP_VORBIS_H
23
#define AVFORMAT_RTP_VORBIS_H
24

  
25
#include "libavcodec/avcodec.h"
26
#include "rtpdec.h"
27

  
28
/**
29
 * Handle a Vorbis-specific FMTP parameter
30
 *
31
 * @param codec The context of the codec
32
 * @param ctx Private Vorbis RTP context
33
 * @param attr Format-specific parameter name
34
 * @param value Format-specific paremeter value
35
 */
36
int
37
ff_vorbis_parse_fmtp_config(AVCodecContext * codec,
38
                            void *ctx, char *attr, char *value);
39

  
40
/**
41
 * Vorbis RTP callbacks.
42
 */
43
extern RTPDynamicProtocolHandler ff_vorbis_dynamic_handler;
44

  
45
#endif /* AVFORMAT_RTP_VORBIS_H */
libavformat/rtpdec.c
30 30
#include "network.h"
31 31

  
32 32
#include "rtpdec.h"
33
#include "rtp_asf.h"
34
#include "rtp_h264.h"
35
#include "rtp_vorbis.h"
36 33
#include "rtpdec_amr.h"
34
#include "rtpdec_asf.h"
37 35
#include "rtpdec_h263.h"
36
#include "rtpdec_h264.h"
37
#include "rtpdec_vorbis.h"
38 38

  
39 39
//#define DEBUG
40 40

  
libavformat/rtpdec_asf.c
1
/*
2
 * Microsoft RTP/ASF support.
3
 * Copyright (c) 2008 Ronald S. Bultje
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

  
22
/**
23
 * @file libavformat/rtpdec_asf.c
24
 * @brief Microsoft RTP/ASF support
25
 * @author Ronald S. Bultje <rbultje@ronald.bitfreak.net>
26
 */
27

  
28
#include <libavutil/base64.h>
29
#include <libavutil/avstring.h>
30
#include <libavutil/intreadwrite.h>
31
#include "rtp.h"
32
#include "rtpdec_asf.h"
33
#include "rtsp.h"
34
#include "asf.h"
35

  
36
/**
37
 * From MSDN 2.2.1.4, we learn that ASF data packets over RTP should not
38
 * contain any padding. Unfortunately, the header min/max_pktsize are not
39
 * updated (thus making min_pktsize invalid). Here, we "fix" these faulty
40
 * min_pktsize values in the ASF file header.
41
 * @return 0 on success, <0 on failure (currently -1).
42
 */
43
static int rtp_asf_fix_header(uint8_t *buf, int len)
44
{
45
    uint8_t *p = buf, *end = buf + len;
46

  
47
    if (len < sizeof(ff_asf_guid) * 2 + 22 ||
48
        memcmp(p, ff_asf_header, sizeof(ff_asf_guid))) {
49
        return -1;
50
    }
51
    p += sizeof(ff_asf_guid) + 14;
52
    do {
53
        uint64_t chunksize = AV_RL64(p + sizeof(ff_asf_guid));
54
        if (memcmp(p, ff_asf_file_header, sizeof(ff_asf_guid))) {
55
            if (chunksize > end - p)
56
                return -1;
57
            p += chunksize;
58
            continue;
59
        }
60

  
61
        /* skip most of the file header, to min_pktsize */
62
        p += 6 * 8 + 3 * 4 + sizeof(ff_asf_guid) * 2;
63
        if (p + 8 <= end && AV_RL32(p) == AV_RL32(p + 4)) {
64
            /* and set that to zero */
65
            AV_WL32(p, 0);
66
            return 0;
67
        }
68
        break;
69
    } while (end - p >= sizeof(ff_asf_guid) + 8);
70

  
71
    return -1;
72
}
73

  
74
/**
75
 * The following code is basically a buffered ByteIOContext,
76
 * with the added benefit of returning -EAGAIN (instead of 0)
77
 * on packet boundaries, such that the ASF demuxer can return
78
 * safely and resume business at the next packet.
79
 */
80
static int packetizer_read(void *opaque, uint8_t *buf, int buf_size)
81
{
82
    return AVERROR(EAGAIN);
83
}
84

  
85
static void init_packetizer(ByteIOContext *pb, uint8_t *buf, int len)
86
{
87
    init_put_byte(pb, buf, len, 0, NULL, packetizer_read, NULL, NULL);
88

  
89
    /* this "fills" the buffer with its current content */
90
    pb->pos     = len;
91
    pb->buf_end = buf + len;
92
}
93

  
94
void ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p)
95
{
96
    if (av_strstart(p, "pgmpu:data:application/vnd.ms.wms-hdr.asfv1;base64,", &p)) {
97
        ByteIOContext pb;
98
        RTSPState *rt = s->priv_data;
99
        int len = strlen(p) * 6 / 8;
100
        char *buf = av_mallocz(len);
101
        av_base64_decode(buf, p, len);
102

  
103
        if (rtp_asf_fix_header(buf, len) < 0)
104
            av_log(s, AV_LOG_ERROR,
105
                   "Failed to fix invalid RTSP-MS/ASF min_pktsize\n");
106
        init_packetizer(&pb, buf, len);
107
        if (rt->asf_ctx) {
108
            av_close_input_stream(rt->asf_ctx);
109
            rt->asf_ctx = NULL;
110
        }
111
        av_open_input_stream(&rt->asf_ctx, &pb, "", &asf_demuxer, NULL);
112
        rt->asf_pb_pos = url_ftell(&pb);
113
        av_free(buf);
114
        rt->asf_ctx->pb = NULL;
115
    }
116
}
117

  
118
static int asfrtp_parse_sdp_line(AVFormatContext *s, int stream_index,
119
                                 PayloadContext *asf, const char *line)
120
{
121
    if (av_strstart(line, "stream:", &line)) {
122
        RTSPState *rt = s->priv_data;
123

  
124
        s->streams[stream_index]->id = strtol(line, NULL, 10);
125

  
126
        if (rt->asf_ctx) {
127
            int i;
128

  
129
            for (i = 0; i < rt->asf_ctx->nb_streams; i++) {
130
                if (s->streams[stream_index]->id == rt->asf_ctx->streams[i]->id) {
131
                    *s->streams[stream_index]->codec =
132
                        *rt->asf_ctx->streams[i]->codec;
133
                    rt->asf_ctx->streams[i]->codec->extradata_size = 0;
134
                    rt->asf_ctx->streams[i]->codec->extradata = NULL;
135
                    av_set_pts_info(s->streams[stream_index], 32, 1, 1000);
136
                }
137
           }
138
        }
139
    }
140

  
141
    return 0;
142
}
143

  
144
struct PayloadContext {
145
    ByteIOContext *pktbuf, pb;
146
    char *buf;
147
};
148

  
149
/**
150
 * @return 0 when a packet was written into /p pkt, and no more data is left;
151
 *         1 when a packet was written into /p pkt, and more packets might be left;
152
 *        <0 when not enough data was provided to return a full packet, or on error.
153
 */
154
static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf,
155
                               AVStream *st, AVPacket *pkt,
156
                               uint32_t *timestamp,
157
                               const uint8_t *buf, int len, int flags)
158
{
159
    ByteIOContext *pb = &asf->pb;
160
    int res, mflags, len_off;
161
    RTSPState *rt = s->priv_data;
162

  
163
    if (!rt->asf_ctx)
164
        return -1;
165

  
166
    if (len > 0) {
167
        int off, out_len;
168

  
169
        if (len < 4)
170
            return -1;
171

  
172
        init_put_byte(pb, buf, len, 0, NULL, NULL, NULL, NULL);
173
        mflags = get_byte(pb);
174
        if (mflags & 0x80)
175
            flags |= RTP_FLAG_KEY;
176
        len_off = get_be24(pb);
177
        if (mflags & 0x20)   /**< relative timestamp */
178
            url_fskip(pb, 4);
179
        if (mflags & 0x10)   /**< has duration */
180
            url_fskip(pb, 4);
181
        if (mflags & 0x8)    /**< has location ID */
182
            url_fskip(pb, 4);
183
        off = url_ftell(pb);
184

  
185
        av_freep(&asf->buf);
186
        if (!(mflags & 0x40)) {
187
            /**
188
             * If 0x40 is not set, the len_off field specifies an offset of this
189
             * packet's payload data in the complete (reassembled) ASF packet.
190
             * This is used to spread one ASF packet over multiple RTP packets.
191
             */
192
            if (asf->pktbuf && len_off != url_ftell(asf->pktbuf)) {
193
                uint8_t *p;
194
                url_close_dyn_buf(asf->pktbuf, &p);
195
                asf->pktbuf = NULL;
196
                av_free(p);
197
            }
198
            if (!len_off && !asf->pktbuf &&
199
                (res = url_open_dyn_buf(&asf->pktbuf)) < 0)
200
                return res;
201
            if (!asf->pktbuf)
202
                return AVERROR(EIO);
203

  
204
            put_buffer(asf->pktbuf, buf + off, len - off);
205
            if (!(flags & RTP_FLAG_MARKER))
206
                return -1;
207
            out_len     = url_close_dyn_buf(asf->pktbuf, &asf->buf);
208
            asf->pktbuf = NULL;
209
        } else {
210
            /**
211
             * If 0x40 is set, the len_off field specifies the length of the
212
             * next ASF packet that can be read from this payload data alone.
213
             * This is commonly the same as the payload size, but could be
214
             * less in case of packet splitting (i.e. multiple ASF packets in
215
             * one RTP packet).
216
             */
217
            if (len_off != len) {
218
                av_log_missing_feature(s,
219
                    "RTSP-MS packet splitting", 1);
220
                return -1;
221
            }
222
            asf->buf = av_malloc(len - off);
223
            out_len  = len - off;
224
            memcpy(asf->buf, buf + off, len - off);
225
        }
226

  
227
        init_packetizer(pb, asf->buf, out_len);
228
        pb->pos += rt->asf_pb_pos;
229
        pb->eof_reached = 0;
230
        rt->asf_ctx->pb = pb;
231
    }
232

  
233
    for (;;) {
234
        int i;
235

  
236
        res = av_read_packet(rt->asf_ctx, pkt);
237
        rt->asf_pb_pos = url_ftell(pb);
238
        if (res != 0)
239
            break;
240
        for (i = 0; i < s->nb_streams; i++) {
241
            if (s->streams[i]->id == rt->asf_ctx->streams[pkt->stream_index]->id) {
242
                pkt->stream_index = i;
243
                return 1; // FIXME: return 0 if last packet
244
            }
245
        }
246
        av_free_packet(pkt);
247
    }
248

  
249
    return res == 1 ? -1 : res;
250
}
251

  
252
static PayloadContext *asfrtp_new_context(void)
253
{
254
    return av_mallocz(sizeof(PayloadContext));
255
}
256

  
257
static void asfrtp_free_context(PayloadContext *asf)
258
{
259
    if (asf->pktbuf) {
260
        uint8_t *p = NULL;
261
        url_close_dyn_buf(asf->pktbuf, &p);
262
        asf->pktbuf = NULL;
263
        av_free(p);
264
    }
265
    av_freep(&asf->buf);
266
    av_free(asf);
267
}
268

  
269
#define RTP_ASF_HANDLER(n, s, t) \
270
RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \
271
    .enc_name         = s, \
272
    .codec_type       = t, \
273
    .codec_id         = CODEC_ID_NONE, \
274
    .parse_sdp_a_line = asfrtp_parse_sdp_line, \
275
    .open             = asfrtp_new_context, \
276
    .close            = asfrtp_free_context, \
277
    .parse_packet     = asfrtp_parse_packet,   \
278
};
279

  
280
RTP_ASF_HANDLER(asf_pfv, "x-asf-pf",  CODEC_TYPE_VIDEO);
281
RTP_ASF_HANDLER(asf_pfa, "x-asf-pf",  CODEC_TYPE_AUDIO);
libavformat/rtpdec_asf.h
1
/*
2
 * Microsoft RTP/ASF support.
3
 * Copyright (c) 2008 Ronald S. Bultje
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

  
22
#ifndef AVFORMAT_RTPDEC_ASF_H
23
#define AVFORMAT_RTPDEC_ASF_H
24

  
25
#include "avformat.h"
26
#include "rtpdec.h"
27

  
28
/**
29
 * Parse a Windows Media Server-specific SDP line
30
 *
31
 * @param s RTSP demux context
32
 * @param line the SDP line to be parsed
33
 */
34
void ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p);
35

  
36
/**
37
 * Handlers for the x-asf-pf payloads (the payload ID for RTP/ASF).
38
 * Defined and implemented in rtp_asf.c, registered in rtpdec.c.
39
 */
40
extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfv_handler,
41
                                 ff_ms_rtp_asf_pfa_handler;
42

  
43
#endif /* AVFORMAT_RTPDEC_ASF_H */
libavformat/rtpdec_h264.c
1
/*
2
 * RTP H264 Protocol (RFC3984)
3
 * Copyright (c) 2006 Ryan Martell
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

  
22
/**
23
* @file libavformat/rtpdec_h264.c
24
 * @brief H.264 / RTP Code (RFC3984)
25
 * @author Ryan Martell <rdm4@martellventures.com>
26
 *
27
 * @note Notes:
28
 * Notes:
29
 * This currently supports packetization mode:
30
 * Single Nal Unit Mode (0), or
31
 * Non-Interleaved Mode (1).  It currently does not support
32
 * Interleaved Mode (2). (This requires implementing STAP-B, MTAP16, MTAP24, FU-B packet types)
33
 *
34
 * @note TODO:
35
 * 1) RTCP sender reports for udp streams are required..
36
 *
37
 */
38

  
39
#include "libavutil/base64.h"
40
#include "libavutil/avstring.h"
41
#include "libavcodec/get_bits.h"
42
#include "avformat.h"
43
#include "mpegts.h"
44

  
45
#include <unistd.h>
46
#include "network.h"
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff