mirror of https://github.com/libsdl-org/SDL
testffmpeg: added support for EGL OES frame formats
This commit is contained in:
parent
d79f865251
commit
41b7036f37
|
@ -46,6 +46,21 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#define DRM_FORMAT_MOD_VENDOR_NONE 0
|
||||
#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1)
|
||||
|
||||
#define fourcc_mod_get_vendor(modifier) \
|
||||
(((modifier) >> 56) & 0xff)
|
||||
|
||||
#define fourcc_mod_is_vendor(modifier, vendor) \
|
||||
(fourcc_mod_get_vendor(modifier) == DRM_FORMAT_MOD_VENDOR_## vendor)
|
||||
|
||||
#define fourcc_mod_code(vendor, val) \
|
||||
((((__u64)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)
|
||||
|
||||
#ifdef SDL_PLATFORM_APPLE
|
||||
#include <CoreVideo/CoreVideo.h>
|
||||
#endif
|
||||
|
@ -635,6 +650,189 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture)
|
|||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
|
||||
static SDL_bool GetOESTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
|
||||
{
|
||||
AVHWFramesContext *frames = (AVHWFramesContext *)(frame->hw_frames_ctx->data);
|
||||
const AVDRMFrameDescriptor *desc = (const AVDRMFrameDescriptor *)frame->data[0];
|
||||
int i, j, k, image_index;
|
||||
EGLDisplay display = eglGetCurrentDisplay();
|
||||
SDL_PropertiesID props;
|
||||
GLuint textureID;
|
||||
EGLAttrib attr[64];
|
||||
SDL_Colorspace colorspace;
|
||||
|
||||
if (*texture) {
|
||||
/* Free the previous texture now that we're about to render a new one */
|
||||
SDL_DestroyTexture(*texture);
|
||||
}
|
||||
|
||||
props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_EXTERNAL_OES, 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);
|
||||
textureID = (GLuint)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_NUMBER, 0);
|
||||
if (!textureID) {
|
||||
SDL_SetError("Couldn't get OpenGL texture");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
colorspace = (SDL_Colorspace)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_COLORSPACE_NUMBER, SDL_COLORSPACE_UNKNOWN);
|
||||
|
||||
/* import the frame into OpenGL */
|
||||
k = 0;
|
||||
attr[k++] = EGL_LINUX_DRM_FOURCC_EXT;
|
||||
attr[k++] = desc->layers[0].format;
|
||||
attr[k++] = EGL_WIDTH;
|
||||
attr[k++] = frames->width;
|
||||
attr[k++] = EGL_HEIGHT;
|
||||
attr[k++] = frames->height;
|
||||
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];
|
||||
|
||||
switch (image_index) {
|
||||
case 0:
|
||||
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 && object->format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attr[k++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
|
||||
attr[k++] = (object->format_modifier & 0xFFFFFFFF);
|
||||
attr[k++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
|
||||
attr[k++] = (object->format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
attr[k++] = EGL_DMA_BUF_PLANE1_FD_EXT;
|
||||
attr[k++] = object->fd;
|
||||
attr[k++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
|
||||
attr[k++] = plane->offset;
|
||||
attr[k++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
|
||||
attr[k++] = plane->pitch;
|
||||
if (has_EGL_EXT_image_dma_buf_import_modifiers && object->format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attr[k++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
|
||||
attr[k++] = (object->format_modifier & 0xFFFFFFFF);
|
||||
attr[k++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
|
||||
attr[k++] = (object->format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
attr[k++] = EGL_DMA_BUF_PLANE2_FD_EXT;
|
||||
attr[k++] = object->fd;
|
||||
attr[k++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
|
||||
attr[k++] = plane->offset;
|
||||
attr[k++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
|
||||
attr[k++] = plane->pitch;
|
||||
if (has_EGL_EXT_image_dma_buf_import_modifiers && object->format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attr[k++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
|
||||
attr[k++] = (object->format_modifier & 0xFFFFFFFF);
|
||||
attr[k++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
|
||||
attr[k++] = (object->format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
attr[k++] = EGL_DMA_BUF_PLANE3_FD_EXT;
|
||||
attr[k++] = object->fd;
|
||||
attr[k++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
|
||||
attr[k++] = plane->offset;
|
||||
attr[k++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
|
||||
attr[k++] = plane->pitch;
|
||||
if (has_EGL_EXT_image_dma_buf_import_modifiers && object->format_modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attr[k++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
|
||||
attr[k++] = (object->format_modifier & 0xFFFFFFFF);
|
||||
attr[k++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
|
||||
attr[k++] = (object->format_modifier >> 32);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++image_index;
|
||||
}
|
||||
}
|
||||
|
||||
switch (SDL_COLORSPACEPRIMARIES(colorspace)) {
|
||||
case SDL_COLOR_PRIMARIES_BT601:
|
||||
case SDL_COLOR_PRIMARIES_SMPTE240:
|
||||
attr[k++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
|
||||
attr[k++] = EGL_ITU_REC601_EXT;
|
||||
break;
|
||||
case SDL_COLOR_PRIMARIES_BT709:
|
||||
attr[k++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
|
||||
attr[k++] = EGL_ITU_REC709_EXT;
|
||||
break;
|
||||
case SDL_COLOR_PRIMARIES_BT2020:
|
||||
attr[k++] = EGL_YUV_COLOR_SPACE_HINT_EXT;
|
||||
attr[k++] = EGL_ITU_REC2020_EXT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (SDL_COLORSPACERANGE(colorspace)) {
|
||||
case SDL_COLOR_RANGE_FULL:
|
||||
attr[k++] = EGL_SAMPLE_RANGE_HINT_EXT;
|
||||
attr[k++] = EGL_YUV_FULL_RANGE_EXT;
|
||||
break;
|
||||
case SDL_COLOR_RANGE_LIMITED:
|
||||
default:
|
||||
attr[k++] = EGL_SAMPLE_RANGE_HINT_EXT;
|
||||
attr[k++] = EGL_YUV_NARROW_RANGE_EXT;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (SDL_COLORSPACECHROMA(colorspace)) {
|
||||
case SDL_CHROMA_LOCATION_LEFT:
|
||||
attr[k++] = EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT;
|
||||
attr[k++] = EGL_YUV_CHROMA_SITING_0_EXT;
|
||||
attr[k++] = EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT;
|
||||
attr[k++] = EGL_YUV_CHROMA_SITING_0_5_EXT;
|
||||
break;
|
||||
case SDL_CHROMA_LOCATION_CENTER:
|
||||
attr[k++] = EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT;
|
||||
attr[k++] = EGL_YUV_CHROMA_SITING_0_5_EXT;
|
||||
attr[k++] = EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT;
|
||||
attr[k++] = EGL_YUV_CHROMA_SITING_0_5_EXT;
|
||||
break;
|
||||
case SDL_CHROMA_LOCATION_TOPLEFT:
|
||||
attr[k++] = EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT;
|
||||
attr[k++] = EGL_YUV_CHROMA_SITING_0_EXT;
|
||||
attr[k++] = EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT;
|
||||
attr[k++] = EGL_YUV_CHROMA_SITING_0_EXT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_assert(k < SDL_arraysize(attr));
|
||||
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);
|
||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureID);
|
||||
glEGLImageTargetTexture2DOESFunc(GL_TEXTURE_EXTERNAL_OES, image);
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#endif // HAVE_EGL
|
||||
|
||||
static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
|
||||
{
|
||||
#ifdef HAVE_EGL
|
||||
|
@ -644,6 +842,12 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
|
|||
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) {
|
||||
return GetOESTextureForDRMFrame(frame, texture);
|
||||
}
|
||||
|
||||
/* FIXME: Assuming NV12 data format */
|
||||
num_planes = 0;
|
||||
|
@ -663,7 +867,7 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
|
|||
SDL_SetHint("SDL_RENDER_OPENGL_NV12_RG_SHADER", "1");
|
||||
}
|
||||
|
||||
props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STATIC);
|
||||
props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_NV12, SDL_TEXTUREACCESS_STATIC);
|
||||
*texture = SDL_CreateTextureWithProperties(renderer, props);
|
||||
SDL_DestroyProperties(props);
|
||||
if (!*texture) {
|
||||
|
@ -720,11 +924,15 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
|
|||
|
||||
attr[k++] = EGL_NONE;
|
||||
|
||||
EGLImage pImage = eglCreateImage(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attr);
|
||||
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, pImage);
|
||||
glEGLImageTargetTexture2DOESFunc(GL_TEXTURE_2D, image);
|
||||
++image_index;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue