Tests of Player::dcp_to_content_video, content_video_to_dcp and
authorCarl Hetherington <cth@carlh.net>
Tue, 14 Jul 2015 11:43:08 +0000 (12:43 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 14 Jul 2015 11:43:08 +0000 (12:43 +0100)
dcp_to_content_audio with some subtle and hopefully reasonable
fixes.

src/lib/audio_stream.h
src/lib/player.cc
src/lib/player.h
test/time_calculation_test.cc

index 3b236542c704d3c9d59a644b01d2fc0b324e3251..506a3c02dc706fce689fee8766006210123073b9 100644 (file)
@@ -50,6 +50,7 @@ protected:
 
 private:
        friend struct audio_sampling_rate_test;
+       friend struct player_time_calculation_test3;
 
        int _frame_rate;
        AudioMapping _mapping;
index ed4519acafa7ddbffdfd85c9b4f6c8a1570ff640..83131e2008997588fb2ea1f3b6a9f91f7f71f76d 100644 (file)
@@ -464,10 +464,10 @@ Player::get_audio (DCPTime time, DCPTime length, bool accurate)
                        request = DCPTime ();
                }
 
-               Frame const content_frame = dcp_to_content_audio (*i, request);
-
                BOOST_FOREACH (AudioStreamPtr j, content->audio_streams ()) {
 
+                       Frame const content_frame = dcp_to_content_audio (*i, j, request);
+
                        if (j->channels() == 0) {
                                /* Some content (e.g. DCPs) can have streams with no channels */
                                continue;
@@ -521,13 +521,12 @@ Player::get_audio (DCPTime time, DCPTime length, bool accurate)
 Frame
 Player::dcp_to_content_video (shared_ptr<const Piece> piece, DCPTime t) const
 {
-       /* s is the offset of t from the start position of this content */
-       DCPTime s = t - piece->content->position ();
+       DCPTime s = t - piece->content->position () + piece->content->trim_start ();
        s = DCPTime (max (DCPTime::Type (0), s.get ()));
        s = DCPTime (min (piece->content->length_after_trim().get(), s.get()));
 
        /* Convert this to the content frame */
-       return DCPTime (s + piece->content->trim_start()).frames (_film->video_frame_rate()) / piece->frc.factor ();
+       return s.frames (_film->video_frame_rate()) / piece->frc.factor ();
 }
 
 DCPTime
@@ -542,15 +541,13 @@ Player::content_video_to_dcp (shared_ptr<const Piece> piece, Frame f) const
 }
 
 Frame
-Player::dcp_to_content_audio (shared_ptr<const Piece> piece, DCPTime t) const
+Player::dcp_to_content_audio (shared_ptr<const Piece> piece, AudioStreamPtr stream, DCPTime t) const
 {
-       /* s is the offset of t from the start position of this content */
-       DCPTime s = t - piece->content->position ();
+       DCPTime s = t - piece->content->position () + piece->content->trim_start ();
        s = DCPTime (max (DCPTime::Type (0), s.get ()));
        s = DCPTime (min (piece->content->length_after_trim().get(), s.get()));
 
-       /* Convert this to the content frame */
-       return DCPTime (s + piece->content->trim_start()).frames (_film->audio_frame_rate());
+       return ContentTime (s, piece->frc).frames (stream->frame_rate ());
 }
 
 ContentTime
index 0abb02daa96123ed8daa0a21c1ee2d58b8bc8ab1..9b2e27251f862c468cd83e9c48b2abafadff6aa1 100644 (file)
@@ -109,6 +109,9 @@ private:
        friend class PlayerWrapper;
        friend class Piece;
        friend struct player_overlaps_test;
+       friend struct player_time_calculation_test1;
+       friend struct player_time_calculation_test2;
+       friend struct player_time_calculation_test3;
 
        void setup_pieces ();
        void flush ();
@@ -119,7 +122,7 @@ private:
        void update_subtitle_from_text ();
        Frame dcp_to_content_video (boost::shared_ptr<const Piece> piece, DCPTime t) const;
        DCPTime content_video_to_dcp (boost::shared_ptr<const Piece> piece, Frame f) const;
-       Frame dcp_to_content_audio (boost::shared_ptr<const Piece> piece, DCPTime t) const;
+       Frame dcp_to_content_audio (boost::shared_ptr<const Piece> piece, AudioStreamPtr stream, DCPTime t) const;
        ContentTime dcp_to_content_subtitle (boost::shared_ptr<const Piece> piece, DCPTime t) const;
        boost::shared_ptr<PlayerVideo> black_player_video_frame (DCPTime) const;
 
index 8ee0797584283476453e61f66b14cf67857ef5d7..92e7b15ec5420cef180905060c7732df7f55e675 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "lib/film.h"
 #include "lib/ffmpeg_content.h"
+#include "lib/player.h"
 #include "test.h"
 #include <boost/test/unit_test.hpp>
 
@@ -26,98 +27,98 @@ using std::string;
 using std::list;
 using boost::shared_ptr;
 
+static string const xml = "<Content>"
+       "<Type>FFmpeg</Type>"
+       "<BurnSubtitles>0</BurnSubtitles>"
+       "<BitsPerPixel>8</BitsPerPixel>"
+       "<Path>/home/c.hetherington/DCP/clapperboard.mp4</Path>"
+       "<Digest>2760e03c7251480f7f02c01a907792673784335</Digest>"
+       "<Position>0</Position>"
+       "<TrimStart>0</TrimStart>"
+       "<TrimEnd>0</TrimEnd>"
+       "<VideoLength>1353600</VideoLength>"
+       "<VideoWidth>1280</VideoWidth>"
+       "<VideoHeight>720</VideoHeight>"
+       "<VideoFrameRate>25</VideoFrameRate>"
+       "<VideoFrameType>0</VideoFrameType>"
+       "<LeftCrop>0</LeftCrop>"
+       "<RightCrop>0</RightCrop>"
+       "<TopCrop>0</TopCrop>"
+       "<BottomCrop>0</BottomCrop>"
+       "<Scale>"
+       "<Ratio>178</Ratio>"
+       "</Scale>"
+       "<ColourConversion>"
+       "<InputTransferFunction>"
+       "<Type>ModifiedGamma</Type>"
+       "<Power>2.222222222222222</Power>"
+       "<Threshold>0.081</Threshold>"
+       "<A>0.099</A>"
+       "<B>4.5</B>"
+       "</InputTransferFunction>"
+       "<RedX>0.64</RedX>"
+       "<RedY>0.33</RedY>"
+       "<GreenX>0.3</GreenX>"
+       "<GreenY>0.6</GreenY>"
+       "<BlueX>0.15</BlueX>"
+       "<BlueY>0.06</BlueY>"
+       "<WhiteX>0.3127</WhiteX>"
+       "<WhiteY>0.329</WhiteY>"
+       "<OutputGamma>2.6</OutputGamma>"
+       "</ColourConversion>"
+       "<FadeIn>0</FadeIn>"
+       "<FadeOut>0</FadeOut>"
+       "<AudioGain>0</AudioGain>"
+       "<AudioDelay>0</AudioDelay>"
+       "<UseSubtitles>0</UseSubtitles>"
+       "<SubtitleXOffset>0</SubtitleXOffset>"
+       "<SubtitleYOffset>0</SubtitleYOffset>"
+       "<SubtitleXScale>1</SubtitleXScale>"
+       "<SubtitleYScale>1</SubtitleYScale>"
+       "<SubtitleLanguage></SubtitleLanguage>"
+       "<AudioStream>"
+       "<Selected>1</Selected>"
+       "<Name>und; 2 channels</Name>"
+       "<Id>2</Id>"
+       "<FrameRate>44100</FrameRate>"
+       "<Channels>2</Channels>"
+       "<FirstAudio>0</FirstAudio>"
+       "<Mapping>"
+       "<InputChannels>2</InputChannels>"
+       "<OutputChannels>12</OutputChannels>"
+       "<Gain Input=\"0\" Output=\"0\">1</Gain>"
+       "<Gain Input=\"0\" Output=\"1\">0</Gain>"
+       "<Gain Input=\"0\" Output=\"2\">0</Gain>"
+       "<Gain Input=\"0\" Output=\"3\">0</Gain>"
+       "<Gain Input=\"0\" Output=\"4\">0</Gain>"
+       "<Gain Input=\"0\" Output=\"5\">0</Gain>"
+       "<Gain Input=\"0\" Output=\"6\">0</Gain>"
+       "<Gain Input=\"0\" Output=\"7\">0</Gain>"
+       "<Gain Input=\"0\" Output=\"8\">0</Gain>"
+       "<Gain Input=\"0\" Output=\"9\">0</Gain>"
+       "<Gain Input=\"0\" Output=\"10\">0</Gain>"
+       "<Gain Input=\"0\" Output=\"11\">0</Gain>"
+       "<Gain Input=\"1\" Output=\"0\">0</Gain>"
+       "<Gain Input=\"1\" Output=\"1\">1</Gain>"
+       "<Gain Input=\"1\" Output=\"2\">0</Gain>"
+       "<Gain Input=\"1\" Output=\"3\">0</Gain>"
+       "<Gain Input=\"1\" Output=\"4\">0</Gain>"
+       "<Gain Input=\"1\" Output=\"5\">0</Gain>"
+       "<Gain Input=\"1\" Output=\"6\">0</Gain>"
+       "<Gain Input=\"1\" Output=\"7\">0</Gain>"
+       "<Gain Input=\"1\" Output=\"8\">0</Gain>"
+       "<Gain Input=\"1\" Output=\"9\">0</Gain>"
+       "<Gain Input=\"1\" Output=\"10\">0</Gain>"
+       "<Gain Input=\"1\" Output=\"11\">0</Gain>"
+       "</Mapping>"
+       "</AudioStream>"
+       "<FirstVideo>0</FirstVideo>"
+       "</Content>";
+
 BOOST_AUTO_TEST_CASE (ffmpeg_time_calculation_test)
 {
        shared_ptr<Film> film = new_test_film ("ffmpeg_time_calculation_test");
 
-       string const xml = "<Content>"
-               "<Type>FFmpeg</Type>"
-               "<BurnSubtitles>0</BurnSubtitles>"
-               "<BitsPerPixel>8</BitsPerPixel>"
-               "<Path>/home/c.hetherington/DCP/clapperboard.mp4</Path>"
-               "<Digest>2760e03c7251480f7f02c01a907792673784335</Digest>"
-               "<Position>0</Position>"
-               "<TrimStart>0</TrimStart>"
-               "<TrimEnd>0</TrimEnd>"
-               "<VideoLength>1353600</VideoLength>"
-               "<VideoWidth>1280</VideoWidth>"
-               "<VideoHeight>720</VideoHeight>"
-               "<VideoFrameRate>25</VideoFrameRate>"
-               "<VideoFrameType>0</VideoFrameType>"
-               "<LeftCrop>0</LeftCrop>"
-               "<RightCrop>0</RightCrop>"
-               "<TopCrop>0</TopCrop>"
-               "<BottomCrop>0</BottomCrop>"
-               "<Scale>"
-               "<Ratio>178</Ratio>"
-               "</Scale>"
-               "<ColourConversion>"
-               "<InputTransferFunction>"
-               "<Type>ModifiedGamma</Type>"
-               "<Power>2.222222222222222</Power>"
-               "<Threshold>0.081</Threshold>"
-               "<A>0.099</A>"
-               "<B>4.5</B>"
-               "</InputTransferFunction>"
-               "<RedX>0.64</RedX>"
-               "<RedY>0.33</RedY>"
-               "<GreenX>0.3</GreenX>"
-               "<GreenY>0.6</GreenY>"
-               "<BlueX>0.15</BlueX>"
-               "<BlueY>0.06</BlueY>"
-               "<WhiteX>0.3127</WhiteX>"
-               "<WhiteY>0.329</WhiteY>"
-               "<OutputGamma>2.6</OutputGamma>"
-               "</ColourConversion>"
-               "<FadeIn>0</FadeIn>"
-               "<FadeOut>0</FadeOut>"
-               "<AudioGain>0</AudioGain>"
-               "<AudioDelay>0</AudioDelay>"
-               "<UseSubtitles>0</UseSubtitles>"
-               "<SubtitleXOffset>0</SubtitleXOffset>"
-               "<SubtitleYOffset>0</SubtitleYOffset>"
-               "<SubtitleXScale>1</SubtitleXScale>"
-               "<SubtitleYScale>1</SubtitleYScale>"
-               "<SubtitleLanguage></SubtitleLanguage>"
-               "<AudioStream>"
-               "<Selected>1</Selected>"
-               "<Name>und; 2 channels</Name>"
-               "<Id>2</Id>"
-               "<FrameRate>44100</FrameRate>"
-               "<Channels>2</Channels>"
-               "<FirstAudio>0</FirstAudio>"
-               "<Mapping>"
-               "<InputChannels>2</InputChannels>"
-               "<OutputChannels>12</OutputChannels>"
-               "<Gain Input=\"0\" Output=\"0\">1</Gain>"
-               "<Gain Input=\"0\" Output=\"1\">0</Gain>"
-               "<Gain Input=\"0\" Output=\"2\">0</Gain>"
-               "<Gain Input=\"0\" Output=\"3\">0</Gain>"
-               "<Gain Input=\"0\" Output=\"4\">0</Gain>"
-               "<Gain Input=\"0\" Output=\"5\">0</Gain>"
-               "<Gain Input=\"0\" Output=\"6\">0</Gain>"
-               "<Gain Input=\"0\" Output=\"7\">0</Gain>"
-               "<Gain Input=\"0\" Output=\"8\">0</Gain>"
-               "<Gain Input=\"0\" Output=\"9\">0</Gain>"
-               "<Gain Input=\"0\" Output=\"10\">0</Gain>"
-               "<Gain Input=\"0\" Output=\"11\">0</Gain>"
-               "<Gain Input=\"1\" Output=\"0\">0</Gain>"
-               "<Gain Input=\"1\" Output=\"1\">1</Gain>"
-               "<Gain Input=\"1\" Output=\"2\">0</Gain>"
-               "<Gain Input=\"1\" Output=\"3\">0</Gain>"
-               "<Gain Input=\"1\" Output=\"4\">0</Gain>"
-               "<Gain Input=\"1\" Output=\"5\">0</Gain>"
-               "<Gain Input=\"1\" Output=\"6\">0</Gain>"
-               "<Gain Input=\"1\" Output=\"7\">0</Gain>"
-               "<Gain Input=\"1\" Output=\"8\">0</Gain>"
-               "<Gain Input=\"1\" Output=\"9\">0</Gain>"
-               "<Gain Input=\"1\" Output=\"10\">0</Gain>"
-               "<Gain Input=\"1\" Output=\"11\">0</Gain>"
-               "</Mapping>"
-               "</AudioStream>"
-               "<FirstVideo>0</FirstVideo>"
-               "</Content>";
-
        shared_ptr<cxml::Document> doc (new cxml::Document);
        doc->read_string (xml);
 
@@ -141,4 +142,611 @@ BOOST_AUTO_TEST_CASE (ffmpeg_time_calculation_test)
        BOOST_CHECK_EQUAL (content->full_length(), DCPTime::from_seconds (content->video_length() * (50.0 / 60) / 25.0));
 }
 
-/* XXX much more stuff to test */
+/** Test Player::dcp_to_content_video */
+BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
+{
+       shared_ptr<Film> film = new_test_film ("player_time_calculation_test1");
+
+       shared_ptr<cxml::Document> doc (new cxml::Document);
+       doc->read_string (xml);
+
+       list<string> notes;
+       shared_ptr<FFmpegContent> content (new FFmpegContent (film, doc, film->state_version(), notes));
+       film->set_sequence_video (false);
+       film->add_content (content);
+
+       shared_ptr<Player> player (new Player (film, film->playlist ()));
+
+       /* Position 0, no trim, content rate = DCP rate */
+       content->set_position (DCPTime ());
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       shared_ptr<Piece> piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.5)), 12);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.0)), 72);
+
+       /* Position 3s, no trim, content rate = DCP rate */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.50)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.50)),  36);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 162);
+
+       /* Position 3s, 1.5s trim, content rate = DCP rate */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime::from_seconds (1.5));
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.50)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),  36);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.50)),  72);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 198);
+
+       /* Position 0, no trim, content rate 24, DCP rate 25.
+          Now, for example, a DCPTime position of 3s means 3s at 25fps.  Since we run the video
+          fast (at 25fps) in this case, this means 75 frames of content video will be used.
+       */
+       content->set_position (DCPTime ());
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (25);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.6)), 15);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.0)), 75);
+
+       /* Position 3s, no trim, content rate 24, DCP rate 25 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (25);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.60)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.60)),  40);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 169);
+
+       /* Position 3s, 1.6s trim, content rate 24, DCP rate 25 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime::from_seconds (1.6));
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (25);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.60)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),  40);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.60)),  80);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 209);
+
+       /* Position 0, no trim, content rate 24, DCP rate 48
+          Now, for example, a DCPTime position of 3s means 3s at 48fps.  Since we run the video
+          with repeated frames in this case, 3 * 24 frames of content video will
+          be used to make 3 * 48 frames of DCP video.  The results should be the same as the
+          content rate = DCP rate case.
+       */
+       content->set_position (DCPTime ());
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (48);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.5)), 12);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.0)), 72);
+
+       /* Position 3s, no trim, content rate 24, DCP rate 48 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (48);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.50)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.50)),  36);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 162);
+
+       /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime::from_seconds (1.5));
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (48);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.50)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),  36);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.50)),  72);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 198);
+
+       /* Position 0, no trim, content rate 48, DCP rate 24
+          Now, for example, a DCPTime position of 3s means 3s at 24fps.  Since we run the video
+          with skipped frames in this case, 3 * 48 frames of content video will
+          be used to make 3 * 24 frames of DCP video.
+       */
+       content->set_position (DCPTime ());
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (48);
+       film->set_video_frame_rate (24);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.5)), 24);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.0)), 144);
+
+       /* Position 3s, no trim, content rate 24, DCP rate 48 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (48);
+       film->set_video_frame_rate (24);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.50)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.50)),  72);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 324);
+
+       /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime::from_seconds (1.5));
+       content->set_video_frame_rate (48);
+       film->set_video_frame_rate (24);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (0.50)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (3.00)),  72);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (4.50)), 144);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_video (piece, DCPTime::from_seconds (9.75)), 396);
+}
+
+/** Test Player::content_video_to_dcp */
+BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
+{
+       shared_ptr<Film> film = new_test_film ("player_time_calculation_test2");
+
+       shared_ptr<cxml::Document> doc (new cxml::Document);
+       doc->read_string (xml);
+
+       list<string> notes;
+       shared_ptr<FFmpegContent> content (new FFmpegContent (film, doc, film->state_version(), notes));
+       film->set_sequence_video (false);
+       film->add_content (content);
+
+       shared_ptr<Player> player (new Player (film, film->playlist ()));
+
+       /* Position 0, no trim, content rate = DCP rate */
+       content->set_position (DCPTime ());
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       shared_ptr<Piece> piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime ());
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 12), DCPTime::from_seconds (0.5));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72), DCPTime::from_seconds (3.0));
+
+       /* Position 3s, no trim, content rate = DCP rate */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (3.00));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 36), DCPTime::from_seconds (4.50));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 162), DCPTime::from_seconds (9.75));
+
+       /* Position 3s, 1.5s trim, content rate = DCP rate */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime::from_seconds (1.5));
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (1.50));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 36), DCPTime::from_seconds (3.00));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72), DCPTime::from_seconds (4.50));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 198), DCPTime::from_seconds (9.75));
+
+       /* Position 0, no trim, content rate 24, DCP rate 25.
+          Now, for example, a DCPTime position of 3s means 3s at 25fps.  Since we run the video
+          fast (at 25fps) in this case, this means 75 frames of content video will be used.
+       */
+       content->set_position (DCPTime ());
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (25);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime ());
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 15), DCPTime::from_seconds (0.6));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 75), DCPTime::from_seconds (3.0));
+
+       /* Position 3s, no trim, content rate 24, DCP rate 25 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (25);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (3.00));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 40), DCPTime::from_seconds (4.60));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 169), DCPTime::from_seconds (9.76));
+
+       /* Position 3s, 1.6s trim, content rate 24, DCP rate 25 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime::from_seconds (1.6));
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (25);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (1.4));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 40), DCPTime::from_seconds (3.00));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 80), DCPTime::from_seconds (4.60));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 209), DCPTime::from_seconds (9.76));
+
+       /* Position 0, no trim, content rate 24, DCP rate 48
+          Now, for example, a DCPTime position of 3s means 3s at 48fps.  Since we run the video
+          with repeated frames in this case, 3 * 24 frames of content video will
+          be used to make 3 * 48 frames of DCP video.  The results should be the same as the
+          content rate = DCP rate case.
+       */
+       content->set_position (DCPTime ());
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (48);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime ());
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 12), DCPTime::from_seconds (0.5));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72), DCPTime::from_seconds (3.0));
+
+       /* Position 3s, no trim, content rate 24, DCP rate 48 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (48);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (3.00));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 36), DCPTime::from_seconds (4.50));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 162), DCPTime::from_seconds (9.75));
+
+       /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime::from_seconds (1.5));
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (48);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (1.50));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 36), DCPTime::from_seconds (3.00));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72), DCPTime::from_seconds (4.50));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 198), DCPTime::from_seconds (9.75));
+
+       /* Position 0, no trim, content rate 48, DCP rate 24
+          Now, for example, a DCPTime position of 3s means 3s at 24fps.  Since we run the video
+          with skipped frames in this case, 3 * 48 frames of content video will
+          be used to make 3 * 24 frames of DCP video.
+       */
+       content->set_position (DCPTime ());
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (48);
+       film->set_video_frame_rate (24);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime ());
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 24), DCPTime::from_seconds (0.5));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 144), DCPTime::from_seconds (3.0));
+
+       /* Position 3s, no trim, content rate 24, DCP rate 48 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (48);
+       film->set_video_frame_rate (24);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (3.00));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72), DCPTime::from_seconds (4.50));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 324), DCPTime::from_seconds (9.75));
+
+       /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime::from_seconds (1.5));
+       content->set_video_frame_rate (48);
+       film->set_video_frame_rate (24);
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 0), DCPTime::from_seconds (1.50));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 72), DCPTime::from_seconds (3.00));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 144), DCPTime::from_seconds (4.50));
+       BOOST_CHECK_EQUAL (player->content_video_to_dcp (piece, 396), DCPTime::from_seconds (9.75));
+}
+
+/** Test Player::dcp_to_content_audio */
+BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
+{
+       shared_ptr<Film> film = new_test_film ("player_time_calculation_test3");
+
+       shared_ptr<cxml::Document> doc (new cxml::Document);
+       doc->read_string (xml);
+
+       list<string> notes;
+       shared_ptr<FFmpegContent> content (new FFmpegContent (film, doc, film->state_version(), notes));
+       AudioStreamPtr stream = content->audio_streams().front();
+       film->set_sequence_video (false);
+       film->add_content (content);
+
+       shared_ptr<Player> player (new Player (film, film->playlist ()));
+
+       /* Position 0, no trim, video/audio content rate = video/audio DCP rate */
+       content->set_position (DCPTime ());
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       stream->_frame_rate = 48000;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       shared_ptr<Piece> piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.5)),  24000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.0)), 144000);
+
+       /* Position 3s, no trim, video/audio content rate = video/audio DCP rate */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       stream->_frame_rate = 48000;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),      0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),      0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)),  72000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 324000);
+
+       /* Position 3s, 1.5s trim, video/audio content rate = video/audio DCP rate */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime::from_seconds (1.5));
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       stream->_frame_rate = 48000;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),  72000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)), 144000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 396000);
+
+       /* Position 0, no trim, content video rate 24, DCP video rate 25, both audio rates still 48k.
+          Now we are resampling the audio so that 48000 content samples become 46080 DCP samples
+          (sounding the same and still corresponding to 1 second) which are then played over 24/25s
+          so that they run fast.  Hence 1 second in the DCP uses (25/24) * 48000 content samples.
+       */
+       content->set_position (DCPTime ());
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (25);
+       stream->_frame_rate = 48000;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.6)),  30000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.0)), 150000);
+
+       /* Position 3s, no trim, content video rate 24, DCP rate 25, both audio rates still 48k. */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (25);
+       stream->_frame_rate = 48000;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.60)),      0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),      0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.60)),  80000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 337500);
+
+       /* Position 3s, 1.6s trim, content rate 24, DCP rate 25, both audio rates still 48k. */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime::from_seconds (1.6));
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (25);
+       stream->_frame_rate = 48000;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.60)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),  80000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.60)), 160000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 417500);
+
+       /* Position 0, no trim, content rate 24, DCP rate 48, both audio rates still 48k.
+          Now, for example, a DCPTime position of 3s means 3s at 48fps.  Since we run the video
+          with repeated frames in this case, audio samples will map straight through.
+          The results should be the same as the content rate = DCP rate case.
+       */
+       content->set_position (DCPTime ());
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (48);
+       stream->_frame_rate = 48000;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.5)),  24000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.0)), 144000);
+
+       /* Position 3s, no trim, content rate 24, DCP rate 48 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       stream->_frame_rate = 48000;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),      0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),      0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)),  72000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 324000);
+
+       /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime::from_seconds (1.5));
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       stream->_frame_rate = 48000;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),  72000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)), 144000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 396000);
+
+       /* Position 0, no trim, content rate 48, DCP rate 24
+          Now, for example, a DCPTime position of 3s means 3s at 24fps.  Since we run the video
+          with skipped frames in this case, audio samples should map straight through.
+       */
+       content->set_position (DCPTime ());
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (48);
+       stream->_frame_rate = 48000;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.5)),  24000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.0)), 144000);
+
+       /* Position 3s, no trim, content rate 24, DCP rate 48 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       stream->_frame_rate = 48000;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),      0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),      0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)),  72000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 324000);
+
+       /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime::from_seconds (1.5));
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       stream->_frame_rate = 48000;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),   0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),  72000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)), 144000);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 396000);
+
+       /* Position 0, no trim, video content rate = video DCP rate, content audio rate = 44.1k
+          Now 44100 content samples correspond to 1s.
+       */
+       content->set_position (DCPTime ());
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       stream->_frame_rate = 44100;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.5)),  22050);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.0)), 132300);
+
+       /* Position 3s, no trim, video content rate = video DCP rate, content audio rate = 44.1k */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime ());
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       stream->_frame_rate = 44100;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),      0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),      0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)),  66150);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 297675);
+
+       /* Position 3s, 1.5s trim, video content rate = video DCP rate, content audio rate = 44.1k */
+       content->set_position (DCPTime::from_seconds (3));
+       content->set_trim_start (DCPTime::from_seconds (1.5));
+       content->set_video_frame_rate (24);
+       film->set_video_frame_rate (24);
+       stream->_frame_rate = 44100;
+       player->setup_pieces ();
+       BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
+       piece = player->_pieces.front ();
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime ()), 0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (0.50)),      0);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (3.00)),  66150);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (4.50)), 132300);
+       BOOST_CHECK_EQUAL (player->dcp_to_content_audio (piece, stream, DCPTime::from_seconds (9.75)), 363825);
+}