00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00028 #include "avformat.h"
00029 #include "libavutil/avstring.h"
00030 #include "rtpdec.h"
00031 #include "rdt.h"
00032 #include "libavutil/base64.h"
00033 #include "libavutil/md5.h"
00034 #include "rm.h"
00035 #include "internal.h"
00036 #include "libavcodec/get_bits.h"
00037
00038 struct RDTDemuxContext {
00039 AVFormatContext *ic;
00045 AVStream **streams;
00046 int n_streams;
00047 void *dynamic_protocol_context;
00048 DynamicPayloadPacketHandlerProc parse_packet;
00049 uint32_t prev_timestamp;
00050 int prev_set_id, prev_stream_id;
00051 };
00052
00053 RDTDemuxContext *
00054 ff_rdt_parse_open(AVFormatContext *ic, int first_stream_of_set_idx,
00055 void *priv_data, RTPDynamicProtocolHandler *handler)
00056 {
00057 RDTDemuxContext *s = av_mallocz(sizeof(RDTDemuxContext));
00058 if (!s)
00059 return NULL;
00060
00061 s->ic = ic;
00062 s->streams = &ic->streams[first_stream_of_set_idx];
00063 do {
00064 s->n_streams++;
00065 } while (first_stream_of_set_idx + s->n_streams < ic->nb_streams &&
00066 s->streams[s->n_streams]->priv_data == s->streams[0]->priv_data);
00067 s->prev_set_id = -1;
00068 s->prev_stream_id = -1;
00069 s->prev_timestamp = -1;
00070 s->parse_packet = handler ? handler->parse_packet : NULL;
00071 s->dynamic_protocol_context = priv_data;
00072
00073 return s;
00074 }
00075
00076 void
00077 ff_rdt_parse_close(RDTDemuxContext *s)
00078 {
00079 int i;
00080
00081 for (i = 1; i < s->n_streams; i++)
00082 s->streams[i]->priv_data = NULL;
00083
00084 av_free(s);
00085 }
00086
00087 struct PayloadContext {
00088 AVFormatContext *rmctx;
00089 RMStream *rmst[MAX_STREAMS];
00090 uint8_t *mlti_data;
00091 unsigned int mlti_data_size;
00092 char buffer[RTP_MAX_PACKET_LENGTH + FF_INPUT_BUFFER_PADDING_SIZE];
00093 int audio_pkt_cnt;
00094 };
00095
00096 void
00097 ff_rdt_calc_response_and_checksum(char response[41], char chksum[9],
00098 const char *challenge)
00099 {
00100 int ch_len = strlen (challenge), i;
00101 unsigned char zres[16],
00102 buf[64] = { 0xa1, 0xe9, 0x14, 0x9d, 0x0e, 0x6b, 0x3b, 0x59 };
00103 #define XOR_TABLE_SIZE 37
00104 const unsigned char xor_table[XOR_TABLE_SIZE] = {
00105 0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53,
00106 0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70,
00107 0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09,
00108 0x63, 0x11, 0x03, 0x71, 0x08, 0x08, 0x70, 0x02,
00109 0x10, 0x57, 0x05, 0x18, 0x54 };
00110
00111
00112 if (ch_len == 40)
00113 ch_len = 32;
00114 else if (ch_len > 56)
00115 ch_len = 56;
00116 memcpy(buf + 8, challenge, ch_len);
00117
00118
00119 for (i = 0; i < XOR_TABLE_SIZE; i++)
00120 buf[8 + i] ^= xor_table[i];
00121
00122 av_md5_sum(zres, buf, 64);
00123 ff_data_to_hex(response, zres, 16, 1);
00124
00125
00126 strcpy (response + 32, "01d0a8e3");
00127
00128
00129 for (i = 0; i < 8; i++)
00130 chksum[i] = response[i * 4];
00131 chksum[8] = 0;
00132 }
00133
00134 static int
00135 rdt_load_mdpr (PayloadContext *rdt, AVStream *st, int rule_nr)
00136 {
00137 ByteIOContext pb;
00138 int size;
00139 uint32_t tag;
00140
00155 if (!rdt->mlti_data)
00156 return -1;
00157 init_put_byte(&pb, rdt->mlti_data, rdt->mlti_data_size, 0,
00158 NULL, NULL, NULL, NULL);
00159 tag = get_le32(&pb);
00160 if (tag == MKTAG('M', 'L', 'T', 'I')) {
00161 int num, chunk_nr;
00162
00163
00164 num = get_be16(&pb);
00165 if (rule_nr < 0 || rule_nr >= num)
00166 return -1;
00167 url_fskip(&pb, rule_nr * 2);
00168 chunk_nr = get_be16(&pb);
00169 url_fskip(&pb, (num - 1 - rule_nr) * 2);
00170
00171
00172 num = get_be16(&pb);
00173 if (chunk_nr >= num)
00174 return -1;
00175 while (chunk_nr--)
00176 url_fskip(&pb, get_be32(&pb));
00177 size = get_be32(&pb);
00178 } else {
00179 size = rdt->mlti_data_size;
00180 url_fseek(&pb, 0, SEEK_SET);
00181 }
00182 if (ff_rm_read_mdpr_codecdata(rdt->rmctx, &pb, st, rdt->rmst[st->index], size) < 0)
00183 return -1;
00184
00185 return 0;
00186 }
00187
00192 int
00193 ff_rdt_parse_header(const uint8_t *buf, int len,
00194 int *pset_id, int *pseq_no, int *pstream_id,
00195 int *pis_keyframe, uint32_t *ptimestamp)
00196 {
00197 GetBitContext gb;
00198 int consumed = 0, set_id, seq_no, stream_id, is_keyframe,
00199 len_included, need_reliable;
00200 uint32_t timestamp;
00201
00202
00203 while (len >= 5 && buf[1] == 0xFF ) {
00204 int pkt_len;
00205
00206 if (!(buf[0] & 0x80))
00207 return -1;
00208
00209 pkt_len = AV_RB16(buf+3);
00210 buf += pkt_len;
00211 len -= pkt_len;
00212 consumed += pkt_len;
00213 }
00214 if (len < 16)
00215 return -1;
00267 init_get_bits(&gb, buf, len << 3);
00268 len_included = get_bits1(&gb);
00269 need_reliable = get_bits1(&gb);
00270 set_id = get_bits(&gb, 5);
00271 skip_bits(&gb, 1);
00272 seq_no = get_bits(&gb, 16);
00273 if (len_included)
00274 skip_bits(&gb, 16);
00275 skip_bits(&gb, 2);
00276 stream_id = get_bits(&gb, 5);
00277 is_keyframe = !get_bits1(&gb);
00278 timestamp = get_bits_long(&gb, 32);
00279 if (set_id == 0x1f)
00280 set_id = get_bits(&gb, 16);
00281 if (need_reliable)
00282 skip_bits(&gb, 16);
00283 if (stream_id == 0x1f)
00284 stream_id = get_bits(&gb, 16);
00285
00286 if (pset_id) *pset_id = set_id;
00287 if (pseq_no) *pseq_no = seq_no;
00288 if (pstream_id) *pstream_id = stream_id;
00289 if (pis_keyframe) *pis_keyframe = is_keyframe;
00290 if (ptimestamp) *ptimestamp = timestamp;
00291
00292 return consumed + (get_bits_count(&gb) >> 3);
00293 }
00294
00296 static int
00297 rdt_parse_packet (AVFormatContext *ctx, PayloadContext *rdt, AVStream *st,
00298 AVPacket *pkt, uint32_t *timestamp,
00299 const uint8_t *buf, int len, int flags)
00300 {
00301 int seq = 1, res;
00302 ByteIOContext pb;
00303
00304 if (rdt->audio_pkt_cnt == 0) {
00305 int pos;
00306
00307 init_put_byte(&pb, buf, len, 0, NULL, NULL, NULL, NULL);
00308 flags = (flags & RTP_FLAG_KEY) ? 2 : 0;
00309 res = ff_rm_parse_packet (rdt->rmctx, &pb, st, rdt->rmst[st->index], len, pkt,
00310 &seq, flags, *timestamp);
00311 pos = url_ftell(&pb);
00312 if (res < 0)
00313 return res;
00314 if (res > 0) {
00315 if (st->codec->codec_id == CODEC_ID_AAC) {
00316 memcpy (rdt->buffer, buf + pos, len - pos);
00317 rdt->rmctx->pb = av_alloc_put_byte (rdt->buffer, len - pos, 0,
00318 NULL, NULL, NULL, NULL);
00319 }
00320 goto get_cache;
00321 }
00322 } else {
00323 get_cache:
00324 rdt->audio_pkt_cnt =
00325 ff_rm_retrieve_cache (rdt->rmctx, rdt->rmctx->pb,
00326 st, rdt->rmst[st->index], pkt);
00327 if (rdt->audio_pkt_cnt == 0 &&
00328 st->codec->codec_id == CODEC_ID_AAC)
00329 av_freep(&rdt->rmctx->pb);
00330 }
00331 pkt->stream_index = st->index;
00332 pkt->pts = *timestamp;
00333
00334 return rdt->audio_pkt_cnt > 0;
00335 }
00336
00337 int
00338 ff_rdt_parse_packet(RDTDemuxContext *s, AVPacket *pkt,
00339 const uint8_t *buf, int len)
00340 {
00341 int seq_no, flags = 0, stream_id, set_id, is_keyframe;
00342 uint32_t timestamp;
00343 int rv= 0;
00344
00345 if (!s->parse_packet)
00346 return -1;
00347
00348 if (!buf && s->prev_stream_id != -1) {
00349
00350 timestamp= 0;
00351 rv= s->parse_packet(s->ic, s->dynamic_protocol_context,
00352 s->streams[s->prev_stream_id],
00353 pkt, ×tamp, NULL, 0, flags);
00354 return rv;
00355 }
00356
00357 if (len < 12)
00358 return -1;
00359 rv = ff_rdt_parse_header(buf, len, &set_id, &seq_no, &stream_id, &is_keyframe, ×tamp);
00360 if (rv < 0)
00361 return rv;
00362 if (is_keyframe &&
00363 (set_id != s->prev_set_id || timestamp != s->prev_timestamp ||
00364 stream_id != s->prev_stream_id)) {
00365 flags |= RTP_FLAG_KEY;
00366 s->prev_set_id = set_id;
00367 s->prev_timestamp = timestamp;
00368 }
00369 s->prev_stream_id = stream_id;
00370 buf += rv;
00371 len -= rv;
00372
00373 if (s->prev_stream_id >= s->n_streams) {
00374 s->prev_stream_id = -1;
00375 return -1;
00376 }
00377
00378 rv = s->parse_packet(s->ic, s->dynamic_protocol_context,
00379 s->streams[s->prev_stream_id],
00380 pkt, ×tamp, buf, len, flags);
00381
00382 return rv;
00383 }
00384
00385 void
00386 ff_rdt_subscribe_rule (char *cmd, int size,
00387 int stream_nr, int rule_nr)
00388 {
00389 av_strlcatf(cmd, size, "stream=%d;rule=%d,stream=%d;rule=%d",
00390 stream_nr, rule_nr * 2, stream_nr, rule_nr * 2 + 1);
00391 }
00392
00393 static unsigned char *
00394 rdt_parse_b64buf (unsigned int *target_len, const char *p)
00395 {
00396 unsigned char *target;
00397 int len = strlen(p);
00398 if (*p == '\"') {
00399 p++;
00400 len -= 2;
00401 }
00402 *target_len = len * 3 / 4;
00403 target = av_mallocz(*target_len + FF_INPUT_BUFFER_PADDING_SIZE);
00404 av_base64_decode(target, p, *target_len);
00405 return target;
00406 }
00407
00408 static int
00409 rdt_parse_sdp_line (AVFormatContext *s, int st_index,
00410 PayloadContext *rdt, const char *line)
00411 {
00412 AVStream *stream = s->streams[st_index];
00413 const char *p = line;
00414
00415 if (av_strstart(p, "OpaqueData:buffer;", &p)) {
00416 rdt->mlti_data = rdt_parse_b64buf(&rdt->mlti_data_size, p);
00417 } else if (av_strstart(p, "StartTime:integer;", &p))
00418 stream->first_dts = atoi(p);
00419 else if (av_strstart(p, "ASMRuleBook:string;", &p)) {
00420 int n, first = -1;
00421
00422 for (n = 0; n < s->nb_streams; n++)
00423 if (s->streams[n]->priv_data == stream->priv_data) {
00424 if (first == -1) first = n;
00425 rdt->rmst[s->streams[n]->index] = ff_rm_alloc_rmstream();
00426 rdt_load_mdpr(rdt, s->streams[n], (n - first) * 2);
00427
00428 if (s->streams[n]->codec->codec_id == CODEC_ID_AAC)
00429 s->streams[n]->codec->frame_size = 1;
00430 }
00431 }
00432
00433 return 0;
00434 }
00435
00436 static void
00437 real_parse_asm_rule(AVStream *st, const char *p, const char *end)
00438 {
00439 do {
00440
00441 if (sscanf(p, " %*1[Aa]verage%*1[Bb]andwidth=%d", &st->codec->bit_rate) == 1)
00442 break;
00443 if (!(p = strchr(p, ',')) || p > end)
00444 p = end;
00445 p++;
00446 } while (p < end);
00447 }
00448
00449 static AVStream *
00450 add_dstream(AVFormatContext *s, AVStream *orig_st)
00451 {
00452 AVStream *st;
00453
00454 if (!(st = av_new_stream(s, 0)))
00455 return NULL;
00456 st->codec->codec_type = orig_st->codec->codec_type;
00457 st->priv_data = orig_st->priv_data;
00458 st->first_dts = orig_st->first_dts;
00459
00460 return st;
00461 }
00462
00463 static void
00464 real_parse_asm_rulebook(AVFormatContext *s, AVStream *orig_st,
00465 const char *p)
00466 {
00467 const char *end;
00468 int n_rules, odd = 0;
00469 AVStream *st;
00470
00485 if (*p == '\"') p++;
00486 for (n_rules = 0; s->nb_streams < MAX_STREAMS;) {
00487 if (!(end = strchr(p, ';')))
00488 break;
00489 if (!odd && end != p) {
00490 if (n_rules > 0)
00491 st = add_dstream(s, orig_st);
00492 else
00493 st = orig_st;
00494 real_parse_asm_rule(st, p, end);
00495 n_rules++;
00496 }
00497 p = end + 1;
00498 odd ^= 1;
00499 }
00500 }
00501
00502 void
00503 ff_real_parse_sdp_a_line (AVFormatContext *s, int stream_index,
00504 const char *line)
00505 {
00506 const char *p = line;
00507
00508 if (av_strstart(p, "ASMRuleBook:string;", &p))
00509 real_parse_asm_rulebook(s, s->streams[stream_index], p);
00510 }
00511
00512 static PayloadContext *
00513 rdt_new_context (void)
00514 {
00515 PayloadContext *rdt = av_mallocz(sizeof(PayloadContext));
00516
00517 av_open_input_stream(&rdt->rmctx, NULL, "", &rdt_demuxer, NULL);
00518
00519 return rdt;
00520 }
00521
00522 static void
00523 rdt_free_context (PayloadContext *rdt)
00524 {
00525 int i;
00526
00527 for (i = 0; i < MAX_STREAMS; i++)
00528 if (rdt->rmst[i]) {
00529 ff_rm_free_rmstream(rdt->rmst[i]);
00530 av_freep(&rdt->rmst[i]);
00531 }
00532 if (rdt->rmctx)
00533 av_close_input_stream(rdt->rmctx);
00534 av_freep(&rdt->mlti_data);
00535 av_free(rdt);
00536 }
00537
00538 #define RDT_HANDLER(n, s, t) \
00539 static RTPDynamicProtocolHandler ff_rdt_ ## n ## _handler = { \
00540 .enc_name = s, \
00541 .codec_type = t, \
00542 .codec_id = CODEC_ID_NONE, \
00543 .parse_sdp_a_line = rdt_parse_sdp_line, \
00544 .open = rdt_new_context, \
00545 .close = rdt_free_context, \
00546 .parse_packet = rdt_parse_packet \
00547 };
00548
00549 RDT_HANDLER(live_video, "x-pn-multirate-realvideo-live", AVMEDIA_TYPE_VIDEO);
00550 RDT_HANDLER(live_audio, "x-pn-multirate-realaudio-live", AVMEDIA_TYPE_AUDIO);
00551 RDT_HANDLER(video, "x-pn-realvideo", AVMEDIA_TYPE_VIDEO);
00552 RDT_HANDLER(audio, "x-pn-realaudio", AVMEDIA_TYPE_AUDIO);
00553
00554 void av_register_rdt_dynamic_payload_handlers(void)
00555 {
00556 ff_register_dynamic_payload_handler(&ff_rdt_video_handler);
00557 ff_register_dynamic_payload_handler(&ff_rdt_audio_handler);
00558 ff_register_dynamic_payload_handler(&ff_rdt_live_video_handler);
00559 ff_register_dynamic_payload_handler(&ff_rdt_live_audio_handler);
00560 }