mirror of
https://git.planet-casio.com/Lephenixnoir/fxsdk.git
synced 2024-12-29 13:03: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)
|
project(fxSDK VERSION 2.5.2 LANGUAGES C)
|
||||||
|
|
||||||
option(FXLINK_DISABLE_UDISKS2 "Do not build the UDisks2-based features of fxlink")
|
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)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(libpng REQUIRED libpng16 IMPORTED_TARGET)
|
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)
|
if(NOT FXLINK_DISABLE_UDISKS2)
|
||||||
pkg_check_modules(udisks2 REQUIRED udisks2 IMPORTED_TARGET)
|
pkg_check_modules(udisks2 REQUIRED udisks2 IMPORTED_TARGET)
|
||||||
endif()
|
endif()
|
||||||
|
if(NOT FXLINK_DISABLE_SDL2)
|
||||||
|
pkg_check_modules(sdl2 REQUIRED sdl2 IMPORTED_TARGET)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CMAKE_INSTALL_MESSAGE LAZY)
|
set(CMAKE_INSTALL_MESSAGE LAZY)
|
||||||
set(SRC "${CMAKE_CURRENT_SOURCE_DIR}")
|
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")
|
configure_file(fxlink/config.h.in "${BIN}/include/fxlink/config.h")
|
||||||
add_executable(fxlink fxlink/usb.c fxlink/filter.c fxlink/interactive.c
|
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/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_link_libraries(fxlink PkgConfig::libpng PkgConfig::libusb) # PkgConfig::libudev
|
||||||
target_include_directories(fxlink PRIVATE "${BIN}/include/fxlink")
|
target_include_directories(fxlink PRIVATE "${BIN}/include/fxlink")
|
||||||
if(NOT FXLINK_DISABLE_UDISKS2)
|
if(NOT FXLINK_DISABLE_UDISKS2)
|
||||||
target_link_libraries(fxlink PkgConfig::udisks2)
|
target_link_libraries(fxlink PkgConfig::udisks2)
|
||||||
endif()
|
endif()
|
||||||
|
if(NOT FXLINK_DISABLE_SDL2)
|
||||||
|
target_link_libraries(fxlink PkgConfig::sdl2)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Install rules
|
# Install rules
|
||||||
|
|
||||||
|
|
|
@ -8,4 +8,7 @@
|
||||||
/* Disables UDisks2 interfaces for systems that don't use it. */
|
/* Disables UDisks2 interfaces for systems that don't use it. */
|
||||||
#cmakedefine FXLINK_DISABLE_UDISKS2
|
#cmakedefine FXLINK_DISABLE_UDISKS2
|
||||||
|
|
||||||
|
/* Disable SDL2 interfaces. */
|
||||||
|
#cmakedefine FXLINK_DISABLE_SDL2
|
||||||
|
|
||||||
#endif /* FXLINK_CONFIG_H */
|
#endif /* FXLINK_CONFIG_H */
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "png.h"
|
#include "png.h"
|
||||||
|
#include "sdl2.h"
|
||||||
|
|
||||||
#include <libusb.h>
|
#include <libusb.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -88,6 +89,18 @@ static void message_finish(message_t *msg)
|
||||||
printf("------------------\n");
|
printf("------------------\n");
|
||||||
return;
|
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 */
|
/* Default to saving to a blob */
|
||||||
|
@ -170,9 +183,13 @@ int main_interactive(filter_t *filter, delay_t *delay, libusb_context *context)
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
|
#ifndef FXLINK_DISABLE_SDL2
|
||||||
|
sdl2_tick();
|
||||||
|
#endif
|
||||||
|
|
||||||
int transferred = -1;
|
int transferred = -1;
|
||||||
rc = libusb_bulk_transfer(dh, 0x81, buffer + buffer_size, 2048,
|
rc = libusb_bulk_transfer(dh, 0x81, buffer + buffer_size, 2048,
|
||||||
&transferred, 2000);
|
&transferred, 500);
|
||||||
|
|
||||||
if(rc == LIBUSB_ERROR_NO_DEVICE) {
|
if(rc == LIBUSB_ERROR_NO_DEVICE) {
|
||||||
printf("Disconnected, leaving.\n");
|
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