[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