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/bitstream.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->parse_packet;
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);
00124 for (i=0;i<32;i++) response[i] = tolower(response[i]);
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 rdt->audio_pkt_cnt = res;
00316 if (rdt->audio_pkt_cnt > 0 &&
00317 st->codec->codec_id == CODEC_ID_AAC) {
00318 memcpy (rdt->buffer, buf + pos, len - pos);
00319 rdt->rmctx->pb = av_alloc_put_byte (rdt->buffer, len - pos, 0,
00320 NULL, NULL, NULL, NULL);
00321 }
00322 } else {
00323 rdt->audio_pkt_cnt =
00324 ff_rm_retrieve_cache (rdt->rmctx, rdt->rmctx->pb,
00325 st, rdt->rmst[st->index], pkt);
00326 if (rdt->audio_pkt_cnt == 0 &&
00327 st->codec->codec_id == CODEC_ID_AAC)
00328 av_freep(&rdt->rmctx->pb);
00329 }
00330 pkt->stream_index = st->index;
00331 pkt->pts = *timestamp;
00332
00333 return rdt->audio_pkt_cnt > 0;
00334 }
00335
00336 int
00337 ff_rdt_parse_packet(RDTDemuxContext *s, AVPacket *pkt,
00338 const uint8_t *buf, int len)
00339 {
00340 int seq_no, flags = 0, stream_id, set_id, is_keyframe;
00341 uint32_t timestamp;
00342 int rv= 0;
00343
00344 if (!s->parse_packet)
00345 return -1;
00346
00347 if (!buf && s->prev_stream_id != -1) {
00348
00349 timestamp= 0;
00350 rv= s->parse_packet(s->ic, s->dynamic_protocol_context,
00351 s->streams[s->prev_stream_id],
00352 pkt, ×tamp, NULL, 0, flags);
00353 return rv;
00354 }
00355
00356 if (len < 12)
00357 return -1;
00358 rv = ff_rdt_parse_header(buf, len, &set_id, &seq_no, &stream_id, &is_keyframe, ×tamp);
00359 if (rv < 0)
00360 return rv;
00361 if (is_keyframe &&
00362 (set_id != s->prev_set_id || timestamp != s->prev_timestamp ||
00363 stream_id != s->prev_stream_id)) {
00364 flags |= RTP_FLAG_KEY;
00365 s->prev_set_id = set_id;
00366 s->prev_timestamp = timestamp;
00367 }
00368 s->prev_stream_id = stream_id;
00369 buf += rv;
00370 len -= rv;
00371
00372 if (s->prev_stream_id >= s->n_streams) {
00373 s->prev_stream_id = -1;
00374 return -1;
00375 }
00376
00377 rv = s->parse_packet(s->ic, s->dynamic_protocol_context,
00378 s->streams[s->prev_stream_id],
00379 pkt, ×tamp, buf, len, flags);
00380
00381 return rv;
00382 }
00383
00384 void
00385 ff_rdt_subscribe_rule (char *cmd, int size,
00386 int stream_nr, int rule_nr)
00387 {
00388 av_strlcatf(cmd, size, "stream=%d;rule=%d,stream=%d;rule=%d",
00389 stream_nr, rule_nr * 2, stream_nr, rule_nr * 2 + 1);
00390 }
00391
00392 static unsigned char *
00393 rdt_parse_b64buf (unsigned int *target_len, const char *p)
00394 {
00395 unsigned char *target;
00396 int len = strlen(p);
00397 if (*p == '\"') {
00398 p++;
00399 len -= 2;
00400 }
00401 *target_len = len * 3 / 4;
00402 target = av_mallocz(*target_len + FF_INPUT_BUFFER_PADDING_SIZE);
00403 av_base64_decode(target, p, *target_len);
00404 return target;
00405 }
00406
00407 static int
00408 rdt_parse_sdp_line (AVFormatContext *s, int st_index,
00409 PayloadContext *rdt, const char *line)
00410 {
00411 AVStream *stream = s->streams[st_index];
00412 const char *p = line;
00413
00414 if (av_strstart(p, "OpaqueData:buffer;", &p)) {
00415 rdt->mlti_data = rdt_parse_b64buf(&rdt->mlti_data_size, p);
00416 } else if (av_strstart(p, "StartTime:integer;", &p))
00417 stream->first_dts = atoi(p);
00418 else if (av_strstart(p, "ASMRuleBook:string;", &p)) {
00419 int n = st_index, first = -1;
00420
00421 for (n = 0; n < s->nb_streams; n++)
00422 if (s->streams[n]->priv_data == stream->priv_data) {
00423 if (first == -1) first = n;
00424 rdt->rmst[s->streams[n]->index] = ff_rm_alloc_rmstream();
00425 rdt_load_mdpr(rdt, s->streams[n], (n - first) * 2);
00426
00427 if (s->streams[n]->codec->codec_id == CODEC_ID_AAC)
00428 s->streams[n]->codec->frame_size = 1;
00429 }
00430 }
00431
00432 return 0;
00433 }
00434
00435 static void
00436 real_parse_asm_rule(AVStream *st, const char *p, const char *end)
00437 {
00438 do {
00439
00440 if (sscanf(p, " %*1[Aa]verage%*1[Bb]andwidth=%d", &st->codec->bit_rate) == 1)
00441 break;
00442 if (!(p = strchr(p, ',')) || p > end)
00443 p = end;
00444 p++;
00445 } while (p < end);
00446 }
00447
00448 static AVStream *
00449 add_dstream(AVFormatContext *s, AVStream *orig_st)
00450 {
00451 AVStream *st;
00452
00453 if (!(st = av_new_stream(s, 0)))
00454 return NULL;
00455 st->codec->codec_type = orig_st->codec->codec_type;
00456 st->priv_data = orig_st->priv_data;
00457 st->first_dts = orig_st->first_dts;
00458
00459 return st;
00460 }
00461
00462 static void
00463 real_parse_asm_rulebook(AVFormatContext *s, AVStream *orig_st,
00464 const char *p)
00465 {
00466 const char *end;
00467 int n_rules, odd = 0;
00468 AVStream *st;
00469
00484 if (*p == '\"') p++;
00485 for (n_rules = 0; s->nb_streams < MAX_STREAMS;) {
00486 if (!(end = strchr(p, ';')))
00487 break;
00488 if (!odd && end != p) {
00489 if (n_rules > 0)
00490 st = add_dstream(s, orig_st);
00491 else
00492 st = orig_st;
00493 real_parse_asm_rule(st, p, end);
00494 n_rules++;
00495 }
00496 p = end + 1;
00497 odd ^= 1;
00498 }
00499 }
00500
00501 void
00502 ff_real_parse_sdp_a_line (AVFormatContext *s, int stream_index,
00503 const char *line)
00504 {
00505 const char *p = line;
00506
00507 if (av_strstart(p, "ASMRuleBook:string;", &p))
00508 real_parse_asm_rulebook(s, s->streams[stream_index], p);
00509 }
00510
00511 static PayloadContext *
00512 rdt_new_extradata (void)
00513 {
00514 PayloadContext *rdt = av_mallocz(sizeof(PayloadContext));
00515
00516 av_open_input_stream(&rdt->rmctx, NULL, "", &rdt_demuxer, NULL);
00517
00518 return rdt;
00519 }
00520
00521 static void
00522 rdt_free_extradata (PayloadContext *rdt)
00523 {
00524 int i;
00525
00526 for (i = 0; i < MAX_STREAMS; i++)
00527 if (rdt->rmst[i]) {
00528 ff_rm_free_rmstream(rdt->rmst[i]);
00529 av_freep(&rdt->rmst[i]);
00530 }
00531 if (rdt->rmctx)
00532 av_close_input_stream(rdt->rmctx);
00533 av_freep(&rdt->mlti_data);
00534 av_free(rdt);
00535 }
00536
00537 #define RDT_HANDLER(n, s, t) \
00538 static RTPDynamicProtocolHandler ff_rdt_ ## n ## _handler = { \
00539 s, \
00540 t, \
00541 CODEC_ID_NONE, \
00542 rdt_parse_sdp_line, \
00543 rdt_new_extradata, \
00544 rdt_free_extradata, \
00545 rdt_parse_packet \
00546 };
00547
00548 RDT_HANDLER(live_video, "x-pn-multirate-realvideo-live", CODEC_TYPE_VIDEO);
00549 RDT_HANDLER(live_audio, "x-pn-multirate-realaudio-live", CODEC_TYPE_AUDIO);
00550 RDT_HANDLER(video, "x-pn-realvideo", CODEC_TYPE_VIDEO);
00551 RDT_HANDLER(audio, "x-pn-realaudio", CODEC_TYPE_AUDIO);
00552
00553 void av_register_rdt_dynamic_payload_handlers(void)
00554 {
00555 ff_register_dynamic_payload_handler(&ff_rdt_video_handler);
00556 ff_register_dynamic_payload_handler(&ff_rdt_audio_handler);
00557 ff_register_dynamic_payload_handler(&ff_rdt_live_video_handler);
00558 ff_register_dynamic_payload_handler(&ff_rdt_live_audio_handler);
00559 }