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