Libav 0.7.1
|
00001 /* 00002 * RL2 Video Decoder 00003 * Copyright (C) 2008 Sascha Sommer (saschasommer@freenet.de) 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00030 #include <stdio.h> 00031 #include <stdlib.h> 00032 #include <string.h> 00033 00034 #include "libavutil/intreadwrite.h" 00035 #include "avcodec.h" 00036 00037 00038 #define EXTRADATA1_SIZE (6 + 256 * 3) ///< video base, clr count, palette 00039 00040 typedef struct Rl2Context { 00041 AVCodecContext *avctx; 00042 AVFrame frame; 00043 00044 unsigned short video_base; 00045 unsigned int clr_count; 00046 unsigned char* back_frame; 00047 unsigned int palette[AVPALETTE_COUNT]; 00048 } Rl2Context; 00049 00059 static void rl2_rle_decode(Rl2Context *s,const unsigned char* in,int size, 00060 unsigned char* out,int stride,int video_base){ 00061 int base_x = video_base % s->avctx->width; 00062 int base_y = video_base / s->avctx->width; 00063 int stride_adj = stride - s->avctx->width; 00064 int i; 00065 const unsigned char* back_frame = s->back_frame; 00066 const unsigned char* in_end = in + size; 00067 const unsigned char* out_end = out + stride * s->avctx->height; 00068 unsigned char* line_end = out + s->avctx->width; 00069 00071 for(i=0;i<=base_y;i++){ 00072 if(s->back_frame) 00073 memcpy(out,back_frame,s->avctx->width); 00074 out += stride; 00075 back_frame += s->avctx->width; 00076 } 00077 back_frame += base_x - s->avctx->width; 00078 line_end = out - stride_adj; 00079 out += base_x - stride; 00080 00082 while(in < in_end){ 00083 unsigned char val = *in++; 00084 int len = 1; 00085 if(val >= 0x80){ 00086 if(in >= in_end) 00087 break; 00088 len = *in++; 00089 if(!len) 00090 break; 00091 } 00092 00093 if(len >= out_end - out) 00094 break; 00095 00096 if(s->back_frame) 00097 val |= 0x80; 00098 else 00099 val &= ~0x80; 00100 00101 while(len--){ 00102 *out++ = (val == 0x80)? *back_frame:val; 00103 back_frame++; 00104 if(out == line_end){ 00105 out += stride_adj; 00106 line_end += stride; 00107 if(len >= out_end - out) 00108 break; 00109 } 00110 } 00111 } 00112 00114 if(s->back_frame){ 00115 while(out < out_end){ 00116 memcpy(out, back_frame, line_end - out); 00117 back_frame += line_end - out; 00118 out = line_end + stride_adj; 00119 line_end += stride; 00120 } 00121 } 00122 } 00123 00124 00130 static av_cold int rl2_decode_init(AVCodecContext *avctx) 00131 { 00132 Rl2Context *s = avctx->priv_data; 00133 int back_size; 00134 int i; 00135 s->avctx = avctx; 00136 avctx->pix_fmt = PIX_FMT_PAL8; 00137 00139 if(!avctx->extradata || avctx->extradata_size < EXTRADATA1_SIZE){ 00140 av_log(avctx, AV_LOG_ERROR, "invalid extradata size\n"); 00141 return -1; 00142 } 00143 00145 s->video_base = AV_RL16(&avctx->extradata[0]); 00146 s->clr_count = AV_RL32(&avctx->extradata[2]); 00147 00148 if(s->video_base >= avctx->width * avctx->height){ 00149 av_log(avctx, AV_LOG_ERROR, "invalid video_base\n"); 00150 return -1; 00151 } 00152 00154 for(i=0;i<AVPALETTE_COUNT;i++) 00155 s->palette[i] = AV_RB24(&avctx->extradata[6 + i * 3]); 00156 00158 back_size = avctx->extradata_size - EXTRADATA1_SIZE; 00159 00160 if(back_size > 0){ 00161 unsigned char* back_frame = av_mallocz(avctx->width*avctx->height); 00162 if(!back_frame) 00163 return -1; 00164 rl2_rle_decode(s,avctx->extradata + EXTRADATA1_SIZE,back_size, 00165 back_frame,avctx->width,0); 00166 s->back_frame = back_frame; 00167 } 00168 return 0; 00169 } 00170 00171 00172 static int rl2_decode_frame(AVCodecContext *avctx, 00173 void *data, int *data_size, 00174 AVPacket *avpkt) 00175 { 00176 const uint8_t *buf = avpkt->data; 00177 int buf_size = avpkt->size; 00178 Rl2Context *s = avctx->priv_data; 00179 00180 if(s->frame.data[0]) 00181 avctx->release_buffer(avctx, &s->frame); 00182 00184 s->frame.reference= 0; 00185 if(avctx->get_buffer(avctx, &s->frame)) { 00186 av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 00187 return -1; 00188 } 00189 00191 rl2_rle_decode(s,buf,buf_size,s->frame.data[0],s->frame.linesize[0],s->video_base); 00192 00194 memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); 00195 00196 *data_size = sizeof(AVFrame); 00197 *(AVFrame*)data = s->frame; 00198 00200 return buf_size; 00201 } 00202 00203 00209 static av_cold int rl2_decode_end(AVCodecContext *avctx) 00210 { 00211 Rl2Context *s = avctx->priv_data; 00212 00213 if(s->frame.data[0]) 00214 avctx->release_buffer(avctx, &s->frame); 00215 00216 av_free(s->back_frame); 00217 00218 return 0; 00219 } 00220 00221 00222 AVCodec ff_rl2_decoder = { 00223 "rl2", 00224 AVMEDIA_TYPE_VIDEO, 00225 CODEC_ID_RL2, 00226 sizeof(Rl2Context), 00227 rl2_decode_init, 00228 NULL, 00229 rl2_decode_end, 00230 rl2_decode_frame, 00231 CODEC_CAP_DR1, 00232 .long_name = NULL_IF_CONFIG_SMALL("RL2 video"), 00233 }; 00234