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