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