Ticket #1537: 0001-Add-CPiA-video-decoder.patch

File 0001-Add-CPiA-video-decoder.patch, 12.0 KB (added by retrosnub, 14 years ago)
  • doc/general.texi

    From 161fac3346d392403e28826009bfc99a3053fa9e Mon Sep 17 00:00:00 2001
    From: Stephan Hilb <stephan@ecshi.net>
    Date: Thu, 23 Aug 2012 18:40:22 +0200
    Subject: [PATCH] Add CPiA video decoder
    
    The cpia video decoder is intended to be used with the v4l2 demuxer.
    There are some small changes to the v4l2 demuxer to support the
    variable frame length of the format.
    ---
     doc/general.texi        |    1 +
     libavcodec/Makefile     |    1 +
     libavcodec/allcodecs.c  |    1 +
     libavcodec/avcodec.h    |    1 +
     libavcodec/codec_desc.c |    6 ++
     libavcodec/cpia.c       |  227 +++++++++++++++++++++++++++++++++++++++++++++++
     libavdevice/v4l2.c      |   18 +++-
     7 files changed, 254 insertions(+), 1 deletion(-)
     create mode 100644 libavcodec/cpia.c
    
    diff --git a/doc/general.texi b/doc/general.texi
    index 419eac7..02f449a 100644
    a b library:  
    177177    @tab Amiga CD video format
    178178@item Core Audio Format         @tab X @tab X
    179179    @tab Apple Core Audio Format
     180@item CPiA Video Format         @tab X @tab
    180181@item CRC testing format        @tab X @tab
    181182@item Creative Voice            @tab X @tab X
    182183    @tab Created for the Sound Blaster Pro.
  • libavcodec/Makefile

    diff --git a/libavcodec/Makefile b/libavcodec/Makefile
    index c3de2cb..e9b4806 100644
    a b OBJS-$(CONFIG_CLJR_DECODER) += cljr.o  
    141141OBJS-$(CONFIG_CLJR_ENCODER)            += cljr.o
    142142OBJS-$(CONFIG_CLLC_DECODER)            += cllc.o
    143143OBJS-$(CONFIG_COOK_DECODER)            += cook.o
     144OBJS-$(CONFIG_CPIA_DECODER)            += cpia.o
    144145OBJS-$(CONFIG_CSCD_DECODER)            += cscd.o
    145146OBJS-$(CONFIG_CYUV_DECODER)            += cyuv.o
    146147OBJS-$(CONFIG_DCA_DECODER)             += dcadec.o dca.o dcadsp.o      \
  • libavcodec/allcodecs.c

    diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
    index 1ddd440..d0cec39 100644
    a b void avcodec_register_all(void)  
    9797    REGISTER_DECODER (CINEPAK, cinepak);
    9898    REGISTER_ENCDEC  (CLJR, cljr);
    9999    REGISTER_DECODER (CLLC, cllc);
     100    REGISTER_DECODER (CPIA, cpia);
    100101    REGISTER_DECODER (CSCD, cscd);
    101102    REGISTER_DECODER (CYUV, cyuv);
    102103    REGISTER_DECODER (DFA, dfa);
  • libavcodec/avcodec.h

    diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
    index c3cde34..40671ca 100644
    a b enum AVCodecID {  
    277277    AV_CODEC_ID_SANM       = MKBETAG('S','A','N','M'),
    278278    AV_CODEC_ID_PAF_VIDEO  = MKBETAG('P','A','F','V'),
    279279    AV_CODEC_ID_AVRN       = MKBETAG('A','V','R','n'),
     280    AV_CODEC_ID_CPIA       = MKBETAG('C','P','I','A'),
    280281
    281282    /* various PCM "codecs" */
    282283    AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
  • libavcodec/codec_desc.c

    diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
    index dd4870d..0b619db 100644
    a b static const AVCodecDescriptor codec_descriptors[] = {  
    11831183        .name      = "avrn",
    11841184        .long_name = NULL_IF_CONFIG_SMALL("Avid AVI Codec"),
    11851185    },
     1186    {
     1187        .id        = AV_CODEC_ID_CPIA,
     1188        .type      = AVMEDIA_TYPE_VIDEO,
     1189        .name      = "cpia",
     1190        .long_name = NULL_IF_CONFIG_SMALL("CPiA video format"),
     1191    },
    11861192
    11871193    /* various PCM "codecs" */
    11881194    {
  • new file libavcodec/cpia.c

    diff --git a/libavcodec/cpia.c b/libavcodec/cpia.c
    new file mode 100644
    index 0000000..a3b3e54
    - +  
     1/*
     2 * CPiA video decoder.
     3 * Copyright (c) 2012
     4 *
     5 * This file is part of FFmpeg.
     6 *
     7 * FFmpeg is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU Lesser General Public
     9 * License as published by the Free Software Foundation; either
     10 * version 2.1 of the License, or (at your option) any later version.
     11 *
     12 * FFmpeg is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15 * Lesser General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU Lesser General Public
     18 * License along with FFmpeg; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     20 */
     21
     22#include "avcodec.h"
     23#include "get_bits.h"
     24
     25
     26#define FRAME_HEADER_SIZE       64
     27#define MAGIC_0         0x19
     28#define MAGIC_1         0x68
     29#define SUBSAMPLE_420   0
     30#define SUBSAMPLE_422   1
     31#define YUVORDER_YUYV   0
     32#define YUVORDER_UYVY   1
     33#define NOT_COMPRESSED  0
     34#define COMPRESSED              1
     35#define NO_DECIMATION   0
     36#define DECIMATION_ENAB 1
     37#define EOL             0xfd    /* End Of Line */
     38#define EOI             0xff    /* End Of Image */
     39
     40
     41typedef struct {
     42        // The frame we decode into
     43    AVFrame frame;
     44} CpiaContext;
     45
     46
     47static int
     48cpia_decode_frame(AVCodecContext* avctx,
     49                 void* data, int* data_size, AVPacket* avpkt)
     50{
     51        CpiaContext* const cpia = avctx->priv_data;
     52
     53        // pointer to header frame data
     54        uint8_t* const header = avpkt->data;
     55        // pointer to frame data, will later point to the start of current line
     56        uint8_t* src;
     57        // size of remaining frame, will later be updated on each line
     58        int src_size;
     59
     60        uint16_t linelength;
     61        uint8_t skip;
     62
     63        int i,j;
     64        // target data
     65        AVFrame* const frame = &cpia->frame;
     66       
     67        // pointer to keep track where we are writing image dat
     68        uint8_t *y, *u, *v;
     69
     70        // Get buffer filled with previous frame
     71    if (avctx->reget_buffer(avctx, frame)) {
     72        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed!\n");
     73        return -1;
     74    }
     75
     76        // Check header
     77        if (    avpkt->size < FRAME_HEADER_SIZE
     78                ||      header[0] != MAGIC_0 || header[1] != MAGIC_1
     79                ||      (header[17] != SUBSAMPLE_420 && header[17] != SUBSAMPLE_422)
     80                ||      (header[18] != YUVORDER_YUYV && header[18] != YUVORDER_UYVY)
     81                ||      (header[28] != NOT_COMPRESSED && header[28] != COMPRESSED)
     82                ||      (header[29] != NO_DECIMATION && header[29] != DECIMATION_ENAB)
     83        ) {
     84        av_log(avctx, AV_LOG_ERROR, "Invalid header!\n");
     85                return AVERROR_INVALIDDATA;
     86        }
     87
     88        // Check for currently unsupported properties
     89        if (header[17] == SUBSAMPLE_422) {
     90        av_log(avctx, AV_LOG_ERROR, "Unsupported subsample!\n");
     91                return -1;
     92        }
     93        if (header[18] == YUVORDER_UYVY) {
     94        av_log(avctx, AV_LOG_ERROR, "Unsupported YUV byte order!\n");
     95                return -1;
     96        }
     97        if (header[29] == DECIMATION_ENAB) {
     98        av_log(avctx, AV_LOG_ERROR, "Decimation unsupported!\n");
     99                return -1;
     100        }
     101
     102        // data starts after header, set proper length
     103        src = header + FRAME_HEADER_SIZE;
     104        src_size = avpkt->size - FRAME_HEADER_SIZE;
     105       
     106        if (header[28] == NOT_COMPRESSED) {
     107                // uncompressed frames are independent
     108                frame->pict_type = AV_PICTURE_TYPE_I;
     109                frame->key_frame = 1;
     110        } else {
     111                // compressed frames depend on previous frame
     112                frame->pict_type = AV_PICTURE_TYPE_P;
     113                frame->key_frame = 0;
     114        }
     115
     116
     117        // Data processing
     118        for (   i = 0;
     119                        i < frame->height;
     120                        i++, src += linelength, src_size -= linelength
     121        ) {
     122                // Read line length, two byte little endian
     123                linelength = AV_RL16(src);
     124                src += 2;
     125               
     126                // Some integrity checking     
     127                if (src_size < linelength) {
     128                        frame->decode_error_flags = FF_DECODE_ERROR_INVALID_BITSTREAM;
     129                        av_log(avctx, AV_LOG_WARNING, "Frame ended enexpectedly!\n");
     130                        break;
     131                }
     132                if (src[linelength - 1] != EOL) {
     133                        frame->decode_error_flags = FF_DECODE_ERROR_INVALID_BITSTREAM;
     134                        av_log(avctx, AV_LOG_WARNING, "Wrong line length %d or line not terminated properly (found 0x%02x)!\n", linelength, src[linelength - 1]);
     135                        break;
     136                }
     137
     138                /* Update the data pointers. Y data is on every line.
     139                 * U and V data on every second line
     140                 */
     141                y = &frame->data[0][i * frame->linesize[0]];
     142                u = &frame->data[1][(i >> 1) * frame->linesize[1]];
     143                v = &frame->data[2][(i >> 1) * frame->linesize[2]];
     144
     145                if ((i & 1) && header[17] == SUBSAMPLE_420) {
     146                        /* We are on a odd line and 420 subsample is used.
     147                         * On this line only Y values are specified, one per pixel.
     148                         */
     149                        for (j = 0; j < linelength - 1; j++) {
     150                                if (src[j] & 1 && header[28] == COMPRESSED) {
     151                                        /* It seems that odd lines are always uncompressed, but
     152                                         * we do it according to specification anyways.
     153                                         */
     154                                        skip = src[j] >> 1;
     155                                        y += skip;
     156                                } else {
     157                                        *(y++) = src[j];
     158                                }
     159                        }
     160                } else if (header[17] == SUBSAMPLE_420) {
     161                        /* We are on an even line and 420 subsample is used.
     162                         * On this line each pair of pixels is described by four bytes.
     163                         */
     164                        for (j = 0; j < linelength - 1; ) {
     165                                if (src[j] & 1 && header[28] == COMPRESSED) {
     166                                        // Skip amount of pixels and move forward one byte
     167                                        skip = src[j] >> 1;
     168                                        y += skip;
     169                                        u += skip / 2;
     170                                        v += skip / 2;
     171                                        j++;
     172                                } else {
     173                                        // Set image data as specified and move forward 4 bytes
     174                                        *(y++) = src[j];
     175                                        *(u++) = src[j+1];
     176                                        *(y++) = src[j+2];
     177                                        *(v++) = src[j+3];
     178                                        j += 4;
     179                                }
     180                        }
     181                }
     182        }
     183       
     184        // Not quite sure how this data_size works
     185        *data_size = sizeof(AVFrame);
     186        *(AVFrame*) data = *frame;
     187
     188        return avpkt->size;
     189}
     190
     191static av_cold int cpia_decode_init(AVCodecContext *avctx)
     192{
     193        /* We don't need to allocate memory for our context here.
     194         * It is done by ffmpeg
     195         */
     196
     197        // The pixel format this decoder outputs
     198    avctx->pix_fmt = PIX_FMT_YUV420P;
     199       
     200        /* The default timebase set by the v4l2 demuxer leads to probing which is buggy.
     201         * Set some reasonable time_base to skip this.
     202         */
     203        if (avctx->time_base.num == 1 && avctx->time_base.den == 1000000) {
     204                avctx->time_base.num = 1;
     205                avctx->time_base.den = 60;
     206        }
     207
     208    return 0;
     209}
     210
     211static av_cold int cpia_decode_end(AVCodecContext *avctx)
     212{
     213    return 0;
     214}
     215
     216
     217AVCodec ff_cpia_decoder = {
     218    .name           = "cpia",
     219    .type           = AVMEDIA_TYPE_VIDEO,
     220    .id             = AV_CODEC_ID_CPIA,
     221    .priv_data_size = sizeof(CpiaContext),              // for ffmpeg to know how much to allocate
     222    .init           = cpia_decode_init,
     223    .decode         = cpia_decode_frame,
     224    .close          = cpia_decode_end,
     225    .capabilities   = CODEC_CAP_DR1,
     226        .long_name      = NULL_IF_CONFIG_SMALL("CPiA video format"),
     227};
  • libavdevice/v4l2.c

    diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
    index 867c363..4b43688 100644
    a b static struct fmt_map fmt_conversion_table[] = {  
    150150    { PIX_FMT_NV12,    AV_CODEC_ID_RAWVIDEO, V4L2_PIX_FMT_NV12    },
    151151    { PIX_FMT_NONE,    AV_CODEC_ID_MJPEG,    V4L2_PIX_FMT_MJPEG   },
    152152    { PIX_FMT_NONE,    AV_CODEC_ID_MJPEG,    V4L2_PIX_FMT_JPEG    },
     153    { PIX_FMT_NONE,    AV_CODEC_ID_CPIA,     V4L2_PIX_FMT_CPIA1   },
    153154};
    154155
    155156static int device_open(AVFormatContext *ctx)
    static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)  
    549550        return AVERROR(errno);
    550551    }
    551552    av_assert0(buf.index < s->buffers);
     553
     554    /* CPIA is a compressed format and we don't know the exact number of bytes
     555     * used by a frame, so set it here as the driver announces it.
     556     */
     557    if (ctx->video_codec_id == AV_CODEC_ID_CPIA)
     558        s->frame_size = buf.bytesused;
     559
    552560    if (s->frame_size > 0 && buf.bytesused != s->frame_size) {
    553561        av_log(ctx, AV_LOG_ERROR,
    554562               "The v4l2 frame is %d bytes, but %d bytes are expected\n",
    static int v4l2_read_header(AVFormatContext *s1)  
    767775    AVStream *st;
    768776    int res = 0;
    769777    uint32_t desired_format;
    770     enum AVCodecID codec_id;
     778    enum AVCodecID codec_id = AV_CODEC_ID_NONE;
    771779    enum PixelFormat pix_fmt = PIX_FMT_NONE;
    772780
    773781    st = avformat_new_stream(s1, NULL);
    static int v4l2_read_header(AVFormatContext *s1)  
    828836
    829837    desired_format = device_try_init(s1, pix_fmt, &s->width, &s->height,
    830838                                     &codec_id);
     839
     840    /* If no pixel_format was specified, the codec_id was not known up
     841     * until now. Set video_codec_id in the context, as codec_id will
     842     * not be available outside this function
     843     */
     844    if (codec_id != AV_CODEC_ID_NONE && s1->video_codec_id == AV_CODEC_ID_NONE)
     845        s1->video_codec_id = codec_id;
     846
    831847    if (desired_format == 0) {
    832848        av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for "
    833849               "codec_id %d, pix_fmt %d.\n", s1->video_codec_id, pix_fmt);