[FFmpeg-devel] [PATCH] ASF-in-Realmedia-RTSP parser.
Ronald S. Bultje
rsbultje
Fri Feb 11 03:49:05 CET 2011
Allows playback of streams with the mediatype x-pn-wmt, such as
rtsp://live1.rte.ie/wmtencoder/1516.wma, and fixes issue 1607.
(Needs work - crashes on exit, and the hacks in rtsp.c/asfdec.c are
not acceptable probably.)
---
libavformat/asfdec.c | 1 +
libavformat/rtpdec.c | 1 +
libavformat/rtpdec_asf.c | 116 +++++++++++++++++++++++++++++++++++++-----
libavformat/rtpdec_formats.h | 1 +
libavformat/rtspdec.c | 4 +-
5 files changed, 108 insertions(+), 15 deletions(-)
diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c
index 35e892c..91839fc 100644
--- a/libavformat/asfdec.c
+++ b/libavformat/asfdec.c
@@ -807,6 +807,7 @@ static int ff_asf_parse_packet(AVFormatContext *s, ByteIOContext *pb, AVPacket *
assert(ret>=0);
/* fail safe */
url_fskip(pb, ret);
+ asf->packet_size_left = asf->packet_padsize = 0; // HACK for x-pn-wmt
asf->packet_pos= url_ftell(pb);
if (asf->data_object_size != (uint64_t)-1 &&
diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c
index c81ba1c..149232a 100644
--- a/libavformat/rtpdec.c
+++ b/libavformat/rtpdec.c
@@ -79,6 +79,7 @@ void av_register_rtp_dynamic_payload_handlers(void)
ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfv_handler);
ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfa_handler);
+ ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_wmt_handler);
ff_register_dynamic_payload_handler(&ff_qt_rtp_aud_handler);
ff_register_dynamic_payload_handler(&ff_qt_rtp_vid_handler);
diff --git a/libavformat/rtpdec_asf.c b/libavformat/rtpdec_asf.c
index db09f8f..74e5a01 100644
--- a/libavformat/rtpdec_asf.c
+++ b/libavformat/rtpdec_asf.c
@@ -146,11 +146,76 @@ static int asfrtp_parse_sdp_line(AVFormatContext *s, int stream_index,
return 0;
}
+static int wmtrtp_parse_sdp_line(AVFormatContext *s, int stream_index,
+ PayloadContext *asf, const char *line)
+{
+ RTSPState *rt = s->priv_data;
+
+ if (av_strstart(line, "RawHeader:buffer;\"", &line)){
+ ByteIOContext pb;
+ int i, ret, len = strlen(line) * 6 / 8;
+ char *buf = av_mallocz(len);
+
+ len = av_base64_decode(buf, line, len);
+ if (rtp_asf_fix_header(buf+8, len-8) < 0)
+ av_log(s, AV_LOG_ERROR,
+ "Failed to fix invalid RTSP-MS/ASF min_pktsize\n");
+ init_packetizer(&pb, buf+8, len-8);
+ if (rt->asf_ctx) {
+ av_close_input_stream(rt->asf_ctx);
+ rt->asf_ctx = NULL;
+ }
+ ret = av_open_input_stream(&rt->asf_ctx, &pb, "", &ff_asf_demuxer, NULL);
+ if (ret < 0)
+ return ret;
+ rt->asf_pb_pos = url_ftell(&pb);
+ av_free(buf);
+ rt->asf_ctx->pb = NULL;
+
+ for (i = 0; i < rt->asf_ctx->nb_streams; i++){
+ AVStream *st = av_new_stream(s, 0);
+ AVCodecContext *ctx = st->codec;
+ *st = *rt->asf_ctx->streams[i];
+ st->codec = ctx;
+ *st->codec = *rt->asf_ctx->streams[i]->codec;
+ rt->asf_ctx->streams[i]->codec->extradata_size = 0;
+ rt->asf_ctx->streams[i]->codec->extradata = NULL;
+ st->priv_data = s->streams[stream_index]->priv_data;
+ }
+ }
+
+ return 0;
+}
+
struct PayloadContext {
ByteIOContext *pktbuf, pb;
uint8_t *buf;
};
+static int get_packet_data(AVFormatContext *s, PayloadContext *asf,
+ AVPacket *pkt)
+{
+ ByteIOContext *pb = &asf->pb;
+ int res, i;
+ RTSPState *rt = s->priv_data;
+
+ for (;;) {
+ res = av_read_packet(rt->asf_ctx, pkt);
+ rt->asf_pb_pos = url_ftell(pb);
+ if (res != 0)
+ break;
+ for (i = 0; i < s->nb_streams; i++) {
+ if (s->streams[i]->id == rt->asf_ctx->streams[pkt->stream_index]->id) {
+ pkt->stream_index = i;
+ return 1; // FIXME: return 0 if last packet
+ }
+ }
+ av_free_packet(pkt);
+ }
+
+ return res == 1 ? -1 : res;
+}
+
/**
* @return 0 when a packet was written into /p pkt, and no more data is left;
* 1 when a packet was written into /p pkt, and more packets might be left;
@@ -243,23 +308,36 @@ static int asfrtp_parse_packet(AVFormatContext *s, PayloadContext *asf,
rt->asf_ctx->pb = pb;
}
- for (;;) {
- int i;
+ return get_packet_data(s, asf, pkt);
+}
- res = av_read_packet(rt->asf_ctx, pkt);
- rt->asf_pb_pos = url_ftell(pb);
- if (res != 0)
- break;
- for (i = 0; i < s->nb_streams; i++) {
- if (s->streams[i]->id == rt->asf_ctx->streams[pkt->stream_index]->id) {
- pkt->stream_index = i;
- return 1; // FIXME: return 0 if last packet
- }
- }
- av_free_packet(pkt);
+/**
+ * @return 0 when a packet was written into /p pkt, and no more data is left;
+ * 1 when a packet was written into /p pkt, and more packets might be left;
+ * <0 when not enough data was provided to return a full packet, or on error.
+ */
+static int wmtrtp_parse_packet(AVFormatContext *s, PayloadContext *asf,
+ AVStream *st, AVPacket *pkt,
+ uint32_t *timestamp,
+ const uint8_t *buf, int len, int flags)
+{
+ ByteIOContext *pb = &asf->pb;
+ RTSPState *rt = s->priv_data;
+
+ if (!rt->asf_ctx)
+ return -1;
+
+ if (len > 0) {
+ av_free(asf->buf);
+ asf->buf = av_malloc(len-8);
+ memcpy(asf->buf, buf+8, len-8);
+ init_packetizer(pb, asf->buf, len-8);
+ pb->pos += rt->asf_pb_pos;
+ pb->eof_reached = 0;
+ rt->asf_ctx->pb = pb;
}
- return res == 1 ? -1 : res;
+ return get_packet_data(s, asf, pkt);
}
static PayloadContext *asfrtp_new_context(void)
@@ -292,3 +370,13 @@ RTPDynamicProtocolHandler ff_ms_rtp_ ## n ## _handler = { \
RTP_ASF_HANDLER(asf_pfv, "x-asf-pf", AVMEDIA_TYPE_VIDEO);
RTP_ASF_HANDLER(asf_pfa, "x-asf-pf", AVMEDIA_TYPE_AUDIO);
+
+RTPDynamicProtocolHandler ff_ms_rtp_asf_wmt_handler = {
+ .enc_name = "x-pn-wmt",
+ .codec_type = AVMEDIA_TYPE_DATA,
+ .codec_id = CODEC_ID_NONE,
+ .parse_sdp_a_line = wmtrtp_parse_sdp_line,
+ .open = asfrtp_new_context,
+ .close = asfrtp_free_context,
+ .parse_packet = wmtrtp_parse_packet,
+};
diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h
index 16f5a9d..1b4b2ec 100644
--- a/libavformat/rtpdec_formats.h
+++ b/libavformat/rtpdec_formats.h
@@ -41,6 +41,7 @@ extern RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler;
extern RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler;
extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfa_handler;
extern RTPDynamicProtocolHandler ff_ms_rtp_asf_pfv_handler;
+extern RTPDynamicProtocolHandler ff_ms_rtp_asf_wmt_handler;
extern RTPDynamicProtocolHandler ff_qcelp_dynamic_handler;
extern RTPDynamicProtocolHandler ff_qdm2_dynamic_handler;
extern RTPDynamicProtocolHandler ff_qt_rtp_aud_handler;
diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c
index 45ed7bb..0373a93 100644
--- a/libavformat/rtspdec.c
+++ b/libavformat/rtspdec.c
@@ -283,7 +283,9 @@ retry:
for (i = 0; i < rt->nb_rtsp_streams; i++) {
rule_nr = 0;
for (r = 0; r < s->nb_streams; r++) {
- if (s->streams[r]->priv_data == rt->rtsp_streams[i]) {
+ if (s->streams[r]->priv_data == rt->rtsp_streams[i] &&
+ s->streams[r]->codec->codec_type != CODEC_TYPE_DATA &&
+ s->streams[r]->codec->channels > 0) { // HACK for x-pn-wmt
if (s->streams[r]->discard != AVDISCARD_ALL) {
if (!first)
av_strlcat(rt->last_subscription, ",",
--
1.7.2.1
More information about the ffmpeg-devel
mailing list