Discussion:
[SDL] Using Renderer Accelerated on Android ?
yoann
2016-11-29 03:17:35 UTC
Permalink
Hi everyone,

I am working on a Android video player using SDL and FFmpeg, but I have an issue using the SDL_RENDERER_ACCELERATED context.

My native main thread creates a window and a renderer, and then I use other threads to do the demuxing and decoding process. After decoding my frames, I store them in a YV12 Texture in a secondary thread, and then call the renderer in the native main thread to display the picture.

If I do that using the SDL_RENDERER_ACCELERATED flag when creating the renderer, my screen only displays a blank green image, but everything is fine when I use the SDL_RENDERER_SOFTWARE context : and I can see my decoded pictures. I have no error thought, and my logs show me that the decoding process is working all right.

I am aware that I should not do any of the rendering process outside the main thread, but what about the accessing the textures ? I also have troubles to understand how changing the rendering context might change the behavior of my textures / renderer.

This issue does not happens running the same code on Linux, so this is probably a platform-related issue. I also noticed than using the SDL_RENDERER_ACCELERATED flag solves other issues I have on recreating the renderer context on onPause / onResume events on Android using SDL_RENDERER_SOFTWARE.


Here are parts of the code (with error checking removed):

========== Main thread ==========

SDL_Window *window;
SDL_Renderer *renderer;

=== renderer creation ===
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER);

window = SDL_CreateWindow("MMLib player",SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,800,480,SDL_WINDOW_RESIZABLE);


renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

=== texture allocation ===
// Getting a pointer to the structure storing my texture
vp = picture_queue_put(&vs->picture_queue);

// if already existing texture (for scaling), need to free the previous
if(vp->texture){
SDL_DestroyTexture(vp->texture);
}

vp->texture = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STATIC,
vs->video_stream->codecpar->width,
vs->video_stream->codecpar->height);

=== Picture Display ===
// Getting a pointer to the structure storing my texture
vp = picture_queue_get(&vs->picture_queue);

if(vp){
if(vp->texture){

SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, vp->texture, NULL, NULL);
SDL_RenderPresent(renderer);

}
}


========== Another Thread =========
// ... Decoding stuff giving me a raw ffmpeg frame ...

// Getting a pointer to the structure storing my texture
vp = picture_queue_put(&vs->picture_queue);

// Allocate space for the buffer if it was not done or if the picture needs
// to be resized
if(!vp->texture ||
vp->width != vs->video_stream->codecpar->width ||
vp->height != vs->video_stream->codecpar->height){

vp->allocated = 0;
// The allocation is done in the main thread (see code above)
SDL_Event event;
event.type = FF_ALLOC_EVENT;
event.user.data1 = vs;
SDL_PushEvent(&event);

// wait until the picture is allocated
SDL_LockMutex(vs->picture_queue.mutex);
while (!vp->allocated && !vs->quit && !vs->stop) {
SDL_CondWait(vs->picture_queue.cond,
vs->picture_queue.mutex);
}
SDL_UnlockMutex(vs->picture_queue.mutex);

}

// We update the texture with our data
if(vp->texture){
if(SDL_UpdateYUVTexture(vp->texture, NULL,
frame->data[0],frame->linesize[0],
frame->data[1],frame->linesize[1],
frame->data[2],frame->linesize[2]) < 0){
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "In queue_picture : %s \n",SDL_GetError());
return -1;
}

Any help would be greatly appreciated !
Yoann
Alex Szpakowski
2016-11-29 03:19:59 UTC
Permalink
SDL_Render functionality (including SDL_Texture functionality) can only be used on the main thread.
Post by yoann
My native main thread creates a window and a renderer, and then I use other threads to do the demuxing and decoding process. After decoding my frames, I store them in a YV12 Texture in a secondary thread, and then call the renderer in the native main thread to display the picture.
yoann
2016-11-29 05:19:28 UTC
Permalink
Ok I modified parts of my code to make the texture updating in the main thread and it works like a charm, thanks a lot !

So it was only luck that make it work with the SDL_RENDERER_SOFTWARE flag ?
-----Origin email-----
Sent Time: Nov 29, 2016 11:19:59 AM
Subject: Re: [SDL] Using Renderer Accelerated on Android ?
SDL_Render functionality (including SDL_Texture functionality) can only be used on the main thread.
Post by yoann
My native main thread creates a window and a renderer, and then I use other threads to do the demuxing and decoding process. After decoding my frames, I store them in a YV12 Texture in a secondary thread, and then call the renderer in the native main thread to display the picture.
_______________________________________________
SDL mailing list
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Mason Wheeler
2016-12-04 16:52:21 UTC
Permalink
OpenGL contexts have thread affinity: the objects they create (including textures) only work in the thread it was created in. The software renderer doesn&#39;t have this same limitation.
Loading...