[FFmpeg-devel] [PATCH 2/3] RSD demuxer

Michael Niedermayer michaelni at gmx.at
Mon May 6 11:40:51 CEST 2013


On Mon, May 06, 2013 at 11:26:33AM +0200, Michael Niedermayer wrote:
> 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

also consider remuxing rsd -> rsd
If you take the global extradata and put it in every packet then
the muxer would have to somehow proof that the data never changes
or risk failure (theres another demuxer where it can change so it
could get either kind of packets)

and it would have to get the first packet to write the global table
in the header.
AVCodecContext.extradata simplifies that alot, the demuxer puts the
table in extradata, the muxer writes it again

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

The educated differ from the uneducated as much as the living from the
dead. -- Aristotle 
-------------- 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/f348ae6c/attachment.asc>


More information about the ffmpeg-devel mailing list