Problem with some SDL_Overlay sizes

Hello!
My name is Vassili Akimov, I try to develop some program, which utilize SDL.
I need to create some number of SDL_Overlays ( software overlays ) and
display them on the main surface. I found, that some x sizes, provided to
SDL_CreateYUVOverlay, results “wrong” overlay, which being displayed, shows
only part of the pixels it should.
For example if I try to create the software overlay 23x23 pixels, I get some
overlay, wich shows only part of the pixels, I provide to it. To illustrate
the problem, I made simple program, which creates SDL surface, than creates
RGB surface 23x23 pixels. Than fill rgb surface with vertical rgb stripes one
pixel wide. Than I create 10 overlays 23x23 convert rgb surface data into
yv12 and fill overlay with this data, and display the overlays on main
surface.

As the result, stripes occured to be diagonal, and only part to destination
rectangle is displayed. If I change the overlay size to 22 pixels ( x
-direction ), everything turnes out correct. Can anyone help me with this
situation?

here is my programm:

/* Bring up a window and play with it */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define BENCHMARK_SDL

#define NOTICE(X) printf("%s", X);

#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

#include “SDL/SDL.h”

SDL_Surface *screen, *pic;
SDL_Overlay *overlay;
int scale;
int w, h;

void putpixel(SDL_Surface surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
/
Here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

switch(bpp) {
case 1:
    *p = pixel;
    break;

case 2:
    *(Uint16 *)p = pixel;
    break;

case 3:
    if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
        p[0] = (pixel >> 16) & 0xff;
        p[1] = (pixel >> 8) & 0xff;
        p[2] = pixel & 0xff;
    } else {
        p[0] = pixel & 0xff;
        p[1] = (pixel >> 8) & 0xff;
        p[2] = (pixel >> 16) & 0xff;
    }
    break;

case 4:
    *(Uint32 *)p = pixel;
    break;
}

}

void fillSDL_Surface( SDL_Surface* surface )
{
int w, h;
int xx, yy, pp;
w = surface->w;
h = surface->h;
Uint32 pixels[3];
pixels[ 0 ] = SDL_MapRGB( surface->format, 255, 0, 0 );
pixels[ 1 ] = SDL_MapRGB( surface->format, 0, 255, 0 );
pixels[ 2 ] = SDL_MapRGB( surface->format, 0, 0, 255 );
for( xx = 0, pp=0; xx < w; xx++, pp++ ) {
if( pp > 2 ) pp = 0;
for( yy = 0; yy < h; yy++ ) {
putpixel( surface, xx, yy, pixels[ pp ] );

}

}
}

void RGB_to_YUV( Uint8 rgb, Uint8 yuv )
{
/
printf( “R %d G %d B %d\n”, rgb[0], rgb[1], rgb[2] );
/
yuv[ 0 ] = 0.257 * rgb[ 0 ] + 0.504 * rgb[ 1 ] + 0.098 * rgb[ 2 ] + 16;
yuv[ 1 ] = -0.148 * rgb[ 0 ] - 0.291 * rgb[ 1 ] + 0.439 * rgb[ 2 ] + 128;
yuv[ 2 ] = 0.439 * rgb[ 0 ] - 0.368 * rgb[ 1 ] -0.071 * rgb[ 2 ] + 128;

};

void ConvertRGBtoYUVOverlay( SDL_Surface* source, SDL_Overlay* dest )
{
int x, y;
Uint8 yuv[ 3 ];
Uint8 *pix, *Plane[ 3 ], *UVPlane[ 3 ];

for( y = 0; y < source->h && y < dest->h; y++ ) {
pix = ( (Uint8*) source->pixels ) + source->pitch * y;
Plane[ 0 ] = dest->pixels[ 0 ] + dest->pitches[ 0 ] * y;
Plane[ 1 ] = dest->pixels[ 1 ] + dest->pitches[ 1 ] * y / 2;
Plane[ 2 ] = dest->pixels[ 2 ] + dest->pitches[ 2 ] * y / 2;
for( x = 0; x < source->w && x < dest->w; x++ ) {
RGB_to_YUV( pix, yuv );
*( Plane[ 0 ]++ ) = yuv[ 0 ];
if( x%2 == 0 && y%2 == 0 ) {
*( Plane[ 1 ]++ ) = yuv[ 2 ];
*( Plane[ 2 ]++ ) = yuv[ 1 ];
}
pix += source->format->BytesPerPixel;
}
}
};

int main(int argc, char **argv)
{
char *argv0 = argv[0];
Uint32 overlay_format;
Uint32 rmask, gmask, bmask, amask;
SDL_Surface bmp_surface =0;
int i;
putenv( “SDL_VIDEO_YUV_HWACCEL=0” );
/
Set default options and check command-line */

overlay_format = SDL_YV12_OVERLAY;

if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
	fprintf(stderr,
		"Couldn't initialize SDL: %s\n", SDL_GetError());
	return(1);
}

