testffmpeg: fixed mismatch between frame size and frame texture size

The AVHWFramesContext associated with the frame has the texture size, and the frame width and height are the displayed size and can be smaller than the texture size
This commit is contained in:
Sam Lantinga 2024-03-04 10:49:38 -08:00
parent 180dd0bb39
commit fb87f8f15c

View File

@ -502,16 +502,32 @@ static SDL_Colorspace GetFrameColorspace(AVFrame *frame)
return colorspace;
}
static SDL_PropertiesID CreateVideoTextureProperties(AVFrame *frame, Uint32 format, int access, int w, int h)
static SDL_PropertiesID CreateVideoTextureProperties(AVFrame *frame, Uint32 format, int access)
{
AVFrameSideData *pSideData;
SDL_PropertiesID props;
int width = frame->width;
int height = frame->height;
SDL_Colorspace colorspace = GetFrameColorspace(frame);
/* ITU-R BT.2408-6 recommends using an SDR white point of 203 nits, which is more likely for game content */
static const float k_flSDRWhitePoint = 203.0f;
float flMaxLuminance = k_flSDRWhitePoint;
if (frame->hw_frames_ctx) {
AVHWFramesContext *frames = (AVHWFramesContext *)(frame->hw_frames_ctx->data);
width = frames->width;
height = frames->height;
if (format == SDL_PIXELFORMAT_UNKNOWN) {
format = GetTextureFormat(frames->sw_format);
}
} else {
if (format == SDL_PIXELFORMAT_UNKNOWN) {
format = GetTextureFormat(frame->format);
}
}
props = SDL_CreateProperties();
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, colorspace);
pSideData = av_frame_get_side_data(frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
@ -528,8 +544,8 @@ static SDL_PropertiesID CreateVideoTextureProperties(AVFrame *frame, Uint32 form
}
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, format);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, access);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, w);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, h);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, width);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, height);
return props;
}
@ -561,9 +577,9 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture)
SDL_PropertiesID props;
if (frame_format == SDL_PIXELFORMAT_UNKNOWN) {
props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height);
props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING);
} else {
props = CreateVideoTextureProperties(frame, frame_format, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height);
props = CreateVideoTextureProperties(frame, frame_format, SDL_TEXTUREACCESS_STREAMING);
}
*texture = SDL_CreateTextureWithProperties(renderer, props);
SDL_DestroyProperties(props);
@ -630,6 +646,7 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture)
static SDL_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();
@ -654,7 +671,7 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
SDL_SetHint("SDL_RENDER_OPENGL_NV12_RG_SHADER", "1");
}
props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_NV12, SDL_TEXTUREACCESS_STATIC, frame->width, frame->height);
props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STATIC);
*texture = SDL_CreateTextureWithProperties(renderer, props);
SDL_DestroyProperties(props);
if (!*texture) {
@ -687,10 +704,10 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture)
attr[k++] = formats[i];
attr[k++] = EGL_WIDTH;
attr[k++] = frame->width / ( image_index + 1 ); /* half size for chroma */
attr[k++] = frames->width / ( image_index + 1 ); /* half size for chroma */
attr[k++] = EGL_HEIGHT;
attr[k++] = frame->height / ( image_index + 1 );
attr[k++] = frames->height / ( image_index + 1 );
attr[k++] = EGL_DMA_BUF_PLANE0_FD_EXT;
attr[k++] = object->fd;
@ -747,38 +764,20 @@ static SDL_bool GetTextureForVAAPIFrame(AVFrame *frame, SDL_Texture **texture)
static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture)
{
#ifdef SDL_PLATFORM_WIN32
AVHWFramesContext *frames = (AVHWFramesContext *)(frame->hw_frames_ctx->data);
int texture_width = 0, texture_height = 0;
ID3D11Texture2D *pTexture = (ID3D11Texture2D *)frame->data[0];
UINT iSliceIndex = (UINT)(uintptr_t)frame->data[1];
D3D11_TEXTURE2D_DESC desc;
SDL_zero(desc);
ID3D11Texture2D_GetDesc(pTexture, &desc);
if (*texture) {
SDL_QueryTexture(*texture, NULL, NULL, &texture_width, &texture_height);
}
if (!*texture || (UINT)texture_width != desc.Width || (UINT)texture_height != desc.Height) {
Uint32 format;
switch (desc.Format) {
case DXGI_FORMAT_NV12:
format = SDL_PIXELFORMAT_NV12;
break;
case DXGI_FORMAT_P010:
format = SDL_PIXELFORMAT_P010;
break;
default:
SDL_SetError("Unsupported texture format %d", desc.Format);
return SDL_FALSE;
}
if (!*texture || texture_width != frames->width || texture_height != frames->height) {
if (*texture) {
SDL_DestroyTexture(*texture);
}
SDL_PropertiesID props = CreateVideoTextureProperties(frame, format, SDL_TEXTUREACCESS_STATIC, desc.Width, desc.Height);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, desc.Height);
SDL_PropertiesID props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STATIC);
*texture = SDL_CreateTextureWithProperties(renderer, props);
SDL_DestroyProperties(props);
if (!*texture) {
@ -803,29 +802,7 @@ static SDL_bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **tex
{
#ifdef SDL_PLATFORM_APPLE
CVPixelBufferRef pPixelBuffer = (CVPixelBufferRef)frame->data[3];
OSType nPixelBufferType = CVPixelBufferGetPixelFormatType(pPixelBuffer);
size_t nPixelBufferWidth = CVPixelBufferGetWidthOfPlane(pPixelBuffer, 0);
size_t nPixelBufferHeight = CVPixelBufferGetHeightOfPlane(pPixelBuffer, 0);
SDL_PropertiesID props;
Uint32 format;
switch (nPixelBufferType) {
case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange:
format = SDL_PIXELFORMAT_NV12;
break;
case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange:
case kCVPixelFormatType_420YpCbCr10BiPlanarFullRange:
format = SDL_PIXELFORMAT_P010;
break;
default:
SDL_SetError("Unsupported texture format %c%c%c%c",
(char)((nPixelBufferType >> 24) & 0xFF),
(char)((nPixelBufferType >> 16) & 0xFF),
(char)((nPixelBufferType >> 8) & 0xFF),
(char)((nPixelBufferType >> 0) & 0xFF));
return SDL_FALSE;
}
if (*texture) {
/* Free the previous texture now that we're about to render a new one */
@ -833,7 +810,7 @@ static SDL_bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **tex
SDL_DestroyTexture(*texture);
}
props = CreateVideoTextureProperties(frame, format, SDL_TEXTUREACCESS_STATIC, nPixelBufferWidth, nPixelBufferHeight);
props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STATIC);
SDL_SetProperty(props, SDL_PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER, pPixelBuffer);
*texture = SDL_CreateTextureWithProperties(renderer, props);
SDL_DestroyProperties(props);
@ -850,11 +827,12 @@ static SDL_bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **tex
static SDL_bool GetTextureForVulkanFrame(AVFrame *frame, SDL_Texture **texture)
{
SDL_PropertiesID props;
if (*texture) {
SDL_DestroyTexture(*texture);
}
props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STATIC, frame->width, frame->height);
props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_STATIC);
*texture = CreateVulkanVideoTexture(vulkan_context, frame, renderer, props);
SDL_DestroyProperties(props);
if (!*texture) {
@ -905,10 +883,15 @@ static void DisplayVideoTexture(AVFrame *frame)
return;
}
SDL_FRect src;
src.x = 0.0f;
src.y = 0.0f;
src.w = (float)frame->width;
src.h = (float)frame->height;
if (frame->linesize[0] < 0) {
SDL_RenderTextureRotated(renderer, video_texture, NULL, NULL, 0.0, NULL, SDL_FLIP_VERTICAL);
SDL_RenderTextureRotated(renderer, video_texture, &src, NULL, 0.0, NULL, SDL_FLIP_VERTICAL);
} else {
SDL_RenderTexture(renderer, video_texture, NULL, NULL);
SDL_RenderTexture(renderer, video_texture, &src, NULL);
}
}