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 int nb_rmst;
00090 RMStream **rmst;
00091 uint8_t *mlti_data;
00092 unsigned int mlti_data_size;
00093 char buffer[RTP_MAX_PACKET_LENGTH + FF_INPUT_BUFFER_PADDING_SIZE];
00094 int audio_pkt_cnt;
00095 };
00096
00097 void
00098 ff_rdt_calc_response_and_checksum(char response[41], char chksum[9],
00099 const char *challenge)
00100 {
00101 int ch_len = strlen (challenge), i;
00102 unsigned char zres[16],
00103 buf[64] = { 0xa1, 0xe9, 0x14, 0x9d, 0x0e, 0x6b, 0x3b, 0x59 };
00104 #define XOR_TABLE_SIZE 37
00105 const unsigned char xor_table[XOR_TABLE_SIZE] = {
00106 0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53,
00107 0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70,
00108 0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09,
00109 0x63, 0x11, 0x03, 0x71, 0x08, 0x08, 0x70, 0x02,
00110 0x10, 0x57, 0x05, 0x18, 0x54 };
00111
00112
00113 if (ch_len == 40)
00114 ch_len = 32;
00115 else if (ch_len > 56)
00116 ch_len = 56;
00117 memcpy(buf + 8, challenge, ch_len);
00118
00119
00120 for (i = 0; i < XOR_TABLE_SIZE; i++)
00121 buf[8 + i] ^= xor_table[i];
00122
00123 av_md5_sum(zres, buf, 64);
00124 ff_data_to_hex(response, zres, 16, 1);
00125
00126
00127 strcpy (response + 32, "01d0a8e3");
00128
00129
00130 for (i = 0; i < 8; i++)
00131 chksum[i] = response[i * 4];
00132 chksum[8] = 0;
00133 }
00134
00135 static int
00136 rdt_load_mdpr (PayloadContext *rdt, AVStream *st, int rule_nr)
00137 {
00138 ByteIOContext pb;
00139 int size;
00140 uint32_t tag;
00141
00156 if (!rdt->mlti_data)
00157 return -1;
00158 init_put_byte(&pb, rdt->mlti_data, rdt->mlti_data_size, 0,
00159 NULL, NULL, NULL, NULL);
00160 tag = get_le32(&pb);
00161 if (tag == MKTAG('M', 'L', 'T', 'I')) {
00162 int num, chunk_nr;
00163
00164
00165 num = get_be16(&pb);
00166 if (rule_nr < 0 || rule_nr >= num)
00167 return -1;
00168 url_fskip(&pb, rule_nr * 2);
00169 chunk_nr = get_be16(&pb);
00170 url_fskip(&pb, (num - 1 - rule_nr) * 2);
00171
00172
00173 num = get_be16(&pb);
00174 if (chunk_nr >= num)
00175 return -1;
00176 while (chunk_nr--)
00177 url_fskip(&pb, get_be32(&pb));
00178 size = get_be32(&pb);
00179 } else {
00180 size = rdt->mlti_data_size;
00181 url_fseek(&pb, 0, SEEK_SET);
00182 }
00183 if (ff_rm_read_mdpr_codecdata(rdt->rmctx, &pb, st, rdt->rmst[st->index], size) < 0)
00184 return -1;
00185
00186 return 0;
00187 }
00188
00193 int
00194 ff_rdt_parse_header(const uint8_t *buf, int len,
00195 int *pset_id, int *pseq_no, int *pstream_id,
00196 int *pis_keyframe, uint32_t *ptimestamp)
00197 {
00198 GetBitContext gb;
00199 int consumed = 0, set_id, seq_no, stream_id, is_keyframe,
00200 len_included, need_reliable;
00201 uint32_t timestamp;
00202
00203
00204 while (len >= 5 && buf[1] == 0xFF ) {
00205 int pkt_len;
00206
00207 if (!(buf[0] & 0x80))
00208 return -1;
00209
00210 pkt_len = AV_RB16(buf+3);
00211 buf += pkt_len;
00212 len -= pkt_len;
00213 consumed += pkt_len;
00214 }
00215 if (len < 16)
00216 return -1;
00268 init_get_bits(&gb, buf, len << 3);
00269 len_included = get_bits1(&gb);
00270 need_reliable = get_bits1(&gb);
00271 set_id = get_bits(&gb, 5);
00272 skip_bits(&gb, 1);
00273 seq_no = get_bits(&gb, 16);
00274 if (len_included)
00275 skip_bits(&gb, 16);
00276 skip_bits(&gb, 2);
00277 stream_id = get_bits(&gb, 5);
00278 is_keyframe = !get_bits1(&gb);
00279 timestamp = get_bits_long(&gb, 32);
00280 if (set_id == 0x1f)
00281 set_id = get_bits(&gb, 16);
00282 if (need_reliable)
00283 skip_bits(&gb, 16);
00284 if (stream_id == 0x1f)
00285 stream_id = get_bits(&gb, 16);
00286
00287 if (pset_id) *pset_id = set_id;
00288 if (pseq_no) *pseq_no = seq_no;
00289 if (pstream_id) *pstream_id = stream_id;
00290 if (pis_keyframe) *pis_keyframe = is_keyframe;
00291 if (ptimestamp) *ptimestamp = timestamp;
00292
00293 return consumed + (get_bits_count(&gb) >> 3);
00294 }
00295
00297 static int
00298 rdt_parse_packet (AVFormatContext *ctx, PayloadContext *rdt, AVStream *st,
00299 AVPacket *pkt, uint32_t *timestamp,
00300 const uint8_t *buf, int len, int flags)
00301 {
00302 int seq = 1, res;
00303 ByteIOContext pb;
00304
00305 if (rdt->audio_pkt_cnt == 0) {
00306 int pos;
00307
00308 init_put_byte(&pb, buf, len, 0, NULL, NULL, NULL, NULL);
00309 flags = (flags & RTP_FLAG_KEY) ? 2 : 0;
00310 res = ff_rm_parse_packet (rdt->rmctx, &pb, st, rdt->rmst[st->index], len, pkt,
00311 &seq, flags, *timestamp);
00312 pos = url_ftell(&pb);
00313 if (res < 0)
00314 return res;
00315 if (res > 0) {
00316 if (st->codec->codec_id == CODEC_ID_AAC) {
00317 memcpy (rdt->buffer, buf + pos, len - pos);
00318 rdt->rmctx->pb = av_alloc_put_byte (rdt->buffer, len - pos, 0,
00319 NULL, NULL, NULL, NULL);
00320 }
00321 goto get_cache;
00322 }
00323 } else {
00324 get_cache:
00325 rdt->audio_pkt_cnt =
00326 ff_rm_retrieve_cache (rdt->rmctx, rdt->rmctx->pb,
00327 st, rdt->rmst[st->index], pkt);
00328 if (rdt->audio_pkt_cnt == 0 &&
00329 st->codec->codec_id == CODEC_ID_AAC)
00330 av_freep(&rdt->rmctx->pb);
00331 }
00332 pkt->stream_index = st->index;
00333 pkt->pts = *timestamp;
00334
00335 return rdt->audio_pkt_cnt > 0;
00336 }
00337
00338 int
00339 ff_rdt_parse_packet(RDTDemuxContext *s, AVPacket *pkt,
00340 uint8_t **bufptr, int len)
00341 {
00342 uint8_t *buf = bufptr ? *bufptr : NULL;
00343 int seq_no, flags = 0, stream_id, set_id, is_keyframe;
00344 uint32_t timestamp;
00345 int rv= 0;
00346
00347 if (!s->parse_packet)
00348 return -1;
00349
00350 if (!buf && s->prev_stream_id != -1) {
00351
00352 timestamp= 0;
00353 rv= s->parse_packet(s->ic, s->dynamic_protocol_context,
00354 s->streams[s->prev_stream_id],
00355 pkt, ×tamp, NULL, 0, flags);
00356 return rv;
00357 }
00358
00359 if (len < 12)
00360 return -1;
00361 rv = ff_rdt_parse_header(buf, len, &set_id, &seq_no, &stream_id, &is_keyframe, ×tamp);
00362 if (rv < 0)
00363 return rv;
00364 if (is_keyframe &&
00365 (set_id != s->prev_set_id || timestamp != s->prev_timestamp ||
00366 stream_id != s->prev_stream_id)) {
00367 flags |= RTP_FLAG_KEY;
00368 s->prev_set_id = set_id;
00369 s->prev_timestamp = timestamp;
00370 }
00371 s->prev_stream_id = stream_id;
00372 buf += rv;
00373 len -= rv;
00374
00375 if (s->prev_stream_id >= s->n_streams) {
00376 s->prev_stream_id = -1;
00377 return -1;
00378 }
00379
00380 rv = s->parse_packet(s->ic, s->dynamic_protocol_context,
00381 s->streams[s->prev_stream_id],
00382 pkt, ×tamp, buf, len, flags);
00383
00384 return rv;
00385 }
00386
00387 void
00388 ff_rdt_subscribe_rule (char *cmd, int size,
00389 int stream_nr, int rule_nr)
00390 {
00391 av_strlcatf(cmd, size, "stream=%d;rule=%d,stream=%d;rule=%d",
00392 stream_nr, rule_nr * 2, stream_nr, rule_nr * 2 + 1);
00393 }
00394
00395 static unsigned char *
00396 rdt_parse_b64buf (unsigned int *target_len, const char *p)
00397 {
00398 unsigned char *target;
00399 int len = strlen(p);
00400 if (*p == '\"') {
00401 p++;
00402 len -= 2;
00403 }
00404 *target_len = len * 3 / 4;
00405 target = av_mallocz(*target_len + FF_INPUT_BUFFER_PADDING_SIZE);
00406 av_base64_decode(target, p, *target_len);
00407 return target;
00408 }
00409
00410 static int
00411 rdt_parse_sdp_line (AVFormatContext *s, int st_index,
00412 PayloadContext *rdt, const char *line)
00413 {
00414 AVStream *stream = s->streams[st_index];
00415 const char *p = line;
00416
00417 if (av_strstart(p, "OpaqueData:buffer;", &p)) {
00418 rdt->mlti_data = rdt_parse_b64buf(&rdt->mlti_data_size, p);
00419 } else if (av_strstart(p, "StartTime:integer;", &p))
00420 stream->first_dts = atoi(p);
00421 else if (av_strstart(p, "ASMRuleBook:string;", &p)) {
00422 int n, first = -1;
00423
00424 for (n = 0; n < s->nb_streams; n++)
00425 if (s->streams[n]->priv_data == stream->priv_data) {
00426 int count = s->streams[n]->index + 1;
00427 if (first == -1) first = n;
00428 if (rdt->nb_rmst < count) {
00429 RMStream **rmst= av_realloc(rdt->rmst, count*sizeof(*rmst));
00430 if (!rmst)
00431 return AVERROR(ENOMEM);
00432 memset(rmst + rdt->nb_rmst, 0,
00433 (count - rdt->nb_rmst) * sizeof(*rmst));
00434 rdt->rmst = rmst;
00435 rdt->nb_rmst = count;
00436 }
00437 rdt->rmst[s->streams[n]->index] = ff_rm_alloc_rmstream();
00438 rdt_load_mdpr(rdt, s->streams[n], (n - first) * 2);
00439
00440 if (s->streams[n]->codec->codec_id == CODEC_ID_AAC)
00441 s->streams[n]->codec->frame_size = 1;
00442 }
00443 }
00444
00445 return 0;
00446 }
00447
00448 static void
00449 real_parse_asm_rule(AVStream *st, const char *p, const char *end)
00450 {
00451 do {
00452
00453 if (sscanf(p, " %*1[Aa]verage%*1[Bb]andwidth=%d", &st->codec->bit_rate) == 1)
00454 break;
00455 if (!(p = strchr(p, ',')) || p > end)
00456 p = end;
00457 p++;
00458 } while (p < end);
00459 }
00460
00461 static AVStream *
00462 add_dstream(AVFormatContext *s, AVStream *orig_st)
00463 {
00464 AVStream *st;
00465
00466 if (!(st = av_new_stream(s, 0)))
00467 return NULL;
00468 st->codec->codec_type = orig_st->codec->codec_type;
00469 st->priv_data = orig_st->priv_data;
00470 st->first_dts = orig_st->first_dts;
00471
00472 return st;
00473 }
00474
00475 static void
00476 real_parse_asm_rulebook(AVFormatContext *s, AVStream *orig_st,
00477 const char *p)
00478 {
00479 const char *end;
00480 int n_rules = 0, odd = 0;
00481 AVStream *st;
00482
00497 if (*p == '\"') p++;
00498 while (1) {
00499 if (!(end = strchr(p, ';')))
00500 break;
00501 if (!odd && end != p) {
00502 if (n_rules > 0)
00503 st = add_dstream(s, orig_st);
00504 else
00505 st = orig_st;
00506 if (!st)
00507 break;
00508 real_parse_asm_rule(st, p, end);
00509 n_rules++;
00510 }
00511 p = end + 1;
00512 odd ^= 1;
00513 }
00514 }
00515
00516 void
00517 ff_real_parse_sdp_a_line (AVFormatContext *s, int stream_index,
00518 const char *line)
00519 {
00520 const char *p = line;
00521
00522 if (av_strstart(p, "ASMRuleBook:string;", &p))
00523 real_parse_asm_rulebook(s, s->streams[stream_index], p);
00524 }
00525
00526 static PayloadContext *
00527 rdt_new_context (void)
00528 {
00529 PayloadContext *rdt = av_mallocz(sizeof(PayloadContext));
00530
00531 av_open_input_stream(&rdt->rmctx, NULL, "", &rdt_demuxer, NULL);
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 av_close_input_stream(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 .open = rdt_new_context, \
00560 .close = 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 }