mirror of
https://git.planet-casio.com/Lephenixnoir/fxsdk.git
synced 2024-12-28 04:23:37 +01:00
fxlink: add video capture with frames displayed in an SDL2 window
This commit is contained in:
parent
05d35eb642
commit
c81f9cdba4
5 changed files with 134 additions and 2 deletions
|
@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 3.15)
|
|||
project(fxSDK VERSION 2.5.2 LANGUAGES C)
|
||||
|
||||
option(FXLINK_DISABLE_UDISKS2 "Do not build the UDisks2-based features of fxlink")
|
||||
option(FXLINK_DISABLE_SDL2 "Do not build the SDL2-based features of fxlink")
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(libpng REQUIRED libpng16 IMPORTED_TARGET)
|
||||
|
@ -12,6 +13,9 @@ pkg_check_modules(libusb REQUIRED libusb-1.0 IMPORTED_TARGET)
|
|||
if(NOT FXLINK_DISABLE_UDISKS2)
|
||||
pkg_check_modules(udisks2 REQUIRED udisks2 IMPORTED_TARGET)
|
||||
endif()
|
||||
if(NOT FXLINK_DISABLE_SDL2)
|
||||
pkg_check_modules(sdl2 REQUIRED sdl2 IMPORTED_TARGET)
|
||||
endif()
|
||||
|
||||
set(CMAKE_INSTALL_MESSAGE LAZY)
|
||||
set(SRC "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
@ -36,12 +40,15 @@ add_custom_target(fxsdk ALL DEPENDS "${BIN}/fxsdk.sh")
|
|||
configure_file(fxlink/config.h.in "${BIN}/include/fxlink/config.h")
|
||||
add_executable(fxlink fxlink/usb.c fxlink/filter.c fxlink/interactive.c
|
||||
fxlink/main.c fxlink/png.c fxlink/properties.c fxlink/ud2.c fxlink/util.c
|
||||
fxlink/protocol.c)
|
||||
fxlink/protocol.c fxlink/sdl2.c)
|
||||
target_link_libraries(fxlink PkgConfig::libpng PkgConfig::libusb) # PkgConfig::libudev
|
||||
target_include_directories(fxlink PRIVATE "${BIN}/include/fxlink")
|
||||
if(NOT FXLINK_DISABLE_UDISKS2)
|
||||
target_link_libraries(fxlink PkgConfig::udisks2)
|
||||
endif()
|
||||
if(NOT FXLINK_DISABLE_SDL2)
|
||||
target_link_libraries(fxlink PkgConfig::sdl2)
|
||||
endif()
|
||||
|
||||
# Install rules
|
||||
|
||||
|
|
|
@ -8,4 +8,7 @@
|
|||
/* Disables UDisks2 interfaces for systems that don't use it. */
|
||||
#cmakedefine FXLINK_DISABLE_UDISKS2
|
||||
|
||||
/* Disable SDL2 interfaces. */
|
||||
#cmakedefine FXLINK_DISABLE_SDL2
|
||||
|
||||
#endif /* FXLINK_CONFIG_H */
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "protocol.h"
|
||||
#include "usb.h"
|
||||
#include "png.h"
|
||||
#include "sdl2.h"
|
||||
|
||||
#include <libusb.h>
|
||||
#include <string.h>
|
||||
|
@ -88,6 +89,18 @@ static void message_finish(message_t *msg)
|
|||
printf("------------------\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!strncmp(msg->header.type, "video", 16)) {
|
||||
usb_fxlink_image_t *img = (void *)msg->output;
|
||||
uint8_t **row_pointers = fxlink_protocol_decode_image(msg);
|
||||
|
||||
#ifndef FXLINK_DISABLE_SDL2
|
||||
sdl2_stream(row_pointers, img->width, img->height);
|
||||
#else
|
||||
warn("SDL2 support disabled, skipping video frame!");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Default to saving to a blob */
|
||||
|
@ -170,9 +183,13 @@ int main_interactive(filter_t *filter, delay_t *delay, libusb_context *context)
|
|||
|
||||
while(1)
|
||||
{
|
||||
#ifndef FXLINK_DISABLE_SDL2
|
||||
sdl2_tick();
|
||||
#endif
|
||||
|
||||
int transferred = -1;
|
||||
rc = libusb_bulk_transfer(dh, 0x81, buffer + buffer_size, 2048,
|
||||
&transferred, 2000);
|
||||
&transferred, 500);
|
||||
|
||||
if(rc == LIBUSB_ERROR_NO_DEVICE) {
|
||||
printf("Disconnected, leaving.\n");
|
||||
|
|
82
fxlink/sdl2.c
Normal file
82
fxlink/sdl2.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
#include "config.h"
|
||||
#ifndef FXLINK_DISABLE_SDL2
|
||||
|
||||
#include "sdl2.h"
|
||||
#include "util.h"
|
||||
|
||||
static SDL_Window *window = NULL;
|
||||
|
||||
static int init(size_t width, size_t height)
|
||||
{
|
||||
if(!SDL_WasInit(SDL_INIT_VIDEO)) {
|
||||
int rc = SDL_Init(SDL_INIT_VIDEO);
|
||||
if(rc < 0)
|
||||
return err("Cannot initialize SDL: %s\n", SDL_GetError());
|
||||
}
|
||||
|
||||
window = SDL_CreateWindow("fxlink", SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED, width, height, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((destructor))
|
||||
static void quit(void)
|
||||
{
|
||||
if(!window)
|
||||
return;
|
||||
SDL_DestroyWindow(window);
|
||||
window = NULL;
|
||||
}
|
||||
|
||||
/* Generate an RGB888 surface from image data. */
|
||||
static SDL_Surface *surface_for_image(uint8_t **RGB888_rows, int width,
|
||||
int height)
|
||||
{
|
||||
/* Little endian setup for RGB */
|
||||
SDL_Surface *s = SDL_CreateRGBSurface(0, width, height, 24,
|
||||
0x000000ff, 0x0000ff00, 0x0000ff00, 0);
|
||||
if(!s) {
|
||||
err("Cannot create surface for image");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(int i = 0; i < height; i++)
|
||||
memcpy(s->pixels + i * s->pitch, RGB888_rows[i], width * 3);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void sdl2_stream(uint8_t **RGB888_rows, int width, int height)
|
||||
{
|
||||
if(!window && init(width, height))
|
||||
return;
|
||||
|
||||
int current_w, current_h;
|
||||
SDL_GetWindowSize(window, ¤t_w, ¤t_h);
|
||||
if(current_w != width || current_h != height)
|
||||
SDL_SetWindowSize(window, width, height);
|
||||
|
||||
SDL_Surface *src = surface_for_image(RGB888_rows, width, height);
|
||||
if(!src)
|
||||
return;
|
||||
|
||||
SDL_Surface *dst = SDL_GetWindowSurface(window);
|
||||
SDL_BlitSurface(src, NULL, dst, NULL);
|
||||
SDL_FreeSurface(src);
|
||||
|
||||
SDL_UpdateWindowSurface(window);
|
||||
}
|
||||
|
||||
void sdl2_tick(void)
|
||||
{
|
||||
if(!window)
|
||||
return;
|
||||
|
||||
SDL_Event e;
|
||||
while(SDL_PollEvent(&e)) {
|
||||
if(e.type == SDL_QUIT)
|
||||
quit();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FXLINK_DISABLE_SDL2 */
|
23
fxlink/sdl2.h
Normal file
23
fxlink/sdl2.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
//---
|
||||
// fxlink:sdl2 - SDL2 functions
|
||||
//---
|
||||
|
||||
#ifndef FXLINK_SDL2_H
|
||||
#define FXLINK_SDL2_H
|
||||
|
||||
#ifndef FXLINK_DISABLE_SDL2
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
/* sdl2_stream(): Display a streaming image on the window
|
||||
This function opens or reuses an SDL2 window to display an image. */
|
||||
void sdl2_stream(uint8_t **RGB888_rows, int width, int height);
|
||||
|
||||
/* sdl2_tick(): Handle SDL events
|
||||
This just needs to be called regularly from the main thread, to respond to
|
||||
events on the window. */
|
||||
void sdl2_tick(void);
|
||||
|
||||
#endif /* FXLINK_DISABLE_SDL2 */
|
||||
|
||||
#endif /* FXLINK_SDL2_H */
|
Loading…
Reference in a new issue