[FFmpeg-devel] [PATCH 2/3] RSD demuxer
Michael Niedermayer
michaelni at gmx.at
Mon May 6 11:26:33 CEST 2013
On Mon, Apr 22, 2013 at 04:40:42PM -0300, James Almer wrote:
>
> Signed-off-by: James Almer <jamrial at gmail.com>
> ---
> Changelog | 1 +
> doc/general.texi | 1 +
> libavformat/Makefile | 1 +
> libavformat/allformats.c | 1 +
> libavformat/rsd.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++
> libavformat/version.h | 2 +-
> 6 files changed, 198 insertions(+), 1 deletion(-)
> create mode 100644 libavformat/rsd.c
>
> diff --git a/Changelog b/Changelog
> index 7481a7c..912110d 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -30,6 +30,7 @@ version <next>:
> - decent native animated GIF encoding
> - asetrate filter
> - interleave filter
> +- RSD demuxer
>
>
> version 1.2:
> diff --git a/doc/general.texi b/doc/general.texi
> index b6e731a..8b98d51 100644
> --- a/doc/general.texi
> +++ b/doc/general.texi
> @@ -353,6 +353,7 @@ library:
> @tab Audio and video format used in some games by Entertainment Software Partners.
> @item RPL/ARMovie @tab @tab X
> @item Lego Mindstorms RSO @tab X @tab X
> + at item RSD @tab @tab X
> @item RTMP @tab X @tab X
> @tab Output is performed by publishing stream to RTMP server
> @item RTP @tab X @tab X
> diff --git a/libavformat/Makefile b/libavformat/Makefile
> index 470e7f3..dbc0e41 100644
> --- a/libavformat/Makefile
> +++ b/libavformat/Makefile
> @@ -309,6 +309,7 @@ OBJS-$(CONFIG_RM_DEMUXER) += rmdec.o rm.o rmsipr.o
> OBJS-$(CONFIG_RM_MUXER) += rmenc.o rm.o
> OBJS-$(CONFIG_ROQ_DEMUXER) += idroqdec.o
> OBJS-$(CONFIG_ROQ_MUXER) += idroqenc.o rawenc.o
> +OBJS-$(CONFIG_RSD_DEMUXER) += rsd.o
> OBJS-$(CONFIG_RSO_DEMUXER) += rsodec.o rso.o pcm.o
> OBJS-$(CONFIG_RSO_MUXER) += rsoenc.o rso.o
> OBJS-$(CONFIG_RPL_DEMUXER) += rpl.o
> diff --git a/libavformat/allformats.c b/libavformat/allformats.c
> index 80c53f6..e18351b 100644
> --- a/libavformat/allformats.c
> +++ b/libavformat/allformats.c
> @@ -234,6 +234,7 @@ void av_register_all(void)
> REGISTER_MUXDEMUX(RM, rm);
> REGISTER_MUXDEMUX(ROQ, roq);
> REGISTER_DEMUXER (RPL, rpl);
> + REGISTER_DEMUXER (RSD, rsd);
> REGISTER_MUXDEMUX(RSO, rso);
> REGISTER_MUXDEMUX(RTP, rtp);
> REGISTER_MUXDEMUX(RTSP, rtsp);
> diff --git a/libavformat/rsd.c b/libavformat/rsd.c
> new file mode 100644
> index 0000000..41ab654
> --- /dev/null
> +++ b/libavformat/rsd.c
> @@ -0,0 +1,193 @@
> +/*
> + * RSD demuxer
> + * Copyright (c) 2013 James Almer
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg 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.
> + *
> + * FFmpeg 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 FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#include "libavcodec/bytestream.h"
> +#include "libavutil/intreadwrite.h"
> +#include "avformat.h"
> +#include "avio.h"
> +#include "internal.h"
> +
> +typedef struct RSDDemuxContext {
> + uint8_t *table;
> +} RSDDemuxContext;
> +
> +static const AVCodecTag rsd_tags[] = {
> + { AV_CODEC_ID_ADPCM_THP, MKTAG('G','A','D','P') },
> + { AV_CODEC_ID_PCM_S16BE, MKTAG('P','C','M','B') },
> + { AV_CODEC_ID_PCM_S16LE, MKTAG('P','C','M',' ') },
> + { AV_CODEC_ID_NONE, 0 },
> +};
> +
> +static const uint32_t rsd_unsupported_tags[] = {
> + MKTAG('O','G','G',' '),
> + MKTAG('R','A','D','P'),
> + MKTAG('V','A','G',' '),
> + MKTAG('W','A','D','P'),
> + MKTAG('X','A','D','P'),
> + MKTAG('X','M','A',' '),
> +};
> +
> +static int rsd_probe(AVProbeData *p)
> +{
> + if (!memcmp(p->buf, "RSD", 3) &&
> + p->buf[3] - '0' >= 2 && p->buf[3] - '0' <= 6)
> + return AVPROBE_SCORE_MAX / 2;
> + return 0;
> +}
> +
> +static int rsd_close(AVFormatContext *s)
> +{
> + RSDDemuxContext *rsd = s->priv_data;
> +
> + av_freep(&rsd->table);
> +
> + return 0;
> +}
> +
> +static int rsd_read_header(AVFormatContext *s)
> +{
> + AVIOContext *pb = s->pb;
> + RSDDemuxContext *rsd = s->priv_data;
> + int version, start = 0x800;
> + AVCodecContext *codec;
> + AVStream *st = avformat_new_stream(s, NULL);
> +
> + if (!st)
> + return AVERROR(ENOMEM);
> +
> + avio_skip(pb, 3); // "RSD"
> + version = avio_r8(pb) - '0';
> +
> + codec = st->codec;
> + codec->codec_type = AVMEDIA_TYPE_AUDIO;
> + codec->codec_tag = avio_rl32(pb);
> + codec->codec_id = ff_codec_get_id(rsd_tags, codec->codec_tag);
> + if (!codec->codec_id) {
> + char tag_buf[5];
> + int i;
> +
> + av_get_codec_tag_string(tag_buf, sizeof(tag_buf), codec->codec_tag);
> + for (i=0; i < FF_ARRAY_ELEMS(rsd_unsupported_tags); i++) {
> + if (codec->codec_tag == rsd_unsupported_tags[i]) {
> + avpriv_request_sample(s, "Codec tag: %s", tag_buf);
> + return AVERROR_PATCHWELCOME;
> + }
> + }
> + av_log(s, AV_LOG_ERROR, "Unknown codec tag: %s\n", tag_buf);
> + return AVERROR_INVALIDDATA;
> + }
> +
> + codec->channels = avio_rl32(pb);
> + if (!codec->channels)
> + return AVERROR_INVALIDDATA;
> +
> + avio_skip(pb, 4); // Bit depth
> + codec->sample_rate = avio_rl32(pb);
> + if (!codec->sample_rate)
> + return AVERROR_INVALIDDATA;
> +
> + avio_skip(pb, 4); // Unknown
> +
> + switch (codec->codec_id) {
> + case AV_CODEC_ID_ADPCM_THP:
> + {
> + /* RSD3GADP is mono, so only alloc enough memory
> + to store the coeff table for a single channel. */
> +
> + rsd->table = av_malloc(32);
> + if (!rsd->table)
> + return AVERROR(ENOMEM);
> +
> + start = avio_rl32(pb);
> +
> + if (avio_read(s->pb, rsd->table, 32) != 32) {
> + rsd_close(s);
> + return AVERROR_INVALIDDATA;
> + }
> + if (pb->seekable)
> + st->duration = (avio_size(pb) - start) / 8 * 14;
> + break;
> + }
> + case AV_CODEC_ID_PCM_S16LE:
> + case AV_CODEC_ID_PCM_S16BE:
> + if (version != 4)
> + start = avio_rl32(pb);
> +
> + if (pb->seekable)
> + st->duration = (avio_size(pb) - start) / 2 / codec->channels;
> + break;
> + }
> +
> + avio_skip(pb, start - avio_tell(pb));
> +
> + avpriv_set_pts_info(st, 64, 1, codec->sample_rate);
> +
> + return 0;
> +}
> +
> +static int rsd_read_packet(AVFormatContext *s, AVPacket *pkt)
> +{
> + AVCodecContext *codec = s->streams[0]->codec;
> + RSDDemuxContext *rsd = s->priv_data;
> + int i, ret, size = 1024;
> +
> + if (url_feof(s->pb))
> + return AVERROR_EOF;
> +
> + if (codec->codec_id == AV_CODEC_ID_ADPCM_THP) {
> + uint8_t *dst;
> +
> + if ((ret = av_new_packet(pkt, size)) < 0)
> + return ret;
> + if (!av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, 32))
> + return AVERROR(ENOMEM);
> + dst = pkt->side_data[0].data;
> + for (i = 0; i < 16; i++)
> + bytestream_put_be16(&dst, AV_RL16(rsd->table + i * 2));
extradata is global data, AV_PKT_DATA_NEW_EXTRADATA is when "global"
data changes due to concatenation of 2 streams with different global
data.
In this case here AVCodecContext->extradata should be used probably
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
DNS cache poisoning attacks, popular search engine, Google internet authority
dont be evil, please
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130506/56764a1b/attachment.asc>
More information about the ffmpeg-devel
mailing list