wow 60 fps!

This commit is contained in:
itsmattkc 2024-10-27 15:34:06 -07:00
parent 8c1db345ad
commit 9252f39336
3 changed files with 73 additions and 57 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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);