mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
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
This commit is contained in:
parent
99b2ac0797
commit
4fce284c08
@ -38,6 +38,8 @@ typedef struct rdt_data {
|
|||||||
AVFormatContext *rmctx;
|
AVFormatContext *rmctx;
|
||||||
uint8_t *mlti_data;
|
uint8_t *mlti_data;
|
||||||
unsigned int mlti_data_size;
|
unsigned int mlti_data_size;
|
||||||
|
uint32_t prev_sn, prev_ts;
|
||||||
|
char buffer[RTP_MAX_PACKET_LENGTH + FF_INPUT_BUFFER_PADDING_SIZE];
|
||||||
} rdt_data;
|
} rdt_data;
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -134,6 +136,103 @@ rdt_load_mdpr (rdt_data *rdt, AVStream *st, int rule_nr)
|
|||||||
return 0;
|
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
|
void
|
||||||
ff_rdt_subscribe_rule (RTPDemuxContext *s, char *cmd, int size,
|
ff_rdt_subscribe_rule (RTPDemuxContext *s, char *cmd, int size,
|
||||||
int stream_nr, int rule_nr)
|
int stream_nr, int rule_nr)
|
||||||
@ -181,6 +280,8 @@ rdt_new_extradata (void)
|
|||||||
rdt_data *rdt = av_mallocz(sizeof(rdt_data));
|
rdt_data *rdt = av_mallocz(sizeof(rdt_data));
|
||||||
|
|
||||||
av_open_input_stream(&rdt->rmctx, NULL, "", &rdt_demuxer, NULL);
|
av_open_input_stream(&rdt->rmctx, NULL, "", &rdt_demuxer, NULL);
|
||||||
|
rdt->prev_ts = -1;
|
||||||
|
rdt->prev_sn = -1;
|
||||||
|
|
||||||
return rdt;
|
return rdt;
|
||||||
}
|
}
|
||||||
|
@ -54,4 +54,11 @@ void av_register_rdt_dynamic_payload_handlers(void);
|
|||||||
void ff_rdt_subscribe_rule(RTPDemuxContext *s, char *cmd, int size,
|
void ff_rdt_subscribe_rule(RTPDemuxContext *s, char *cmd, int size,
|
||||||
int stream_nr, int rule_nr);
|
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 */
|
#endif /* AVFORMAT_RDT_H */
|
||||||
|
@ -1326,6 +1326,9 @@ static int rtsp_read_packet(AVFormatContext *s,
|
|||||||
|
|
||||||
/* get next frames from the same RTP packet */
|
/* get next frames from the same RTP packet */
|
||||||
if (rt->cur_rtp) {
|
if (rt->cur_rtp) {
|
||||||
|
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);
|
ret = rtp_parse_packet(rt->cur_rtp, pkt, NULL, 0);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
rt->cur_rtp = NULL;
|
rt->cur_rtp = NULL;
|
||||||
@ -1353,6 +1356,9 @@ static int rtsp_read_packet(AVFormatContext *s,
|
|||||||
}
|
}
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
return len;
|
return 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);
|
ret = rtp_parse_packet(rtsp_st->rtp_ctx, pkt, buf, len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto redo;
|
goto redo;
|
||||||
|
Loading…
Reference in New Issue
Block a user