+ dcp::Size const s = size ();
+ switch (frame_type ()) {
+ case VIDEO_FRAME_TYPE_2D:
+ case VIDEO_FRAME_TYPE_3D:
+ case VIDEO_FRAME_TYPE_3D_ALTERNATE:
+ case VIDEO_FRAME_TYPE_3D_LEFT:
+ case VIDEO_FRAME_TYPE_3D_RIGHT:
+ return s;
+ case VIDEO_FRAME_TYPE_3D_LEFT_RIGHT:
+ return dcp::Size (s.width / 2, s.height);
+ case VIDEO_FRAME_TYPE_3D_TOP_BOTTOM:
+ return dcp::Size (s.width, s.height / 2);
+ }
+
+ DCPOMATIC_ASSERT (false);
+}
+
+/** @return Video size after 3D split and crop */
+dcp::Size
+VideoContent::size_after_crop () const
+{
+ return crop().apply (size_after_3d_split ());
+}
+
+
+/** @param f Frame index within the whole (untrimmed) content.
+ * @return Fade factor (between 0 and 1) or unset if there is no fade.
+ */
+optional<double>
+VideoContent::fade (shared_ptr<const Film> film, Frame f) const
+{
+ DCPOMATIC_ASSERT (f >= 0);
+
+ double const vfr = _parent->active_video_frame_rate(film);
+
+ Frame const ts = _parent->trim_start().frames_round(vfr);
+ if ((f - ts) < fade_in()) {
+ return double (f - ts) / fade_in();
+ }
+
+ Frame fade_out_start = length() - _parent->trim_end().frames_round(vfr) - fade_out();
+ if (f >= fade_out_start) {
+ return 1 - double (f - fade_out_start) / fade_out();
+ }
+
+ return optional<double> ();
+}
+
+string
+VideoContent::processing_description (shared_ptr<const Film> film)
+{
+ string d;
+ char buffer[256];
+
+ if (size().width && size().height) {
+ d += String::compose (
+ _("Content video is %1x%2"),
+ size_after_3d_split().width,
+ size_after_3d_split().height
+ );
+
+
+ double ratio = size_after_3d_split().ratio ();
+
+ if (sample_aspect_ratio ()) {
+ snprintf (buffer, sizeof(buffer), _(", pixel aspect ratio %.2f:1"), sample_aspect_ratio().get());
+ d += buffer;
+ ratio *= sample_aspect_ratio().get ();