"Fossies" - the Fresh Open Source Software Archive

Member "ffmpeg-4.0.1/libavcodec/8bps.c" (13 Apr 2018, 6350 Bytes) of package /linux/misc/ffmpeg-4.0.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "8bps.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Quicktime Planar RGB (8BPS) Video Decoder
    3  * Copyright (C) 2003 Roberto Togni
    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 /**
   23  * @file
   24  * QT 8BPS Video Decoder by Roberto Togni
   25  * For more information about the 8BPS format, visit:
   26  *   http://www.pcisys.net/~melanson/codecs/
   27  *
   28  * Supports: PAL8 (RGB 8bpp, paletted)
   29  *         : BGR24 (RGB 24bpp) (can also output it as RGB32)
   30  *         : RGB32 (RGB 32bpp, 4th plane is alpha)
   31  */
   32 
   33 #include <stdio.h>
   34 #include <stdlib.h>
   35 #include <string.h>
   36 
   37 #include "libavutil/internal.h"
   38 #include "libavutil/intreadwrite.h"
   39 #include "avcodec.h"
   40 #include "internal.h"
   41 
   42 
   43 static const enum AVPixelFormat pixfmt_rgb24[] = {
   44     AV_PIX_FMT_BGR24, AV_PIX_FMT_0RGB32, AV_PIX_FMT_NONE };
   45 
   46 typedef struct EightBpsContext {
   47     AVCodecContext *avctx;
   48 
   49     unsigned char planes;
   50     unsigned char planemap[4];
   51 
   52     uint32_t pal[256];
   53 } EightBpsContext;
   54 
   55 static int decode_frame(AVCodecContext *avctx, void *data,
   56                         int *got_frame, AVPacket *avpkt)
   57 {
   58     AVFrame *frame = data;
   59     const uint8_t *buf = avpkt->data;
   60     int buf_size       = avpkt->size;
   61     EightBpsContext * const c = avctx->priv_data;
   62     const unsigned char *encoded = buf;
   63     unsigned char *pixptr, *pixptr_end;
   64     unsigned int height = avctx->height; // Real image height
   65     unsigned int dlen, p, row;
   66     const unsigned char *lp, *dp, *ep;
   67     unsigned char count;
   68     unsigned int px_inc;
   69     unsigned int planes     = c->planes;
   70     unsigned char *planemap = c->planemap;
   71     int ret;
   72 
   73     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
   74         return ret;
   75 
   76     ep = encoded + buf_size;
   77 
   78     /* Set data pointer after line lengths */
   79     dp = encoded + planes * (height << 1);
   80 
   81     px_inc = planes + (avctx->pix_fmt == AV_PIX_FMT_0RGB32);
   82 
   83     for (p = 0; p < planes; p++) {
   84         /* Lines length pointer for this plane */
   85         lp = encoded + p * (height << 1);
   86 
   87         /* Decode a plane */
   88         for (row = 0; row < height; row++) {
   89             pixptr = frame->data[0] + row * frame->linesize[0] + planemap[p];
   90             pixptr_end = pixptr + frame->linesize[0];
   91             if (ep - lp < row * 2 + 2)
   92                 return AVERROR_INVALIDDATA;
   93             dlen = av_be2ne16(*(const unsigned short *)(lp + row * 2));
   94             /* Decode a row of this plane */
   95             while (dlen > 0) {
   96                 if (ep - dp <= 1)
   97                     return AVERROR_INVALIDDATA;
   98                 if ((count = *dp++) <= 127) {
   99                     count++;
  100                     dlen -= count + 1;
  101                     if (pixptr_end - pixptr < count * px_inc)
  102                         break;
  103                     if (ep - dp < count)
  104                         return AVERROR_INVALIDDATA;
  105                     while (count--) {
  106                         *pixptr = *dp++;
  107                         pixptr += px_inc;
  108                     }
  109                 } else {
  110                     count = 257 - count;
  111                     if (pixptr_end - pixptr < count * px_inc)
  112                         break;
  113                     while (count--) {
  114                         *pixptr = *dp;
  115                         pixptr += px_inc;
  116                     }
  117                     dp++;
  118                     dlen -= 2;
  119                 }
  120             }
  121         }
  122     }
  123 
  124     if (avctx->bits_per_coded_sample <= 8) {
  125         int size;
  126         const uint8_t *pal = av_packet_get_side_data(avpkt,
  127                                                      AV_PKT_DATA_PALETTE,
  128                                                      &size);
  129         if (pal && size == AVPALETTE_SIZE) {
  130             frame->palette_has_changed = 1;
  131             memcpy(c->pal, pal, AVPALETTE_SIZE);
  132         } else if (pal) {
  133             av_log(avctx, AV_LOG_ERROR, "Palette size %d is wrong\n", size);
  134         }
  135 
  136         memcpy (frame->data[1], c->pal, AVPALETTE_SIZE);
  137     }
  138 
  139     *got_frame = 1;
  140 
  141     /* always report that the buffer was completely consumed */
  142     return buf_size;
  143 }
  144 
  145 static av_cold int decode_init(AVCodecContext *avctx)
  146 {
  147     EightBpsContext * const c = avctx->priv_data;
  148 
  149     c->avctx       = avctx;
  150 
  151     switch (avctx->bits_per_coded_sample) {
  152     case 8:
  153         avctx->pix_fmt = AV_PIX_FMT_PAL8;
  154         c->planes      = 1;
  155         c->planemap[0] = 0; // 1st plane is palette indexes
  156         break;
  157     case 24:
  158         avctx->pix_fmt = ff_get_format(avctx, pixfmt_rgb24);
  159         c->planes      = 3;
  160         c->planemap[0] = 2; // 1st plane is red
  161         c->planemap[1] = 1; // 2nd plane is green
  162         c->planemap[2] = 0; // 3rd plane is blue
  163         break;
  164     case 32:
  165         avctx->pix_fmt = AV_PIX_FMT_RGB32;
  166         c->planes      = 4;
  167         /* handle planemap setup later for decoding rgb24 data as rbg32 */
  168         break;
  169     default:
  170         av_log(avctx, AV_LOG_ERROR, "Error: Unsupported color depth: %u.\n",
  171                avctx->bits_per_coded_sample);
  172         return AVERROR_INVALIDDATA;
  173     }
  174 
  175     if (avctx->pix_fmt == AV_PIX_FMT_RGB32) {
  176         c->planemap[0] = HAVE_BIGENDIAN ? 1 : 2; // 1st plane is red
  177         c->planemap[1] = HAVE_BIGENDIAN ? 2 : 1; // 2nd plane is green
  178         c->planemap[2] = HAVE_BIGENDIAN ? 3 : 0; // 3rd plane is blue
  179         c->planemap[3] = HAVE_BIGENDIAN ? 0 : 3; // 4th plane is alpha
  180     }
  181     return 0;
  182 }
  183 
  184 AVCodec ff_eightbps_decoder = {
  185     .name           = "8bps",
  186     .long_name      = NULL_IF_CONFIG_SMALL("QuickTime 8BPS video"),
  187     .type           = AVMEDIA_TYPE_VIDEO,
  188     .id             = AV_CODEC_ID_8BPS,
  189     .priv_data_size = sizeof(EightBpsContext),
  190     .init           = decode_init,
  191     .decode         = decode_frame,
  192     .capabilities   = AV_CODEC_CAP_DR1,
  193 };