Use new write() method in example.
[libdcp.git] / examples / make_dcp.cc
index 6da9cf20f8499174f0eb8c5af499822ba503c419..fb17059a3dbfcc822615b498613164551adab36e 100644 (file)
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
 
-    This program is free software; you can redistribute it and/or modify
+    This file is part of libdcp.
+
+    libdcp is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 2 of the License, or
     (at your option) any later version.
 
-    This program is distributed in the hope that it will be useful,
+    libdcp is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
+    along with libdcp.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 /** @file examples/make_dcp.cc
- *  @brief Shows how to make a DCP from some JPEG2000 and WAV files.
+ *  @brief Shows how to make a DCP from some JPEG2000 and audio data.
  */
 
 #include <vector>
 #include <string>
 
 /* If you are using an installed libdcp, these #includes would need to be changed to
-#include <libdcp/dcp.h>
-#include <libdcp/cpl.h>
-#include <libdcp/picture_asset.h>
+#include <dcp/dcp.h>
+#include <dcp/cpl.h>
+#include <dcp/mono_picture_asset.h>
 ... etc. ...
 */
 
 #include "dcp.h"
 #include "cpl.h"
-#include "picture_asset.h"
+#include "mono_picture_asset.h"
+#include "mono_picture_asset_writer.h"
 #include "sound_asset.h"
+#include "sound_asset_writer.h"
 #include "reel.h"
-
-/* This method returns the filename of the JPEG2000 file to use for a given frame.
-   In this example, we are using the same file for each frame, so we don't bother
-   looking at the frame parameter, but it will called with frame=0, frame=1, ...
-*/
-std::string
-video_frame (int /* frame */)
-{
-       return "examples/help.j2c";
-}
+#include "reel_mono_picture_asset.h"
+#include "reel_sound_asset.h"
+#include <cmath>
 
 int
 main ()
 {
-       /* Make a DCP object.  "My Film DCP" is the directory name for the DCP */
-       libdcp::DCP dcp ("My Film DCP");
-       
-       /* Now make a CPL object.
+       /* Set up libdcp */
+       dcp::init();
 
-          "My Film" is the title that will be shown on the projector / TMS when the DCP is ingested.
-          FEATURE is the type that the projector will list the DCP as.
-          24 is the frame rate, and the DCP will be 48 frames long (ie 2 seconds at 24 fps).
-       */      
-       boost::shared_ptr<libdcp::CPL> cpl (new libdcp::CPL ("My Film DCP", "My Film", libdcp::FEATURE, 24, 48));
+       /* Create a directory to put the DCP in */
+       boost::filesystem::create_directory("DCP");
 
-       /* And add the CPL to the DCP */
-       dcp.add_cpl (cpl);
+       /* Make a picture asset.  This is a file which combines JPEG2000 files together to make
+          up the video of the DCP.  First, create the object, specifying a frame rate of 24 frames
+          per second.
+       */
 
-       /* Now make a `picture asset'.  This is a collection of the JPEG2000 files that make up the picture, one per frame.
-          Here we're using a function (video_frame) to obtain the name of the JPEG2000 file for each frame.
+       auto picture_asset = std::make_shared<dcp::MonoPictureAsset>(dcp::Fraction(24, 1), dcp::Standard::SMPTE);
 
-          The result will be an MXF file written to the directory "My Film DCP" (which should be the same as the DCP's
-          directory above) called "video.mxf".
+       /* Start off a write to it */
+       auto picture_writer = picture_asset->start_write("DCP/picture.mxf", false);
 
-          The other parameters specify the entry_point (the frame at which the projector should start showing the picture),
-          the frame rate, the number of frames and the resolution of the frames; 1998x1080 is the DCI Flat specification
-          for 2K projectors.
-       */
-       boost::shared_ptr<libdcp::MonoPictureAsset> picture_asset (
-               new libdcp::MonoPictureAsset (video_frame, "My Film DCP", "video.mxf", 0, 24, 48, false, libdcp::Size (1998, 1080), false)
-               );
-
-       /* Now we will create a `sound asset', which is made up of a WAV file for each channel of audio.  Here we're using
-          stereo, so we add two WAV files to a vector.
-
-          We could add more files here to use more channels; the file order is:
-              Left
-              Right
-              Centre
-              LFE (sub)
-              Left surround
-              Right surround
+       /* Write 24 frames of the same JPEG2000 file */
+       dcp::ArrayData picture("examples/help.j2c");
+       for (int i = 0; i < 24; ++i) {
+               picture_writer->write (picture);
+       }
+
+       /* And finish off */
+       picture_writer->finalize();
+
+       /* Now create a sound MXF.  As before, create an object and a writer.
+          When creating the object we specify the sampling rate (48kHz) and the number of channels (2).
        */
-       std::vector<std::string> sound_files;
-       sound_files.push_back ("examples/sine_440_-12dB.wav");
-       sound_files.push_back ("examples/sine_880_-12dB.wav");
-
-       /* Now we can create the sound asset using these files */
-       boost::shared_ptr<libdcp::SoundAsset> sound_asset (
-               new libdcp::SoundAsset (sound_files, "My Film DCP", "audio.mxf", 0, 24, 48, false, false)
-               );
-
-       /* Now that we have the assets, we can create a Reel to put them in and add it to the CPL */
-       cpl->add_reel (
-               boost::shared_ptr<libdcp::Reel> (
-                       new libdcp::Reel (picture_asset, sound_asset, boost::shared_ptr<libdcp::SubtitleAsset> ())
-                       )
-               );
-
-       /* Finally, we call this to write the XML description files to the DCP.  After this, the DCP
-          is ready to ingest and play.
+       auto sound_asset = std::make_shared<dcp::SoundAsset>(dcp::Fraction(24, 1), 48000, 2, dcp::LanguageTag("en-GB"), dcp::Standard::SMPTE);
+       /* Here we must also say which of our channels will have "real" sound data in them */
+       std::vector<dcp::Channel> active_channels;
+       active_channels.push_back(dcp::Channel::LEFT);
+       active_channels.push_back(dcp::Channel::RIGHT);
+       auto sound_writer = sound_asset->start_write("DCP/sound.mxf", active_channels);
+
+       /* Write some sine waves */
+       float* audio[2];
+       audio[0] = new float[48000];
+       audio[1] = new float[48000];
+       for (int i = 0; i < 48000; ++i) {
+               audio[0][i] = sin (2 * M_PI * i * 440 / 48000) * 0.25;
+               audio[1][i] = sin (2 * M_PI * i * 880 / 48000) * 0.25;
+       }
+       sound_writer->write (audio, 48000);
+
+       /* And tidy up */
+       delete[] audio[0];
+       delete[] audio[1];
+       sound_writer->finalize ();
+
+       /* Now create a reel */
+       auto reel = std::make_shared<dcp::Reel>();
+
+       /* Add picture and sound to it.  The zeros are the `entry points', i.e. the first
+          (video) frame from the assets that the reel should play.
        */
-       libdcp::XMLMetadata metadata;
-       dcp.write_xml (false, metadata);
+       reel->add(std::make_shared<dcp::ReelMonoPictureAsset>(picture_asset, 0));
+       reel->add(std::make_shared<dcp::ReelSoundAsset>(sound_asset, 0));
+
+       /* Make a CPL with this reel */
+       auto cpl = std::make_shared<dcp::CPL>("My film", dcp::ContentKind::FEATURE);
+       cpl->add(reel);
+
+       /* Write the DCP */
+       dcp::DCP dcp ("DCP");
+       dcp.add (cpl);
+       dcp.write_xml (dcp::Standard::SMPTE);
 
        return 0;
 }