+Piece::set_last_push_end (AudioStreamPtr stream, DCPTime end)
+{
+ DCPOMATIC_ASSERT (_stream_last_push_end.find(stream) != _stream_last_push_end.end());
+ _stream_last_push_end[stream] = end;
+}
+
+
+DCPTime
+Piece::position () const
+{
+ return _content[0]->position();
+}
+
+
+DCPTime
+Piece::end (shared_ptr<const Film> film) const
+{
+ return _content[0]->end(film);
+}
+
+
+DCPTime
+Piece::content_video_to_dcp (Frame f) const
+{
+ /* It might seem more logical here to convert s to a ContentTime (using the FrameRateChange)
+ then convert that ContentTime to frames at the content's rate. However this fails for
+ situations like content at 29.9978733fps, DCP at 30fps. The accuracy of the Time type is not
+ enough to distinguish between the two with low values of time (e.g. 3200 in Time units).
+
+ Instead we convert the DCPTime using the DCP video rate then account for any skip/repeat.
+ */
+
+ DCPTime const d = DCPTime::from_frames(f * _frc.factor(), _frc.dcp) - DCPTime(_content[0]->trim_start(), _frc);
+ return d + position();
+}
+
+
+DCPTime
+Piece::resampled_audio_to_dcp (shared_ptr<const Film> film, Frame f) const