From 456001486ee8fe1cd906e497b603f98159191175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 6 Apr 2012 23:07:12 +0300 Subject: [PATCH 1/6] rtsp: Don't expose the MS-RTSP RTX data stream to the caller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids exposing a dummy AVStream which won't get any data and which will make avformat_find_stream_info wait for info about this stream. Signed-off-by: Martin Storsjö --- libavformat/rtpdec.c | 2 +- libavformat/rtpdec_amr.c | 3 +++ libavformat/rtpdec_asf.c | 2 ++ libavformat/rtpdec_h264.c | 9 +++++++-- libavformat/rtpdec_latm.c | 3 +++ libavformat/rtpdec_mpeg4.c | 3 +++ libavformat/rtpdec_xiph.c | 3 +++ libavformat/rtsp.c | 24 ++++++++++++++++-------- 8 files changed, 38 insertions(+), 11 deletions(-) diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index 61653f7b39..41e6eb4cab 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -385,7 +385,7 @@ RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext av_free(s); return NULL; } - } else { + } else if (st) { switch(st->codec->codec_id) { case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: diff --git a/libavformat/rtpdec_amr.c b/libavformat/rtpdec_amr.c index 9f5ab26aa9..b2e3d6042e 100644 --- a/libavformat/rtpdec_amr.c +++ b/libavformat/rtpdec_amr.c @@ -169,6 +169,9 @@ static int amr_parse_sdp_line(AVFormatContext *s, int st_index, const char *p; int ret; + if (st_index < 0) + return 0; + /* Parse an fmtp line this one: * a=fmtp:97 octet-align=1; interleaving=0 * That is, a normal fmtp: line followed by semicolon & space diff --git a/libavformat/rtpdec_asf.c b/libavformat/rtpdec_asf.c index c1690ef8f1..bbb7609175 100644 --- a/libavformat/rtpdec_asf.c +++ b/libavformat/rtpdec_asf.c @@ -130,6 +130,8 @@ int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p) static int asfrtp_parse_sdp_line(AVFormatContext *s, int stream_index, PayloadContext *asf, const char *line) { + if (stream_index < 0) + return 0; if (av_strstart(line, "stream:", &line)) { RTSPState *rt = s->priv_data; diff --git a/libavformat/rtpdec_h264.c b/libavformat/rtpdec_h264.c index 9da79fcbf5..32a57d3ec7 100644 --- a/libavformat/rtpdec_h264.c +++ b/libavformat/rtpdec_h264.c @@ -357,10 +357,15 @@ static void h264_free_context(PayloadContext *data) static int parse_h264_sdp_line(AVFormatContext *s, int st_index, PayloadContext *h264_data, const char *line) { - AVStream *stream = s->streams[st_index]; - AVCodecContext *codec = stream->codec; + AVStream *stream; + AVCodecContext *codec; const char *p = line; + if (st_index < 0) + return 0; + + stream = s->streams[st_index]; + codec = stream->codec; assert(h264_data->cookie == MAGIC_COOKIE); if (av_strstart(p, "framesize:", &p)) { diff --git a/libavformat/rtpdec_latm.c b/libavformat/rtpdec_latm.c index ed0a435514..5b0ece2bfe 100644 --- a/libavformat/rtpdec_latm.c +++ b/libavformat/rtpdec_latm.c @@ -168,6 +168,9 @@ static int latm_parse_sdp_line(AVFormatContext *s, int st_index, { const char *p; + if (st_index < 0) + return 0; + if (av_strstart(line, "fmtp:", &p)) return ff_parse_fmtp(s->streams[st_index], data, p, parse_fmtp); diff --git a/libavformat/rtpdec_mpeg4.c b/libavformat/rtpdec_mpeg4.c index 99792c9628..5ba88173a4 100644 --- a/libavformat/rtpdec_mpeg4.c +++ b/libavformat/rtpdec_mpeg4.c @@ -223,6 +223,9 @@ static int parse_sdp_line(AVFormatContext *s, int st_index, { const char *p; + if (st_index < 0) + return 0; + if (av_strstart(line, "fmtp:", &p)) return ff_parse_fmtp(s->streams[st_index], data, p, parse_fmtp); diff --git a/libavformat/rtpdec_xiph.c b/libavformat/rtpdec_xiph.c index a7f36ef59a..2de8a68b88 100644 --- a/libavformat/rtpdec_xiph.c +++ b/libavformat/rtpdec_xiph.c @@ -376,6 +376,9 @@ static int xiph_parse_sdp_line(AVFormatContext *s, int st_index, { const char *p; + if (st_index < 0) + return 0; + if (av_strstart(line, "fmtp:", &p)) { return ff_parse_fmtp(s->streams[st_index], data, p, xiph_parse_fmtp_pair); diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index fa761f54a8..403f038875 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -374,6 +374,10 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) { /* no corresponding stream */ + } else if (rt->server_type == RTSP_SERVER_WMS && + codec_type == AVMEDIA_TYPE_DATA) { + /* RTX stream, a stream that carries all the other actual + * audio/video streams. Don't expose this to the callers. */ } else { st = avformat_new_stream(s, NULL); if (!st) @@ -430,9 +434,11 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, /* NOTE: rtpmap is only supported AFTER the 'm=' tag */ get_word(buf1, sizeof(buf1), &p); payload_type = atoi(buf1); - st = s->streams[s->nb_streams - 1]; rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1]; - sdp_parse_rtpmap(s, st, rtsp_st, payload_type, p); + if (rtsp_st->stream_index >= 0) { + st = s->streams[rtsp_st->stream_index]; + sdp_parse_rtpmap(s, st, rtsp_st, payload_type, p); + } } else if (av_strstart(p, "fmtp:", &p) || av_strstart(p, "framesize:", &p)) { /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */ @@ -467,14 +473,15 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, if (rt->server_type == RTSP_SERVER_WMS) ff_wms_parse_sdp_a_line(s, p); if (s->nb_streams > 0) { - if (rt->server_type == RTSP_SERVER_REAL) - ff_real_parse_sdp_a_line(s, s->nb_streams - 1, p); - rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1]; + + if (rt->server_type == RTSP_SERVER_REAL) + ff_real_parse_sdp_a_line(s, rtsp_st->stream_index, p); + if (rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) rtsp_st->dynamic_handler->parse_sdp_a_line(s, - s->nb_streams - 1, + rtsp_st->stream_index, rtsp_st->dynamic_protocol_context, buf); } } @@ -1250,8 +1257,9 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, * UDP. When trying to set it up for TCP streams, the server * will return an error. Therefore, we skip those streams. */ if (rt->server_type == RTSP_SERVER_WMS && - s->streams[rtsp_st->stream_index]->codec->codec_type == - AVMEDIA_TYPE_DATA) + (rtsp_st->stream_index < 0 || + s->streams[rtsp_st->stream_index]->codec->codec_type == + AVMEDIA_TYPE_DATA)) continue; snprintf(transport, sizeof(transport) - 1, "%s/TCP;", trans_pref); From 2ce7f4d4e6f3498f8a15a8bee3d124b589474197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 7 Apr 2012 23:40:37 +0300 Subject: [PATCH 2/6] cosmetics: Fix indentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/rtpdec_xiph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/rtpdec_xiph.c b/libavformat/rtpdec_xiph.c index 2de8a68b88..6c2e7120e2 100644 --- a/libavformat/rtpdec_xiph.c +++ b/libavformat/rtpdec_xiph.c @@ -372,7 +372,7 @@ static int xiph_parse_fmtp_pair(AVStream* stream, } static int xiph_parse_sdp_line(AVFormatContext *s, int st_index, - PayloadContext *data, const char *line) + PayloadContext *data, const char *line) { const char *p; From 9cb150c9ab520eba5636bbcf925db6a70e67f3e5 Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Sun, 18 Mar 2012 09:46:58 +0100 Subject: [PATCH 3/6] hwaccel: mpeg2: decode first field, if requested. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If user opted to present fields as they come, then the first field picture needs to be submitted to the HW for decoding. In particular, this fixes MPEG-2 decoding of interlaced streams. Tested on Intel Cedar Trail, Sandy Bridge and Ivy Bridge platforms. Someone reported on the ffmpeg-devel@ list this also works on DXVA (Windows) and other Linux platforms (NVIDIA, through the VA wrapper). This also means a similar patch to non-hwaccel VDPAU may be necessary. Note: I believe the SLICE_FLAG_ALLOW_FIELD is useless since the first field shall always be submitted to the HW anyway. Nobody uses HW accels (dxva, vaapi, vdpau, etc.) without that flag though. Signed-off-by: Gwenole Beauchesne Signed-off-by: Martin Storsjö --- libavcodec/mpeg12.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 27765b32e3..8cdc704c73 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -1590,6 +1590,12 @@ static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size) return -1; } + if (s->avctx->hwaccel && + (s->avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD)) { + if (s->avctx->hwaccel->end_frame(s->avctx) < 0) + av_log(avctx, AV_LOG_ERROR, "hardware accelerator failed to decode first field\n"); + } + for (i = 0; i < 4; i++) { s->current_picture.f.data[i] = s->current_picture_ptr->f.data[i]; if (s->picture_structure == PICT_BOTTOM_FIELD) { From 58e1032d8fddab10fc2cae845aa84c5772d4cdca Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Sun, 18 Mar 2012 09:30:05 +0100 Subject: [PATCH 4/6] vaapi: mpeg2: fix slice_vertical_position calculation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VASliceParameterBufferMPEG2.slice_vertical_position shall express the slice vertical position from the original bitstream. The HW decoder will correctly decode to the right line computed from the appropriate top_field_first and is_first_field flags. This patch aligns with DXVA's definition, which is what most HW and drivers expect. In particular, Intel PowerVR (Cedarview et al.) and NVIDIA (through VA-to-VDPAU layer). Since it looks more complex to fix binary drivers, I aligned the Intel Gen driver (Sandy Bridge et al.) to this behaviour, while maintaining compatibility with codec layers not providing this patch yet. Signed-off-by: Gwenole Beauchesne Signed-off-by: Martin Storsjö --- libavcodec/vaapi_mpeg2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/vaapi_mpeg2.c b/libavcodec/vaapi_mpeg2.c index 95107c8a37..ee7b536928 100644 --- a/libavcodec/vaapi_mpeg2.c +++ b/libavcodec/vaapi_mpeg2.c @@ -132,7 +132,7 @@ static int vaapi_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer return -1; slice_param->macroblock_offset = macroblock_offset; slice_param->slice_horizontal_position = s->mb_x; - slice_param->slice_vertical_position = s->mb_y; + slice_param->slice_vertical_position = s->mb_y >> (s->picture_structure != PICT_FRAME); slice_param->quantiser_scale_code = quantiser_scale_code; slice_param->intra_slice_flag = intra_slice_flag; return 0; From 62c3c8ca78ee2da7dc20c2d6371866266c82966d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 6 Apr 2012 22:35:48 +0300 Subject: [PATCH 5/6] rtsp: Don't use uninitialized data if there are no streams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/rtsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 403f038875..9ee7a758e4 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1391,7 +1391,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, goto fail; } - if (reply->timeout > 0) + if (rt->nb_rtsp_streams && reply->timeout > 0) rt->timeout = reply->timeout; if (rt->server_type == RTSP_SERVER_REAL) From 9294f538e924dcb8f3938e4e3476340f1e5b552f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 6 Apr 2012 22:36:16 +0300 Subject: [PATCH 6/6] rtsp: Don't use av_malloc(0) if there are no streams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavformat/rtspdec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 9306384555..063e82501c 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -159,8 +159,9 @@ static int rtsp_read_header(AVFormatContext *s) if (ret) return ret; - rt->real_setup_cache = av_mallocz(2 * s->nb_streams * sizeof(*rt->real_setup_cache)); - if (!rt->real_setup_cache) + rt->real_setup_cache = !s->nb_streams ? NULL : + av_mallocz(2 * s->nb_streams * sizeof(*rt->real_setup_cache)); + if (!rt->real_setup_cache && s->nb_streams) return AVERROR(ENOMEM); rt->real_setup = rt->real_setup_cache + s->nb_streams;