mirror of
https://github.com/vanilla-wiiu/vanilla.git
synced 2025-01-22 08:11:47 -05:00
wow 60 fps!
This commit is contained in:
parent
8c1db345ad
commit
9252f39336
3 changed files with 73 additions and 57 deletions
70
rpi/drm.c
70
rpi/drm.c
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include <drm_fourcc.h>
|
||||
#include <fcntl.h>
|
||||
#include <libavutil/hwcontext_drm.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -10,12 +9,11 @@
|
|||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#define DRM_FORMAT_MAX_PLANES 4u
|
||||
#define ALIGN(x, a) ((x) + (a - 1)) & (~(a - 1))
|
||||
|
||||
int set_tty(int mode)
|
||||
{
|
||||
/*int tty_fd = open("/dev/tty", O_RDWR);
|
||||
/*int tty_fd = open("/dev/tty0", O_RDWR);
|
||||
if (tty_fd == -1) {
|
||||
fprintf(stderr, "Failed to open /dev/tty\n");
|
||||
return 0;
|
||||
|
@ -26,10 +24,11 @@ int set_tty(int mode)
|
|||
}
|
||||
close(tty_fd);*/
|
||||
|
||||
if (ioctl(STDIN_FILENO, KDSETMODE, mode) < 0) {
|
||||
/*if (ioctl(STDIN_FILENO, KDSETMODE, mode) < 0) {
|
||||
fprintf(stderr, "Failed to set KDSETMODE: %s (%i)\n", strerror(errno), errno);
|
||||
return 0;
|
||||
}
|
||||
}*/
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -81,6 +80,8 @@ int initialize_drm(vanilla_drm_ctx_t *ctx)
|
|||
|
||||
ctx->got_plane = 0;
|
||||
ctx->got_fb = 0;
|
||||
ctx->got_handles = 0;
|
||||
memset(ctx->handles, 0, sizeof(ctx->handles));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -148,10 +149,6 @@ extern int running;
|
|||
int display_drm(vanilla_drm_ctx_t *ctx, AVFrame *frame)
|
||||
{
|
||||
const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *) frame->data[0];
|
||||
/*if (!desc) {
|
||||
return 1;
|
||||
}*/
|
||||
|
||||
const uint32_t format = desc->layers[0].format;
|
||||
|
||||
if (!ctx->got_plane) {
|
||||
|
@ -179,28 +176,15 @@ int display_drm(vanilla_drm_ctx_t *ctx, AVFrame *frame)
|
|||
return 1;
|
||||
}*/
|
||||
|
||||
uint32_t handles[AV_DRM_MAX_PLANES];
|
||||
uint32_t pitches[DRM_FORMAT_MAX_PLANES] = {0};
|
||||
uint32_t offsets[DRM_FORMAT_MAX_PLANES] = {0};
|
||||
uint32_t bo_handles[DRM_FORMAT_MAX_PLANES] = {0};
|
||||
uint64_t modifiers[DRM_FORMAT_MAX_PLANES] = {0};
|
||||
uint32_t pitches[AV_DRM_MAX_PLANES] = {0};
|
||||
uint32_t offsets[AV_DRM_MAX_PLANES] = {0};
|
||||
uint32_t bo_handles[AV_DRM_MAX_PLANES] = {0};
|
||||
uint64_t modifiers[AV_DRM_MAX_PLANES] = {0};
|
||||
|
||||
// Free old handles
|
||||
if (ctx->got_fb) {
|
||||
drmModeRmFB(ctx->fd, ctx->fb_id);
|
||||
ctx->fb_id = 0;
|
||||
|
||||
struct drm_gem_close gem_close = {0};
|
||||
for (int i = 0; i < desc->nb_objects; i++) {
|
||||
if (handles[i]) {
|
||||
gem_close.handle = handles[i];
|
||||
drmIoctl(ctx->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t new_handles[AV_DRM_MAX_PLANES] = {0};
|
||||
|
||||
for (int i = 0; i < desc->nb_objects; i++) {
|
||||
if (drmPrimeFDToHandle(ctx->fd, desc->objects[i].fd, &handles[i]) != 0) {
|
||||
if (drmPrimeFDToHandle(ctx->fd, desc->objects[i].fd, &new_handles[i]) != 0) {
|
||||
fprintf(stderr, "Failed to get handle from file descriptor: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
@ -216,7 +200,7 @@ int display_drm(vanilla_drm_ctx_t *ctx, AVFrame *frame)
|
|||
pitches[n] = plane->pitch;
|
||||
offsets[n] = plane->offset;
|
||||
modifiers[n] = obj->format_modifier;
|
||||
bo_handles[n] = handles[plane->object_index];
|
||||
bo_handles[n] = new_handles[plane->object_index];
|
||||
|
||||
n++;
|
||||
}
|
||||
|
@ -245,23 +229,41 @@ int display_drm(vanilla_drm_ctx_t *ctx, AVFrame *frame)
|
|||
(long long)modifiers[3]
|
||||
);*/
|
||||
|
||||
|
||||
uint32_t new_fb;
|
||||
if (drmModeAddFB2WithModifiers(ctx->fd,
|
||||
frame->width, frame->height, desc->layers[0].format,
|
||||
bo_handles, pitches, offsets, modifiers,
|
||||
&ctx->fb_id, DRM_MODE_FB_MODIFIERS) != 0) {
|
||||
&new_fb, DRM_MODE_FB_MODIFIERS) != 0) {
|
||||
fprintf(stderr, "Failed to create framebuffer: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx->got_fb = 1;
|
||||
|
||||
if (drmModeSetPlane(ctx->fd, ctx->plane_id, ctx->crtc, ctx->fb_id, 0,
|
||||
if (drmModeSetPlane(ctx->fd, ctx->plane_id, ctx->crtc, new_fb, 0,
|
||||
0, 0, frame->width, frame->height,
|
||||
0, 0, frame->width << 16, frame->height << 16) != 0) {
|
||||
fprintf(stderr, "Failed to set plane: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Free old framebuffer
|
||||
if (ctx->got_fb) {
|
||||
drmModeRmFB(ctx->fd, ctx->fb_id);
|
||||
}
|
||||
ctx->fb_id = new_fb;
|
||||
ctx->got_fb = 1;
|
||||
|
||||
if (ctx->got_handles) {
|
||||
struct drm_gem_close gem_close = {0};
|
||||
for (int i = 0; i < desc->nb_objects; i++) {
|
||||
if (ctx->handles[i]) {
|
||||
gem_close.handle = ctx->handles[i];
|
||||
drmIoctl(ctx->fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
|
||||
ctx->handles[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(ctx->handles, new_handles, sizeof(ctx->handles));
|
||||
ctx->got_handles = 1;
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
#define VANILLA_PI_DRM_H
|
||||
|
||||
#include <libavutil/frame.h>
|
||||
#include <libavutil/hwcontext_drm.h>
|
||||
#include <linux/kd.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -13,6 +14,8 @@ typedef struct {
|
|||
int got_plane;
|
||||
uint32_t fb_id;
|
||||
int got_fb;
|
||||
uint32_t handles[AV_DRM_MAX_PLANES];
|
||||
int got_handles;
|
||||
} vanilla_drm_ctx_t;
|
||||
|
||||
int set_tty(int mode);
|
||||
|
|
57
rpi/main.c
57
rpi/main.c
|
@ -8,6 +8,7 @@
|
|||
#include <libavfilter/buffersrc.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
@ -19,8 +20,8 @@
|
|||
|
||||
AVFrame *present_frame;
|
||||
AVFrame *decoding_frame;
|
||||
sem_t decoding_sem;
|
||||
SDL_mutex *decoding_mutex;
|
||||
pthread_mutex_t decoding_mutex;
|
||||
pthread_cond_t decoding_wait_cond;
|
||||
AVCodecContext *video_codec_ctx;
|
||||
AVCodecParserContext *video_parser;
|
||||
AVPacket *video_packet;
|
||||
|
@ -43,7 +44,7 @@ enum AVPixelFormat get_format(AVCodecContext* ctx, const enum AVPixelFormat *pix
|
|||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
int decode_frame(const void *data, size_t size)
|
||||
int decode(const void *data, size_t size)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -80,20 +81,14 @@ int decode_frame(const void *data, size_t size)
|
|||
fprintf(stderr, "GOT A CORRUPT FRAME??????\n");
|
||||
abort();
|
||||
} else {
|
||||
SDL_LockMutex(decoding_mutex);
|
||||
pthread_mutex_lock(&decoding_mutex);
|
||||
|
||||
// Swap frames
|
||||
// Swap refs from decoding_frame to present_frame
|
||||
av_frame_unref(present_frame);
|
||||
av_frame_ref(present_frame, decoding_frame);
|
||||
|
||||
// printf("Frame decoded (%i), sent to display...\n", present_frame->format);
|
||||
|
||||
// Un-ref frame
|
||||
av_frame_unref(decoding_frame);
|
||||
av_frame_move_ref(present_frame, decoding_frame);
|
||||
|
||||
SDL_UnlockMutex(decoding_mutex);
|
||||
|
||||
sem_post(&decoding_sem);
|
||||
pthread_cond_broadcast(&decoding_wait_cond);
|
||||
pthread_mutex_unlock(&decoding_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +101,7 @@ int run_backend(void *data)
|
|||
|
||||
while (vanilla_wait_event(&event)) {
|
||||
if (event.type == VANILLA_EVENT_VIDEO) {
|
||||
decode_frame(event.data, event.size);
|
||||
decode(event.data, event.size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,14 +125,22 @@ int display_loop(void *data)
|
|||
|
||||
AVFrame *frame = av_frame_alloc();
|
||||
|
||||
pthread_mutex_lock(&decoding_mutex);
|
||||
|
||||
while (running) {
|
||||
sem_wait(&decoding_sem);
|
||||
while (running && !present_frame->data[0]) {
|
||||
pthread_cond_wait(&decoding_wait_cond, &decoding_mutex);
|
||||
}
|
||||
|
||||
if (!running) {
|
||||
break;
|
||||
}
|
||||
|
||||
// If a frame is available, present it here
|
||||
SDL_LockMutex(decoding_mutex);
|
||||
av_frame_unref(frame);
|
||||
av_frame_ref(frame, present_frame);
|
||||
SDL_UnlockMutex(decoding_mutex);
|
||||
av_frame_move_ref(frame, present_frame);
|
||||
|
||||
pthread_mutex_unlock(&decoding_mutex);
|
||||
|
||||
display_drm(drm_ctx, frame);
|
||||
|
||||
|
@ -157,8 +160,12 @@ int display_loop(void *data)
|
|||
|
||||
tick_delta_index = 0;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&decoding_mutex);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&decoding_mutex);
|
||||
|
||||
av_frame_free(&frame);
|
||||
|
||||
return 0;
|
||||
|
@ -187,8 +194,6 @@ void sigint_handler(int signum)
|
|||
ev.type = SDL_QUIT;
|
||||
ev.timestamp = SDL_GetTicks();
|
||||
SDL_PushEvent((SDL_Event *) &ev);
|
||||
|
||||
sem_post(&decoding_sem);
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
|
@ -272,7 +277,8 @@ int main(int argc, const char **argv)
|
|||
running = 1;
|
||||
signal(SIGINT, sigint_handler);
|
||||
|
||||
sem_init(&decoding_sem, 0, 0);
|
||||
pthread_mutex_init(&decoding_mutex, NULL);
|
||||
pthread_cond_init(&decoding_wait_cond, NULL);
|
||||
|
||||
// Start background threads
|
||||
SDL_Thread *backend_thread = SDL_CreateThread(run_backend, "Backend", NULL);
|
||||
|
@ -345,12 +351,17 @@ int main(int argc, const char **argv)
|
|||
|
||||
// Terminate background threads and wait for them to end gracefully
|
||||
vanilla_stop();
|
||||
|
||||
pthread_mutex_lock(&decoding_mutex);
|
||||
running = 0;
|
||||
pthread_cond_broadcast(&decoding_wait_cond);
|
||||
pthread_mutex_unlock(&decoding_mutex);
|
||||
|
||||
SDL_WaitThread(backend_thread, NULL);
|
||||
SDL_WaitThread(display_thread, NULL);
|
||||
|
||||
sem_destroy(&decoding_sem);
|
||||
pthread_cond_destroy(&decoding_wait_cond);
|
||||
pthread_mutex_destroy(&decoding_mutex);
|
||||
|
||||
av_parser_close(video_parser);
|
||||
av_frame_free(&present_frame);
|
||||
|
|
Loading…
Reference in a new issue