]> git.sesse.net Git - ffmpeg/blob - libavformat/rdt.c
Fix compilation with only Theora decoder enabled
[ffmpeg] / libavformat / rdt.c
1 /*
2  * Realmedia RTSP protocol (RDT) support.
3  * Copyright (c) 2007 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 rdt.c
24  * @brief Realmedia RTSP protocol (RDT) support
25  * @author Ronald S. Bultje <rbultje@ronald.bitfreak.net>
26  */
27
28 #include "avformat.h"
29 #include "libavutil/avstring.h"
30 #include "rtp_internal.h"
31 #include "rdt.h"
32 #include "libavutil/base64.h"
33 #include "libavutil/md5.h"
34 #include "rm.h"
35 #include "internal.h"
36 #include <libavcodec/bitstream.h>
37
38 struct RDTDemuxContext {
39     AVFormatContext *ic; /**< the containing (RTSP) demux context */
40     /** Each RDT stream-set (represented by one RTSPStream) can contain
41      * multiple streams (of the same content, but with possibly different
42      * codecs/bitrates). Each such stream is represented by one AVStream
43      * in the AVFormatContext, and this variable points to the offset in
44      * that array such that the first is the first stream of this set. */
45     AVStream **streams;
46     int n_streams; /**< streams with identifical content in this set */
47     void *dynamic_protocol_context;
48     DynamicPayloadPacketHandlerProc parse_packet;
49     uint32_t prev_timestamp;
50     int prev_set_id, prev_stream_id;
51 };
52
53 RDTDemuxContext *
54 ff_rdt_parse_open(AVFormatContext *ic, int first_stream_of_set_idx,
55                   void *priv_data, RTPDynamicProtocolHandler *handler)
56 {
57     RDTDemuxContext *s = av_mallocz(sizeof(RDTDemuxContext));
58     if (!s)
59         return NULL;
60
61     s->ic = ic;
62     s->streams = &ic->streams[first_stream_of_set_idx];
63     do {
64         s->n_streams++;
65     } while (first_stream_of_set_idx + s->n_streams < ic->nb_streams &&
66              s->streams[s->n_streams]->priv_data == s->streams[0]->priv_data);
67     s->prev_set_id    = -1;
68     s->prev_stream_id = -1;
69     s->prev_timestamp = -1;
70     s->parse_packet = handler->parse_packet;
71     s->dynamic_protocol_context = priv_data;
72
73     return s;
74 }
75
76 void
77 ff_rdt_parse_close(RDTDemuxContext *s)
78 {
79     av_free(s);
80 }
81
82 struct PayloadContext {
83     AVFormatContext *rmctx;
84     uint8_t *mlti_data;
85     unsigned int mlti_data_size;
86     char buffer[RTP_MAX_PACKET_LENGTH + FF_INPUT_BUFFER_PADDING_SIZE];
87 };
88
89 void
90 ff_rdt_calc_response_and_checksum(char response[41], char chksum[9],
91                                   const char *challenge)
92 {
93     int ch_len = strlen (challenge), i;
94     unsigned char zres[16],
95         buf[64] = { 0xa1, 0xe9, 0x14, 0x9d, 0x0e, 0x6b, 0x3b, 0x59 };
96 #define XOR_TABLE_SIZE 37
97     const unsigned char xor_table[XOR_TABLE_SIZE] = {
98         0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53,
99         0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70,
100         0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09,
101         0x63, 0x11, 0x03, 0x71, 0x08, 0x08, 0x70, 0x02,
102         0x10, 0x57, 0x05, 0x18, 0x54 };
103
104     /* some (length) checks */
105     if (ch_len == 40) /* what a hack... */
106         ch_len = 32;
107     else if (ch_len > 56)
108         ch_len = 56;
109     memcpy(buf + 8, challenge, ch_len);
110
111     /* xor challenge bytewise with xor_table */
112     for (i = 0; i < XOR_TABLE_SIZE; i++)
113         buf[8 + i] ^= xor_table[i];
114
115     av_md5_sum(zres, buf, 64);
116     ff_data_to_hex(response, zres, 16);
117     for (i=0;i<32;i++) response[i] = tolower(response[i]);
118
119     /* add tail */
120     strcpy (response + 32, "01d0a8e3");
121
122     /* calculate checksum */
123     for (i = 0; i < 8; i++)
124         chksum[i] = response[i * 4];
125     chksum[8] = 0;
126 }
127
128 static int
129 rdt_load_mdpr (PayloadContext *rdt, AVStream *st, int rule_nr)
130 {
131     ByteIOContext pb;
132     int size;
133     uint32_t tag;
134
135     /**
136      * Layout of the MLTI chunk:
137      * 4:MLTI
138      * 2:<number of streams>
139      * Then for each stream ([number_of_streams] times):
140      *     2:<mdpr index>
141      * 2:<number of mdpr chunks>
142      * Then for each mdpr chunk ([number_of_mdpr_chunks] times):
143      *     4:<size>
144      *     [size]:<data>
145      * we skip MDPR chunks until we reach the one of the stream
146      * we're interested in, and forward that ([size]+[data]) to
147      * the RM demuxer to parse the stream-specific header data.
148      */
149     if (!rdt->mlti_data)
150         return -1;
151     init_put_byte(&pb, rdt->mlti_data, rdt->mlti_data_size, 0,
152                   NULL, NULL, NULL, NULL);
153     tag = get_le32(&pb);
154     if (tag == MKTAG('M', 'L', 'T', 'I')) {
155         int num, chunk_nr;
156
157         /* read index of MDPR chunk numbers */
158         num = get_be16(&pb);
159         if (rule_nr < 0 || rule_nr >= num)
160             return -1;
161         url_fskip(&pb, rule_nr * 2);
162         chunk_nr = get_be16(&pb);
163         url_fskip(&pb, (num - 1 - rule_nr) * 2);
164
165         /* read MDPR chunks */
166         num = get_be16(&pb);
167         if (chunk_nr >= num)
168             return -1;
169         while (chunk_nr--)
170             url_fskip(&pb, get_be32(&pb));
171         size = get_be32(&pb);
172     } else {
173         size = rdt->mlti_data_size;
174         url_fseek(&pb, 0, SEEK_SET);
175     }
176     if (ff_rm_read_mdpr_codecdata(rdt->rmctx, &pb, st, size) < 0)
177         return -1;
178
179     return 0;
180 }
181
182 /**
183  * Actual data handling.
184  */
185
186 int
187 ff_rdt_parse_header(const uint8_t *buf, int len,
188                     int *pset_id, int *pseq_no, int *pstream_id,
189                     int *pis_keyframe, uint32_t *ptimestamp)
190 {
191     GetBitContext gb;
192     int consumed = 0, set_id, seq_no, stream_id, is_keyframe,
193         len_included, need_reliable;
194     uint32_t timestamp;
195
196     /* skip status packets */
197     while (len >= 5 && buf[1] == 0xFF /* status packet */) {
198         int pkt_len;
199
200         if (!(buf[0] & 0x80))
201             return -1; /* not followed by a data packet */
202
203         pkt_len = AV_RB16(buf+3);
204         buf += pkt_len;
205         len -= pkt_len;
206         consumed += pkt_len;
207     }
208     if (len < 16)
209         return -1;
210     /**
211      * Layout of the header (in bits):
212      * 1:  len_included
213      *     Flag indicating whether this header includes a length field;
214      *     this can be used to concatenate multiple RDT packets in a
215      *     single UDP/TCP data frame and is used to precede RDT data
216      *     by stream status packets
217      * 1:  need_reliable
218      *     Flag indicating whether this header includes a "reliable
219      *     sequence number"; these are apparently sequence numbers of
220      *     data packets alone. For data packets, this flag is always
221      *     set, according to the Real documentation [1]
222      * 5:  set_id
223      *     ID of a set of streams of identical content, possibly with
224      *     different codecs or bitrates
225      * 1:  is_reliable
226      *     Flag set for certain streams deemed less tolerable for packet
227      *     loss
228      * 16: seq_no
229      *     Packet sequence number; if >=0xFF00, this is a non-data packet
230      *     containing stream status info, the second byte indicates the
231      *     type of status packet (see wireshark docs / source code [2])
232      * if (len_included) {
233      *     16: packet_len
234      * } else {
235      *     packet_len = remainder of UDP/TCP frame
236      * }
237      * 1:  is_back_to_back
238      *     Back-to-Back flag; used for timing, set for one in every 10
239      *     packets, according to the Real documentation [1]
240      * 1:  is_slow_data
241      *     Slow-data flag; currently unused, according to Real docs [1]
242      * 5:  stream_id
243      *     ID of the stream within this particular set of streams
244      * 1:  is_no_keyframe
245      *     Non-keyframe flag (unset if packet belongs to a keyframe)
246      * 32: timestamp (PTS)
247      * if (set_id == 0x1F) {
248      *     16: set_id (extended set-of-streams ID; see set_id)
249      * }
250      * if (need_reliable) {
251      *     16: reliable_seq_no
252      *         Reliable sequence number (see need_reliable)
253      * }
254      * if (stream_id == 0x3F) {
255      *     16: stream_id (extended stream ID; see stream_id)
256      * }
257      * [1] https://protocol.helixcommunity.org/files/2005/devdocs/RDT_Feature_Level_20.txt
258      * [2] http://www.wireshark.org/docs/dfref/r/rdt.html and
259      *     http://anonsvn.wireshark.org/viewvc/trunk/epan/dissectors/packet-rdt.c
260      */
261     init_get_bits(&gb, buf, len << 3);
262     len_included  = get_bits1(&gb);
263     need_reliable = get_bits1(&gb);
264     set_id        = get_bits(&gb, 5);
265     skip_bits(&gb, 1);
266     seq_no        = get_bits(&gb, 16);
267     if (len_included)
268         skip_bits(&gb, 16);
269     skip_bits(&gb, 2);
270     stream_id     = get_bits(&gb, 5);
271     is_keyframe   = !get_bits1(&gb);
272     timestamp     = get_bits_long(&gb, 32);
273     if (set_id == 0x1f)
274         set_id    = get_bits(&gb, 16);
275     if (need_reliable)
276         skip_bits(&gb, 16);
277     if (stream_id == 0x1f)
278         stream_id = get_bits(&gb, 16);
279
280     if (pset_id)      *pset_id      = set_id;
281     if (pseq_no)      *pseq_no      = seq_no;
282     if (pstream_id)   *pstream_id   = stream_id;
283     if (pis_keyframe) *pis_keyframe = is_keyframe;
284     if (ptimestamp)   *ptimestamp   = timestamp;
285
286     return consumed + (get_bits_count(&gb) >> 3);
287 }
288
289 /**< return 0 on packet, no more left, 1 on packet, 1 on partial packet... */
290 static int
291 rdt_parse_packet (PayloadContext *rdt, AVStream *st,
292                   AVPacket *pkt, uint32_t *timestamp,
293                   const uint8_t *buf, int len, int flags)
294 {
295     int seq = 1, res;
296     ByteIOContext pb;
297     RMContext *rm = rdt->rmctx->priv_data;
298
299     if (rm->audio_pkt_cnt == 0) {
300         int pos;
301
302         init_put_byte(&pb, buf, len, 0, NULL, NULL, NULL, NULL);
303         flags = (flags & PKT_FLAG_KEY) ? 2 : 0;
304         res = ff_rm_parse_packet (rdt->rmctx, &pb, st, len, pkt,
305                                   &seq, &flags, timestamp);
306         pos = url_ftell(&pb);
307         if (res < 0)
308             return res;
309         if (rm->audio_pkt_cnt > 0 &&
310             st->codec->codec_id == CODEC_ID_AAC) {
311             memcpy (rdt->buffer, buf + pos, len - pos);
312             rdt->rmctx->pb = av_alloc_put_byte (rdt->buffer, len - pos, 0,
313                                                 NULL, NULL, NULL, NULL);
314         }
315     } else {
316         ff_rm_retrieve_cache (rdt->rmctx, rdt->rmctx->pb, st, pkt);
317         if (rm->audio_pkt_cnt == 0 &&
318             st->codec->codec_id == CODEC_ID_AAC)
319             av_freep(&rdt->rmctx->pb);
320     }
321     pkt->stream_index = st->index;
322     pkt->pts = *timestamp;
323
324     return rm->audio_pkt_cnt > 0;
325 }
326
327 int
328 ff_rdt_parse_packet(RDTDemuxContext *s, AVPacket *pkt,
329                     const uint8_t *buf, int len)
330 {
331     int seq_no, flags = 0, stream_id, set_id, is_keyframe;
332     uint32_t timestamp;
333     int rv= 0;
334
335     if (!s->parse_packet)
336         return -1;
337
338     if (!buf && s->prev_stream_id != -1) {
339         /* return the next packets, if any */
340         timestamp= 0; ///< Should not be used if buf is NULL, but should be set to the timestamp of the packet returned....
341         rv= s->parse_packet(s->dynamic_protocol_context,
342                             s->streams[s->prev_stream_id],
343                             pkt, &timestamp, NULL, 0, flags);
344         return rv;
345     }
346
347     if (len < 12)
348         return -1;
349     rv = ff_rdt_parse_header(buf, len, &set_id, &seq_no, &stream_id, &is_keyframe, &timestamp);
350     if (rv < 0)
351         return rv;
352     if (is_keyframe &&
353         (set_id != s->prev_set_id || timestamp != s->prev_timestamp ||
354          stream_id != s->prev_stream_id)) {
355         flags |= PKT_FLAG_KEY;
356         s->prev_set_id    = set_id;
357         s->prev_timestamp = timestamp;
358     }
359     s->prev_stream_id = stream_id;
360     buf += rv;
361     len -= rv;
362
363      if (s->prev_stream_id >= s->n_streams) {
364          s->prev_stream_id = -1;
365          return -1;
366      }
367
368     rv = s->parse_packet(s->dynamic_protocol_context,
369                          s->streams[s->prev_stream_id],
370                          pkt, &timestamp, buf, len, flags);
371
372     return rv;
373 }
374
375 void
376 ff_rdt_subscribe_rule (char *cmd, int size,
377                        int stream_nr, int rule_nr)
378 {
379     av_strlcatf(cmd, size, "stream=%d;rule=%d,stream=%d;rule=%d",
380                 stream_nr, rule_nr * 2, stream_nr, rule_nr * 2 + 1);
381 }
382
383 void
384 ff_rdt_subscribe_rule2 (RDTDemuxContext *s, char *cmd, int size,
385                         int stream_nr, int rule_nr)
386 {
387     PayloadContext *rdt = s->dynamic_protocol_context;
388
389     rdt_load_mdpr(rdt, s->streams[0], rule_nr * 2);
390 }
391
392 static unsigned char *
393 rdt_parse_b64buf (unsigned int *target_len, const char *p)
394 {
395     unsigned char *target;
396     int len = strlen(p);
397     if (*p == '\"') {
398         p++;
399         len -= 2; /* skip embracing " at start/end */
400     }
401     *target_len = len * 3 / 4;
402     target = av_mallocz(*target_len + FF_INPUT_BUFFER_PADDING_SIZE);
403     av_base64_decode(target, p, *target_len);
404     return target;
405 }
406
407 static int
408 rdt_parse_sdp_line (AVFormatContext *s, int st_index,
409                     PayloadContext *rdt, const char *line)
410 {
411     AVStream *stream = s->streams[st_index];
412     const char *p = line;
413
414     if (av_strstart(p, "OpaqueData:buffer;", &p)) {
415         rdt->mlti_data = rdt_parse_b64buf(&rdt->mlti_data_size, p);
416     } else if (av_strstart(p, "StartTime:integer;", &p))
417         stream->first_dts = atoi(p);
418
419     return 0;
420 }
421
422 static PayloadContext *
423 rdt_new_extradata (void)
424 {
425     PayloadContext *rdt = av_mallocz(sizeof(PayloadContext));
426
427     av_open_input_stream(&rdt->rmctx, NULL, "", &rdt_demuxer, NULL);
428
429     return rdt;
430 }
431
432 static void
433 rdt_free_extradata (PayloadContext *rdt)
434 {
435     if (rdt->rmctx)
436         av_close_input_stream(rdt->rmctx);
437     av_freep(&rdt->mlti_data);
438     av_free(rdt);
439 }
440
441 #define RDT_HANDLER(n, s, t) \
442 static RTPDynamicProtocolHandler ff_rdt_ ## n ## _handler = { \
443     s, \
444     t, \
445     CODEC_ID_NONE, \
446     rdt_parse_sdp_line, \
447     rdt_new_extradata, \
448     rdt_free_extradata, \
449     rdt_parse_packet \
450 };
451
452 RDT_HANDLER(live_video, "x-pn-multirate-realvideo-live", CODEC_TYPE_VIDEO);
453 RDT_HANDLER(live_audio, "x-pn-multirate-realaudio-live", CODEC_TYPE_AUDIO);
454 RDT_HANDLER(video,      "x-pn-realvideo",                CODEC_TYPE_VIDEO);
455 RDT_HANDLER(audio,      "x-pn-realaudio",                CODEC_TYPE_AUDIO);
456
457 void av_register_rdt_dynamic_payload_handlers(void)
458 {
459     ff_register_dynamic_payload_handler(&ff_rdt_video_handler);
460     ff_register_dynamic_payload_handler(&ff_rdt_audio_handler);
461     ff_register_dynamic_payload_handler(&ff_rdt_live_video_handler);
462     ff_register_dynamic_payload_handler(&ff_rdt_live_audio_handler);
463 }