[Ffmpeg-devel] libswscale 8 bit decoding

Steven Johnson mplayer
Thu Nov 16 11:03:20 CET 2006


Michael Niedermayer wrote:
> Hi
>
> On Thu, Nov 16, 2006 at 08:32:24AM +1100, Steven Johnson wrote:
> [...]
>   
>> [snip]
>>     
>>> the palette8tobgr (or palette8torgb) are redundant and should be removed
>>> and the pal should be R<->B, actually your code halfway does that but
>>> its totally broken (dont submit untested code!)
>>>  
>>>       
>> Sorry, it wasn't a submission.  I was trying to see if I was on the 
>> right track and it is difficult to do that without showing the code I am 
>> working on.  I apologise for not making that clear in my original post. 
>>
>> How did you exercise this code?  The reason I haven't tested it is I 
>> haven't come up with a way to get the code path to execute.
>>     
>
> hmm, maybe mplayer -vf scale with some -vf format and a paletted codec
> will help
>   
I will look into that next. thx.
>
> [...]
>   
>>> also the downscaling of chroma is wrong (discarding 3/4 of the samples is
>>> not ok)
>>>  
>>>       
>> The code is exactly the same as the C code in rgb24toyv12, with the 
>> exception of palette expansion.  I noticed the image quality was 
>> significantly reduced using libswscale over imgresample, and mentioned 
>> that in my original post, that is the probably cause.  Any pointers to a 
>> reference for converting RGB to YV12 I can look at?
>>     
>
> a simple variant is to average the 4 rgb values before rgb->yuv (or
> do rgb->yuv on them and then average the 4 u and 4 v, the result is the
> same) (note this is not entirely correct but its ok while the current
> code in rgb24toyv12 and your code is not)
> btw see bgr32ToUV and the similar functions in libswscale/swscale_template.c
> they also still use hardcoded rgb2yuv coeffs but except that they look
> more sane
>   
Is this what you are after? : (not a patch, just don't apply and test, I 
am just showing you what I have interpreted you to be saying)

static inline void RENAME(pal8toyv12)(const uint8_t *src, const uint8_t 
*pal, uint8_t *ydst, uint8_t *udst, uint8_t *vdst,
    long width, long height,
    long lumStride, long chromStride, long srcStride)
{
    long y;
    const long chromWidth= width>>1;
    const int max_palette_entries = 256;
    const int blue_offset  = 0;
        const int green_offset = 1;
    const int red_offset   = 2;
    const int palette_entry_size = 4;
    const int palette_size       = max_palette_entries * palette_entry_size;

    unsigned int b,g,r, idx0, idx1, idx2, idx3;
    long i;

    unsigned char Ypal[max_palette_entries],
              Upal[max_palette_entries],
              Vpal[max_palette_entries];

#ifdef HAVE_MMX
/* NO MMX Optimised version (YET) */
#else
#endif
    /* Convert Palette to YUV */
    for (i = 0; i < palette_size; i++)
    {
        b= pal[(i*palette_entry_size)+blue_offset];
        g= pal[(i*palette_entry_size)+red_offset];
        r= pal[(i*palette_entry_size)+green_offset];

        Ypal[i]  =  ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
        Upal[i]  =  ((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128;
        Vpal[i]  =  ((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128;
    }
   
    for(y=0; y<height; y+=2)
    {
        for(i=0; i<chromWidth; i++)
        {
            /* Pixel Indexes */
            idx0 = src[2*i];
            idx1 = src[2*i+1];
            idx2 = src[2*i+srcStride];
            idx3 = src[2*i+srcStride+1];

            /* 4 Luma Samples */
            ydst[2*i]        = Ypal[idx0];
            ydst[2*i+1]        = Ypal[idx1];
            ydst[2*i+lumStride]    = Ypal[idx2];
            ydst[2*i+lumStride+1]    = Ypal[idx3];

            udst[i] = ((Upal[idx0]+Upal[idx1]+Upal[idx2]+Upal[idx3]) >> 2);
            udst[i] = ((Vpal[idx0]+Vpal[idx1]+Vpal[idx2]+Vpal[idx3]) >> 2);
        }
        ydst += (lumStride * 2);
        src  += (srcStride * 2);
        udst += chromStride;
        vdst += chromStride;
    }
}

I have tested, and it does seem to work.

>
>   
>> And following the thread "moving non-SIMD parts of libswscale to LGPL" I 
>> am confused about libswscale, imgresample and the future.  As it stands, 
>> imgresample does more than libswscale does (it handles palletised 
>> formats), and (at least for me) produces a nicer result, but it seems is 
>> probably slower in certain cases where the functionality overlaps.  But 
>> is imgresample deprecated in favour of libswscale? 
>>     
>
> yes
>   
I get a visible quality decrease using libswscale over imgresample.  
That is concerning me some what. See: 
ftp://ftp.sakuraindustries.com/pub/Screenshot.png

The Image on the Left is ffmpeg WITH libswscale, the image on the right 
is the same file, played with ffmpeg using the imgresample code.  There 
is noticeable blockiness in the image over the same picture on the 
right.  The image is very low resolution 80x48 pixels, so is somewhat 
blocky to begin with, but adding more blockiness results in very poor 
image quality for this image.  This is an 8bpp source image.  How do I 
go about getting a quality of display using libswscale equal to 
imgresample, I must be doing something wrong, but I can't see what? 

Steven J





More information about the ffmpeg-devel mailing list