#define MMAL_ADJUST_REFRESHRATE_TEXT N_("Adjust HDMI refresh rate to the video.")
#define MMAL_ADJUST_REFRESHRATE_LONGTEXT N_("Adjust HDMI refresh rate to the video.")
+#define MMAL_NATIVE_INTERLACED "mmal-native-interlaced"
+#define MMAL_NATIVE_INTERLACE_TEXT N_("Force interlaced video mode.")
+#define MMAL_NATIVE_INTERLACE_LONGTEXT N_("Force the HDMI output into an " \
+ "interlaced video mode for interlaced video content.")
+
/* Ideal rendering phase target is at rough 25% of frame duration */
#define PHASE_OFFSET_TARGET ((double)0.25)
#define PHASE_CHECK_INTERVAL 100
add_integer(MMAL_LAYER_NAME, 1, MMAL_LAYER_TEXT, MMAL_LAYER_LONGTEXT, false)
add_bool(MMAL_ADJUST_REFRESHRATE_NAME, false, MMAL_ADJUST_REFRESHRATE_TEXT,
MMAL_ADJUST_REFRESHRATE_LONGTEXT, false)
+ add_bool(MMAL_NATIVE_INTERLACED, false, MMAL_NATIVE_INTERLACE_TEXT,
+ MMAL_NATIVE_INTERLACE_LONGTEXT, false)
set_callbacks(Open, Close)
vlc_module_end()
};
struct vout_display_sys_t {
+ vlc_cond_t buffer_cond;
+ vlc_mutex_t buffer_mutex;
+ vlc_mutex_t manage_mutex;
+
+ plane_t planes[3];
picture_t **pictures;
picture_pool_t *picture_pool;
MMAL_PORT_T *input;
MMAL_POOL_T *pool;
struct dmx_region_t *dmx_region;
- plane_t planes[3];
int i_planes;
- vlc_mutex_t buffer_mutex;
- vlc_mutex_t manage_mutex;
- vlc_cond_t buffer_cond;
uint32_t buffer_size;
int buffers_in_transit;
unsigned num_buffers;
DISPMANX_RESOURCE_HANDLE_T bkg_resource;
unsigned display_width;
unsigned display_height;
- bool need_configure_display;
- bool adjust_refresh_rate;
+ int i_frame_rate_base;
+ int i_frame_rate;
+
int next_phase_check;
int phase_offset;
-
int layer;
+
+ bool need_configure_display;
+ bool adjust_refresh_rate;
+ bool native_interlaced;
+ bool b_top_field_first;
+ bool b_progressive;
bool opaque;
};
vd->info.has_hide_mouse = true;
sys->opaque = vd->fmt.i_chroma == VLC_CODEC_MMAL_OPAQUE;
- vd->fmt.i_sar_num = vd->source.i_sar_num;
- vd->fmt.i_sar_den = vd->source.i_sar_den;
-
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)",
vc_tv_register_callback(tvservice_cb, vd);
if (query_resolution(vd, &sys->display_width, &sys->display_height) >= 0) {
- vout_display_SendEventDisplaySize(vd, sys->display_width, sys->display_height,
- vd->cfg->is_fullscreen);
+ vout_display_SendEventDisplaySize(vd, sys->display_width, sys->display_height);
} else {
sys->display_width = vd->cfg->display.width;
sys->display_height = vd->cfg->display.height;
{
vout_display_t *vd = (vout_display_t *)object;
vout_display_sys_t *sys = vd->sys;
+ char response[20]; /* answer is hvs_update_fields=%1d */
unsigned i;
vc_tv_unregister_callback_full(tvservice_cb, vd);
vlc_cond_destroy(&sys->buffer_cond);
vlc_mutex_destroy(&sys->manage_mutex);
+ if (sys->native_interlaced) {
+ if (vc_gencmd(response, sizeof(response), "hvs_update_fields 0") < 0 ||
+ response[18] != '0')
+ msg_Warn(vd, "Could not reset hvs field mode");
+ }
+
free(sys->pictures);
free(sys);
return -EINVAL;
}
} else {
- fmt = &vd->fmt;
+ fmt = &vd->source;
}
if (!cfg)
show_background(vd, cfg->is_fullscreen);
sys->adjust_refresh_rate = var_InheritBool(vd, MMAL_ADJUST_REFRESHRATE_NAME);
+ sys->native_interlaced = var_InheritBool(vd, MMAL_NATIVE_INTERLACED);
if (sys->adjust_refresh_rate) {
adjust_refresh_rate(vd, fmt);
set_latency_target(vd, true);
}
- if (fmt != &vd->fmt)
- memcpy(&vd->fmt, fmt, sizeof(video_format_t));
-
return 0;
}
MMAL_BUFFER_HEADER_T *buffer = pic_sys->buffer;
MMAL_STATUS_T status;
+ if (picture->format.i_frame_rate != sys->i_frame_rate ||
+ picture->format.i_frame_rate_base != sys->i_frame_rate_base ||
+ picture->b_progressive != sys->b_progressive ||
+ picture->b_top_field_first != sys->b_top_field_first) {
+ sys->b_top_field_first = picture->b_top_field_first;
+ sys->b_progressive = picture->b_progressive;
+ sys->i_frame_rate = picture->format.i_frame_rate;
+ sys->i_frame_rate_base = picture->format.i_frame_rate_base;
+ configure_display(vd, NULL, &picture->format);
+ }
+
if (!pic_sys->displayed || !sys->opaque) {
buffer->cmd = 0;
buffer->length = sys->input->buffer_size;
vout_display_sys_t *sys = vd->sys;
vout_display_cfg_t cfg;
const vout_display_cfg_t *tmp_cfg;
- video_format_t fmt;
const video_format_t *tmp_fmt;
int ret = VLC_EGENERIC;
case VOUT_DISPLAY_CHANGE_FULLSCREEN:
tmp_cfg = va_arg(args, const vout_display_cfg_t *);
vout_display_SendEventDisplaySize(vd, sys->display_width,
- sys->display_height, tmp_cfg->is_fullscreen);
+ sys->display_height);
ret = VLC_SUCCESS;
break;
}
break;
- case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
- cfg = *vd->cfg;
- tmp_cfg = va_arg(args, const vout_display_cfg_t *);
- cfg.is_display_filled = tmp_cfg->is_display_filled;
- if (configure_display(vd, &cfg, NULL) >= 0)
- ret = VLC_SUCCESS;
- break;
-
case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
- fmt = vd->fmt;
- tmp_fmt = va_arg(args, const video_format_t *);
- fmt.i_sar_num = tmp_fmt->i_sar_num;
- fmt.i_sar_den = tmp_fmt->i_sar_den;
- if (configure_display(vd, NULL, &fmt) >= 0)
- ret = VLC_SUCCESS;
- break;
-
case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
- fmt = vd->fmt;
tmp_fmt = va_arg(args, const video_format_t *);
- fmt.i_x_offset = tmp_fmt->i_x_offset;
- fmt.i_y_offset = tmp_fmt->i_y_offset;
- fmt.i_visible_width = tmp_fmt->i_visible_width;
- fmt.i_visible_height = tmp_fmt->i_visible_height;
- if (configure_display(vd, NULL, &fmt) >= 0)
+ if (configure_display(vd, NULL, tmp_fmt) >= 0)
ret = VLC_SUCCESS;
break;
if (query_resolution(vd, &width, &height) >= 0) {
sys->display_width = width;
sys->display_height = height;
- vout_display_SendEventDisplaySize(vd, width, height, vd->cfg->is_fullscreen);
+ vout_display_SendEventDisplaySize(vd, width, height);
}
sys->need_configure_display = false;
static void adjust_refresh_rate(vout_display_t *vd, const video_format_t *fmt)
{
+ vout_display_sys_t *sys = vd->sys;
TV_DISPLAY_STATE_T display_state;
TV_SUPPORTED_MODE_NEW_T supported_modes[VC_TV_MAX_MODE_IDS];
+ char response[20]; /* answer is hvs_update_fields=%1d */
int num_modes;
double frame_rate = (double)fmt->i_frame_rate / fmt->i_frame_rate_base;
int best_id = -1;
num_modes = vc_tv_hdmi_get_supported_modes_new(display_state.display.hdmi.group,
supported_modes, VC_TV_MAX_MODE_IDS, NULL, NULL);
- for(i = 0; i < num_modes; ++i) {
- if(supported_modes[i].width != display_state.display.hdmi.width ||
- supported_modes[i].height != display_state.display.hdmi.height ||
- supported_modes[i].scan_mode != display_state.display.hdmi.scan_mode)
- continue;
+ for (i = 0; i < num_modes; ++i) {
+ TV_SUPPORTED_MODE_NEW_T *mode = &supported_modes[i];
+ if (!sys->native_interlaced) {
+ if (mode->width != display_state.display.hdmi.width ||
+ mode->height != display_state.display.hdmi.height ||
+ mode->scan_mode == HDMI_INTERLACED)
+ continue;
+ } else {
+ if (mode->width != vd->fmt.i_visible_width ||
+ mode->height != vd->fmt.i_visible_height)
+ continue;
+ if (mode->scan_mode != sys->b_progressive ? HDMI_NONINTERLACED : HDMI_INTERLACED)
+ continue;
+ }
score = fmod(supported_modes[i].frame_rate, frame_rate);
if((best_id < 0) || (score < best_score)) {
}
}
- if((best_id >= 0) && (display_state.display.hdmi.frame_rate != supported_modes[best_id].frame_rate)) {
+ 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(HDMI_MODE_HDMI,
supported_modes[best_id].group,
supported_modes[best_id].code);
}
+
+ if (sys->native_interlaced &&
+ supported_modes[best_id].scan_mode == HDMI_INTERLACED) {
+ char hvs_mode = sys->b_top_field_first ? '1' : '2';
+ if (vc_gencmd(response, sizeof(response), "hvs_update_fields %c",
+ hvs_mode) != 0 || response[18] != hvs_mode)
+ msg_Warn(vd, "Could not set hvs field mode");
+ else
+ msg_Info(vd, "Configured hvs field mode for interlaced %s playback",
+ sys->b_top_field_first ? "tff" : "bff");
+ }
}
}
.hdr = { MMAL_PARAMETER_VIDEO_RENDER_STATS, sizeof(render_stats) },
};
int32_t frame_duration = 1000000 /
- ((double)vd->fmt.i_frame_rate /
- vd->fmt.i_frame_rate_base);
+ ((double)vd->source.i_frame_rate /
+ vd->source.i_frame_rate_base);
vout_display_sys_t *sys = vd->sys;
int32_t phase_offset;
MMAL_STATUS_T status;