Simplified and fixed media foundation buffer handling

This commit is contained in:
Sam Lantinga
2025-02-17 07:59:37 -08:00
parent de12cb92dc
commit 6ef687c864
@@ -433,7 +433,7 @@ static void SDLCALL CleanupIMFMediaBuffer(void *userdata, void *value)
static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS) static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS)
{ {
SDL_assert(device->hidden->current_sample != NULL); SDL_assert(device->hidden->current_sample != NULL);
SDL_CameraFrameResult result = SDL_CAMERA_FRAME_READY; SDL_CameraFrameResult result = SDL_CAMERA_FRAME_READY;
HRESULT ret; HRESULT ret;
LONGLONG timestamp100NS = 0; LONGLONG timestamp100NS = 0;
@@ -466,54 +466,60 @@ static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SD
} else { } else {
BYTE *pixels = NULL; BYTE *pixels = NULL;
LONG pitch = 0; LONG pitch = 0;
DWORD buflen = 0;
if (SUCCEEDED(IMFMediaBuffer_QueryInterface(objs->buffer, &SDL_IID_IMF2DBuffer2, (void **)&objs->buffer2d2))) { if (SUCCEEDED(IMFMediaBuffer_QueryInterface(objs->buffer, &SDL_IID_IMF2DBuffer2, (void **)&objs->buffer2d2))) {
BYTE *bufstart = NULL; BYTE *bufstart = NULL;
DWORD buflen = 0;
ret = IMF2DBuffer2_Lock2DSize(objs->buffer2d2, MF2DBuffer_LockFlags_Read, &pixels, &pitch, &bufstart, &buflen); ret = IMF2DBuffer2_Lock2DSize(objs->buffer2d2, MF2DBuffer_LockFlags_Read, &pixels, &pitch, &bufstart, &buflen);
if (FAILED(ret)) { if (FAILED(ret)) {
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
CleanupIMF2DBuffer2(NULL, objs); CleanupIMF2DBuffer2(NULL, objs);
} else { } else {
frame->pixels = pixels;
if (frame->format == SDL_PIXELFORMAT_MJPG) { if (frame->format == SDL_PIXELFORMAT_MJPG) {
frame->pitch = (int)buflen; pitch = (LONG)buflen;
} else {
frame->pitch = (int)pitch;
} }
if (pitch < 0) { // image rows are reversed.
pixels += -pitch * (frame->h - 1);
}
frame->pixels = pixels;
frame->pitch = (int)pitch;
if (!SDL_SetPointerPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMF2DBuffer2, NULL)) { if (!SDL_SetPointerPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMF2DBuffer2, NULL)) {
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
} }
} }
} else if (SUCCEEDED(IMFMediaBuffer_QueryInterface(objs->buffer, &SDL_IID_IMF2DBuffer, (void **)&objs->buffer2d))) { } else if (frame->format != SDL_PIXELFORMAT_MJPG &&
SUCCEEDED(IMFMediaBuffer_QueryInterface(objs->buffer, &SDL_IID_IMF2DBuffer, (void **)&objs->buffer2d))) {
ret = IMF2DBuffer_Lock2D(objs->buffer2d, &pixels, &pitch); ret = IMF2DBuffer_Lock2D(objs->buffer2d, &pixels, &pitch);
if (FAILED(ret)) { if (FAILED(ret)) {
CleanupIMF2DBuffer(NULL, objs); CleanupIMF2DBuffer(NULL, objs);
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
} else { } else {
if (pitch < 0) { // image rows are reversed.
pixels += -pitch * (frame->h - 1);
}
frame->pixels = pixels; frame->pixels = pixels;
frame->pitch = (int) pitch; frame->pitch = (int)pitch;
if (!SDL_SetPointerPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMF2DBuffer, NULL)) { if (!SDL_SetPointerPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMF2DBuffer, NULL)) {
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
} }
} }
} else { } else {
DWORD maxlen = 0, currentlen = 0; DWORD maxlen = 0;
ret = IMFMediaBuffer_Lock(objs->buffer, &pixels, &maxlen, &currentlen); ret = IMFMediaBuffer_Lock(objs->buffer, &pixels, &maxlen, &buflen);
if (FAILED(ret)) { if (FAILED(ret)) {
CleanupIMFMediaBuffer(NULL, objs); CleanupIMFMediaBuffer(NULL, objs);
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
} else { } else {
if (frame->format == SDL_PIXELFORMAT_MJPG) { if (frame->format == SDL_PIXELFORMAT_MJPG) {
pitch = (LONG)currentlen; pitch = (LONG)buflen;
} else { } else {
pitch = (LONG)device->hidden->pitch; pitch = (LONG)device->hidden->pitch;
if (pitch < 0) { // image rows are reversed. }
pixels += -pitch * (frame->h - 1); if (pitch < 0) { // image rows are reversed.
} pixels += -pitch * (frame->h - 1);
} }
frame->pixels = pixels; frame->pixels = pixels;
frame->pitch = (int) pitch; frame->pitch = (int)pitch;
if (!SDL_SetPointerPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMFMediaBuffer, NULL)) { if (!SDL_SetPointerPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMFMediaBuffer, NULL)) {
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
} }
@@ -539,15 +545,20 @@ static void MEDIAFOUNDATION_ReleaseFrame(SDL_Camera *device, SDL_Surface *frame)
#else #else
static SDL_CameraFrameResult MEDIAFOUNDATION_CopyFrame(SDL_Surface *frame, const void *pixels, LONG pitch, DWORD buflen) static SDL_CameraFrameResult MEDIAFOUNDATION_CopyFrame(SDL_Surface *frame, const BYTE *pixels, LONG pitch, DWORD buflen)
{ {
frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen); frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen);
if (!frame->pixels) { if (!frame->pixels) {
return SDL_CAMERA_FRAME_ERROR; return SDL_CAMERA_FRAME_ERROR;
} }
SDL_memcpy(frame->pixels, pixels, buflen); const BYTE *start = pixels;
if (pitch < 0) { // image rows are reversed.
start += -pitch * (frame->h - 1);
}
SDL_memcpy(frame->pixels, start, buflen);
frame->pitch = (int)pitch; frame->pitch = (int)pitch;
return SDL_CAMERA_FRAME_READY; return SDL_CAMERA_FRAME_READY;
} }
@@ -584,19 +595,18 @@ static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SD
IMF2DBuffer2 *buffer2d2 = NULL; IMF2DBuffer2 *buffer2d2 = NULL;
BYTE *pixels = NULL; BYTE *pixels = NULL;
LONG pitch = 0; LONG pitch = 0;
DWORD buflen = 0;
if (SUCCEEDED(IMFMediaBuffer_QueryInterface(buffer, &SDL_IID_IMF2DBuffer2, (void **)&buffer2d2))) { if (SUCCEEDED(IMFMediaBuffer_QueryInterface(buffer, &SDL_IID_IMF2DBuffer2, (void **)&buffer2d2))) {
BYTE *bufstart = NULL; BYTE *bufstart = NULL;
DWORD buflen = 0;
ret = IMF2DBuffer2_Lock2DSize(buffer2d2, MF2DBuffer_LockFlags_Read, &pixels, &pitch, &bufstart, &buflen); ret = IMF2DBuffer2_Lock2DSize(buffer2d2, MF2DBuffer_LockFlags_Read, &pixels, &pitch, &bufstart, &buflen);
if (FAILED(ret)) { if (FAILED(ret)) {
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
} else { } else {
if (frame->format == SDL_PIXELFORMAT_MJPG) { if (frame->format == SDL_PIXELFORMAT_MJPG) {
result = MEDIAFOUNDATION_CopyFrame(frame, pixels, (LONG)buflen, buflen); pitch = (LONG)buflen;
} else {
result = MEDIAFOUNDATION_CopyFrame(frame, pixels, pitch, buflen);
} }
result = MEDIAFOUNDATION_CopyFrame(frame, pixels, pitch, buflen);
IMF2DBuffer2_Unlock2D(buffer2d2); IMF2DBuffer2_Unlock2D(buffer2d2);
} }
IMF2DBuffer2_Release(buffer2d2); IMF2DBuffer2_Release(buffer2d2);
@@ -606,32 +616,23 @@ static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SD
if (FAILED(ret)) { if (FAILED(ret)) {
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
} else { } else {
BYTE *bufstart = pixels; buflen = SDL_abs((int)pitch) * frame->h;
const DWORD buflen = SDL_abs((int)pitch) * frame->h; result = MEDIAFOUNDATION_CopyFrame(frame, pixels, pitch, buflen);
if (pitch < 0) { // image rows are reversed.
bufstart += -pitch * (frame->h - 1);
}
result = MEDIAFOUNDATION_CopyFrame(frame, bufstart, pitch, buflen);
IMF2DBuffer_Unlock2D(buffer2d); IMF2DBuffer_Unlock2D(buffer2d);
} }
IMF2DBuffer_Release(buffer2d); IMF2DBuffer_Release(buffer2d);
} else { } else {
DWORD maxlen = 0, currentlen = 0; DWORD maxlen = 0;
ret = IMFMediaBuffer_Lock(buffer, &pixels, &maxlen, &currentlen); ret = IMFMediaBuffer_Lock(buffer, &pixels, &maxlen, &buflen);
if (FAILED(ret)) { if (FAILED(ret)) {
result = SDL_CAMERA_FRAME_ERROR; result = SDL_CAMERA_FRAME_ERROR;
} else { } else {
if (frame->format == SDL_PIXELFORMAT_MJPG) { if (frame->format == SDL_PIXELFORMAT_MJPG) {
result = MEDIAFOUNDATION_CopyFrame(frame, pixels, (LONG)currentlen, currentlen); pitch = (LONG)buflen;
} else { } else {
BYTE *bufstart = pixels;
pitch = (LONG)device->hidden->pitch; pitch = (LONG)device->hidden->pitch;
const DWORD buflen = (SDL_abs((int)pitch) * frame->w) * frame->h;
if (pitch < 0) { // image rows are reversed.
bufstart += -pitch * (frame->h - 1);
}
result = MEDIAFOUNDATION_CopyFrame(frame, bufstart, pitch, buflen);
} }
result = MEDIAFOUNDATION_CopyFrame(frame, pixels, pitch, buflen);
IMFMediaBuffer_Unlock(buffer); IMFMediaBuffer_Unlock(buffer);
} }
} }