yoann
2016-11-29 03:17:35 UTC
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
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