static void event_handler(void *arg) { SDL_Event event; char ch; (void)arg; tmr_start(&sdl.tmr, 100, event_handler, NULL); while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_ESCAPE: if (!sdl.fullscreen) break; sdl.fullscreen = false; sdl_reset(); break; case SDLK_f: if (sdl.fullscreen) break; sdl.fullscreen = true; sdl_reset(); break; default: ch = event.key.keysym.unicode & 0x7f; /* Relay key-press to UI subsystem */ if (isprint(ch)) { tmr_start(&sdl.tmr, KEY_RELEASE_VAL, timeout, NULL); ui_input(ch); } break; } break; case SDL_VIDEORESIZE: handle_resize(event.resize.w, event.resize.h); break; case SDL_QUIT: ui_input('q'); break; default: break; } } }
static void destructor(void *arg) { struct vidisp_st *st = arg; tmr_cancel(&st->tmr); sdl_reset(st); }
static void sdl_close(void) { tmr_cancel(&sdl.tmr); sdl_reset(); if (sdl.open) { SDL_Quit(); sdl.open = false; } }
static int display(struct vidisp_st *st, const char *title, const struct vidframe *frame) { void *pixels; uint8_t *p; int pitch, ret; unsigned i, h; if (!vidsz_cmp(&st->size, &frame->size)) { if (st->size.w && st->size.h) { info("sdl: reset size: %u x %u ---> %u x %u\n", st->size.w, st->size.h, frame->size.w, frame->size.h); } sdl_reset(st); } if (!st->window) { Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_INPUT_FOCUS; char capt[256]; if (st->fullscreen) flags |= SDL_WINDOW_FULLSCREEN; if (title) { re_snprintf(capt, sizeof(capt), "%s - %u x %u", title, frame->size.w, frame->size.h); } else { re_snprintf(capt, sizeof(capt), "%u x %u", frame->size.w, frame->size.h); } st->window = SDL_CreateWindow(capt, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, frame->size.w, frame->size.h, flags); if (!st->window) { warning("sdl: unable to create sdl window: %s\n", SDL_GetError()); return ENODEV; } st->size = frame->size; SDL_RaiseWindow(st->window); SDL_SetWindowBordered(st->window, true); SDL_ShowWindow(st->window); } if (!st->renderer) { Uint32 flags = 0; flags |= SDL_RENDERER_ACCELERATED; flags |= SDL_RENDERER_PRESENTVSYNC; st->renderer = SDL_CreateRenderer(st->window, -1, flags); if (!st->renderer) { warning("sdl: unable to create renderer: %s\n", SDL_GetError()); return ENOMEM; } } if (!st->texture) { st->texture = SDL_CreateTexture(st->renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, frame->size.w, frame->size.h); if (!st->texture) { warning("sdl: unable to create texture: %s\n", SDL_GetError()); return ENODEV; } } ret = SDL_LockTexture(st->texture, NULL, &pixels, &pitch); if (ret != 0) { warning("sdl: unable to lock texture (ret=%d)\n", ret); return ENODEV; } p = pixels; for (i=0; i<3; i++) { const uint8_t *s = frame->data[i]; const unsigned stp = frame->linesize[0] / frame->linesize[i]; const unsigned sz = frame->size.w / stp; for (h = 0; h < frame->size.h; h += stp) { memcpy(p, s, sz); s += frame->linesize[i]; p += (pitch / stp); } } SDL_UnlockTexture(st->texture); /* Blit the sprite onto the screen */ SDL_RenderCopy(st->renderer, st->texture, NULL, NULL); /* Update the screen! */ SDL_RenderPresent(st->renderer); return 0; }
static void destructor(void *arg) { struct vidisp_st *st = arg; sdl_reset(st); }
/** * Display a video frame * * @param st Video display state * @param title Window title * @param frame Video frame * * @return 0 if success, otherwise errorcode * * @note: On Darwin, this must be called from the main thread */ static int display(struct vidisp_st *st, const char *title, const struct vidframe *frame) { SDL_Rect rect; if (!st || !sdl.open) return EINVAL; if (!vidsz_cmp(&sdl.size, &frame->size)) { if (sdl.size.w && sdl.size.h) { info("sdl: reset size %u x %u ---> %u x %u\n", sdl.size.w, sdl.size.h, frame->size.w, frame->size.h); } sdl_reset(); } if (!sdl.screen) { int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL; char capt[256]; if (sdl.fullscreen) flags |= SDL_FULLSCREEN; else if (sdl.resizeh) flags |= SDL_RESIZABLE; if (title) { re_snprintf(capt, sizeof(capt), "%s - %u x %u", title, frame->size.w, frame->size.h); } else { re_snprintf(capt, sizeof(capt), "%u x %u", frame->size.w, frame->size.h); } SDL_WM_SetCaption(capt, capt); sdl.screen = SDL_SetVideoMode(frame->size.w, frame->size.h, 0, flags); if (!sdl.screen) { warning("sdl: unable to get video screen: %s\n", SDL_GetError()); return ENODEV; } sdl.size = frame->size; } if (!sdl.bmp) { sdl.bmp = SDL_CreateYUVOverlay(frame->size.w, frame->size.h, SDL_YV12_OVERLAY, sdl.screen); if (!sdl.bmp) { warning("sdl: unable to create overlay: %s\n", SDL_GetError()); return ENODEV; } } SDL_LockYUVOverlay(sdl.bmp); picture_copy(sdl.bmp->pixels, sdl.bmp->pitches, frame); SDL_UnlockYUVOverlay(sdl.bmp); rect.x = 0; rect.y = 0; rect.w = sdl.size.w; rect.h = sdl.size.h; SDL_DisplayYUVOverlay(sdl.bmp, &rect); return 0; }
static int display(struct vidisp_st *st, const char *title, const struct vidframe *frame) { void *pixels; uint8_t *d; int dpitch, ret; unsigned i, h; uint32_t format; if (!st || !frame) return EINVAL; format = match_fmt(frame->fmt); if (format == SDL_PIXELFORMAT_UNKNOWN) { warning("sdl2: pixel format not supported (%s)\n", vidfmt_name(frame->fmt)); return ENOTSUP; } if (!vidsz_cmp(&st->size, &frame->size) || frame->fmt != st->fmt) { if (st->size.w && st->size.h) { info("sdl: reset size:" " %s %u x %u ---> %s %u x %u\n", vidfmt_name(st->fmt), st->size.w, st->size.h, vidfmt_name(frame->fmt), frame->size.w, frame->size.h); } sdl_reset(st); } if (!st->window) { char capt[256]; st->flags = SDL_WINDOW_SHOWN | SDL_WINDOW_INPUT_FOCUS; if (st->fullscreen) st->flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; if (title) { re_snprintf(capt, sizeof(capt), "%s - %u x %u", title, frame->size.w, frame->size.h); } else { re_snprintf(capt, sizeof(capt), "%u x %u", frame->size.w, frame->size.h); } st->window = SDL_CreateWindow(capt, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, frame->size.w, frame->size.h, st->flags); if (!st->window) { warning("sdl: unable to create sdl window: %s\n", SDL_GetError()); return ENODEV; } st->size = frame->size; st->fmt = frame->fmt; SDL_RaiseWindow(st->window); SDL_SetWindowBordered(st->window, true); SDL_ShowWindow(st->window); } if (!st->renderer) { Uint32 flags = 0; flags |= SDL_RENDERER_ACCELERATED; flags |= SDL_RENDERER_PRESENTVSYNC; st->renderer = SDL_CreateRenderer(st->window, -1, flags); if (!st->renderer) { warning("sdl: unable to create renderer: %s\n", SDL_GetError()); return ENOMEM; } } if (!st->texture) { st->texture = SDL_CreateTexture(st->renderer, format, SDL_TEXTUREACCESS_STREAMING, frame->size.w, frame->size.h); if (!st->texture) { warning("sdl: unable to create texture: %s\n", SDL_GetError()); return ENODEV; } } ret = SDL_LockTexture(st->texture, NULL, &pixels, &dpitch); if (ret != 0) { warning("sdl: unable to lock texture (ret=%d)\n", ret); return ENODEV; } d = pixels; for (i=0; i<3; i++) { const uint8_t *s = frame->data[i]; unsigned sz, dsz, hstep, wstep; if (!frame->data[i] || !frame->linesize[i]) break; hstep = i==0 ? 1 : 2; wstep = i==0 ? 1 : chroma_step(frame->fmt); dsz = dpitch / wstep; sz = min(frame->linesize[i], dsz); for (h = 0; h < frame->size.h; h += hstep) { memcpy(d, s, sz); s += frame->linesize[i]; d += dsz; } } SDL_UnlockTexture(st->texture); /* Blit the sprite onto the screen */ SDL_RenderCopy(st->renderer, st->texture, NULL, NULL); /* Update the screen! */ SDL_RenderPresent(st->renderer); return 0; }