The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
Porting to SDL2 - V4L2 Buffer Problem
IshtarUK


Joined: 06 May 2016
Posts: 8
Dear All

I am in the process of learning SDL and Video4Linux. My webcam is outputting a YUYV stream and I have successfully had a working prototype with SDL1. However, I am now trying to port to SDL2 but am having problems because SDL_CreateYUVOverlay does not exist. I have researched this and found that I can use SDL_UpdateTexture but my program is segfaulting.

For reference purposes, here is a snippet of the appropriate parts of my working SDL1 program. All unnecessary code, for example error handling has been removed to make the snippet as small as possible. The code following this snippet is my poor attempt at porting my program to SDL2.

I would really appreciate it if somebody could help me with this little porting problem.

Many thanks
Amanda


Code:


screen = SDL_SetVideoMode(width, height, 0, SDL_ANYFORMAT | SDL_DOUBLEBUF | SDL_RESIZABLE);

SDL_WM_SetCaption(title, NULL);

data = SDL_CreateYUVOverlay(width, height, SDL_YUY2_OVERLAY, screen);

rect.x = 0;
rect.y = 0;
rect.w = (Uint16) width;
rect.h = (Uint16) height;

SDL_Event event;

int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

while (true)
{
    SDL_LockYUVOverlay(data);

    // **********************************************************
    // READ DATA FROM THE CAMERA
    // ************************************************************

    struct v4l2_buffer buf;

    memset(&buf, 0, sizeof (buf));

    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;

    if (ioctl(cam_device, VIDIOC_DQBUF, &buf) < 0)
    {
        // ERROR HANDLING
    }

    memcpy(buffer, device.buffers[buf.index].start, device.buffers[buf.index].length);

    if (ioctl(cam_device, VIDIOC_QBUF, &buf) < 0)
    {
        // ERROR HANDLING
    }

    // **********************************************************
    //  END OF CAMERA READ
    // ************************************************************

    SDL_UnlockYUVOverlay(data);
    SDL_DisplayYUVOverlay(data, &rect);

    // EVENT LOOP
    while (SDL_PollEvent(&event) != 0)
    {
        if (event.type == SDL_QUIT)
        {
            // Deactivate Streaming and Return
        }
    }
}




Now, here is my poor attempt at porting the above to SDL2. This concept compiles fine but segfaults at the memcpy() line. I would really appreciate it if somebody could help me with this little porting problem.


Code:


SDL_Init(SDL_INIT_VIDEO)


SDL_Window *sdl_window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_RESIZABLE);


// *****************************************************
// Create an SDL Renderer, attach to an SDL WINDOW
// and Error Check
// *****************************************************
renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_ACCELERATED);


// Create a Texture  with YUY2 and assign to the renderer
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YUY2, SDL_TEXTUREACCESS_TARGET, width, height);


SDL_Event event;

int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

// BUFFER FOR V4L2
void * buffer;

while (true)
{

    // ************************************************************
    // GET FRAME FROM THE CAMERA
    // ************************************************************

    struct v4l2_buffer buf;

    memset(&buf, 0, sizeof (buf));

    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;

    if (ioctl(cam_device, VIDIOC_DQBUF, &buf) < 0)
    {
       // ERROR HANDLING
    }

    memcpy(buffer, device.buffers[buf.index].start, device.buffers[buf.index].length);

    SDL_UpdateTexture(texture, NULL, buffer, 640 * 3);


    if (ioctl(cam_device, VIDIOC_QBUF, &buf) < 0)
    {
        // ERROR HANDLING
    }


    // ************************************************************
    // DISPLAY THE TEXTURE ON THE RENDERER
    // ************************************************************
    SDL_RenderClear(renderer);
    SDL_RenderCopy(renderer, texture, NULL, NULL);
    SDL_RenderPresent(renderer);

    // EVENT LOOP
    while (SDL_PollEvent(&event) != 0)
    {
        if (event.type == SDL_QUIT)
        {
            // RETURN TO THE CALLER
        }
    }
}


IshtarUK


Joined: 06 May 2016
Posts: 8
*** UPDATE ***

I seem to have this working now. The reason I was getting a segfault was due to not allocating my void * buffer. I added the following line and suddenly it worked.

Code:

    void * buffer;
     
    buffer = ( void* ) malloc( width * height * 3); // Added this line to stop the segfault.


However, this has given rise to another question. I am using SD_UpdateTexture() but I don't really understand the pitch parameter. My texture is using YUY2 so I would have thought that my pitch parameter should be width * colour depth which does not work. After playing around I found that the following works but don't understand why.

Code:

 SDL_UpdateTexture(texture, NULL, buffer, width + width);


Can anybody shed any light on the pitch parameter?

Kind Regards
Amanda