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);
}