diff options
author | Ronald S. Bultje <rsbultje@gmail.com> | 2008-09-07 05:25:47 +0400 |
---|---|---|
committer | Ronald S. Bultje <rsbultje@gmail.com> | 2008-09-07 05:25:47 +0400 |
commit | 4fce284c085aa9d88aa7881015500964f70dbf55 (patch) | |
tree | e767655d6aa0e92ef9cdf129090d8a642d78ac95 /libavformat | |
parent | 99b2ac0797ea9ef5ef79ef1e4c42240551fd28e1 (diff) |
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.
Originally committed as revision 15237 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/rdt.c | 101 | ||||
-rw-r--r-- | libavformat/rdt.h | 7 | ||||
-rw-r--r-- | libavformat/rtsp.c | 10 |
3 files changed, 116 insertions, 2 deletions
diff --git a/libavformat/rdt.c b/libavformat/rdt.c index 6ed0f19417..2007566b3a 100644 --- a/libavformat/rdt.c +++ b/libavformat/rdt.c @@ -38,6 +38,8 @@ typedef struct rdt_data { 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 @@ rdt_load_mdpr (rdt_data *rdt, AVStream *st, int rule_nr) 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_new_extradata (void) 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 --git a/libavformat/rdt.h b/libavformat/rdt.h index 37b1928570..fe2f4f484b 100644 --- a/libavformat/rdt.h +++ b/libavformat/rdt.h @@ -54,4 +54,11 @@ void av_register_rdt_dynamic_payload_handlers(void); 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 --git a/libavformat/rtsp.c b/libavformat/rtsp.c index fddd60843b..950ec46474 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1326,7 +1326,10 @@ static int rtsp_read_packet(AVFormatContext *s, /* 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 @@ static int rtsp_read_packet(AVFormatContext *s, } 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) { |