00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032
00033 #include "libavutil/intreadwrite.h"
00034 #include "avcodec.h"
00035
00036
00037 #define EXTRADATA1_SIZE (6 + 256 * 3)
00038
00039 typedef struct Rl2Context {
00040 AVCodecContext *avctx;
00041 AVFrame frame;
00042
00043 unsigned short video_base;
00044 unsigned int clr_count;
00045 unsigned char* back_frame;
00046 unsigned int palette[AVPALETTE_COUNT];
00047 } Rl2Context;
00048
00058 static void rl2_rle_decode(Rl2Context *s,const unsigned char* in,int size,
00059 unsigned char* out,int stride,int video_base){
00060 int base_x = video_base % s->avctx->width;
00061 int base_y = video_base / s->avctx->width;
00062 int stride_adj = stride - s->avctx->width;
00063 int i;
00064 const unsigned char* back_frame = s->back_frame;
00065 const unsigned char* in_end = in + size;
00066 const unsigned char* out_end = out + stride * s->avctx->height;
00067 unsigned char* line_end = out + s->avctx->width;
00068
00070 for(i=0;i<=base_y;i++){
00071 if(s->back_frame)
00072 memcpy(out,back_frame,s->avctx->width);
00073 out += stride;
00074 back_frame += s->avctx->width;
00075 }
00076 back_frame += base_x - s->avctx->width;
00077 line_end = out - stride_adj;
00078 out += base_x - stride;
00079
00081 while(in < in_end){
00082 unsigned char val = *in++;
00083 int len = 1;
00084 if(val >= 0x80){
00085 if(in >= in_end)
00086 break;
00087 len = *in++;
00088 if(!len)
00089 break;
00090 }
00091
00092 if(len >= out_end - out)
00093 break;
00094
00095 if(s->back_frame)
00096 val |= 0x80;
00097 else
00098 val &= ~0x80;
00099
00100 while(len--){
00101 *out++ = (val == 0x80)? *back_frame:val;
00102 back_frame++;
00103 if(out == line_end){
00104 out += stride_adj;
00105 line_end += stride;
00106 if(len >= out_end - out)
00107 break;
00108 }
00109 }
00110 }
00111
00113 if(s->back_frame){
00114 while(out < out_end){
00115 memcpy(out, back_frame, line_end - out);
00116 back_frame += line_end - out;
00117 out = line_end + stride_adj;
00118 line_end += stride;
00119 }
00120 }
00121 }
00122
00123
00129 static av_cold int rl2_decode_init(AVCodecContext *avctx)
00130 {
00131 Rl2Context *s = avctx->priv_data;
00132 int back_size;
00133 int i;
00134 s->avctx = avctx;
00135 avctx->pix_fmt = PIX_FMT_PAL8;
00136 avcodec_get_frame_defaults(&s->frame);
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] = 0xFF << 24 | 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 .name = "rl2",
00224 .type = AVMEDIA_TYPE_VIDEO,
00225 .id = CODEC_ID_RL2,
00226 .priv_data_size = sizeof(Rl2Context),
00227 .init = rl2_decode_init,
00228 .close = rl2_decode_end,
00229 .decode = rl2_decode_frame,
00230 .capabilities = CODEC_CAP_DR1,
00231 .long_name = NULL_IF_CONFIG_SMALL("RL2 video"),
00232 };