+static void ThreadChangeAspectRatio(vout_thread_t *vout,
+ unsigned num, unsigned den)
+{
+ const video_format_t *source = &vout->p->original;
+
+ if (num > 0 && den > 0) {
+ num *= source->i_visible_height;
+ den *= source->i_visible_width;
+ vlc_ureduce(&num, &den, num, den, 0);
+ }
+ vout_SetDisplayAspect(vout->p->display.vd, num, den);
+}
+
+
+static void ThreadExecuteCropWindow(vout_thread_t *vout,
+ unsigned crop_num, unsigned crop_den,
+ unsigned x, unsigned y,
+ unsigned width, unsigned height)
+{
+ const video_format_t *source = &vout->p->original;
+
+ vout_SetDisplayCrop(vout->p->display.vd,
+ crop_num, crop_den,
+ source->i_x_offset + x,
+ source->i_y_offset + y,
+ width, height);
+}
+static void ThreadExecuteCropBorder(vout_thread_t *vout,
+ unsigned left, unsigned top,
+ unsigned right, unsigned bottom)
+{
+ const video_format_t *source = &vout->p->original;
+ ThreadExecuteCropWindow(vout, 0, 0,
+ left,
+ top,
+ /* At worst, it becomes < 0 (but unsigned) and will be rejected */
+ source->i_visible_width - (left + right),
+ source->i_visible_height - (top + bottom));
+}
+
+static void ThreadExecuteCropRatio(vout_thread_t *vout,
+ unsigned num, unsigned den)
+{
+ const video_format_t *source = &vout->p->original;
+
+ int x, y;
+ int width, height;
+ if (num <= 0 || den <= 0) {
+ num = 0;
+ den = 0;
+ x = 0;
+ y = 0;
+ width = source->i_visible_width;
+ height = source->i_visible_height;
+ } else {
+ unsigned scaled_width = (uint64_t)source->i_visible_height * num * source->i_sar_den / den / source->i_sar_num;
+ unsigned scaled_height = (uint64_t)source->i_visible_width * den * source->i_sar_num / num / source->i_sar_den;
+
+ if (scaled_width < source->i_visible_width) {
+ x = (source->i_visible_width - scaled_width) / 2;
+ y = 0;
+ width = scaled_width;
+ height = source->i_visible_height;
+ } else {
+ x = 0;
+ y = (source->i_visible_height - scaled_height) / 2;
+ width = source->i_visible_width;
+ height = scaled_height;
+ }
+ }
+ ThreadExecuteCropWindow(vout, num, den, x, y, width, height);
+}
+
+static int ThreadInit(vout_thread_t *vout)
+{
+ vout->p->dead = false;
+ vout->p->is_late_dropped = var_InheritBool(vout, "drop-late-frames");
+ vlc_mouse_Init(&vout->p->mouse);
+ vout->p->decoder_fifo = picture_fifo_New();
+ vout->p->decoder_pool = NULL;
+ vout->p->display_pool = NULL;
+ vout->p->private_pool = NULL;
+
+ vout->p->vfilter_chain =
+ filter_chain_New( vout, "video filter2", false,
+ VoutVideoFilterAllocationSetup, NULL, vout);
+
+ if (vout_OpenWrapper(vout, vout->p->splitter_name))
+ return VLC_EGENERIC;
+ if (vout_InitWrapper(vout))
+ return VLC_EGENERIC;
+ assert(vout->p->decoder_pool);
+
+ vout_chrono_Init(&vout->p->render, 5, 10000); /* Arbitrary initial time */
+
+ vout->p->displayed.decoded = NULL;
+ vout->p->displayed.date = VLC_TS_INVALID;
+ vout->p->displayed.decoded = NULL;
+ vout->p->displayed.timestamp = VLC_TS_INVALID;
+ vout->p->displayed.qtype = QTYPE_NONE;
+ vout->p->displayed.is_interlaced = false;
+
+ vout->p->step.last = VLC_TS_INVALID;
+ vout->p->step.timestamp = VLC_TS_INVALID;
+
+ vout->p->pause.is_on = false;
+ vout->p->pause.date = VLC_TS_INVALID;
+
+ video_format_Print(VLC_OBJECT(vout), "original format", &vout->p->original);
+ return VLC_SUCCESS;
+}
+