[FFmpeg-devel] [PATCH] Rl2 Video decoder
Michael Niedermayer
michaelni
Fri Mar 21 00:14:50 CET 2008
On Thu, Mar 20, 2008 at 07:45:21PM +0100, Sascha Sommer wrote:
> Hi,
>
> > This still contains several redundant checks
> > A (unlikely) buffer overflow
> > A redundant variable
> >
> > if(out == line_end){
> > out += row_inc;
> > line_end += stride;
> > }
> > avoids the ++
> >
>
> Changed the code a bit. Some other changes were also needed because one sample
> did not decode properly.
>
> >
> > > + uint8_t* back_frame = av_mallocz(avctx->width*avctx->height);
> > > + if(!back_frame)
> > > + return -1;
> > > + rl2_rle_decode(s,avctx->extradata + EXTRADATA1_SIZE,back_size,
> > > + back_frame,avctx->width);
> > > + s->back_frame = back_frame;
> >
> > the back_frame variable isnt really needed
> >
> > [...]
>
> Why? Just removing it here won't work because in case of decoding a video with
> back_frame the back_frame itself has to be decoded without backframe.
> Of course one could solve this differently if this is what you meant?
hmm no, forget what i said.
[...]
> +typedef struct Rl2Context {
> + AVCodecContext *avctx;
> + AVFrame frame;
> +
> + unsigned short video_base; ///< initial drawing offset
> + int base_x; ///< x in the current line
> + int base_y; ///< how often the stride needs to be incremented
I think they would fit better as local variables of rl2_rle_decode(), after
all there is no other function useing them.
> + unsigned int clr_count; ///< number of used colors (currently unused)
> + unsigned char* back_frame; ///< background frame
> + unsigned int palette[AVPALETTE_COUNT];
> +} Rl2Context;
> +
> +/**
> + * Run Length Decode a single 320x200 frame
> + * @param s rl2 context
> + * @param buf input buffer
> + * @param size input buffer size
> + * @param out ouput buffer
> + * @param stride stride of the output buffer
> + * @param ignore_base ignore video_base
> + */
> +static void rl2_rle_decode(Rl2Context *s,const unsigned char* in,int size,
> + unsigned char* out,int stride,int ignore_base){
Instead of passing ignore_base you could pass base itself and set it to 0
for the ignore case.
> + int stride_adj = stride - s->avctx->width;
> + const unsigned char* back_frame = s->back_frame;
> + const unsigned char* in_end = in + size;
> + const unsigned char* out_end = out + stride * s->avctx->height;
> + unsigned char* line_end = out + s->avctx->width;
> +
> + /** copy start of the background frame */
> + if(s->back_frame){
> + int i;
> + for(i=0;i<s->base_y;i++){
> + memcpy(out,back_frame,s->avctx->width);
> + out += stride;
> + back_frame += s->avctx->width;
> + }
> + if(s->base_x){
> + memcpy(out, back_frame, s->base_x);
> + back_frame += s->base_x;
> + }
> + line_end = out + s->avctx->width;
> + out += s->base_x;
> + }else if(!ignore_base){
> + line_end = out + s->base_y * stride + s->avctx->width;
> + out += s->video_base + s->base_y * stride_adj;
> + back_frame += s->video_base;
> + }
for(i=0;i<=base_y;i++){
if(s->back_frame)
memcpy(out,back_frame,s->avctx->width);
out += stride;
back_frame += s->avctx->width;
}
back_frame += base_x - s->avctx->width;
line_end = out - stride_adj;
out += base_x - stride;
> +
> + /** decode the variable part of the frame */
> + while(in < in_end){
> + unsigned char val = *in++;
> + int len = 1;
> + if(val >= 0x80){
> + if(in >= in_end)
> + break;
> + len = *in++;
> + if(!len)
> + break;
> + }
> +
> + if(out >= out_end - len)
if(len >= out_end - out)
out_end - len could theoretically overflow
> + break;
> +
> + if(s->back_frame)
> + val |= 0x80;
> + else
> + val &= ~0x80;
> +
> + while(len--){
> + *out++ = (val == 0x80)? *back_frame:val;
> + back_frame++;
> + if(out == line_end){
> + out += stride_adj;
> + line_end += stride;
> + if(out >= out_end - len)
> + break;
> + }
> + }
> + }
> +
> + /** copy the rest from the background frame */
> + if(s->back_frame){
> + while(out < out_end){
> + *out++ = *back_frame++;
> + if(out == line_end){
> + out += stride_adj;
> + line_end += stride;
> + }
following might be faster, but ignore it if its not
memcpy(out, back_frame, line_end - out);
back_frame += line_end - out;
out= line_end + stride_adj;
line_end += stride;
patch looks ok except these
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
In a rich man's house there is no place to spit but his face.
-- Diogenes of Sinope
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080321/68dd6ff7/attachment.pgp>
More information about the ffmpeg-devel
mailing list