update SDL3 to latest commit

This commit is contained in:
Sasha Szpakowski
2024-10-06 20:30:44 -03:00
parent 1b0fdc338b
commit 9e5eb1b018
1426 changed files with 242456 additions and 103496 deletions
+233 -229
View File
@@ -14,9 +14,6 @@
* For a more complete video example, see ffplay.c in the ffmpeg sources.
*/
#include <stdlib.h>
#include <time.h>
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <SDL3/SDL_test.h>
@@ -29,9 +26,9 @@
#include <libswscale/swscale.h>
#ifdef HAVE_EGL
#include <SDL3/SDL_egl.h>
#include <SDL3/SDL_opengl.h>
#include <SDL3/SDL_opengles2.h>
#include <SDL3/SDL_egl.h>
#include <libavutil/hwcontext_drm.h>
@@ -46,20 +43,20 @@
#endif
#endif
#define DRM_FORMAT_MOD_VENDOR_NONE 0
#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1)
#define DRM_FORMAT_MOD_VENDOR_NONE 0
#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1)
#define fourcc_mod_get_vendor(modifier) \
(((modifier) >> 56) & 0xff)
(((modifier) >> 56) & 0xff)
#define fourcc_mod_is_vendor(modifier, vendor) \
(fourcc_mod_get_vendor(modifier) == DRM_FORMAT_MOD_VENDOR_## vendor)
(fourcc_mod_get_vendor(modifier) == DRM_FORMAT_MOD_VENDOR_##vendor)
#define fourcc_mod_code(vendor, val) \
((((Uint64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | ((val) & 0x00ffffffffffffffULL))
((((Uint64)DRM_FORMAT_MOD_VENDOR_##vendor) << 56) | ((val) & 0x00ffffffffffffffULL))
#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
#define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0)
#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
#define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0)
#ifdef SDL_PLATFORM_APPLE
#include <CoreVideo/CoreVideo.h>
@@ -74,7 +71,6 @@
#include "icon.h"
static SDL_Texture *sprite;
static SDL_FRect *positions;
static SDL_FRect *velocities;
@@ -86,11 +82,11 @@ static SDL_Renderer *renderer;
static SDL_AudioStream *audio;
static SDL_Texture *video_texture;
static Uint64 video_start;
static SDL_bool software_only;
static SDL_bool has_eglCreateImage;
static bool software_only;
static bool has_eglCreateImage;
#ifdef HAVE_EGL
static SDL_bool has_EGL_EXT_image_dma_buf_import;
static SDL_bool has_EGL_EXT_image_dma_buf_import_modifiers;
static bool has_EGL_EXT_image_dma_buf_import;
static bool has_EGL_EXT_image_dma_buf_import_modifiers;
static PFNGLACTIVETEXTUREARBPROC glActiveTextureARBFunc;
static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOESFunc;
#endif
@@ -106,15 +102,14 @@ struct SwsContextContainer
};
static const char *SWS_CONTEXT_CONTAINER_PROPERTY = "SWS_CONTEXT_CONTAINER";
static int done;
static SDL_bool verbose;
static bool verbose;
static SDL_bool CreateWindowAndRenderer(SDL_WindowFlags window_flags, const char *driver)
static bool CreateWindowAndRenderer(SDL_WindowFlags window_flags, const char *driver)
{
SDL_PropertiesID props;
SDL_RendererInfo info;
SDL_bool useOpenGL = (driver && (SDL_strcmp(driver, "opengl") == 0 || SDL_strcmp(driver, "opengles2") == 0));
SDL_bool useEGL = (driver && SDL_strcmp(driver, "opengles2") == 0);
SDL_bool useVulkan = (driver && SDL_strcmp(driver, "vulkan") == 0);
bool useOpenGL = (driver && (SDL_strcmp(driver, "opengl") == 0 || SDL_strcmp(driver, "opengles2") == 0));
bool useEGL = (driver && SDL_strcmp(driver, "opengles2") == 0);
bool useVulkan = (driver && SDL_strcmp(driver, "vulkan") == 0);
Uint32 flags = SDL_WINDOW_HIDDEN;
if (useOpenGL) {
@@ -142,7 +137,7 @@ static SDL_bool CreateWindowAndRenderer(SDL_WindowFlags window_flags, const char
/* The window will be resized to the video size when it's loaded, in OpenVideoStream() */
window = SDL_CreateWindow("testffmpeg", 1920, 1080, flags);
if (!window) {
return SDL_FALSE;
return false;
}
if (useVulkan) {
@@ -150,17 +145,17 @@ static SDL_bool CreateWindowAndRenderer(SDL_WindowFlags window_flags, const char
if (!vulkan_context) {
SDL_DestroyWindow(window);
window = NULL;
return SDL_FALSE;
return false;
}
}
props = SDL_CreateProperties();
SDL_SetStringProperty(props, SDL_PROP_RENDERER_CREATE_NAME_STRING, driver);
SDL_SetProperty(props, SDL_PROP_RENDERER_CREATE_WINDOW_POINTER, window);
SDL_SetPointerProperty(props, SDL_PROP_RENDERER_CREATE_WINDOW_POINTER, window);
if (useVulkan) {
SetupVulkanRenderProperties(vulkan_context, props);
}
if (SDL_GetBooleanProperty(SDL_GetDisplayProperties(SDL_GetDisplayForWindow(window)), SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN, SDL_FALSE)) {
if (SDL_GetBooleanProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_HDR_ENABLED_BOOLEAN, false)) {
/* Try to create an HDR capable renderer */
SDL_SetNumberProperty(props, SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER, SDL_COLORSPACE_SRGB_LINEAR);
renderer = SDL_CreateRendererWithProperties(props);
@@ -174,36 +169,34 @@ static SDL_bool CreateWindowAndRenderer(SDL_WindowFlags window_flags, const char
if (!renderer) {
SDL_DestroyWindow(window);
window = NULL;
return SDL_FALSE;
return false;
}
if (SDL_GetRendererInfo(renderer, &info) == 0) {
SDL_Log("Created renderer %s\n", info.name);
}
SDL_Log("Created renderer %s\n", SDL_GetRendererName(renderer));
#ifdef HAVE_EGL
if (useEGL) {
const char *egl_extensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS);
if (!egl_extensions) {
return SDL_FALSE;
return false;
}
char *extensions = SDL_strdup(egl_extensions);
if (!extensions) {
return SDL_FALSE;
return false;
}
char *saveptr, *token;
token = SDL_strtok_r(extensions, " ", &saveptr);
if (!token) {
SDL_free(extensions);
return SDL_FALSE;
return false;
}
do {
if (SDL_strcmp(token, "EGL_EXT_image_dma_buf_import") == 0) {
has_EGL_EXT_image_dma_buf_import = SDL_TRUE;
has_EGL_EXT_image_dma_buf_import = true;
} else if (SDL_strcmp(token, "EGL_EXT_image_dma_buf_import_modifiers") == 0) {
has_EGL_EXT_image_dma_buf_import_modifiers = SDL_TRUE;
has_EGL_EXT_image_dma_buf_import_modifiers = true;
}
} while ((token = SDL_strtok_r(NULL, " ", &saveptr)) != NULL);
@@ -218,31 +211,32 @@ static SDL_bool CreateWindowAndRenderer(SDL_WindowFlags window_flags, const char
if (has_EGL_EXT_image_dma_buf_import &&
glEGLImageTargetTexture2DOESFunc &&
glActiveTextureARBFunc) {
has_eglCreateImage = SDL_TRUE;
has_eglCreateImage = true;
}
}
#endif /* HAVE_EGL */
#ifdef SDL_PLATFORM_WIN32
d3d11_device = (ID3D11Device *)SDL_GetProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_D3D11_DEVICE_POINTER, NULL);
d3d11_device = (ID3D11Device *)SDL_GetPointerProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_D3D11_DEVICE_POINTER, NULL);
if (d3d11_device) {
ID3D11Device_AddRef(d3d11_device);
ID3D11Device_GetImmediateContext(d3d11_device, &d3d11_context);
}
#endif
return SDL_TRUE;
return true;
}
static SDL_Texture *CreateTexture(SDL_Renderer *r, unsigned char *data, unsigned int len, int *w, int *h) {
static SDL_Texture *CreateTexture(SDL_Renderer *r, unsigned char *data, unsigned int len, int *w, int *h)
{
SDL_Texture *texture = NULL;
SDL_Surface *surface;
SDL_IOStream *src = SDL_IOFromConstMem(data, len);
if (src) {
surface = SDL_LoadBMP_IO(src, SDL_TRUE);
surface = SDL_LoadBMP_IO(src, true);
if (surface) {
/* Treat white as transparent */
SDL_SetSurfaceColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 255, 255, 255));
SDL_SetSurfaceColorKey(surface, true, SDL_MapSurfaceRGB(surface, 255, 255, 255));
texture = SDL_CreateTextureFromSurface(r, surface);
*w = surface->w;
@@ -285,17 +279,17 @@ static void MoveSprite(void)
}
}
static SDL_PixelFormatEnum GetTextureFormat(enum AVPixelFormat format)
static SDL_PixelFormat GetTextureFormat(enum AVPixelFormat format)
{
switch (format) {
case AV_PIX_FMT_RGB8:
return SDL_PIXELFORMAT_RGB332;
case AV_PIX_FMT_RGB444:
return SDL_PIXELFORMAT_RGB444;
return SDL_PIXELFORMAT_XRGB4444;
case AV_PIX_FMT_RGB555:
return SDL_PIXELFORMAT_RGB555;
return SDL_PIXELFORMAT_XRGB1555;
case AV_PIX_FMT_BGR555:
return SDL_PIXELFORMAT_BGR555;
return SDL_PIXELFORMAT_XBGR1555;
case AV_PIX_FMT_RGB565:
return SDL_PIXELFORMAT_RGB565;
case AV_PIX_FMT_BGR565:
@@ -337,32 +331,32 @@ static SDL_PixelFormatEnum GetTextureFormat(enum AVPixelFormat format)
}
}
static SDL_bool SupportedPixelFormat(enum AVPixelFormat format)
static bool SupportedPixelFormat(enum AVPixelFormat format)
{
if (!software_only) {
if (has_eglCreateImage &&
(format == AV_PIX_FMT_VAAPI || format == AV_PIX_FMT_DRM_PRIME)) {
return SDL_TRUE;
return true;
}
#ifdef SDL_PLATFORM_APPLE
if (format == AV_PIX_FMT_VIDEOTOOLBOX) {
return SDL_TRUE;
return true;
}
#endif
#ifdef SDL_PLATFORM_WIN32
if (d3d11_device && format == AV_PIX_FMT_D3D11) {
return SDL_TRUE;
return true;
}
#endif
if (vulkan_context && format == AV_PIX_FMT_VULKAN) {
return SDL_TRUE;
return true;
}
}
if (GetTextureFormat(format) != SDL_PIXELFORMAT_UNKNOWN) {
return SDL_TRUE;
return true;
}
return SDL_FALSE;
return false;
}
static enum AVPixelFormat GetSupportedPixelFormat(AVCodecContext *s, const enum AVPixelFormat *pix_fmts)
@@ -478,6 +472,14 @@ static AVCodecContext *OpenVideoStream(AVFormatContext *ic, int stream, const AV
/* Allow supported hardware accelerated pixel formats */
context->get_format = GetSupportedPixelFormat;
if (codecpar->codec_id == AV_CODEC_ID_VVC) {
context->strict_std_compliance = -2;
/* Enable threaded decoding, VVC decode is slow */
context->thread_count = SDL_GetNumLogicalCPUCores();
context->thread_type = (FF_THREAD_FRAME | FF_THREAD_SLICE);
}
result = avcodec_open2(context, codec, NULL);
if (result < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open codec %s: %s", avcodec_get_name(context->codec_id), av_err2str(result));
@@ -509,7 +511,7 @@ static SDL_Colorspace GetFrameColorspace(AVFrame *frame)
return colorspace;
}
static SDL_PropertiesID CreateVideoTextureProperties(AVFrame *frame, SDL_PixelFormatEnum format, int access)
static SDL_PropertiesID CreateVideoTextureProperties(AVFrame *frame, SDL_PixelFormat format, int access)
{
AVFrameSideData *pSideData;
SDL_PropertiesID props;
@@ -566,14 +568,17 @@ static void SDLCALL FreeSwsContextContainer(void *userdata, void *value)
SDL_free(sws_container);
}
static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture)
static bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture)
{
int texture_width = 0, texture_height = 0;
SDL_PixelFormatEnum texture_format = SDL_PIXELFORMAT_UNKNOWN;
SDL_PixelFormatEnum frame_format = GetTextureFormat(frame->format);
SDL_PixelFormat texture_format = SDL_PIXELFORMAT_UNKNOWN;
SDL_PixelFormat frame_format = GetTextureFormat(frame->format);
if (*texture) {
SDL_QueryTexture(*texture, &texture_format, NULL, &texture_width, &texture_height);
SDL_PropertiesID props = SDL_GetTextureProperties(*texture);
texture_format = (SDL_PixelFormat)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_FORMAT_NUMBER, SDL_PIXELFORMAT_UNKNOWN);
texture_width = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_WIDTH_NUMBER, 0);
texture_height = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_HEIGHT_NUMBER, 0);
}
if (!*texture || texture_width != frame->width || texture_height != frame->height ||
(frame_format != SDL_PIXELFORMAT_UNKNOWN && texture_format != frame_format) ||
@@ -591,7 +596,7 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture)
*texture = SDL_CreateTextureWithProperties(renderer, props);
SDL_DestroyProperties(props);
if (!*texture) {
return SDL_FALSE;
return false;
}
if (frame_format == SDL_PIXELFORMAT_UNKNOWN || SDL_ISPIXELFORMAT_ALPHA(frame_format)) {
@@ -606,37 +611,37 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture)
case SDL_PIXELFORMAT_UNKNOWN:
{
SDL_PropertiesID props = SDL_GetTextureProperties(*texture);
struct SwsContextContainer *sws_container = (struct SwsContextContainer *)SDL_GetProperty(props, SWS_CONTEXT_CONTAINER_PROPERTY, NULL);
struct SwsContextContainer *sws_container = (struct SwsContextContainer *)SDL_GetPointerProperty(props, SWS_CONTEXT_CONTAINER_PROPERTY, NULL);
if (!sws_container) {
sws_container = (struct SwsContextContainer *)SDL_calloc(1, sizeof(*sws_container));
if (!sws_container) {
return SDL_FALSE;
return false;
}
SDL_SetPropertyWithCleanup(props, SWS_CONTEXT_CONTAINER_PROPERTY, sws_container, FreeSwsContextContainer, NULL);
SDL_SetPointerPropertyWithCleanup(props, SWS_CONTEXT_CONTAINER_PROPERTY, sws_container, FreeSwsContextContainer, NULL);
}
sws_container->context = sws_getCachedContext(sws_container->context, frame->width, frame->height, frame->format, frame->width, frame->height, AV_PIX_FMT_BGRA, SWS_POINT, NULL, NULL, NULL);
if (sws_container->context) {
uint8_t *pixels[4];
int pitch[4];
if (SDL_LockTexture(*texture, NULL, (void **)&pixels[0], &pitch[0]) == 0) {
sws_scale(sws_container->context, (const uint8_t * const *)frame->data, frame->linesize, 0, frame->height, pixels, pitch);
if (SDL_LockTexture(*texture, NULL, (void **)&pixels[0], &pitch[0])) {
sws_scale(sws_container->context, (const uint8_t *const *)frame->data, frame->linesize, 0, frame->height, pixels, pitch);
SDL_UnlockTexture(*texture);
}
} else {
SDL_SetError("Can't initialize the conversion context");
return SDL_FALSE;
return false;
}
break;
}
case SDL_PIXELFORMAT_IYUV:
if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) {
SDL_UpdateYUVTexture(*texture, NULL, frame->data[0], frame->linesize[0],
frame->data[1], frame->linesize[1],
frame->data[2], frame->linesize[2]);
frame->data[1], frame->linesize[1],
frame->data[2], frame->linesize[2]);
} else if (frame->linesize[0] < 0 && frame->linesize[1] < 0 && frame->linesize[2] < 0) {
SDL_UpdateYUVTexture(*texture, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0],
frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1],
frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]);
SDL_UpdateYUVTexture(*texture, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0],
frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1],
frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]);
}
break;
default:
@@ -647,14 +652,103 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture)
}
break;
}
return SDL_TRUE;
return true;
}
#ifdef HAVE_EGL
static SDL_bool GetOESTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
static bool GetNV12TextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
{
AVHWFramesContext *frames = (AVHWFramesContext *)(frame->hw_frames_ctx->data);
AVHWFramesContext *frames = (AVHWFramesContext *)(frame->hw_frames_ctx ? frame->hw_frames_ctx->data : NULL);
const AVDRMFrameDescriptor *desc = (const AVDRMFrameDescriptor *)frame->data[0];
int i, j, image_index;
EGLDisplay display = eglGetCurrentDisplay();
SDL_PropertiesID props;
GLuint textures[2];
if (*texture) {
/* Free the previous texture now that we're about to render a new one */
SDL_DestroyTexture(*texture);
} else {
/* First time set up for NV12 textures */
SDL_SetHint("SDL_RENDER_OPENGL_NV12_RG_SHADER", "1");
}
props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_NV12, SDL_TEXTUREACCESS_STATIC);
*texture = SDL_CreateTextureWithProperties(renderer, props);
SDL_DestroyProperties(props);
if (!*texture) {
return false;
}
SDL_SetTextureBlendMode(*texture, SDL_BLENDMODE_NONE);
SDL_SetTextureScaleMode(*texture, SDL_SCALEMODE_LINEAR);
props = SDL_GetTextureProperties(*texture);
textures[0] = (GLuint)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_NUMBER, 0);
textures[1] = (GLuint)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER, 0);
if (!textures[0] || !textures[1]) {
SDL_SetError("Couldn't get NV12 OpenGL textures");
return false;
}
/* import the frame into OpenGL */
image_index = 0;
for (i = 0; i < desc->nb_layers; ++i) {
const AVDRMLayerDescriptor *layer = &desc->layers[i];
for (j = 0; j < layer->nb_planes; ++j) {
const AVDRMPlaneDescriptor *plane = &layer->planes[j];
const AVDRMObjectDescriptor *object = &desc->objects[plane->object_index];
EGLAttrib attr[32];
size_t k = 0;
attr[k++] = EGL_LINUX_DRM_FOURCC_EXT;
attr[k++] = layer->format;
attr[k++] = EGL_WIDTH;
attr[k++] = (frames ? frames->width : frame->width) / (image_index + 1); /* half size for chroma */
attr[k++] = EGL_HEIGHT;
attr[k++] = (frames ? frames->height : frame->height) / (image_index + 1);
attr[k++] = EGL_DMA_BUF_PLANE0_FD_EXT;
attr[k++] = object->fd;
attr[k++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
attr[k++] = plane->offset;
attr[k++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
attr[k++] = plane->pitch;
if (has_EGL_EXT_image_dma_buf_import_modifiers) {
attr[k++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
attr[k++] = (object->format_modifier >> 0) & 0xFFFFFFFF;
attr[k++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
attr[k++] = (object->format_modifier >> 32) & 0xFFFFFFFF;
}
attr[k++] = EGL_NONE;
EGLImage image = eglCreateImage(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attr);
if (image == EGL_NO_IMAGE) {
SDL_Log("Couldn't create image: %d\n", glGetError());
return false;
}
glActiveTextureARBFunc(GL_TEXTURE0_ARB + image_index);
glBindTexture(GL_TEXTURE_2D, textures[image_index]);
glEGLImageTargetTexture2DOESFunc(GL_TEXTURE_2D, image);
++image_index;
}
}
return true;
}
static bool GetOESTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
{
AVHWFramesContext *frames = (AVHWFramesContext *)(frame->hw_frames_ctx ? frame->hw_frames_ctx->data : NULL);
const AVDRMFrameDescriptor *desc = (const AVDRMFrameDescriptor *)frame->data[0];
int i, j, k, image_index;
EGLDisplay display = eglGetCurrentDisplay();
@@ -672,7 +766,7 @@ static SDL_bool GetOESTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
*texture = SDL_CreateTextureWithProperties(renderer, props);
SDL_DestroyProperties(props);
if (!*texture) {
return SDL_FALSE;
return false;
}
SDL_SetTextureBlendMode(*texture, SDL_BLENDMODE_NONE);
SDL_SetTextureScaleMode(*texture, SDL_SCALEMODE_LINEAR);
@@ -681,7 +775,7 @@ static SDL_bool GetOESTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
textureID = (GLuint)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_NUMBER, 0);
if (!textureID) {
SDL_SetError("Couldn't get OpenGL texture");
return SDL_FALSE;
return false;
}
colorspace = (SDL_Colorspace)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_COLORSPACE_NUMBER, SDL_COLORSPACE_UNKNOWN);
@@ -690,9 +784,9 @@ static SDL_bool GetOESTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
attr[k++] = EGL_LINUX_DRM_FOURCC_EXT;
attr[k++] = desc->layers[0].format;
attr[k++] = EGL_WIDTH;
attr[k++] = frames->width;
attr[k++] = frames ? frames->width : frame->width;
attr[k++] = EGL_HEIGHT;
attr[k++] = frames->height;
attr[k++] = frames ? frames->height : frame->height;
image_index = 0;
for (i = 0; i < desc->nb_layers; ++i) {
const AVDRMLayerDescriptor *layer = &desc->layers[i];
@@ -778,6 +872,7 @@ static SDL_bool GetOESTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
case SDL_COLOR_PRIMARIES_BT2020:
attr[k++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
attr[k++] = EGL_ITU_REC2020_EXT;
break;
default:
break;
}
@@ -823,130 +918,37 @@ static SDL_bool GetOESTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
EGLImage image = eglCreateImage(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attr);
if (image == EGL_NO_IMAGE) {
SDL_Log("Couldn't create image: %d\n", glGetError());
return SDL_FALSE;
return false;
}
glActiveTextureARBFunc(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureID);
glEGLImageTargetTexture2DOESFunc(GL_TEXTURE_EXTERNAL_OES, image);
return SDL_TRUE;
return true;
}
#endif // HAVE_EGL
static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
static bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
{
#ifdef HAVE_EGL
AVHWFramesContext *frames = (AVHWFramesContext *)(frame->hw_frames_ctx->data);
const AVDRMFrameDescriptor *desc = (const AVDRMFrameDescriptor *)frame->data[0];
int i, j, image_index, num_planes;
EGLDisplay display = eglGetCurrentDisplay();
SDL_PropertiesID props;
GLuint textures[2];
uint64_t format_modifier = desc->objects[0].format_modifier;
if (format_modifier != DRM_FORMAT_MOD_INVALID &&
format_modifier != DRM_FORMAT_MOD_LINEAR) {
if (desc->nb_layers == 2 &&
desc->layers[0].format == DRM_FORMAT_R8 &&
desc->layers[1].format == DRM_FORMAT_GR88) {
return GetNV12TextureForDRMFrame(frame, texture);
} else {
return GetOESTextureForDRMFrame(frame, texture);
}
/* FIXME: Assuming NV12 data format */
num_planes = 0;
for (i = 0; i < desc->nb_layers; ++i) {
num_planes += desc->layers[i].nb_planes;
}
if (num_planes != 2) {
SDL_SetError("Expected NV12 frames with 2 planes, instead got %d planes", num_planes);
return SDL_FALSE;
}
if (*texture) {
/* Free the previous texture now that we're about to render a new one */
SDL_DestroyTexture(*texture);
} else {
/* First time set up for NV12 textures */
SDL_SetHint("SDL_RENDER_OPENGL_NV12_RG_SHADER", "1");
}
props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_NV12, SDL_TEXTUREACCESS_STATIC);
*texture = SDL_CreateTextureWithProperties(renderer, props);
SDL_DestroyProperties(props);
if (!*texture) {
return SDL_FALSE;
}
SDL_SetTextureBlendMode(*texture, SDL_BLENDMODE_NONE);
SDL_SetTextureScaleMode(*texture, SDL_SCALEMODE_LINEAR);
props = SDL_GetTextureProperties(*texture);
textures[0] = (GLuint)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_NUMBER, 0);
textures[1] = (GLuint)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER, 0);
if (!textures[0] || !textures[1]) {
SDL_SetError("Couldn't get NV12 OpenGL textures");
return SDL_FALSE;
}
/* import the frame into OpenGL */
image_index = 0;
for (i = 0; i < desc->nb_layers; ++i) {
const AVDRMLayerDescriptor *layer = &desc->layers[i];
for (j = 0; j < layer->nb_planes; ++j) {
static const uint32_t formats[ 2 ] = { DRM_FORMAT_R8, DRM_FORMAT_GR88 };
const AVDRMPlaneDescriptor *plane = &layer->planes[j];
const AVDRMObjectDescriptor *object = &desc->objects[plane->object_index];
EGLAttrib attr[32];
size_t k = 0;
attr[k++] = EGL_LINUX_DRM_FOURCC_EXT;
attr[k++] = formats[i];
attr[k++] = EGL_WIDTH;
attr[k++] = frames->width / ( image_index + 1 ); /* half size for chroma */
attr[k++] = EGL_HEIGHT;
attr[k++] = frames->height / ( image_index + 1 );
attr[k++] = EGL_DMA_BUF_PLANE0_FD_EXT;
attr[k++] = object->fd;
attr[k++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
attr[k++] = plane->offset;
attr[k++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
attr[k++] = plane->pitch;
if (has_EGL_EXT_image_dma_buf_import_modifiers) {
attr[k++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
attr[k++] = (object->format_modifier >> 0) & 0xFFFFFFFF;
attr[k++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
attr[k++] = (object->format_modifier >> 32) & 0xFFFFFFFF;
}
attr[k++] = EGL_NONE;
EGLImage image = eglCreateImage(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attr);
if (image == EGL_NO_IMAGE) {
SDL_Log("Couldn't create image: %d\n", glGetError());
return SDL_FALSE;
}
glActiveTextureARBFunc(GL_TEXTURE0_ARB + image_index);
glBindTexture(GL_TEXTURE_2D, textures[image_index]);
glEGLImageTargetTexture2DOESFunc(GL_TEXTURE_2D, image);
++image_index;
}
}
return SDL_TRUE;
#else
return SDL_FALSE;
return false;
#endif
}
static SDL_bool GetTextureForVAAPIFrame(AVFrame *frame, SDL_Texture **texture)
static bool GetTextureForVAAPIFrame(AVFrame *frame, SDL_Texture **texture)
{
AVFrame *drm_frame;
SDL_bool result = SDL_FALSE;
bool result = false;
drm_frame = av_frame_alloc();
if (drm_frame) {
@@ -961,7 +963,7 @@ static SDL_bool GetTextureForVAAPIFrame(AVFrame *frame, SDL_Texture **texture)
return result;
}
static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture)
static bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture)
{
#ifdef SDL_PLATFORM_WIN32
AVHWFramesContext *frames = (AVHWFramesContext *)(frame->hw_frames_ctx->data);
@@ -970,7 +972,9 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture)
UINT iSliceIndex = (UINT)(uintptr_t)frame->data[1];
if (*texture) {
SDL_QueryTexture(*texture, NULL, NULL, &texture_width, &texture_height);
SDL_PropertiesID props = SDL_GetTextureProperties(*texture);
texture_width = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_WIDTH_NUMBER, 0);
texture_height = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_HEIGHT_NUMBER, 0);
}
if (!*texture || texture_width != frames->width || texture_height != frames->height) {
if (*texture) {
@@ -981,24 +985,24 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture)
*texture = SDL_CreateTextureWithProperties(renderer, props);
SDL_DestroyProperties(props);
if (!*texture) {
return SDL_FALSE;
return false;
}
}
ID3D11Resource *dx11_resource = SDL_GetProperty(SDL_GetTextureProperties(*texture), SDL_PROP_TEXTURE_D3D11_TEXTURE_POINTER, NULL);
ID3D11Resource *dx11_resource = SDL_GetPointerProperty(SDL_GetTextureProperties(*texture), SDL_PROP_TEXTURE_D3D11_TEXTURE_POINTER, NULL);
if (!dx11_resource) {
SDL_SetError("Couldn't get texture ID3D11Resource interface");
return SDL_FALSE;
return false;
}
ID3D11DeviceContext_CopySubresourceRegion(d3d11_context, dx11_resource, 0, 0, 0, 0, (ID3D11Resource *)pTexture, iSliceIndex, NULL);
return SDL_TRUE;
return true;
#else
return SDL_FALSE;
return false;
#endif
}
static SDL_bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **texture)
static bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **texture)
{
#ifdef SDL_PLATFORM_APPLE
CVPixelBufferRef pPixelBuffer = (CVPixelBufferRef)frame->data[3];
@@ -1011,20 +1015,20 @@ static SDL_bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **tex
}
props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STATIC);
SDL_SetProperty(props, SDL_PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER, pPixelBuffer);
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER, pPixelBuffer);
*texture = SDL_CreateTextureWithProperties(renderer, props);
SDL_DestroyProperties(props);
if (!*texture) {
return SDL_FALSE;
return false;
}
return SDL_TRUE;
return true;
#else
return SDL_FALSE;
return false;
#endif
}
static SDL_bool GetTextureForVulkanFrame(AVFrame *frame, SDL_Texture **texture)
static bool GetTextureForVulkanFrame(AVFrame *frame, SDL_Texture **texture)
{
SDL_PropertiesID props;
@@ -1036,12 +1040,12 @@ static SDL_bool GetTextureForVulkanFrame(AVFrame *frame, SDL_Texture **texture)
*texture = CreateVulkanVideoTexture(vulkan_context, frame, renderer, props);
SDL_DestroyProperties(props);
if (!*texture) {
return SDL_FALSE;
return false;
}
return SDL_TRUE;
return true;
}
static SDL_bool GetTextureForFrame(AVFrame *frame, SDL_Texture **texture)
static bool GetTextureForFrame(AVFrame *frame, SDL_Texture **texture)
{
switch (frame->format) {
case AV_PIX_FMT_VAAPI:
@@ -1160,9 +1164,9 @@ static AVCodecContext *OpenAudioStream(AVFormatContext *ic, int stream, const AV
}
SDL_AudioSpec spec = { SDL_AUDIO_F32, codecpar->ch_layout.nb_channels, codecpar->sample_rate };
audio = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &spec, NULL, NULL);
audio = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, NULL, NULL);
if (audio) {
SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(audio));
SDL_ResumeAudioStreamDevice(audio);
} else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open audio: %s", SDL_GetError());
}
@@ -1190,7 +1194,7 @@ static SDL_AudioFormat GetAudioFormat(enum AVSampleFormat format)
}
}
static SDL_bool IsPlanarAudioFormat(enum AVSampleFormat format)
static bool IsPlanarAudioFormat(enum AVSampleFormat format)
{
switch (format) {
case AV_SAMPLE_FMT_U8P:
@@ -1199,9 +1203,9 @@ static SDL_bool IsPlanarAudioFormat(enum AVSampleFormat format)
case AV_SAMPLE_FMT_FLTP:
case AV_SAMPLE_FMT_DBLP:
case AV_SAMPLE_FMT_S64P:
return SDL_TRUE;
return true;
default:
return SDL_FALSE;
return false;
}
}
@@ -1219,7 +1223,7 @@ static void InterleaveAudio(AVFrame *frame, const SDL_AudioSpec *spec)
for (c = 0; c < spec->channels; ++c) {
const Uint8 *src = frame->data[c];
Uint8 *dst = data + c * samplesize;
for (n = frame->nb_samples; n--; ) {
for (n = frame->nb_samples; n--;) {
SDL_memcpy(dst, src, samplesize);
src += samplesize;
dst += framesize;
@@ -1243,7 +1247,7 @@ static void HandleAudioFrame(AVFrame *frame)
}
}
static void av_log_callback(void* avcl, int level, const char *fmt, va_list vl)
static void av_log_callback(void *avcl, int level, const char *fmt, va_list vl)
{
const char *pszCategory = NULL;
char *message;
@@ -1282,7 +1286,8 @@ static void av_log_callback(void* avcl, int level, const char *fmt, va_list vl)
SDL_free(message);
}
static void print_usage(SDLTest_CommonState *state, const char *argv0) {
static void print_usage(SDLTest_CommonState *state, const char *argv0)
{
static const char *options[] = { "[--verbose]", "[--sprites N]", "[--audio-codec codec]", "[--video-codec codec]", "[--software]", "video_file", NULL };
SDLTest_CommonLogUsage(state, argv0, options);
}
@@ -1306,18 +1311,18 @@ int main(int argc, char *argv[])
int result;
int return_code = -1;
SDL_WindowFlags window_flags;
SDL_bool flushing = SDL_FALSE;
SDL_bool decoded = SDL_FALSE;
bool flushing = false;
bool decoded = false;
SDLTest_CommonState *state;
/* Initialize test framework */
state = SDLTest_CommonCreateState(argv, 0);
/* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
/* Log ffmpeg messages */
av_log_set_callback( av_log_callback );
av_log_set_callback(av_log_callback);
/* Parse commandline */
for (i = 1; i < argc;) {
@@ -1326,19 +1331,19 @@ int main(int argc, char *argv[])
consumed = SDLTest_CommonArg(state, i);
if (!consumed) {
if (SDL_strcmp(argv[i], "--verbose") == 0) {
verbose = SDL_TRUE;
verbose = true;
consumed = 1;
} else if (SDL_strcmp(argv[i], "--sprites") == 0 && argv[i+1]) {
num_sprites = SDL_atoi(argv[i+1]);
} else if (SDL_strcmp(argv[i], "--sprites") == 0 && argv[i + 1]) {
num_sprites = SDL_atoi(argv[i + 1]);
consumed = 2;
} else if (SDL_strcmp(argv[i], "--audio-codec") == 0 && argv[i+1]) {
audio_codec_name = argv[i+1];
} else if (SDL_strcmp(argv[i], "--audio-codec") == 0 && argv[i + 1]) {
audio_codec_name = argv[i + 1];
consumed = 2;
} else if (SDL_strcmp(argv[i], "--video-codec") == 0 && argv[i+1]) {
video_codec_name = argv[i+1];
} else if (SDL_strcmp(argv[i], "--video-codec") == 0 && argv[i + 1]) {
video_codec_name = argv[i + 1];
consumed = 2;
} else if (SDL_strcmp(argv[i], "--software") == 0) {
software_only = SDL_TRUE;
software_only = true;
consumed = 1;
} else if (!file) {
/* We'll try to open this as a media file */
@@ -1361,7 +1366,7 @@ int main(int argc, char *argv[])
goto quit;
}
if (SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0) {
if (!SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO)) {
return_code = 2;
goto quit;
}
@@ -1398,7 +1403,7 @@ int main(int argc, char *argv[])
}
}
if (SDL_SetWindowTitle(window, file) < 0) {
if (!SDL_SetWindowTitle(window, file)) {
SDL_Log("SDL_SetWindowTitle: %s", SDL_GetError());
}
@@ -1475,17 +1480,16 @@ int main(int argc, char *argv[])
/* Position sprites and set their velocities */
SDL_Rect viewport;
SDL_GetRenderViewport(renderer, &viewport);
srand((unsigned int)time(NULL));
for (i = 0; i < num_sprites; ++i) {
positions[i].x = (float)(rand() % (viewport.w - sprite_w));
positions[i].y = (float)(rand() % (viewport.h - sprite_h));
positions[i].x = (float)SDL_rand(viewport.w - sprite_w);
positions[i].y = (float)SDL_rand(viewport.h - sprite_h);
positions[i].w = (float)sprite_w;
positions[i].h = (float)sprite_h;
velocities[i].x = 0.0f;
velocities[i].y = 0.0f;
while (!velocities[i].x || !velocities[i].y) {
velocities[i].x = (float)((rand() % (2 + 1)) - 1);
velocities[i].y = (float)((rand() % (2 + 1)) - 1);
while (velocities[i].x == 0.f || velocities[i].y == 0.f) {
velocities[i].x = (float)(SDL_rand(2 + 1) - 1);
velocities[i].y = (float)(SDL_rand(2 + 1) - 1);
}
}
@@ -1501,7 +1505,7 @@ int main(int argc, char *argv[])
/* Check for events */
while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_QUIT ||
(event.type == SDL_EVENT_KEY_DOWN && event.key.keysym.sym == SDLK_ESCAPE)) {
(event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_ESCAPE)) {
done = 1;
}
}
@@ -1516,7 +1520,7 @@ int main(int argc, char *argv[])
if (video_context) {
avcodec_flush_buffers(video_context);
}
flushing = SDL_TRUE;
flushing = true;
} else {
if (pkt->stream_index == audio_stream) {
result = avcodec_send_packet(audio_context, pkt);
@@ -1533,11 +1537,11 @@ int main(int argc, char *argv[])
}
}
decoded = SDL_FALSE;
decoded = false;
if (audio_context) {
while (avcodec_receive_frame(audio_context, frame) >= 0) {
HandleAudioFrame(frame);
decoded = SDL_TRUE;
decoded = true;
}
if (flushing) {
/* Let SDL know we're done sending audio */
@@ -1553,7 +1557,7 @@ int main(int argc, char *argv[])
pts -= first_pts;
HandleVideoFrame(frame, pts);
decoded = SDL_TRUE;
decoded = true;
}
} else {
/* Update video rendering */