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

File 0001-Add-CPiA-video-decoder.patch, 12.0 KB (added by retrosnub, 4 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);