summaryrefslogtreecommitdiffstats
path: root/video/out/vo_rpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/vo_rpi.c')
-rw-r--r--video/out/vo_rpi.c128
1 files changed, 90 insertions, 38 deletions
diff --git a/video/out/vo_rpi.c b/video/out/vo_rpi.c
index b192476e52..e5ca1d79e3 100644
--- a/video/out/vo_rpi.c
+++ b/video/out/vo_rpi.c
@@ -30,8 +30,6 @@
#include <libavutil/rational.h>
-#include "osdep/atomics.h"
-
#include "common/common.h"
#include "common/msg.h"
#include "options/m_config.h"
@@ -69,11 +67,10 @@ struct priv {
// for RAM input
MMAL_POOL_T *swpool;
- atomic_bool update_display;
-
pthread_mutex_t vsync_mutex;
pthread_cond_t vsync_cond;
int64_t vsync_counter;
+ bool reload_display;
int background_layer;
int video_layer;
@@ -89,6 +86,8 @@ struct priv {
#define ALIGN_W 32
#define ALIGN_H 16
+static void recreate_renderer(struct vo *vo);
+
// Make mpi point to buffer, assuming MMAL_ENCODING_I420.
// buffer can be NULL.
// Return the required buffer space.
@@ -255,6 +254,9 @@ static int create_overlays(struct vo *vo)
struct priv *p = vo->priv;
destroy_overlays(vo);
+ if (!p->display)
+ return -1;
+
if (vo->opts->fullscreen && p->background) {
// Use the whole screen.
VC_RECT_T dst = {.width = p->w, .height = p->h};
@@ -362,7 +364,7 @@ static void wait_next_vsync(struct vo *vo)
struct priv *p = vo->priv;
pthread_mutex_lock(&p->vsync_mutex);
int64_t old = p->vsync_counter;
- while (old == p->vsync_counter)
+ while (old == p->vsync_counter && !p->reload_display)
pthread_cond_wait(&p->vsync_cond, &p->vsync_mutex);
pthread_mutex_unlock(&p->vsync_mutex);
}
@@ -370,6 +372,10 @@ static void wait_next_vsync(struct vo *vo)
static void flip_page(struct vo *vo)
{
struct priv *p = vo->priv;
+
+ if (!p->renderer_enabled)
+ return;
+
struct mp_image *mpi = p->next_image;
p->next_image = NULL;
@@ -405,6 +411,9 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
{
struct priv *p = vo->priv;
+ if (!p->renderer_enabled)
+ return;
+
mp_image_t *mpi = NULL;
if (!frame->redraw && !frame->repeat)
mpi = mp_image_new_ref(frame->current);
@@ -506,6 +515,9 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
MMAL_PORT_T *input = p->renderer->input[0];
bool opaque = params->imgfmt == IMGFMT_MMAL;
+ if (!p->display)
+ return -1;
+
disable_renderer(vo);
input->format->encoding = opaque ? MMAL_ENCODING_OPAQUE : MMAL_ENCODING_I420;
@@ -560,6 +572,9 @@ static struct mp_image *take_screenshot(struct vo *vo)
{
struct priv *p = vo->priv;
+ if (!p->display)
+ return NULL;
+
struct mp_image *img = mp_image_alloc(IMGFMT_BGR0, p->w, p->h);
if (!img)
return NULL;
@@ -612,14 +627,15 @@ static int control(struct vo *vo, uint32_t request, void *data)
case VOCTRL_SCREENSHOT_WIN:
*(struct mp_image **)data = take_screenshot(vo);
return VO_TRUE;
- case VOCTRL_CHECK_EVENTS:
- if (atomic_load(&p->update_display)) {
- atomic_store(&p->update_display, false);
- update_display_size(vo);
- if (p->renderer_enabled)
- set_geometry(vo);
- }
+ case VOCTRL_CHECK_EVENTS: {
+ pthread_mutex_lock(&p->vsync_mutex);
+ bool reload_required = p->reload_display;
+ p->reload_display = false;
+ pthread_mutex_unlock(&p->vsync_mutex);
+ if (reload_required)
+ recreate_renderer(vo);
return VO_TRUE;
+ }
case VOCTRL_GET_DISPLAY_FPS:
*(double *)data = p->display_fps;
return VO_TRUE;
@@ -633,7 +649,10 @@ static void tv_callback(void *callback_data, uint32_t reason, uint32_t param1,
{
struct vo *vo = callback_data;
struct priv *p = vo->priv;
- atomic_store(&p->update_display, true);
+ pthread_mutex_lock(&p->vsync_mutex);
+ p->reload_display = true;
+ pthread_cond_signal(&p->vsync_cond);
+ pthread_mutex_unlock(&p->vsync_mutex);
vo_wakeup(vo);
}
@@ -647,6 +666,55 @@ static void vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *arg)
pthread_mutex_unlock(&p->vsync_mutex);
}
+static void destroy_dispmanx(struct vo *vo)
+{
+ struct priv *p = vo->priv;
+
+ disable_renderer(vo);
+ destroy_overlays(vo);
+
+ if (p->display) {
+ vc_dispmanx_vsync_callback(p->display, NULL, NULL);
+ vc_dispmanx_display_close(p->display);
+ }
+ p->display = 0;
+}
+
+static int recreate_dispmanx(struct vo *vo)
+{
+ struct priv *p = vo->priv;
+
+ p->display = vc_dispmanx_display_open(p->display_nr);
+ p->update = vc_dispmanx_update_start(0);
+ if (!p->display || !p->update) {
+ MP_FATAL(vo, "Could not get DISPMANX objects.\n");
+ if (p->display)
+ vc_dispmanx_display_close(p->display);
+ p->display = 0;
+ p->update = 0;
+ return -1;
+ }
+
+ update_display_size(vo);
+
+ vc_dispmanx_vsync_callback(p->display, vsync_callback, vo);
+
+ return 0;
+}
+
+static void recreate_renderer(struct vo *vo)
+{
+ MP_WARN(vo, "Recreating renderer after display change.\n");
+
+ destroy_dispmanx(vo);
+ recreate_dispmanx(vo);
+
+ if (vo->params) {
+ if (reconfig(vo, vo->params) < 0)
+ MP_FATAL(vo, "Recreation failed.\n");
+ }
+}
+
static void uninit(struct vo *vo)
{
struct priv *p = vo->priv;
@@ -655,20 +723,10 @@ static void uninit(struct vo *vo)
talloc_free(p->next_image);
- destroy_overlays(vo);
-
- if (p->update)
- vc_dispmanx_update_submit_sync(p->update);
+ destroy_dispmanx(vo);
- if (p->renderer) {
- disable_renderer(vo);
+ if (p->renderer)
mmal_component_release(p->renderer);
- }
-
- if (p->display) {
- vc_dispmanx_vsync_callback(p->display, NULL, NULL);
- vc_dispmanx_display_close(p->display);
- }
mmal_vc_deinit();
@@ -693,12 +751,14 @@ static int preinit(struct vo *vo)
return -1;
}
- p->display = vc_dispmanx_display_open(p->display_nr);
- p->update = vc_dispmanx_update_start(0);
- if (!p->display || !p->update) {
- MP_FATAL(vo, "Could not get DISPMANX objects.\n");
+ pthread_mutex_init(&p->vsync_mutex, NULL);
+ pthread_cond_init(&p->vsync_cond, NULL);
+
+ if (recreate_dispmanx(vo) < 0)
+ goto fail;
+
+ if (update_display_size(vo) < 0)
goto fail;
- }
if (mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &p->renderer))
{
@@ -706,16 +766,8 @@ static int preinit(struct vo *vo)
goto fail;
}
- if (update_display_size(vo) < 0)
- goto fail;
-
vc_tv_register_callback(tv_callback, vo);
- pthread_mutex_init(&p->vsync_mutex, NULL);
- pthread_cond_init(&p->vsync_cond, NULL);
-
- vc_dispmanx_vsync_callback(p->display, vsync_callback, vo);
-
return 0;
fail: