From 0b4949b51816bc2fd23ba4c4de183b877b58aa25 Mon Sep 17 00:00:00 2001 From: Martin Storsjö Date: Mon, 9 May 2011 20:11:16 +0300 Subject: rtsp: Only do keepalive using GET_PARAMETER if the server supports it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is more like what VLC does. If the server doesn't mention supporting GET_PARAMETER in response to an OPTIONS request, VLC doesn't send any keepalive requests at all. After this patch, libavformat will still send OPTIONS keepalives if GET_PARAMETER isn't explicitly said to be supported. Some RTSP cameras don't support GET_PARAMETER, and will close the connection if this is sent as keepalive request (but support OPTIONS just fine, but probably don't need any keepalive at all). Some other cameras don't support using OPTIONS as keepalive, but require GET_PARAMETER instead. Signed-off-by: Martin Storsjö --- libavformat/rtsp.c | 4 ++++ libavformat/rtsp.h | 5 +++++ libavformat/rtspdec.c | 4 +++- 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'libavformat') diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 14111e69fd..2ebf7e0510 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -808,6 +808,10 @@ void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf, p += strspn(p, SPACE_CHARS); if (method && !strcmp(method, "PLAY")) rtsp_parse_rtp_info(rt, p); + } else if (av_stristart(p, "Public:", &p) && rt) { + if (strstr(p, "GET_PARAMETER") && + method && !strcmp(method, "OPTIONS")) + rt->get_parameter_supported = 1; } } diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index e1f1df990e..ff66502626 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -331,6 +331,11 @@ typedef struct RTSPState { * Polling array for udp */ struct pollfd *p; + + /** + * Whether the server supports the GET_PARAMETER method. + */ + int get_parameter_supported; } RTSPState; /** diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 866f313d10..ccfc4d8e27 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -341,7 +341,9 @@ retry: /* send dummy request to keep TCP connection alive */ if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) { - if (rt->server_type != RTSP_SERVER_REAL) { + if (rt->server_type == RTSP_SERVER_WMS || + (rt->server_type != RTSP_SERVER_REAL && + rt->get_parameter_supported)) { ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL); } else { ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL); -- cgit v1.2.3 From 9aa91043f30cee1419555c0e299c94e655b0930a Mon Sep 17 00:00:00 2001 From: Baptiste Coudurier Date: Tue, 12 Apr 2011 15:29:09 -0700 Subject: Port SMPTE S302M audio decoder from FFmbc 0.3. --- Changelog | 1 + doc/general.texi | 1 + libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/s302m.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/mpegts.c | 1 + 7 files changed, 147 insertions(+) create mode 100644 libavcodec/s302m.c (limited to 'libavformat') diff --git a/Changelog b/Changelog index b5ceea9444..3d3fe6eb57 100644 --- a/Changelog +++ b/Changelog @@ -7,6 +7,7 @@ version : - Lots of deprecated API cruft removed - fft and imdct optimizations for AVX (Sandy Bridge) processors - DPX image encoder +- SMPTE 302M AES3 audio decoder version 0.7_beta1: diff --git a/doc/general.texi b/doc/general.texi index 598b9bc873..53482273f9 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -673,6 +673,7 @@ following image formats are supported: @item Sierra VMD audio @tab @tab X @tab Used in Sierra VMD files. @item Smacker audio @tab @tab X +@item SMPTE 302M AES3 audio @tab @tab X @item Speex @tab @tab E @tab supported through external library libspeex @item True Audio (TTA) @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 996b9b4d81..9040b32f57 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -324,6 +324,7 @@ OBJS-$(CONFIG_RV30_DECODER) += rv30.o rv34.o rv30dsp.o \ mpegvideo.o error_resilience.o OBJS-$(CONFIG_RV40_DECODER) += rv40.o rv34.o rv40dsp.o \ mpegvideo.o error_resilience.o +OBJS-$(CONFIG_S302M_DECODER) += s302m.o OBJS-$(CONFIG_SGI_DECODER) += sgidec.o OBJS-$(CONFIG_SGI_ENCODER) += sgienc.o rle.o OBJS-$(CONFIG_SHORTEN_DECODER) += shorten.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 694674ce7b..3466ad94fd 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -177,6 +177,7 @@ void avcodec_register_all(void) REGISTER_ENCDEC (RV20, rv20); REGISTER_DECODER (RV30, rv30); REGISTER_DECODER (RV40, rv40); + REGISTER_DECODER (S302M, s302m); REGISTER_ENCDEC (SGI, sgi); REGISTER_DECODER (SMACKER, smacker); REGISTER_DECODER (SMC, smc); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 876ba8c21b..2eb218ba4f 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -232,6 +232,7 @@ enum CodecID { CODEC_ID_PCM_F64LE, CODEC_ID_PCM_BLURAY, CODEC_ID_PCM_LXF, + CODEC_ID_S302M, /* various ADPCM codecs */ CODEC_ID_ADPCM_IMA_QT= 0x11000, diff --git a/libavcodec/s302m.c b/libavcodec/s302m.c new file mode 100644 index 0000000000..fb1fd867d0 --- /dev/null +++ b/libavcodec/s302m.c @@ -0,0 +1,141 @@ +/* + * SMPTE 302M decoder + * Copyright (c) 2008 Laurent Aimar + * Copyright (c) 2009 Baptiste Coudurier + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "avcodec.h" + +#define AES3_HEADER_LEN 4 + +static int s302m_parse_frame_header(AVCodecContext *avctx, const uint8_t *buf, + int buf_size) +{ + uint32_t h; + int frame_size, channels, id, bits; + + if (buf_size <= AES3_HEADER_LEN) { + av_log(avctx, AV_LOG_ERROR, "frame is too short\n"); + return AVERROR_INVALIDDATA; + } + + /* + * AES3 header : + * size: 16 + * number channels 2 + * channel_id 8 + * bits per samples 2 + * alignments 4 + */ + + h = AV_RB32(buf); + frame_size = (h >> 16) & 0xffff; + channels = ((h >> 14) & 0x0003) * 2 + 2; + id = (h >> 6) & 0x00ff; + bits = ((h >> 4) & 0x0003) * 4 + 16; + + if (AES3_HEADER_LEN + frame_size != buf_size || bits > 24) { + av_log(avctx, AV_LOG_ERROR, "frame has invalid header\n"); + return AVERROR_INVALIDDATA; + } + + /* Set output properties */ + avctx->bits_per_coded_sample = bits; + if (bits > 16) + avctx->sample_fmt = SAMPLE_FMT_S32; + else + avctx->sample_fmt = SAMPLE_FMT_S16; + + avctx->channels = channels; + avctx->sample_rate = 48000; + avctx->bit_rate = 48000 * avctx->channels * (avctx->bits_per_coded_sample + 4) + + 32 * (48000 / (buf_size * 8 / + (avctx->channels * + (avctx->bits_per_coded_sample + 4)))); + + return frame_size; +} + +static int s302m_decode_frame(AVCodecContext *avctx, void *data, + int *data_size, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + + int frame_size = s302m_parse_frame_header(avctx, buf, buf_size); + if (frame_size < 0) + return frame_size; + + buf_size -= AES3_HEADER_LEN; + buf += AES3_HEADER_LEN; + + if (*data_size < 4 * buf_size * 8 / (avctx->bits_per_coded_sample + 4)) + return -1; + + if (avctx->bits_per_coded_sample == 24) { + uint32_t *o = data; + for (; buf_size > 6; buf_size -= 7) { + *o++ = (av_reverse[buf[2]] << 24) | + (av_reverse[buf[1]] << 16) | + (av_reverse[buf[0]] << 8); + *o++ = (av_reverse[buf[6] & 0xf0] << 28) | + (av_reverse[buf[5]] << 20) | + (av_reverse[buf[4]] << 12) | + (av_reverse[buf[3] & 0x0f] << 8); + buf += 7; + } + *data_size = (uint8_t*) o - (uint8_t*) data; + } else if (avctx->bits_per_coded_sample == 20) { + uint32_t *o = data; + for (; buf_size > 5; buf_size -= 6) { + *o++ = (av_reverse[buf[2] & 0xf0] << 28) | + (av_reverse[buf[1]] << 20) | + (av_reverse[buf[0]] << 12); + *o++ = (av_reverse[buf[5] & 0xf0] << 28) | + (av_reverse[buf[4]] << 20) | + (av_reverse[buf[3]] << 12); + buf += 6; + } + *data_size = (uint8_t*) o - (uint8_t*) data; + } else { + uint16_t *o = data; + for (; buf_size > 4; buf_size -= 5) { + *o++ = (av_reverse[buf[1]] << 8) | + av_reverse[buf[0]]; + *o++ = (av_reverse[buf[4] & 0xf0] << 12) | + (av_reverse[buf[3]] << 4) | + av_reverse[buf[2] & 0x0f]; + buf += 5; + } + *data_size = (uint8_t*) o - (uint8_t*) data; + } + + return buf - avpkt->data; +} + + +AVCodec ff_s302m_decoder = { + .name = "s302m", + .type = AVMEDIA_TYPE_AUDIO, + .id = CODEC_ID_S302M, + .priv_data_size = 0, + .decode = s302m_decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("SMPTE 302M"), +}; diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 3130eb9ff5..cdefb84864 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -524,6 +524,7 @@ static const StreamType MISC_types[] = { static const StreamType REGD_types[] = { { MKTAG('d','r','a','c'), AVMEDIA_TYPE_VIDEO, CODEC_ID_DIRAC }, { MKTAG('A','C','-','3'), AVMEDIA_TYPE_AUDIO, CODEC_ID_AC3 }, + { MKTAG('B','S','S','D'), AVMEDIA_TYPE_AUDIO, CODEC_ID_S302M }, { 0 }, }; -- cgit v1.2.3