Browse Source

mmal/vout: use a window and report the size from there

pull/170/head
Steve Lhomme 2 years ago
parent
commit
960e5a50b9
  1. 2
      include/vlc_window.h
  2. 208
      modules/hw/mmal/vout.c

2
include/vlc_window.h

@ -66,6 +66,7 @@ enum vlc_window_type {
VLC_WINDOW_TYPE_WAYLAND /**< Wayland surface */,
VLC_WINDOW_TYPE_DCOMP /**< Win32 DirectComposition */,
VLC_WINDOW_TYPE_KMS /**< DRM KMS CRTC */,
VLC_WINDOW_TYPE_MMAL /**< MMAL window */,
};
/**
@ -398,6 +399,7 @@ typedef struct vlc_window {
struct wl_surface *wl; /**< Wayland surface (client pointer) */
void *dcomp_visual; /**< Win32 direct composition visual */
uint32_t crtc; /**< KMS CRTC identifier */
int display_id; /**< MMAL display ID */
} handle;
/** Display server (mandatory)

208
modules/hw/mmal/vout.c

@ -64,6 +64,7 @@
#define PHASE_CHECK_INTERVAL 100
static int OpenMmalVout(vout_display_t *, video_format_t *, vlc_video_context *);
static int OpenMmalWindow(vlc_window_t *);
#define SUBS_MAX 4
@ -79,9 +80,13 @@ vlc_module_begin()
NULL)
add_bool(MMAL_NATIVE_INTERLACED, false, MMAL_NATIVE_INTERLACE_TEXT,
MMAL_NATIVE_INTERLACE_LONGTEXT)
add_string(MMAL_DISPLAY_NAME, "auto", MMAL_DISPLAY_TEXT,
MMAL_DISPLAY_LONGTEXT)
set_callback_display(OpenMmalVout, 16) // 1 point better than ASCII art
add_submodule()
set_capability("vout window", 10)
set_callback(OpenMmalWindow)
add_string(MMAL_DISPLAY_NAME, "auto", MMAL_DISPLAY_TEXT,
MMAL_DISPLAY_LONGTEXT)
vlc_module_end()
typedef struct vout_subpic_s {
@ -90,8 +95,6 @@ typedef struct vout_subpic_s {
} vout_subpic_t;
typedef struct vout_display_sys_t {
vlc_mutex_t manage_mutex;
vlc_decoder_device *dec_dev;
MMAL_COMPONENT_T *component;
MMAL_PORT_T *input;
@ -101,10 +104,6 @@ typedef struct vout_display_sys_t {
int buffers_in_transit; /* number of buffers currently pushed to mmal component */
unsigned num_buffers; /* number of buffers allocated at mmal port */
int display_id;
unsigned display_width;
unsigned display_height;
MMAL_RECT_T dest_rect; // Output rectangle in display coords
unsigned int i_frame_rate_base; /* cached framerate to detect changes for rate adjustment */
@ -114,7 +113,6 @@ typedef struct vout_display_sys_t {
int phase_offset; /* currently applied offset to presentation time in ns */
int layer; /* the dispman layer (z-index) used for video rendering */
bool need_configure_display; /* indicates a required display reconfigure to main thread */
bool adjust_refresh_rate;
bool native_interlaced;
bool b_top_field_first; /* cached interlaced settings to detect changes for native mode */
@ -460,8 +458,6 @@ static MMAL_STATUS_T isp_check(vout_display_t * const vd, vout_display_sys_t * c
}
/* TV service */
static void tvservice_cb(void *callback_data, uint32_t reason, uint32_t param1,
uint32_t param2);
static void adjust_refresh_rate(vout_display_t *vd);
static int set_latency_target(vout_display_t *vd, bool enable);
@ -477,35 +473,6 @@ static void vd_input_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buf)
mmal_buffer_header_release(buf);
}
static int query_resolution(vout_display_t *vd, const int display_id, unsigned *width, unsigned *height)
{
TV_DISPLAY_STATE_T display_state = {0};
int ret = 0;
if (vc_tv_get_display_state_id(display_id, &display_state) == 0) {
msg_Dbg(vd, "State=%#x", display_state.state);
if (display_state.state & 0xFF) {
msg_Dbg(vd, "HDMI: %dx%d", display_state.display.hdmi.width, display_state.display.hdmi.height);
*width = display_state.display.hdmi.width;
*height = display_state.display.hdmi.height;
vout_display_SetSize(vd, *width, *height);
} else if (display_state.state & 0xFF00) {
msg_Dbg(vd, "SDTV: %dx%d", display_state.display.sdtv.width, display_state.display.sdtv.height);
*width = display_state.display.sdtv.width;
*height = display_state.display.sdtv.height;
vout_display_SetSize(vd, *width, *height);
} else {
msg_Warn(vd, "Invalid display state %"PRIx32, display_state.state);
ret = -1;
}
} else {
msg_Warn(vd, "Failed to query display resolution");
ret = -1;
}
return ret;
}
static MMAL_RECT_T
place_to_mmal_rect(const vout_display_place_t place)
{
@ -521,14 +488,9 @@ static void
place_dest(vout_display_t *vd)
{
vout_display_sys_t * const sys = vd->sys;
// Ignore what VLC thinks might be going on with display size
struct vout_display_placement dp = vd->cfg->display;
vout_display_place_t place;
dp.width = sys->display_width;
dp.height = sys->display_height;
dp.fitting = VLC_VIDEO_FIT_SMALLER;
vout_display_PlacePicture(&place, vd->source, &dp);
vout_display_PlacePicture(&place, vd->source, &vd->cfg->display);
sys->dest_rect = place_to_mmal_rect(place);
}
@ -704,27 +666,6 @@ static int vd_control(vout_display_t *vd, int query)
return ret;
}
static void vd_manage(vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
unsigned width, height;
vlc_mutex_lock(&sys->manage_mutex);
if (sys->need_configure_display) {
if (query_resolution(vd, sys->display_id, &width, &height) >= 0) {
sys->display_width = width;
sys->display_height = height;
// vlc_window_ReportSize(vd->cfg->window, width, height);
}
sys->need_configure_display = false;
}
vlc_mutex_unlock(&sys->manage_mutex);
}
static int attach_subpics(vout_display_t * const vd, vout_display_sys_t * const sys,
const vlc_render_subpicture * const spic)
{
@ -773,8 +714,6 @@ static void vd_prepare(vout_display_t *vd, picture_t *p_pic,
VLC_UNUSED(date);
vout_display_sys_t * const sys = vd->sys;
vd_manage(vd);
if (sys->force_config ||
p_pic->format.i_frame_rate != sys->i_frame_rate ||
p_pic->format.i_frame_rate_base != sys->i_frame_rate_base ||
@ -833,20 +772,6 @@ static void vd_control_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
mmal_buffer_header_release(buffer);
}
static void tvservice_cb(void *callback_data, uint32_t reason, uint32_t param1, uint32_t param2)
{
VLC_UNUSED(reason);
VLC_UNUSED(param1);
VLC_UNUSED(param2);
vout_display_t *vd = (vout_display_t *)callback_data;
vout_display_sys_t *sys = vd->sys;
vlc_mutex_lock(&sys->manage_mutex);
sys->need_configure_display = true;
vlc_mutex_unlock(&sys->manage_mutex);
}
static int set_latency_target(vout_display_t *vd, bool enable)
{
vout_display_sys_t *sys = vd->sys;
@ -885,9 +810,9 @@ static void adjust_refresh_rate(vout_display_t *vd)
double best_score, score;
int i;
vc_tv_get_display_state_id(sys->display_id, &display_state);
vc_tv_get_display_state_id(vd->cfg->window->handle.display_id, &display_state);
if(display_state.display.hdmi.mode != HDMI_MODE_OFF) {
num_modes = vc_tv_hdmi_get_supported_modes_new_id(sys->display_id, display_state.display.hdmi.group,
num_modes = vc_tv_hdmi_get_supported_modes_new_id(vd->cfg->window->handle.display_id, display_state.display.hdmi.group,
supported_modes, VC_TV_MAX_MODE_IDS, NULL, NULL);
for (i = 0; i < num_modes; ++i) {
@ -915,7 +840,7 @@ static void adjust_refresh_rate(vout_display_t *vd)
if((best_id >= 0) && (display_state.display.hdmi.mode != supported_modes[best_id].code)) {
msg_Info(vd, "Setting HDMI refresh rate to %"PRIu32,
supported_modes[best_id].frame_rate);
vc_tv_hdmi_power_on_explicit_new_id(sys->display_id, HDMI_MODE_HDMI,
vc_tv_hdmi_power_on_explicit_new_id(vd->cfg->window->handle.display_id, HDMI_MODE_HDMI,
supported_modes[best_id].group,
supported_modes[best_id].code);
}
@ -987,8 +912,6 @@ static void CloseMmalVout(vout_display_t * vd)
vout_display_sys_t * const sys = vd->sys;
char response[20]; /* answer is hvs_update_fields=%1d */
vc_tv_unregister_callback_full(tvservice_cb, vd);
// Shouldn't be anything here - but just in case
for (unsigned int i = 0; i != SUBS_MAX; ++i)
if (sys->subpic_bufs[i] != NULL)
@ -1074,6 +997,9 @@ static const struct vlc_display_operations ops = {
static int OpenMmalVout(vout_display_t *vd,
video_format_t *fmtp, vlc_video_context *vctx)
{
if (vd->cfg->window->type != VLC_WINDOW_TYPE_MMAL)
return VLC_ENOTSUP;
vout_display_sys_t *sys;
MMAL_DISPLAYREGION_T display_region;
MMAL_STATUS_T status;
@ -1106,26 +1032,8 @@ static int OpenMmalVout(vout_display_t *vd,
goto fail;
}
vlc_mutex_init(&sys->manage_mutex);
vc_tv_register_callback(tvservice_cb, vd);
sys->layer = var_InheritInteger(vd, MMAL_LAYER_NAME);
{
const char *display_name = var_InheritString(vd, MMAL_DISPLAY_NAME);
int qt_num = -1;
int display_id = find_display_num(display_name);
// sys->display_id = display_id < 0 ? vc_tv_get_default_display_id() : display_id;
sys->display_id = display_id >= 0 ? display_id : DISPMANX_ID_HDMI;
if (display_id < -1)
msg_Warn(vd, "Unknown display device: '%s'", display_name);
else
msg_Dbg(vd, "Display device: %s, qt=%d id=%d display=%d", display_name,
qt_num, display_id, sys->display_id);
free(display_name);
}
status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &sys->component);
if (status != MMAL_SUCCESS) {
msg_Err(vd, "Failed to create MMAL component %s (status=%"PRIx32" %s)",
@ -1178,17 +1086,11 @@ static int OpenMmalVout(vout_display_t *vd,
}
}
if (query_resolution(vd, sys->display_id, &sys->display_width, &sys->display_height) < 0)
{
sys->display_width = vd->cfg->display.width;
sys->display_height = vd->cfg->display.height;
}
place_dest(vd); // Sets sys->dest_rect
display_region.hdr.id = MMAL_PARAMETER_DISPLAYREGION;
display_region.hdr.size = sizeof(MMAL_DISPLAYREGION_T);
display_region.display_num = sys->display_id;
display_region.display_num = vd->cfg->window->handle.display_id;
display_region.fullscreen = MMAL_FALSE;
display_src_rect(vd, &display_region.src_rect);
display_region.dest_rect = sys->dest_rect;
@ -1238,7 +1140,7 @@ static int OpenMmalVout(vout_display_t *vd,
goto fail;
}
if ((status = hw_mmal_subpic_open(VLC_OBJECT(vd), &sub->sub, sub->component->input[0],
sys->display_id, sys->layer + i + 1)) != MMAL_SUCCESS) {
vd->cfg->window->handle.display_id, sys->layer + i + 1)) != MMAL_SUCCESS) {
msg_Dbg(vd, "Failed to open subpic %d", i);
goto fail;
}
@ -1265,3 +1167,81 @@ fail:
return ret;
}
///////////////////////////////
static int send_resolution(vlc_window_t *wnd)
{
TV_DISPLAY_STATE_T display_state = {0};
int ret = VLC_SUCCESS;
if (vc_tv_get_display_state_id(wnd->handle.display_id, &display_state) == 0) {
msg_Dbg(wnd, "State=%#x", display_state.state);
if (display_state.state & 0xFF) {
msg_Dbg(wnd, "HDMI: %dx%d", display_state.display.hdmi.width, display_state.display.hdmi.height);
vlc_window_ReportSize(wnd, display_state.display.hdmi.width, display_state.display.hdmi.height);
} else if (display_state.state & 0xFF00) {
msg_Dbg(wnd, "SDTV: %dx%d", display_state.display.sdtv.width, display_state.display.sdtv.height);
vlc_window_ReportSize(wnd, display_state.display.sdtv.width, display_state.display.sdtv.height);
} else {
msg_Warn(wnd, "Invalid display state %"PRIx32, display_state.state);
ret = VLC_EINVAL;
}
} else {
msg_Warn(wnd, "Failed to query display resolution");
ret = VLC_EACCES;
}
return ret;
}
static void tvservice_cb(void *callback_data, uint32_t reason, uint32_t param1, uint32_t param2)
{
VLC_UNUSED(reason);
VLC_UNUSED(param1);
VLC_UNUSED(param2);
vlc_window_t *wnd = callback_data;
send_resolution(wnd);
}
static int EnableWindow(vlc_window_t *wnd, const vlc_window_cfg_t *cfg)
{
int err = send_resolution(wnd);
if (err != VLC_SUCCESS)
return err;
vc_tv_register_callback(tvservice_cb, wnd);
return VLC_SUCCESS;
}
static void DisableWindow(vlc_window_t *wnd)
{
vc_tv_unregister_callback_full(tvservice_cb, wnd);
}
static int OpenMmalWindow(vlc_window_t *wnd)
{
{
char *display_name = var_InheritString(wnd, MMAL_DISPLAY_NAME);
int qt_num = -1;
int display_id = find_display_num(display_name);
// wnd->handle.display_id = display_id < 0 ? vc_tv_get_default_display_id() : display_id;
wnd->handle.display_id = display_id >= 0 ? display_id : DISPMANX_ID_HDMI;
if (display_id < -1)
msg_Warn(wnd, "Unknown display device: '%s'", display_name);
else
msg_Dbg(wnd, "Display device: %s, qt=%d id=%d display=%d", display_name,
qt_num, display_id, wnd->handle.display_id);
free(display_name);
}
static const struct vlc_window_operations ops = {
.enable = EnableWindow,
.disable = DisableWindow,
};
wnd->type = VLC_WINDOW_TYPE_MMAL;
wnd->ops = &ops;
return VLC_SUCCESS;
}

Loading…
Cancel
Save