• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/rl2.c

Go to the documentation of this file.
00001 /*
00002  * RL2 Video Decoder
00003  * Copyright (C) 2008 Sascha Sommer (saschasommer@freenet.de)
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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 #include <unistd.h>
00034 
00035 #include "libavutil/intreadwrite.h"
00036 #include "avcodec.h"
00037 
00038 
00039 #define EXTRADATA1_SIZE (6 + 256 * 3) ///< video base, clr count, palette
00040 
00041 typedef struct Rl2Context {
00042     AVCodecContext *avctx;
00043     AVFrame frame;
00044 
00045     unsigned short video_base; 
00046     unsigned int clr_count;    
00047     unsigned char* back_frame; 
00048     unsigned int palette[AVPALETTE_COUNT];
00049 } Rl2Context;
00050 
00060 static void rl2_rle_decode(Rl2Context *s,const unsigned char* in,int size,
00061                                unsigned char* out,int stride,int video_base){
00062     int base_x = video_base % s->avctx->width;
00063     int base_y = video_base / s->avctx->width;
00064     int stride_adj = stride - s->avctx->width;
00065     int i;
00066     const unsigned char* back_frame = s->back_frame;
00067     const unsigned char* in_end = in + size;
00068     const unsigned char* out_end = out + stride * s->avctx->height;
00069     unsigned char* line_end = out + s->avctx->width;
00070 
00072     for(i=0;i<=base_y;i++){
00073         if(s->back_frame)
00074             memcpy(out,back_frame,s->avctx->width);
00075         out += stride;
00076         back_frame += s->avctx->width;
00077     }
00078     back_frame += base_x - s->avctx->width;
00079     line_end = out - stride_adj;
00080     out += base_x - stride;
00081 
00083     while(in < in_end){
00084         unsigned char val = *in++;
00085         int len = 1;
00086         if(val >= 0x80){
00087             if(in >= in_end)
00088                 break;
00089             len = *in++;
00090             if(!len)
00091                 break;
00092         }
00093 
00094         if(len >= out_end - out)
00095             break;
00096 
00097         if(s->back_frame)
00098             val |= 0x80;
00099         else
00100             val &= ~0x80;
00101 
00102         while(len--){
00103             *out++ = (val == 0x80)? *back_frame:val;
00104             back_frame++;
00105             if(out == line_end){
00106                  out += stride_adj;
00107                  line_end += stride;
00108                  if(len >= out_end - out)
00109                      break;
00110             }
00111         }
00112     }
00113 
00115     if(s->back_frame){
00116         while(out < out_end){
00117             memcpy(out, back_frame, line_end - out);
00118             back_frame += line_end - out;
00119             out = line_end + stride_adj;
00120             line_end += stride;
00121         }
00122     }
00123 }
00124 
00125 
00131 static av_cold int rl2_decode_init(AVCodecContext *avctx)
00132 {
00133     Rl2Context *s = avctx->priv_data;
00134     int back_size;
00135     int i;
00136     s->avctx = avctx;
00137     avctx->pix_fmt = PIX_FMT_PAL8;
00138 
00140     if(!avctx->extradata || avctx->extradata_size < EXTRADATA1_SIZE){
00141         av_log(avctx, AV_LOG_ERROR, "invalid extradata size\n");
00142         return -1;
00143     }
00144 
00146     s->video_base = AV_RL16(&avctx->extradata[0]);
00147     s->clr_count = AV_RL32(&avctx->extradata[2]);
00148 
00149     if(s->video_base >= avctx->width * avctx->height){
00150         av_log(avctx, AV_LOG_ERROR, "invalid video_base\n");
00151         return -1;
00152     }
00153 
00155     for(i=0;i<AVPALETTE_COUNT;i++)
00156         s->palette[i] = AV_RB24(&avctx->extradata[6 + i * 3]);
00157 
00159     back_size = avctx->extradata_size - EXTRADATA1_SIZE;
00160 
00161     if(back_size > 0){
00162         unsigned char* back_frame = av_mallocz(avctx->width*avctx->height);
00163         if(!back_frame)
00164             return -1;
00165         rl2_rle_decode(s,avctx->extradata + EXTRADATA1_SIZE,back_size,
00166                            back_frame,avctx->width,0);
00167         s->back_frame = back_frame;
00168     }
00169     return 0;
00170 }
00171 
00172 
00182 static int rl2_decode_frame(AVCodecContext *avctx,
00183                               void *data, int *data_size,
00184                               const uint8_t *buf, int buf_size)
00185 {
00186     Rl2Context *s = avctx->priv_data;
00187 
00188     if(s->frame.data[0])
00189         avctx->release_buffer(avctx, &s->frame);
00190 
00192     s->frame.reference= 0;
00193     if(avctx->get_buffer(avctx, &s->frame)) {
00194         av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00195         return -1;
00196     }
00197 
00199     rl2_rle_decode(s,buf,buf_size,s->frame.data[0],s->frame.linesize[0],s->video_base);
00200 
00202     memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
00203 
00204     *data_size = sizeof(AVFrame);
00205     *(AVFrame*)data = s->frame;
00206 
00208     return buf_size;
00209 }
00210 
00211 
00217 static av_cold int rl2_decode_end(AVCodecContext *avctx)
00218 {
00219     Rl2Context *s = avctx->priv_data;
00220 
00221     if(s->frame.data[0])
00222         avctx->release_buffer(avctx, &s->frame);
00223 
00224     av_free(s->back_frame);
00225 
00226     return 0;
00227 }
00228 
00229 
00230 AVCodec rl2_decoder = {
00231     "rl2",
00232     CODEC_TYPE_VIDEO,
00233     CODEC_ID_RL2,
00234     sizeof(Rl2Context),
00235     rl2_decode_init,
00236     NULL,
00237     rl2_decode_end,
00238     rl2_decode_frame,
00239     CODEC_CAP_DR1,
00240     .long_name = NULL_IF_CONFIG_SMALL("RL2 video"),
00241 };
00242 

Generated on Sat Feb 16 2013 09:23:13 for ffmpeg by  doxygen 1.7.1