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) < 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 == 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 == 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 if (s->streams[n]->codec->codec_id == CODEC_ID_AAC)
00437 s->streams[n]->codec->frame_size = 1;
00438 }
00439 }
00440
00441 return 0;
00442 }
00443
00444 static void
00445 real_parse_asm_rule(AVStream *st, const char *p, const char *end)
00446 {
00447 do {
00448
00449 if (sscanf(p, " %*1[Aa]verage%*1[Bb]andwidth=%d", &st->codec->bit_rate) == 1)
00450 break;
00451 if (!(p = strchr(p, ',')) || p > end)
00452 p = end;
00453 p++;
00454 } while (p < end);
00455 }
00456
00457 static AVStream *
00458 add_dstream(AVFormatContext *s, AVStream *orig_st)
00459 {
00460 AVStream *st;
00461
00462 if (!(st = avformat_new_stream(s, NULL)))
00463 return NULL;
00464 st->id = orig_st->id;
00465 st->codec->codec_type = orig_st->codec->codec_type;
00466 st->first_dts = orig_st->first_dts;
00467
00468 return st;
00469 }
00470
00471 static void
00472 real_parse_asm_rulebook(AVFormatContext *s, AVStream *orig_st,
00473 const char *p)
00474 {
00475 const char *end;
00476 int n_rules = 0, odd = 0;
00477 AVStream *st;
00478
00493 if (*p == '\"') p++;
00494 while (1) {
00495 if (!(end = strchr(p, ';')))
00496 break;
00497 if (!odd && end != p) {
00498 if (n_rules > 0)
00499 st = add_dstream(s, orig_st);
00500 else
00501 st = orig_st;
00502 if (!st)
00503 break;
00504 real_parse_asm_rule(st, p, end);
00505 n_rules++;
00506 }
00507 p = end + 1;
00508 odd ^= 1;
00509 }
00510 }
00511
00512 void
00513 ff_real_parse_sdp_a_line (AVFormatContext *s, int stream_index,
00514 const char *line)
00515 {
00516 const char *p = line;
00517
00518 if (av_strstart(p, "ASMRuleBook:string;", &p))
00519 real_parse_asm_rulebook(s, s->streams[stream_index], p);
00520 }
00521
00522 static PayloadContext *
00523 rdt_new_context (void)
00524 {
00525 PayloadContext *rdt = av_mallocz(sizeof(PayloadContext));
00526
00527 int ret = avformat_open_input(&rdt->rmctx, "", &ff_rdt_demuxer, NULL);
00528 if (ret < 0) {
00529 av_free(rdt);
00530 return NULL;
00531 }
00532
00533 return rdt;
00534 }
00535
00536 static void
00537 rdt_free_context (PayloadContext *rdt)
00538 {
00539 int i;
00540
00541 for (i = 0; i < rdt->nb_rmst; i++)
00542 if (rdt->rmst[i]) {
00543 ff_rm_free_rmstream(rdt->rmst[i]);
00544 av_freep(&rdt->rmst[i]);
00545 }
00546 if (rdt->rmctx)
00547 avformat_close_input(&rdt->rmctx);
00548 av_freep(&rdt->mlti_data);
00549 av_freep(&rdt->rmst);
00550 av_free(rdt);
00551 }
00552
00553 #define RDT_HANDLER(n, s, t) \
00554 static RTPDynamicProtocolHandler ff_rdt_ ## n ## _handler = { \
00555 .enc_name = s, \
00556 .codec_type = t, \
00557 .codec_id = CODEC_ID_NONE, \
00558 .parse_sdp_a_line = rdt_parse_sdp_line, \
00559 .alloc = rdt_new_context, \
00560 .free = rdt_free_context, \
00561 .parse_packet = rdt_parse_packet \
00562 }
00563
00564 RDT_HANDLER(live_video, "x-pn-multirate-realvideo-live", AVMEDIA_TYPE_VIDEO);
00565 RDT_HANDLER(live_audio, "x-pn-multirate-realaudio-live", AVMEDIA_TYPE_AUDIO);
00566 RDT_HANDLER(video, "x-pn-realvideo", AVMEDIA_TYPE_VIDEO);
00567 RDT_HANDLER(audio, "x-pn-realaudio", AVMEDIA_TYPE_AUDIO);
00568
00569 void av_register_rdt_dynamic_payload_handlers(void)
00570 {
00571 ff_register_dynamic_payload_handler(&ff_rdt_video_handler);
00572 ff_register_dynamic_payload_handler(&ff_rdt_audio_handler);
00573 ff_register_dynamic_payload_handler(&ff_rdt_live_video_handler);
00574 ff_register_dynamic_payload_handler(&ff_rdt_live_audio_handler);
00575 }