# HG changeset patch # User rbultje # Date 1220750747 0 # Node ID 91987686113d0fd8d9397b7b2cf2cd57b4d1f63b # Parent 52e586c0440258274a418cf18c9d24adfd2d68eb Implement RDT-specific data parsing routines. After these changes, simple playback of RTSP/RDT streams should work. See discussion in "Realmedia patch" thread on ML. diff -r 52e586c04402 -r 91987686113d rdt.c --- a/rdt.c Sun Sep 07 01:24:01 2008 +0000 +++ b/rdt.c Sun Sep 07 01:25:47 2008 +0000 @@ -38,6 +38,8 @@ AVFormatContext *rmctx; uint8_t *mlti_data; unsigned int mlti_data_size; + uint32_t prev_sn, prev_ts; + char buffer[RTP_MAX_PACKET_LENGTH + FF_INPUT_BUFFER_PADDING_SIZE]; } rdt_data; void @@ -134,6 +136,103 @@ return 0; } +/** + * Actual data handling. + */ + +static int rdt_parse_header(struct RTPDemuxContext *s, const uint8_t *buf, + int len, int *seq, uint32_t *timestamp, int *flags) +{ + rdt_data *rdt = s->dynamic_protocol_context; + int consumed = 0, sn; + + if (buf[0] < 0x40 || buf[0] > 0x42) { + buf += 9; + len -= 9; + consumed += 9; + } + sn = (buf[0]>>1) & 0x1f; + *seq = AV_RB16(buf+1); + *timestamp = AV_RB32(buf+4); + if (!(buf[3] & 1) && (sn != rdt->prev_sn || *timestamp != rdt->prev_ts)) { + *flags |= PKT_FLAG_KEY; + rdt->prev_sn = sn; + rdt->prev_ts = *timestamp; + } + + return consumed + 10; +} + +/**< return 0 on packet, no more left, 1 on packet, 1 on partial packet... */ +static int +rdt_parse_packet (RTPDemuxContext *s, AVPacket *pkt, uint32_t *timestamp, + const uint8_t *buf, int len, int flags) +{ + rdt_data *rdt = s->dynamic_protocol_context; + int seq = 1, res; + ByteIOContext *pb = rdt->rmctx->pb; + RMContext *rm = rdt->rmctx->priv_data; + AVStream *st = s->st; + + if (rm->audio_pkt_cnt == 0) { + int pos; + + url_open_buf (&pb, buf, len, URL_RDONLY); + flags = (flags & PKT_FLAG_KEY) ? 2 : 0; + rdt->rmctx->pb = pb; + res = ff_rm_parse_packet (rdt->rmctx, st, len, pkt, + &seq, &flags, timestamp); + pos = url_ftell(pb); + url_close_buf (pb); + if (res < 0) + return res; + if (rm->audio_pkt_cnt > 0 && + st->codec->codec_id == CODEC_ID_AAC) { + memcpy (rdt->buffer, buf + pos, len - pos); + url_open_buf (&pb, rdt->buffer, len - pos, URL_RDONLY); + rdt->rmctx->pb = pb; + } + } else { + ff_rm_retrieve_cache (rdt->rmctx, st, pkt); + if (rm->audio_pkt_cnt == 0 && + st->codec->codec_id == CODEC_ID_AAC) + url_close_buf (pb); + } + pkt->stream_index = st->index; + pkt->pts = *timestamp; + + return rm->audio_pkt_cnt > 0; +} + +int +ff_rdt_parse_packet(RTPDemuxContext *s, AVPacket *pkt, + const uint8_t *buf, int len) +{ + int seq, flags = 0; + uint32_t timestamp; + int rv= 0; + + if (!buf) { + /* return the next packets, if any */ + timestamp= 0; ///< Should not be used if buf is NULL, but should be set to the timestamp of the packet returned.... + rv= rdt_parse_packet(s, pkt, ×tamp, NULL, 0, flags); + return rv; + } + + if (len < 12) + return -1; + rv = rdt_parse_header(s, buf, len, &seq, ×tamp, &flags); + if (rv < 0) + return rv; + buf += rv; + len -= rv; + s->seq = seq; + + rv = rdt_parse_packet(s, pkt, ×tamp, buf, len, flags); + + return rv; +} + void ff_rdt_subscribe_rule (RTPDemuxContext *s, char *cmd, int size, int stream_nr, int rule_nr) @@ -181,6 +280,8 @@ rdt_data *rdt = av_mallocz(sizeof(rdt_data)); av_open_input_stream(&rdt->rmctx, NULL, "", &rdt_demuxer, NULL); + rdt->prev_ts = -1; + rdt->prev_sn = -1; return rdt; } diff -r 52e586c04402 -r 91987686113d rdt.h --- a/rdt.h Sun Sep 07 01:24:01 2008 +0000 +++ b/rdt.h Sun Sep 07 01:25:47 2008 +0000 @@ -54,4 +54,11 @@ void ff_rdt_subscribe_rule(RTPDemuxContext *s, char *cmd, int size, int stream_nr, int rule_nr); +/** + * Parse RDT-style packet data (header + media data). + * Usage similar to rtp_parse_packet(). + */ +int ff_rdt_parse_packet(RTPDemuxContext *s, AVPacket *pkt, + const uint8_t *buf, int len); + #endif /* AVFORMAT_RDT_H */ diff -r 52e586c04402 -r 91987686113d rtsp.c --- a/rtsp.c Sun Sep 07 01:24:01 2008 +0000 +++ b/rtsp.c Sun Sep 07 01:25:47 2008 +0000 @@ -1326,7 +1326,10 @@ /* get next frames from the same RTP packet */ if (rt->cur_rtp) { - ret = rtp_parse_packet(rt->cur_rtp, pkt, NULL, 0); + if (rt->server_type == RTSP_SERVER_RDT) + ret = ff_rdt_parse_packet(rt->cur_rtp, pkt, NULL, 0); + else + ret = rtp_parse_packet(rt->cur_rtp, pkt, NULL, 0); if (ret == 0) { rt->cur_rtp = NULL; return 0; @@ -1353,7 +1356,10 @@ } if (len < 0) return len; - ret = rtp_parse_packet(rtsp_st->rtp_ctx, pkt, buf, len); + if (rt->server_type == RTSP_SERVER_RDT) + ret = ff_rdt_parse_packet(rtsp_st->rtp_ctx, pkt, buf, len); + else + ret = rtp_parse_packet(rtsp_st->rtp_ctx, pkt, buf, len); if (ret < 0) goto redo; if (ret == 1) {