1/* 2 * Micrsoft RLE Video Decoder 3 * Copyright (C) 2003 the ffmpeg project 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 * MS RLE Video Decoder by Mike Melanson (melanson@pcisys.net) 25 * For more information about the MS RLE format, visit: 26 * http://www.pcisys.net/~melanson/codecs/ 27 * 28 * The MS RLE decoder outputs PAL8 colorspace data. 29 * 30 * Note that this decoder expects the palette colors from the end of the 31 * BITMAPINFO header passed through palctrl. 32 */ 33 34#include <stdio.h> 35#include <stdlib.h> 36#include <string.h> 37 38#include "avcodec.h" 39#include "dsputil.h" 40#include "msrledec.h" 41 42typedef struct MsrleContext { 43 AVCodecContext *avctx; 44 AVFrame frame; 45 46 const unsigned char *buf; 47 int size; 48 49} MsrleContext; 50 51static av_cold int msrle_decode_init(AVCodecContext *avctx) 52{ 53 MsrleContext *s = avctx->priv_data; 54 55 s->avctx = avctx; 56 57 switch (avctx->bits_per_coded_sample) { 58 case 4: 59 case 8: 60 avctx->pix_fmt = PIX_FMT_PAL8; 61 break; 62 case 24: 63 avctx->pix_fmt = PIX_FMT_BGR24; 64 break; 65 default: 66 av_log(avctx, AV_LOG_ERROR, "unsupported bits per sample\n"); 67 return -1; 68 } 69 70 s->frame.data[0] = NULL; 71 72 return 0; 73} 74 75static int msrle_decode_frame(AVCodecContext *avctx, 76 void *data, int *data_size, 77 AVPacket *avpkt) 78{ 79 const uint8_t *buf = avpkt->data; 80 int buf_size = avpkt->size; 81 MsrleContext *s = avctx->priv_data; 82 int istride = FFALIGN(avctx->width*avctx->bits_per_coded_sample, 32) / 8; 83 84 s->buf = buf; 85 s->size = buf_size; 86 87 s->frame.reference = 1; 88 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; 89 if (avctx->reget_buffer(avctx, &s->frame)) { 90 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); 91 return -1; 92 } 93 94 if (s->avctx->palctrl) { 95 /* make the palette available */ 96 memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE); 97 if (s->avctx->palctrl->palette_changed) { 98 s->frame.palette_has_changed = 1; 99 s->avctx->palctrl->palette_changed = 0; 100 } 101 } 102 103 /* FIXME how to correctly detect RLE ??? */ 104 if (avctx->height * istride == avpkt->size) { /* assume uncompressed */ 105 int linesize = avctx->width * avctx->bits_per_coded_sample / 8; 106 uint8_t *ptr = s->frame.data[0]; 107 uint8_t *buf = avpkt->data + (avctx->height-1)*istride; 108 int i, j; 109 110 for (i = 0; i < avctx->height; i++) { 111 if (avctx->bits_per_coded_sample == 4) { 112 for (j = 0; j < avctx->width - 1; j += 2) { 113 ptr[j+0] = buf[j>>1] >> 4; 114 ptr[j+1] = buf[j>>1] & 0xF; 115 } 116 if (avctx->width & 1) 117 ptr[j+0] = buf[j>>1] >> 4; 118 } else { 119 memcpy(ptr, buf, linesize); 120 } 121 buf -= istride; 122 ptr += s->frame.linesize[0]; 123 } 124 } else { 125 ff_msrle_decode(avctx, (AVPicture*)&s->frame, avctx->bits_per_coded_sample, buf, buf_size); 126 } 127 128 *data_size = sizeof(AVFrame); 129 *(AVFrame*)data = s->frame; 130 131 /* report that the buffer was completely consumed */ 132 return buf_size; 133} 134 135static av_cold int msrle_decode_end(AVCodecContext *avctx) 136{ 137 MsrleContext *s = avctx->priv_data; 138 139 /* release the last frame */ 140 if (s->frame.data[0]) 141 avctx->release_buffer(avctx, &s->frame); 142 143 return 0; 144} 145 146AVCodec msrle_decoder = { 147 "msrle", 148 AVMEDIA_TYPE_VIDEO, 149 CODEC_ID_MSRLE, 150 sizeof(MsrleContext), 151 msrle_decode_init, 152 NULL, 153 msrle_decode_end, 154 msrle_decode_frame, 155 CODEC_CAP_DR1, 156 .long_name= NULL_IF_CONFIG_SMALL("Microsoft RLE"), 157}; 158