commit 7cf4d6a0168582a1e926964410222e087700ca00
Author: Nicolas Chauvet <kwizart(a)gmail.com>
Date: Fri Oct 30 10:11:07 2020 +0100
Update to mmal_20
mmal_20.patch | 587 +++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 394 insertions(+), 193 deletions(-)
---
diff --git a/mmal_20.patch b/mmal_20.patch
index 9ea7a60..923f3ba 100644
--- a/mmal_20.patch
+++ b/mmal_20.patch
@@ -1,6 +1,6 @@
--- a/configure.ac
+++ b/configure.ac
-@@ -3444,6 +3444,9 @@
+@@ -3444,6 +3444,9 @@ dnl
AC_ARG_ENABLE(mmal,
AS_HELP_STRING([--enable-mmal],
[Multi-Media Abstraction Layer (MMAL) hardware plugin (default enable)]))
@@ -10,7 +10,7 @@
if test "${enable_mmal}" != "no"; then
VLC_SAVE_FLAGS
LDFLAGS="${LDFLAGS} -L/opt/vc/lib -lvchostif"
-@@ -3454,7 +3457,7 @@
+@@ -3454,7 +3457,7 @@ if test "${enable_mmal}" != "no"; then
VLC_ADD_PLUGIN([mmal])
VLC_ADD_LDFLAGS([mmal],[ -L/opt/vc/lib ])
VLC_ADD_CFLAGS([mmal],[ -isystem /opt/vc/include -isystem
/opt/vc/include/interface/vcos/pthreads -isystem /opt/vc/include/interface/vmcs_host/linux
])
@@ -19,7 +19,7 @@
AS_IF([test "${enable_mmal}" = "yes"],
[ AC_MSG_ERROR([Cannot find bcm library...]) ],
[ AC_MSG_WARN([Cannot find bcm library...]) ])
-@@ -3466,6 +3469,7 @@
+@@ -3466,6 +3469,7 @@ if test "${enable_mmal}" != "no"; then
VLC_RESTORE_FLAGS
fi
AM_CONDITIONAL([HAVE_MMAL], [test "${have_mmal}" = "yes"])
@@ -562,14 +562,7 @@
-static int OpenDecoder(decoder_t *dec);
-static void CloseDecoder(decoder_t *dec);
-+#define MMAL_RESIZE_NAME "mmal-resize"
-+#define MMAL_RESIZE_TEXT N_("Use mmal resizer rather than hvs.")
-+#define MMAL_RESIZE_LONGTEXT N_("Use mmal resizer rather than isp. This uses less
gpu memory than the ISP but is slower.")
-+
-+#define MMAL_ISP_NAME "mmal-isp"
-+#define MMAL_ISP_TEXT N_("Use mmal isp rather than hvs.")
-+#define MMAL_ISP_LONGTEXT N_("Use mmal isp rather than hvs. This may be faster but
has no blend.")
-
+-
-vlc_module_begin()
- set_shortname(N_("MMAL decoder"))
- set_description(N_("MMAL-based decoder plugin for Raspberry Pi"))
@@ -578,7 +571,14 @@
- add_bool(MMAL_OPAQUE_NAME, true, MMAL_OPAQUE_TEXT, MMAL_OPAQUE_LONGTEXT, false)
- set_callbacks(OpenDecoder, CloseDecoder)
-vlc_module_end()
--
++#define MMAL_RESIZE_NAME "mmal-resize"
++#define MMAL_RESIZE_TEXT N_("Use mmal resizer rather than hvs.")
++#define MMAL_RESIZE_LONGTEXT N_("Use mmal resizer rather than isp. This uses less
gpu memory than the ISP but is slower.")
++
++#define MMAL_ISP_NAME "mmal-isp"
++#define MMAL_ISP_TEXT N_("Use mmal isp rather than hvs.")
++#define MMAL_ISP_LONGTEXT N_("Use mmal isp rather than hvs. This may be faster but
has no blend.")
+
-struct decoder_sys_t {
- bool opaque;
+typedef struct decoder_sys_t
@@ -1128,7 +1128,7 @@
if (atomic_load(&sys->started)) {
mmal_format_full_copy(sys->output->format, sys->output_format);
status = mmal_port_format_commit(sys->output);
-@@ -300,7 +476,9 @@
+@@ -300,7 +476,9 @@ static int change_output_format(decoder_
}
port_reset:
@@ -1138,7 +1138,7 @@
status = mmal_port_disable(sys->output);
if (status != MMAL_SUCCESS) {
msg_Err(dec, "Failed to disable output port (status=%"PRIx32"
%s)",
-@@ -310,6 +488,7 @@
+@@ -310,6 +488,7 @@ port_reset:
}
mmal_format_full_copy(sys->output->format, sys->output_format);
@@ -1146,7 +1146,7 @@
status = mmal_port_format_commit(sys->output);
if (status != MMAL_SUCCESS) {
msg_Err(dec, "Failed to commit output format (status=%"PRIx32"
%s)",
-@@ -318,18 +497,10 @@
+@@ -318,18 +497,10 @@ port_reset:
goto out;
}
@@ -1167,7 +1167,7 @@
if (status != MMAL_SUCCESS) {
msg_Err(dec, "Failed to enable output port (status=%"PRIx32"
%s)",
status, mmal_status_to_string(status));
-@@ -338,25 +509,14 @@
+@@ -338,25 +509,14 @@ port_reset:
}
if (!atomic_load(&sys->started)) {
@@ -1196,7 +1196,7 @@
}
apply_fmt:
-@@ -366,8 +526,8 @@
+@@ -366,8 +526,8 @@ apply_fmt:
dec->fmt_out.video.i_y_offset =
sys->output->format->es->video.crop.y;
dec->fmt_out.video.i_visible_width =
sys->output->format->es->video.crop.width;
dec->fmt_out.video.i_visible_height =
sys->output->format->es->video.crop.height;
@@ -1207,7 +1207,7 @@
dec->fmt_out.video.i_frame_rate =
sys->output->format->es->video.frame_rate.num;
dec->fmt_out.video.i_frame_rate_base =
sys->output->format->es->video.frame_rate.den;
-@@ -382,12 +542,19 @@
+@@ -382,12 +542,19 @@ apply_fmt:
sys->b_progressive = (interlace_type.eMode == MMAL_InterlaceProgressive);
sys->b_top_field_first = sys->b_progressive ? true :
(interlace_type.eMode == MMAL_InterlaceFieldsInterleavedUpperFirst);
@@ -1227,7 +1227,7 @@
out:
mmal_format_free(sys->output_format);
sys->output_format = NULL;
-@@ -395,144 +562,85 @@
+@@ -395,144 +562,85 @@ out:
return ret;
}
@@ -1242,7 +1242,7 @@
MMAL_STATUS_T status;
- unsigned buffer_size = 0;
- int ret = 0;
--
+
- if (!sys->output->is_enabled)
- return VLC_EGENERIC;
-
@@ -1267,7 +1267,7 @@
- p_sys = picture->p_sys;
- for (int i = 0; i < picture->i_planes; i++)
- buffer_size += picture->p[i].i_lines * picture->p[i].i_pitch;
-
+-
- if (sys->output_pool) {
- mmal_buffer_header_reset(buffer);
- buffer->alloc_size = sys->output->buffer_size;
@@ -1409,7 +1409,8 @@
MMAL_BUFFER_HEADER_T *buffer;
- bool need_flush = false;
uint32_t len;
- uint32_t flags = 0;
+- uint32_t flags = 0;
++ uint32_t flags = MMAL_BUFFER_HEADER_FLAG_FRAME_START;
MMAL_STATUS_T status;
+#if TRACE_ALL
@@ -1425,7 +1426,7 @@
/*
* Configure output port if necessary
*/
-@@ -541,18 +649,50 @@
+@@ -541,18 +649,50 @@ static int decode(decoder_t *dec, block_
msg_Err(dec, "Failed to change output port format");
}
@@ -1479,7 +1480,7 @@
if (atomic_load(&sys->started))
fill_output_port(dec);
-@@ -563,18 +703,21 @@
+@@ -563,18 +703,21 @@ static int decode(decoder_t *dec, block_
if (block->i_flags & BLOCK_FLAG_CORRUPTED)
flags |= MMAL_BUFFER_HEADER_FLAG_CORRUPTED;
@@ -1506,12 +1507,24 @@
len = block->i_buffer;
if (len > buffer->alloc_size)
-@@ -590,89 +733,1751 @@
+@@ -585,94 +728,1808 @@ static int decode(decoder_t *dec, block_
+ block->i_buffer -= len;
+ buffer->length = len;
+ if (block->i_buffer == 0) {
++ flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END;
++ if (block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE) {
++ msg_Dbg(dec, "EOS sent");
++ flags |= MMAL_BUFFER_HEADER_FLAG_EOS;
++ }
+ buffer->user_data = block;
+ block = NULL;
}
buffer->flags = flags;
+#if TRACE_ALL
-+ msg_Dbg(dec, "%s: -- Send buffer: len=%d", __func__, len);
++ msg_Dbg(dec, "%s: -- Send buffer: cmd=%d, data=%p, size=%d, len=%d,
offset=%d, flags=%#x, pts=%lld, dts=%lld", __func__,\
++ buffer->cmd, buffer->data, buffer->alloc_size,
buffer->length, buffer->offset,
++ buffer->flags, (long long)buffer->pts, (long
long)buffer->dts);
+#endif
status = mmal_port_send_buffer(sys->input, buffer);
if (status != MMAL_SUCCESS) {
@@ -1524,6 +1537,7 @@
+
+ // Reset flushed flag once we have sent a buf
+ sys->b_flushed = false;
++ flags &= ~MMAL_BUFFER_HEADER_FLAG_FRAME_START;
}
+ return VLCDEC_SUCCESS;
@@ -1671,6 +1685,21 @@
+ goto fail;
+ }
+
++ // Set vanishingly unlikely shape (or at least crop)
++ // to ensure that we get a resolution changed event
++ // Small wxh are rejected (128x128 is rejected) so pick a
++ // plausible size.
++ // Crop doesn't seem to be checked for being constrained by wxh
++ // so we could place it outside the pic to be sure that it is
++ // never matched but stick with something legal in case it is ever
++ // actually checked
++ sys->output->format->es->video.height = 256;
++ sys->output->format->es->video.width = 256;
++ sys->output->format->es->video.crop.height = 4;
++ sys->output->format->es->video.crop.width = 2;
++ sys->output->format->es->video.crop.x = 66;
++ sys->output->format->es->video.crop.y = 88;
++
+ if ((status = hw_mmal_opaque_output(VLC_OBJECT(dec), &sys->ppr,
+ sys->output, NUM_EXTRA_BUFFERS,
decoder_output_cb)) != MMAL_SUCCESS)
+ goto fail;
@@ -2257,10 +2286,25 @@
+ return MMAL_SUCCESS;
+}
+
++
++static picture_t *conv_get_out_pics(filter_sys_t * const sys)
++{
++ picture_t * ret_pics;
++
++ vlc_sem_wait(&sys->sem);
++
++ // Return a single pending buffer
++ vlc_mutex_lock(&sys->lock);
++ ret_pics = pic_fifo_get(&sys->ret_pics);
++ vlc_mutex_unlock(&sys->lock);
++
++ return ret_pics;
++}
++
+static picture_t *conv_filter(filter_t *p_filter, picture_t *p_pic)
+{
+ filter_sys_t * const sys = p_filter->p_sys;
-+ picture_t * ret_pics;
++ picture_t * ret_pics = NULL;
+ MMAL_STATUS_T err;
+ const uint64_t frame_seq = ++sys->frame_seq;
+ conv_frame_stash_t * const stash = sys->stash + (frame_seq & 0xf);
@@ -2286,12 +2330,29 @@
+ }
+
+ // Check pic fmt corresponds to what we have set up
-+ // ??? ISP may require flush (disable) but actually seems quite happy
-+ // without
+ if (hw_mmal_vlc_pic_to_mmal_fmt_update(sys->input->format, p_pic))
+ {
+ msg_Dbg(p_filter, "Reset input port format");
-+ mmal_port_format_commit(sys->input);
++
++ // HVS can take new formats without disable, others need it
++ if (sys->resizer_type != FILTER_RESIZER_HVS) {
++ // Extract any pending pic
++ if (sys->pic_n >= 2) {
++ ret_pics = conv_get_out_pics(sys);
++ // If pic_n == 1 then we return without trying to get stuff
++ sys->pic_n = 1;
++ }
++ if (sys->input->is_enabled) {
++ if ((err = mmal_port_disable(sys->input)) != MMAL_SUCCESS)
++ msg_Warn(p_filter, "Format update disable failed: %s",
mmal_status_to_string(err));
++ }
++ }
++
++// mmal_log_dump_port(sys->input);
++ if ((err = mmal_port_format_commit(sys->input)) != MMAL_SUCCESS)
++ msg_Warn(p_filter, "Format update commit failed: %s",
mmal_status_to_string(err));
++
++ // (Re)enable if required will be done later
+ }
+
+ if (p_pic->context == NULL) {
@@ -2497,16 +2558,12 @@
+ // This means we get a single static pic out
+ if (sys->pic_n++ == 1) {
+#if TRACE_ALL
-+ msg_Dbg(p_filter, ">>> %s: Pic1=NULL", __func__);
++ msg_Dbg(p_filter, ">>> %s: Pic1=%p", __func__, ret_pics);
+#endif
-+ return NULL;
++ return ret_pics;
+ }
-+ vlc_sem_wait(&sys->sem);
+
-+ // Return a single pending buffer
-+ vlc_mutex_lock(&sys->lock);
-+ ret_pics = pic_fifo_get(&sys->ret_pics);
-+ vlc_mutex_unlock(&sys->lock);
++ ret_pics = conv_get_out_pics(sys);
+
+ if (sys->err_stream != MMAL_SUCCESS)
+ goto stream_fail;
@@ -2524,8 +2581,9 @@
+fail:
+#if TRACE_ALL
+ msg_Err(p_filter, ">>> %s: FAIL", __func__);
-+ picture_Release(ret_pics);
+#endif
++ if (ret_pics != NULL)
++ picture_Release(ret_pics);
+ if (out_buf != NULL)
+ mmal_buffer_header_release(out_buf);
+ if (p_pic != NULL)
@@ -2653,8 +2711,10 @@
+ if (use_isp || use_resizer)
+ return VLC_EGENERIC;
+ }
-+
-+
+
+- sys->output_format = format;
+
+- mmal_buffer_header_release(buffer);
+ if (use_resizer) {
+ // use resizer overrides use_isp
+ use_isp = false;
@@ -2685,16 +2745,14 @@
+ p_filter->fmt_out.video.i_sar_num,
p_filter->fmt_out.video.i_sar_den,
+ gpu_mem);
+ }
-
-- sys->output_format = format;
++
+ sys = calloc(1, sizeof(filter_sys_t));
+ if (!sys) {
+ ret = VLC_ENOMEM;
+ goto fail;
+ }
+ p_filter->p_sys = sys;
-
-- mmal_buffer_header_release(buffer);
++
+ // Init stuff the we destroy unconditionaly in Close first
+ vlc_mutex_init(&sys->lock);
+ vlc_sem_init(&sys->sem, 0);
@@ -2741,7 +2799,7 @@
+ msg_Err(p_filter, "Failed to create MMAL component %s
(status=%"PRIx32" %s)",
+ MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status,
mmal_status_to_string(status));
+ goto fail;
-+ }
+ }
+ sys->output = sys->component->output[0];
+ sys->input = sys->component->input[0];
+
@@ -2919,7 +2977,7 @@
+static void to_zc_flush(filter_t * p_filter)
+{
+ VLC_UNUSED(p_filter);
-+}
+ }
+
+static void CloseConverterToZc(vlc_object_t * obj)
+{
@@ -3060,8 +3118,8 @@
+ hw_mmal_pic_sub_buf_add(dst, buf);
+
+ sys->last_dst = dst;
- }
- }
++ }
++}
+
+static void FlushBlendMmal(filter_t * p_filter)
+{
@@ -4984,7 +5042,7 @@
-}
--- /dev/null
+++ b/modules/hw/mmal/mmal_avcodec.c
-@@ -0,0 +1,2172 @@
+@@ -0,0 +1,2175 @@
+/*****************************************************************************
+ * video.c: video decoder using the libavcodec library
+ *****************************************************************************
@@ -7035,7 +7093,10 @@
+ bool error = false;
+ while( ( p_pic = DecodeBlock( p_dec, pp_block, &error ) ) != NULL )
+ decoder_QueueVideo( p_dec, p_pic );
-+ return error ? VLCDEC_ECRITICAL : VLCDEC_SUCCESS;
++ return VLCDEC_SUCCESS;
++// Easiest to just ignore all errors - returning a real error seems to
++// kill output forever
++// return error ? VLCDEC_ECRITICAL : VLCDEC_SUCCESS;
+}
+
+/*****************************************************************************
@@ -9126,7 +9187,7 @@
+}
+
+static MMAL_RECT_T
-+rect_transform(MMAL_RECT_T s, const MMAL_RECT_T c, const MMAL_DISPLAYTRANSFORM_T t)
++rect_untransform(MMAL_RECT_T s, const MMAL_RECT_T c, const MMAL_DISPLAYTRANSFORM_T t)
+{
+#if TRACE_TRANSFORMS
+ fprintf(stderr, "t=%d, s=%d,%d:%dx%d, c=%d,%d:%dx%d -> ", (int)t,
@@ -9160,7 +9221,7 @@
+ const MMAL_RECT_T c = (scale_transform & 4) == 0 ? *scale_rect :
rect_transpose(*scale_rect);
+ rescale_rect(&sb->dreg.dest_rect, &sb->orig_dest_rect,
+ &c, &sb->pic_rect);
-+ sb->dreg.dest_rect = rect_transform(sb->dreg.dest_rect, c,
scale_transform);
++ sb->dreg.dest_rect = rect_untransform(sb->dreg.dest_rect, c,
scale_transform);
+ sb->dreg.transform = scale_transform;
+ }
+}
@@ -10330,7 +10391,7 @@
+
--- /dev/null
+++ b/modules/hw/mmal/transform_ops.h
-@@ -0,0 +1,94 @@
+@@ -0,0 +1,99 @@
+#ifndef VLC_MMAL_TRANSFORM_OPS_H
+#define VLC_MMAL_TRANSFORM_OPS_H
+
@@ -10371,7 +10432,6 @@
+ return ((unsigned int)t & XFORM_V_BIT) != 0;
+}
+
-+
+static inline MMAL_DISPLAYTRANSFORM_T
+swap_transform_hv(const MMAL_DISPLAYTRANSFORM_T x)
+{
@@ -10380,6 +10440,12 @@
+ (x & XFORM_T_BIT);
+}
+
++static inline MMAL_DISPLAYTRANSFORM_T
++transform_inverse(const MMAL_DISPLAYTRANSFORM_T x)
++{
++ return is_transform_transpose(x) ? swap_transform_hv(x) : x;
++}
++
+// Transform generated by A then B
+// All ops are self inverse so can simply be XORed on their own
+// H & V flips after a transpose need to be swapped
@@ -10842,7 +10908,7 @@
#define MAX_BUFFERS_IN_TRANSIT 1
#define VC_TV_MAX_MODE_IDS 127
-@@ -50,10 +57,18 @@
+@@ -50,10 +57,28 @@
#define MMAL_LAYER_TEXT N_("VideoCore layer where the video is displayed.")
#define MMAL_LAYER_LONGTEXT N_("VideoCore layer where the video is displayed.
Subpictures are displayed directly above and a black background directly below.")
@@ -10862,17 +10928,26 @@
+#define MMAL_VOUT_TRANSFORM_LONGTEXT N_("Video transform for Rpi
fullscreen."\
+"Transforms availible: auto, 0, 90, 180, 270, hflip, vflip, transpose,
antitranspose")
+
++#define MMAL_VOUT_WINDOW_NAME "mmal-vout-window"
++#define MMAL_VOUT_WINDOW_TEXT N_("Display window for Rpi fullscreen")
++#define MMAL_VOUT_WINDOW_LONGTEXT N_("Display window for Rpi fullscreen."\
++"fullscreen|<width>x<height>+<x>+<y>")
++
++#define MMAL_VOUT_TRANSPARENT_NAME "mmal-vout-transparent"
++#define MMAL_VOUT_TRANSPARENT_TEXT N_("Enable layers beneeth the vodeo
layer.")
++#define MMAL_VOUT_TRANSPARENT_LONGTEXT N_("Enable layers beneath the video
layer."\
++" By default these are disabled."\
++" Having the lower layers enabled can impact video performance")
#define MMAL_ADJUST_REFRESHRATE_NAME "mmal-adjust-refreshrate"
#define MMAL_ADJUST_REFRESHRATE_TEXT N_("Adjust HDMI refresh rate to the
video.")
-@@ -68,64 +83,36 @@
+@@ -68,332 +93,628 @@
#define PHASE_OFFSET_TARGET ((double)0.25)
#define PHASE_CHECK_INTERVAL 100
-static int Open(vlc_object_t *);
-static void Close(vlc_object_t *);
-+#define SUBS_MAX 4
-
+-
-vlc_module_begin()
- set_shortname(N_("MMAL vout"))
- set_description(N_("MMAL-based vout plugin for Raspberry Pi"))
@@ -10887,7 +10962,8 @@
- MMAL_NATIVE_INTERLACE_LONGTEXT, false)
- set_callbacks(Open, Close)
-vlc_module_end()
--
++#define SUBS_MAX 4
+
-struct dmx_region_t {
- struct dmx_region_t *next;
- picture_t *picture;
@@ -10928,23 +11004,31 @@
- DISPMANX_DISPLAY_HANDLE_T dmx_handle;
- DISPMANX_ELEMENT_HANDLE_T bkg_element;
- DISPMANX_RESOURCE_HANDLE_T bkg_resource;
+- unsigned display_width;
+- unsigned display_height;
+ int display_id;
- unsigned display_width;
- unsigned display_height;
-
-- int i_frame_rate_base; /* cached framerate to detect changes for rate adjustment */
-- int i_frame_rate;
++ MMAL_RECT_T win_rect; // Window rect after transform(s)
++ MMAL_RECT_T display_rect; // Actual shape of display (x, y always 0)
++ MMAL_RECT_T req_win; // User requested window (w=0 => fullscreen)
++
+ MMAL_RECT_T spu_rect; // Output rectangle in cfg coords (for subpic
placement)
+ MMAL_RECT_T dest_rect; // Output rectangle in display coords
++ MMAL_DISPLAYTRANSFORM_T dest_transform; // Dest window coord transform
+ MMAL_DISPLAYTRANSFORM_T display_transform; // "Native" display transform
-+ MMAL_DISPLAYTRANSFORM_T dest_transform; // Combined config+native transform
-+
++ MMAL_DISPLAYTRANSFORM_T video_transform; // Combined config+native transform
+
+- int i_frame_rate_base; /* cached framerate to detect changes for rate adjustment */
+- int i_frame_rate;
+ unsigned int i_frame_rate_base; /* cached framerate to detect changes for rate
adjustment */
+ unsigned int i_frame_rate;
int next_phase_check; /* lowpass for phase check frequency */
int phase_offset; /* currently applied offset to presentation time in ns */
-@@ -136,264 +123,565 @@
+ int layer; /* the dispman layer (z-index) used for video rendering */
++ bool transparent; // Do not disable layers beneath ours
+
+ 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 */
bool b_progressive;
@@ -11114,14 +11198,17 @@
+ msg_Dbg(vd, "WxH: %dx%d, Crop: %dx%d", v_fmt->width, v_fmt->height,
v_fmt->crop.width, v_fmt->crop.height);
+}
+
-+static MMAL_RECT_T display_src_rect(const vout_display_t * const vd)
++static MMAL_RECT_T
++display_src_rect(const vout_display_t * const vd, const video_format_t * const src)
+{
+ const bool wants_isp = want_isp(vd);
++
++ // Scale source derived cropping to actual picture shape
+ return (MMAL_RECT_T){
-+ .x = wants_isp ? 0 : vd->fmt.i_x_offset,
-+ .y = wants_isp ? 0 : vd->fmt.i_y_offset,
-+ .width = vd->fmt.i_visible_width,
-+ .height = vd->fmt.i_visible_height
++ .x = wants_isp ? 0 : src->i_x_offset * vd->fmt.i_width / src->i_width,
++ .y = wants_isp ? 0 : src->i_y_offset * vd->fmt.i_height /
src->i_height,
++ .width = src->i_visible_width * vd->fmt.i_width / src->i_width,
++ .height = src->i_visible_height * vd->fmt.i_height / src->i_height
+ };
+}
+
@@ -11456,8 +11543,7 @@
+ isp->output->buffer_size = isp->output->buffer_size_recommended;
+ isp->output->buffer_num = 2;
+ isp->output->userdata = (void *)vd;
-
-- bcm_host_deinit();
++
+ if ((isp->out_pool = mmal_port_pool_create(isp->output,
isp->output->buffer_num, isp->output->buffer_size)) == NULL)
+ {
+ msg_Err(vd, "Failed to make ISP port pool");
@@ -11470,7 +11556,8 @@
+ goto fail;
+
+ return MMAL_SUCCESS;
-+
+
+- bcm_host_deinit();
+fail:
+ isp_close(vd, vd_sys);
+ return err;
@@ -11579,7 +11666,7 @@
+static MMAL_RECT_T
+place_out(const vout_display_cfg_t * cfg,
+ const video_format_t * fmt,
-+ unsigned int w, unsigned int h)
++ const MMAL_RECT_T r)
+{
+ video_format_t tfmt;
+ vout_display_cfg_t tcfg;
@@ -11595,30 +11682,42 @@
+
+ // Override what VLC thinks might be going on with display size
+ // if we know better
-+ if (w != 0 && h != 0)
++ if (r.width != 0 && r.height != 0)
+ {
+ tcfg = *cfg;
-+ tcfg.display.width = w;
-+ tcfg.display.height = h;
++ tcfg.display.width = r.width;
++ tcfg.display.height = r.height;
+ cfg = &tcfg;
+ }
+
+ vout_display_PlacePicture(&place, fmt, cfg, false);
++
++ place.x += r.x;
++ place.y += r.y;
++
+ return place_to_mmal_rect(place);
+}
+
++static MMAL_RECT_T
++rect_transform(MMAL_RECT_T s, const MMAL_RECT_T c, const MMAL_DISPLAYTRANSFORM_T t)
++{
++ if (is_transform_transpose(t))
++ s = rect_transpose(s);
++ if (is_transform_hflip(t))
++ s = rect_hflip(s, c);
++ if (is_transform_vflip(t) != 0)
++ s = rect_vflip(s, c);
++ return s;
++}
++
+static void
+place_dest_rect(vout_display_t * const vd,
+ const vout_display_cfg_t * const cfg,
+ const video_format_t * fmt)
+{
+ vout_display_sys_t * const sys = vd->sys;
-+ // If the display is transposed then we need to swap width/height
-+ // when asking for placement. Video orientation will we dealt with
-+ // in place_out
-+ sys->dest_rect = is_transform_transpose(sys->display_transform) ?
-+ rect_transpose(place_out(cfg, fmt, sys->display_height,
sys->display_width)) :
-+ place_out(cfg, fmt, sys->display_width, sys->display_height);
++ sys->dest_rect = rect_transform(place_out(cfg, fmt, sys->win_rect),
++ sys->display_rect, sys->dest_transform);
+}
+
+static void
@@ -11627,8 +11726,9 @@
+ const video_format_t * fmt)
+{
+ vout_display_sys_t * const sys = vd->sys;
++ static const MMAL_RECT_T r0 = {0};
+
-+ sys->spu_rect = place_out(cfg, fmt, 0, 0);
++ sys->spu_rect = place_out(cfg, fmt, r0);
+ sys->spu_rect.x = 0;
+ sys->spu_rect.y = 0;
+
@@ -11636,8 +11736,8 @@
+ // This info doesn't appear to reside anywhere natively
+
+ if (fmt->i_width * fmt->i_height >= (unsigned int)(sys->spu_rect.width *
sys->spu_rect.height)) {
-+ sys->spu_rect.width = fmt->i_width;
-+ sys->spu_rect.height = fmt->i_height;
++ sys->spu_rect.width = fmt->i_visible_width;
++ sys->spu_rect.height = fmt->i_visible_height;
+ }
+
+ if (ORIENT_IS_SWAP(fmt->orientation))
@@ -11654,7 +11754,7 @@
+}
+
+static int
-+set_input_region(vout_display_t * const vd)
++set_input_region(vout_display_t * const vd, const video_format_t * const fmt)
+{
+ const vout_display_sys_t * const sys = vd->sys;
+ MMAL_DISPLAYREGION_T display_region = {
@@ -11664,17 +11764,21 @@
+ },
+ .display_num = sys->display_id,
+ .fullscreen = MMAL_FALSE,
-+ .transform = sys->dest_transform,
-+ .src_rect = display_src_rect(vd),
++ .transform = sys->video_transform,
+ .dest_rect = sys->dest_rect,
++ .src_rect = display_src_rect(vd, fmt),
++ .noaspect = MMAL_TRUE,
++ .mode = MMAL_DISPLAY_MODE_FILL,
+ .layer = sys->layer,
-+ .alpha = 0xff | (1 << 29),
++ .alpha = 0xff | (sys->transparent ? 0 : (1 << 29)),
+ .set =
+ MMAL_DISPLAY_SET_NUM |
+ MMAL_DISPLAY_SET_FULLSCREEN |
+ MMAL_DISPLAY_SET_TRANSFORM |
-+ MMAL_DISPLAY_SET_SRC_RECT |
+ MMAL_DISPLAY_SET_DEST_RECT |
++ MMAL_DISPLAY_SET_SRC_RECT |
++ MMAL_DISPLAY_SET_NOASPECT |
++ MMAL_DISPLAY_SET_MODE |
+ MMAL_DISPLAY_SET_LAYER |
+ MMAL_DISPLAY_SET_ALPHA
+ };
@@ -11706,12 +11810,12 @@
if (fmt) {
sys->input->format->es->video.par.num = fmt->i_sar_num;
-@@ -412,30 +700,14 @@
+@@ -412,30 +733,14 @@ static int configure_display(vout_displa
if (!cfg)
cfg = vd->cfg;
- vout_display_PlacePicture(&place, fmt, cfg, false);
-+ sys->dest_transform = combine_transform(
++ sys->video_transform = combine_transform(
+ vlc_to_mmal_transform(fmt->orientation), sys->display_transform);
- display_region.hdr.id = MMAL_PARAMETER_DISPLAYREGION;
@@ -11734,7 +11838,7 @@
- status, mmal_status_to_string(status));
+ place_rects(vd, cfg, fmt);
+
-+ if (set_input_region(vd) != 0)
++ if (set_input_region(vd, fmt) != 0)
return -EINVAL;
- }
@@ -11742,12 +11846,20 @@
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) {
-@@ -446,204 +718,202 @@
+@@ -446,204 +751,217 @@ static int configure_display(vout_displa
return 0;
}
--static picture_pool_t *vd_pool(vout_display_t *vd, unsigned count)
+static void kill_pool(vout_display_sys_t * const sys)
++{
++ if (sys->pic_pool != NULL) {
++ picture_pool_Release(sys->pic_pool);
++ sys->pic_pool = NULL;
++ }
++}
++
++// Actual picture pool for MMAL opaques is just a set of trivial containers
+ static picture_pool_t *vd_pool(vout_display_t *vd, unsigned count)
{
- vout_display_sys_t *sys = vd->sys;
- picture_resource_t picture_res;
@@ -11755,33 +11867,43 @@
- video_format_t fmt = vd->fmt;
- MMAL_STATUS_T status;
- unsigned i;
--
++ vout_display_sys_t * const sys = vd->sys;
+
- if (sys->picture_pool) {
- if (sys->num_buffers < count)
- msg_Warn(vd, "Picture pool with %u pictures requested, but we already
have one with %u pictures",
- count, sys->num_buffers);
--
++ msg_Dbg(vd, "%s: fmt:%dx%d,sar:%d/%d; source:%dx%d", __func__,
++ vd->fmt.i_width, vd->fmt.i_height, vd->fmt.i_sar_num,
vd->fmt.i_sar_den, vd->source.i_width, vd->source.i_height);
+
- goto out;
-+ if (sys->pic_pool != NULL) {
-+ picture_pool_Release(sys->pic_pool);
-+ sys->pic_pool = NULL;
++ if (sys->pic_pool == NULL) {
++ sys->pic_pool = picture_pool_NewFromFormat(&vd->fmt, count);
}
++ return sys->pic_pool;
+}
- if (sys->opaque) {
- if (count <= NUM_ACTUAL_OPAQUE_BUFFERS)
- count = NUM_ACTUAL_OPAQUE_BUFFERS;
-+// Actual picture pool for MMAL opaques is just a set of trivial containers
-+static picture_pool_t *vd_pool(vout_display_t *vd, unsigned count)
++static inline bool
++check_shape(vout_display_t * const vd, const picture_t * const p_pic)
+{
-+ vout_display_sys_t * const sys = vd->sys;
++ if (vd->fmt.i_width == p_pic->format.i_width &&
++ vd->fmt.i_height == p_pic->format.i_height)
++ return true;
++ return false;
++}
- MMAL_PARAMETER_BOOLEAN_T zero_copy = {
- { MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T) },
- 1
- };
-+ msg_Dbg(vd, "%s: fmt:%dx%d,sar:%d/%d; source:%dx%d", __func__,
-+ vd->fmt.i_width, vd->fmt.i_height, vd->fmt.i_sar_num,
vd->fmt.i_sar_den, vd->source.i_width, vd->source.i_height);
++static void vd_display(vout_display_t *vd, picture_t *p_pic,
++ subpicture_t *subpicture)
++{
++ vout_display_sys_t * const sys = vd->sys;
++ MMAL_STATUS_T err;
- status = mmal_port_parameter_set(sys->input, &zero_copy.hdr);
- if (status != MMAL_SUCCESS) {
@@ -11789,22 +11911,6 @@
- sys->input->name, status, mmal_status_to_string(status));
- goto out;
- }
-+ if (sys->pic_pool == NULL) {
-+ sys->pic_pool = picture_pool_NewFromFormat(&vd->fmt, count);
- }
-+ return sys->pic_pool;
-+}
-
-- if (count < sys->input->buffer_num_recommended)
-- count = sys->input->buffer_num_recommended;
-+static void vd_display(vout_display_t *vd, picture_t *p_pic,
-+ subpicture_t *subpicture)
-+{
-+ vout_display_sys_t * const sys = vd->sys;
-+ MMAL_STATUS_T err;
-
--#ifndef NDEBUG
-- msg_Dbg(vd, "Creating picture pool with %u pictures", count);
+#if TRACE_ALL
+ {
+ char dbuf0[5];
@@ -11814,7 +11920,13 @@
+ p_pic->format.i_visible_width, p_pic->format.i_visible_height,
+ p_pic->format.i_sar_num, p_pic->format.i_sar_den,
+ sys->dest_rect.width, sys->dest_rect.height, sys->dest_rect.x,
sys->dest_rect.y);
-+ }
+ }
+-
+- if (count < sys->input->buffer_num_recommended)
+- count = sys->input->buffer_num_recommended;
+-
+-#ifndef NDEBUG
+- msg_Dbg(vd, "Creating picture pool with %u pictures", count);
#endif
- sys->input->buffer_num = count;
@@ -11834,6 +11946,12 @@
- msg_Err(vd, "Failed to enable component %s (status=%"PRIx32"
%s)",
- sys->component->name, status,
mmal_status_to_string(status));
- goto out;
++ if (!check_shape(vd, p_pic))
++ {
++ msg_Err(vd, "Pic/fmt shape mismatch");
++ goto fail;
++ }
++
+ if (!sys->input->is_enabled &&
+ (err = mmal_port_enable(sys->input, vd_input_port_cb)) != MMAL_SUCCESS)
+ {
@@ -11998,19 +12116,19 @@
+ else if (rv < 0)
+ goto fail;
}
-+ }
-
+-
- pic_sys->displayed = true;
- } else {
- picture_Release(picture);
+ }
+
+- display_subpicture(vd, subpicture);
+fail:
+ for (unsigned int i = 0; i != SUBS_MAX && sys->subpic_bufs[i] != NULL;
++i) {
+ mmal_buffer_header_release(sys->subpic_bufs[i]);
+ sys->subpic_bufs[i] = NULL;
- }
++ }
-- display_subpicture(vd, subpicture);
--
- if (subpicture)
- subpicture_Delete(subpicture);
+ picture_Release(p_pic);
@@ -12101,7 +12219,31 @@
default:
msg_Warn(vd, "Unknown control query %d", query);
-@@ -661,13 +931,11 @@
+@@ -653,79 +971,207 @@ static int vd_control(vout_display_t *vd
+ return ret;
+ }
+
++static void set_display_windows(vout_display_t *const vd, vout_display_sys_t *const
sys)
++{
++ unsigned int width, height;
++ if (query_resolution(vd, sys->display_id, &width, &height) < 0) {
++ width = vd->cfg->display.width;
++ height = vd->cfg->display.height;
++ }
++ sys->display_rect = (MMAL_RECT_T){0, 0, width, height};
++
++ sys->win_rect = (sys->req_win.width != 0) ?
++ sys->req_win :
++ is_transform_transpose(sys->display_transform) ?
++ rect_transpose(sys->display_rect) : sys->display_rect;
++}
++
+ static void vd_manage(vout_display_t *vd)
+ {
+- vout_display_sys_t *sys = vd->sys;
+- unsigned width, height;
++ vout_display_sys_t *const sys = vd->sys;
+
vlc_mutex_lock(&sys->manage_mutex);
if (sys->need_configure_display) {
@@ -12109,16 +12251,15 @@
- sys->dmx_handle = vc_dispmanx_display_open(0);
-
- if (query_resolution(vd, &width, &height) >= 0) {
-+ if (query_resolution(vd, sys->display_id, &width, &height) >= 0)
{
- sys->display_width = width;
- sys->display_height = height;
+- sys->display_width = width;
+- sys->display_height = height;
- vout_display_SendEventDisplaySize(vd, width, height);
-+// msg_Dbg(vd, "%s: %dx%d", __func__, width, height);
-+// vout_window_ReportSize(vd->cfg->window, width, height);
- }
-
+- }
+-
sys->need_configure_display = false;
-@@ -676,56 +944,175 @@
++ set_display_windows(vd, sys);
+ }
+
vlc_mutex_unlock(&sys->manage_mutex);
}
@@ -12204,6 +12345,9 @@
+
+ vd_manage(vd);
+
++ if (!check_shape(vd, p_pic))
++ return;
++
+ 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 ||
@@ -12215,7 +12359,7 @@
+ sys->b_progressive = p_pic->b_progressive;
+ sys->i_frame_rate = p_pic->format.i_frame_rate;
+ sys->i_frame_rate_base = p_pic->format.i_frame_rate_base;
-+ configure_display(vd, NULL, &p_pic->format);
++ configure_display(vd, NULL, &vd->source);
+ }
+
+ // Subpics can either turn up attached to the main pic or in the
@@ -12328,7 +12472,7 @@
}
static void tvservice_cb(void *callback_data, uint32_t reason, uint32_t param1, uint32_t
param2)
-@@ -780,9 +1167,9 @@
+@@ -780,9 +1226,9 @@ static void adjust_refresh_rate(vout_dis
double best_score, score;
int i;
@@ -12340,7 +12484,7 @@
supported_modes, VC_TV_MAX_MODE_IDS, NULL, NULL);
for (i = 0; i < num_modes; ++i) {
-@@ -810,7 +1197,7 @@
+@@ -810,7 +1256,7 @@ static void adjust_refresh_rate(vout_dis
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);
@@ -12349,7 +12493,7 @@
supported_modes[best_id].group,
supported_modes[best_id].code);
}
-@@ -828,148 +1215,12 @@
+@@ -828,148 +1274,12 @@ static void adjust_refresh_rate(vout_dis
}
}
@@ -12499,7 +12643,7 @@
((double)vd->sys->i_frame_rate /
vd->sys->i_frame_rate_base);
vout_display_sys_t *sys = vd->sys;
-@@ -1012,32 +1263,403 @@
+@@ -1012,32 +1322,436 @@ static void maintain_phase_sync(vout_dis
}
}
@@ -12559,7 +12703,7 @@
+ mmal_component_release(sub->component);
+ sub->component = NULL;
+ }
-+ }
+ }
+
+ if (sys->input && sys->input->is_enabled)
+ mmal_port_disable(sys->input);
@@ -12701,6 +12845,33 @@
+}
+#endif
+
++static MMAL_RECT_T str_to_rect(const char * s)
++{
++ MMAL_RECT_T rect = {0};
++ rect.width = strtoul(s, (char**)&s, 0);
++ if (*s == '\0')
++ return rect;
++ if (*s++ != 'x')
++ goto fail;
++ rect.height = strtoul(s, (char**)&s, 0);
++ if (*s == '\0')
++ return rect;
++ if (*s++ != '+')
++ goto fail;
++ rect.x = strtoul(s, (char**)&s, 0);
++ if (*s == '\0')
++ return rect;
++ if (*s++ != '+')
++ goto fail;
++ rect.y = strtoul(s, (char**)&s, 0);
++ if (*s != '\0')
++ goto fail;
++ return rect;
++
++fail:
++ return (MMAL_RECT_T){0,0,0,0};
++}
++
+static int OpenMmalVout(vlc_object_t *object)
+{
+ vout_display_t *vd = (vout_display_t *)object;
@@ -12734,6 +12905,7 @@
+ vc_tv_register_callback(tvservice_cb, vd);
+
+ sys->layer = var_InheritInteger(vd, MMAL_LAYER_NAME);
++ sys->transparent = var_InheritBool(vd, MMAL_VOUT_TRANSPARENT_NAME);
+
+ {
+ const char *display_name = var_InheritString(vd, MMAL_DISPLAY_NAME);
@@ -12750,6 +12922,15 @@
+ }
+
+ {
++ const char *window_str = var_InheritString(vd, MMAL_VOUT_WINDOW_NAME);
++ sys->req_win = str_to_rect(window_str);
++ if (sys->req_win.width != 0)
++ msg_Dbg(vd, "Window: %dx%d @ %d,%d",
++ sys->req_win.width, sys->req_win.height,
++ sys->req_win.x, sys->req_win.y);
++ }
++
++ {
+ const char *transform_name = var_InheritString(vd, MMAL_VOUT_TRANSFORM_NAME);
+ int transform_num = find_transform_num(transform_name);
+ sys->display_transform = transform_num < 0 ?
@@ -12762,8 +12943,9 @@
+ msg_Dbg(vd, "Display transform: %s, mmal_display_transform=%d",
+ transform_name, (int)sys->display_transform);
+
-+ sys->dest_transform = combine_transform(
++ sys->video_transform = combine_transform(
+ vlc_to_mmal_transform(vd->fmt.orientation), sys->display_transform);
++ sys->dest_transform = transform_inverse(sys->display_transform);
+ }
+
+ status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER,
&sys->component);
@@ -12818,16 +13000,9 @@
+ }
+ }
+
-+ 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_rects(vd, vd->cfg, &vd->source); // Sets sys->dest_rect
++ set_display_windows(vd, sys);
+
-+ if (set_input_region(vd) != 0)
-+ goto fail;
++ configure_display(vd, vd->cfg, &vd->source);
+
+ status = mmal_port_enable(sys->input, vd_input_port_cb);
+ if (status != MMAL_SUCCESS) {
@@ -12841,7 +13016,7 @@
+ msg_Err(vd, "Failed to enable component %s (status=%"PRIx32"
%s)",
+ sys->component->name, status, mmal_status_to_string(status));
+ goto fail;
- }
++ }
+
+ if ((sys->pool = mmal_pool_create(sys->input->buffer_num, 0)) == NULL)
+ {
@@ -12920,10 +13095,12 @@
+ MMAL_NATIVE_INTERLACE_LONGTEXT, false)
+ add_string(MMAL_DISPLAY_NAME, "auto", MMAL_DISPLAY_TEXT,
+ MMAL_DISPLAY_LONGTEXT, false)
-+ add_string(MMAL_DISPLAY_NAME, "auto", MMAL_DISPLAY_TEXT,
-+ MMAL_DISPLAY_LONGTEXT, false)
+ add_string(MMAL_VOUT_TRANSFORM_NAME, "auto", MMAL_VOUT_TRANSFORM_TEXT,
+ MMAL_VOUT_TRANSFORM_LONGTEXT, false)
++ add_string(MMAL_VOUT_WINDOW_NAME, "fullscreen", MMAL_VOUT_WINDOW_TEXT,
++ MMAL_VOUT_WINDOW_LONGTEXT, false)
++ add_bool(MMAL_VOUT_TRANSPARENT_NAME, false, MMAL_VOUT_TRANSPARENT_TEXT,
++ MMAL_VOUT_TRANSPARENT_LONGTEXT, false)
+ set_callbacks(OpenMmalVout, CloseMmalVout)
+
+vlc_module_end()
@@ -12931,7 +13108,7 @@
+
--- /dev/null
+++ b/modules/hw/mmal/xsplitter.c
-@@ -0,0 +1,560 @@
+@@ -0,0 +1,584 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
@@ -13230,7 +13407,7 @@
+}
+
+
-+static int vout_display_Control(display_desc_t * const dd, int query, ...)
++static int vout_display_Control(const display_desc_t * const dd, int query, ...)
+{
+ va_list args;
+ int result;
@@ -13248,6 +13425,46 @@
+ (sys->x_desc.vout == NULL || var_InheritBool(vd, "fullscreen"));
+}
+
++static inline int
++up_rv(const int a, const int b)
++{
++ return a != 0 ? a : b;
++}
++
++static int
++reset_pictures(vout_display_t * const vd, const display_desc_t * const desc)
++{
++ int rv = 0;
++ VLC_UNUSED(vd);
++ if (desc->vout)
++ {
++ // If the display doesn't have has_pictures_invalid then it doesn't
++ // expect RESET_PICTURES
++ if (desc->vout->info.has_pictures_invalid)
++ vout_display_Control(desc, VOUT_DISPLAY_RESET_PICTURES);
++ }
++ return rv;
++}
++
++static int
++replay_controls(vout_display_t * const vd, const display_desc_t * const desc, const
int32_t changed)
++{
++ if ((changed & (1 << VOUT_DISPLAY_CHANGE_DISPLAY_FILLED)) != 0)
++ vout_display_Control(desc, VOUT_DISPLAY_CHANGE_DISPLAY_FILLED, vd->cfg);
++ if ((changed & (1 << VOUT_DISPLAY_CHANGE_ZOOM)) != 0)
++ vout_display_Control(desc, VOUT_DISPLAY_CHANGE_ZOOM, vd->cfg);
++ if ((changed & ((1 << VOUT_DISPLAY_CHANGE_SOURCE_CROP) |
++ (1 << VOUT_DISPLAY_CHANGE_SOURCE_ASPECT))) != 0)
++ cpy_fmt_limit_size(desc, &desc->vout->source, &vd->source);
++ if ((changed & (1 << VOUT_DISPLAY_CHANGE_SOURCE_ASPECT)) != 0)
++ vout_display_Control(desc, VOUT_DISPLAY_CHANGE_SOURCE_ASPECT);
++ if ((changed & (1 << VOUT_DISPLAY_CHANGE_SOURCE_CROP)) != 0)
++ vout_display_Control(desc, VOUT_DISPLAY_CHANGE_SOURCE_CROP);
++ if ((changed & (1 << VOUT_DISPLAY_CHANGE_VIEWPOINT)) != 0)
++ vout_display_Control(desc, VOUT_DISPLAY_CHANGE_VIEWPOINT, vd->cfg);
++ return 0;
++}
++
+/* Control on the module (mandatory) */
+static int mmal_x11_control(vout_display_t * vd, int ctl, va_list va)
+{
@@ -13273,6 +13490,13 @@
+ cfg->display.width, cfg->display.height,
sys->mmal_desc.vout, want_mmal,
+ var_InheritBool(vd, "fullscreen"));
+
++ // Repeat any control calls that we sent to the previous vd
++ if (swap_vout && sys->changed != 0) {
++ const uint32_t changed = sys->changed;
++ sys->changed = 0;
++ replay_controls(vd, new_desc, changed);
++ }
++
+ if (swap_vout) {
+ if (sys->use_mmal) {
+ vout_display_Control(x_desc, VOUT_DISPLAY_CHANGE_MMAL_HIDE);
@@ -13287,24 +13511,6 @@
+ sys->use_mmal = want_mmal;
+ }
+
-+ // Repeat any control calls that we sent to the previous vd
-+ if (swap_vout && sys->changed != 0) {
-+ const uint32_t changed = sys->changed;
-+ sys->changed = 0;
-+ if ((changed & (1 << VOUT_DISPLAY_CHANGE_DISPLAY_FILLED)) !=
0)
-+ vout_display_Control(new_desc, VOUT_DISPLAY_CHANGE_DISPLAY_FILLED,
vd->cfg);
-+ if ((changed & (1 << VOUT_DISPLAY_CHANGE_ZOOM)) != 0)
-+ vout_display_Control(new_desc, VOUT_DISPLAY_CHANGE_ZOOM,
vd->cfg);
-+ if ((changed & ((1 << VOUT_DISPLAY_CHANGE_SOURCE_CROP) |
-+ (1 << VOUT_DISPLAY_CHANGE_SOURCE_ASPECT))) != 0)
-+ cpy_fmt_limit_size(new_desc, &new_desc->vout->source,
&vd->source);
-+ if ((changed & (1 << VOUT_DISPLAY_CHANGE_SOURCE_ASPECT)) !=
0)
-+ vout_display_Control(new_desc, VOUT_DISPLAY_CHANGE_SOURCE_ASPECT);
-+ if ((changed & (1 << VOUT_DISPLAY_CHANGE_SOURCE_CROP)) != 0)
-+ vout_display_Control(new_desc, VOUT_DISPLAY_CHANGE_SOURCE_CROP);
-+ if ((changed & (1 << VOUT_DISPLAY_CHANGE_VIEWPOINT)) != 0)
-+ vout_display_Control(new_desc, VOUT_DISPLAY_CHANGE_VIEWPOINT,
vd->cfg);
-+ }
+
+ break;
+ }
@@ -13318,14 +13524,9 @@
+ str_fourcc(dbuf2, vd->source.i_chroma),
vd->source.i_width, vd->source.i_height, x_desc->vout->source.i_width,
+ x_desc->vout->source.i_height);
+ }
-+ // If the display doesn't have has_pictures_invalid then it doesn't
-+ // expect RESET_PICTURES
-+ if (sys->x_desc.vout->info.has_pictures_invalid) {
-+ rv = sys->x_desc.vout->control(sys->x_desc.vout, ctl, va);
-+ }
-+ if (sys->mmal_desc.vout &&
sys->mmal_desc.vout->info.has_pictures_invalid) {
-+ rv = sys->mmal_desc.vout->control(sys->mmal_desc.vout, ctl,
va);
-+ }
++ rv = reset_pictures(vd, &sys->x_desc);
++ rv = up_rv(rv, reset_pictures(vd, &sys->mmal_desc));
++
+ vd->fmt = x_desc->vout->fmt;
+ break;
+
@@ -13503,7 +13704,7 @@
typedef struct vlc_gl_sys_t
{
EGLDisplay display;
-@@ -355,6 +357,14 @@
+@@ -355,6 +357,14 @@ static int Open (vlc_object_t *obj, cons
goto error;
}
@@ -13520,7 +13721,7 @@
EGL_GREEN_SIZE, 5,
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
-@@ -1995,6 +1995,7 @@
+@@ -1995,6 +1995,7 @@ void input_DecoderDelete( decoder_t *p_d
vlc_mutex_lock( &p_owner->lock );
p_owner->b_waiting = false;
vlc_cond_signal( &p_owner->wait_request );
@@ -13528,7 +13729,7 @@
/* If the video output is paused or slow, or if the picture pool size was
* under-estimated (e.g. greedy video filter, buggy decoder...), the
-@@ -2005,7 +2006,6 @@
+@@ -2005,7 +2006,6 @@ void input_DecoderDelete( decoder_t *p_d
* worker threads (if any) and the decoder thread to terminate. */
if( p_owner->p_vout != NULL )
vout_Cancel( p_owner->p_vout, true );
@@ -13538,7 +13739,7 @@
--- a/src/misc/fourcc.c
+++ b/src/misc/fourcc.c
-@@ -755,8 +755,13 @@
+@@ -755,8 +755,13 @@ static const struct
{ { VLC_CODEC_VDPAU_VIDEO_420, VLC_CODEC_VDPAU_VIDEO_422,
VLC_CODEC_VDPAU_VIDEO_444, VLC_CODEC_VDPAU_OUTPUT },
FAKE_FMT() },
@@ -13556,7 +13757,7 @@
FAKE_FMT() },
--- a/src/misc/picture.c
+++ b/src/misc/picture.c
-@@ -365,10 +365,30 @@
+@@ -365,10 +365,30 @@ void picture_CopyProperties( picture_t *
p_dst->b_top_field_first = p_src->b_top_field_first;
}
@@ -13591,7 +13792,7 @@
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
-@@ -964,6 +964,17 @@
+@@ -964,6 +964,17 @@ static picture_t *ConvertRGB32AndBlend(v
return NULL;
}
@@ -13609,7 +13810,7 @@
static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
{
vout_thread_sys_t *sys = vout->p;
-@@ -1098,7 +1109,7 @@
+@@ -1098,7 +1109,7 @@ static int ThreadDisplayRenderPicture(vo
}
assert(vout_IsDisplayFiltered(vd) == !sys->display.use_dr);