/* Initialize the display */
screen = SDL_SetVideoMode(316, 310, 0, 0 );
if ( screen == NULL ) {
	fprintf(stderr, "Couldn't set %dx%dx video mode: %s\n",
				w, h, SDL_GetError());
	exit(0);
}

SDL_Rect rc;
rc.x = 30;
rc.y = 30;
rc.w = 23;
rc.h = 23;	

#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif

bmp_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, rc.w, rc.h, 

screen->format->BitsPerPixel, rmask, gmask, bmask, amask);
if( bmp_surface == NULL ) {
fprintf(stderr, “CreateRGBSurface failed: %s\n”, SDL_GetError());
exit(1);
}
fillSDL_Surface( bmp_surface );
int ee = 0;
int cc = 0;
for( ; cc < 3; cc++ ) {
for( ee = 0; ee < 3; ee++ ) {
/* Create the overlay */
overlay = SDL_CreateYUVOverlay( rc.w, rc.h, overlay_format, screen);
if ( overlay == NULL ) {
fprintf(stderr, “Couldn’t create overlay: %s\n”, SDL_GetError());
exit( 0 );
}
ConvertRGBtoYUVOverlay( bmp_surface, overlay );
SDL_DisplayYUVOverlay( overlay, &rc );
rc.x = rc.x + rc.w;
sleep( 1 );
}
rc.y = rc.y + rc.h;
rc.x = 30;
}
return(0);
}

  Hello!

My name is Vassili Akimov, I try to develop some program, which
utilize SDL.
I need to create some number of SDL_Overlays ( software overlays ) and
display them on the main surface. I found, that some x sizes,
provided to
SDL_CreateYUVOverlay, results “wrong” overlay, which being
displayed, shows
only part of the pixels it should.
For example if I try to create the software overlay 23x23 pixels, I
get some
overlay, wich shows only part of the pixels, I provide to it. To
illustrate
the problem, I made simple program, which creates SDL surface, than
creates
RGB surface 23x23 pixels. Than fill rgb surface with vertical rgb
stripes one
pixel wide. Than I create 10 overlays 23x23 convert rgb surface
data into
yv12 and fill overlay with this data, and display the overlays on main
surface.

As the result, stripes occured to be diagonal, and only part to
destination
rectangle is displayed. If I change the overlay size to 22 pixels ( x
-direction ), everything turnes out correct. Can anyone help me
with this
situation?

You can’t have “nice” arbitrary size YV12 overlays because of
subsampling: number of values stored for chroma components is 1/4 of
number of pixels, so you want your overlays have even sizes (e.g.
24x24 or 22x22)

I’m not sure what goes on when you request incompatible sizes, i
would say “behaviour is unspecified” ;-)On 17 Oct 2006, at 14:17, Vassili A akimov wrote:

Thanks, but is there any criteria to find out which size is “wrong”? So I can
correct it before creating the overlay?
This problem looks to my very odd, it appeares, that 23x22 pixels is "wrong"
size and 22x23 is correct one. This problem doesn’t appear if I create the
hardware overlay. Which still YV12 and according to your explanation must be
displayed with “uncpecified behavior”.
I can make workaround and avoid creating “wrong” overlays, if I would have
exact criteria which size is “wrong”. Can you help me with that?> On 17 Oct 2006, at 14:17, Vassili A akimov wrote:

  Hello!
My name is Vassili Akimov, I try to develop some program, which

utilize SDL.
I need to create some number of SDL_Overlays ( software overlays ) and
display them on the main surface. I found, that some x sizes,
provided to
SDL_CreateYUVOverlay, results “wrong” overlay, which being
displayed, shows
only part of the pixels it should.
For example if I try to create the software overlay 23x23 pixels, I
get some
overlay, wich shows only part of the pixels, I provide to it. To
illustrate
the problem, I made simple program, which creates SDL surface, than
creates
RGB surface 23x23 pixels. Than fill rgb surface with vertical rgb
stripes one
pixel wide. Than I create 10 overlays 23x23 convert rgb surface
data into
yv12 and fill overlay with this data, and display the overlays on main
surface.

As the result, stripes occured to be diagonal, and only part to
destination
rectangle is displayed. If I change the overlay size to 22 pixels ( x
-direction ), everything turnes out correct. Can anyone help me
with this
situation?

You can’t have “nice” arbitrary size YV12 overlays because of
subsampling: number of values stored for chroma components is 1/4 of
number of pixels, so you want your overlays have even sizes (e.g.
24x24 or 22x22)

I’m not sure what goes on when you request incompatible sizes, i
would say “behaviour is unspecified” :wink: