diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/make_dcp.cc | 140 | ||||
| -rw-r--r-- | examples/read_dcp.cc | 90 | ||||
| -rw-r--r-- | examples/wscript | 12 |
3 files changed, 163 insertions, 79 deletions
diff --git a/examples/make_dcp.cc b/examples/make_dcp.cc index 6aa4268b..d86cd30a 100644 --- a/examples/make_dcp.cc +++ b/examples/make_dcp.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,7 +18,7 @@ */ /** @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> @@ -33,94 +33,80 @@ #include "dcp.h" #include "cpl.h" -#include "mono_picture_asset.h" -#include "sound_asset.h" +#include "mono_picture_mxf.h" +#include "mono_picture_mxf_writer.h" +#include "sound_mxf.h" +#include "sound_mxf_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 "file.h" +#include "reel_mono_picture_asset.h" +#include "reel_sound_asset.h" int main () { - /* Make a DCP object. "My Film DCP" is the directory name for the DCP */ - libdcp::DCP dcp ("My Film DCP"); + /* Create a directory to put the DCP in */ + boost::filesystem::create_directory ("DCP"); - /* Now make a CPL object. - - "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)); - - /* And add the CPL to the DCP */ - dcp.add_cpl (cpl); - - /* Now make a `picture asset'. This is a collection of the JPEG2000 files that make up the picture; one per frame. - First, create the object. + /* Make a picture MXF. 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. */ - boost::shared_ptr<libdcp::MonoPictureAsset> picture_asset ( - new libdcp::MonoPictureAsset ("My Film DCP", "video.mxf") - ); + boost::shared_ptr<dcp::MonoPictureMXF> picture_mxf (new dcp::MonoPictureMXF (dcp::Fraction (24, 1))); - /* Now set up its parameters; we have the frame rate, the - number of frames and the resolution of the frames; - 1998x1080 is the DCI Flat specification for 2K projectors. - */ - - picture_asset->set_edit_rate (24); - picture_asset->set_intrinsic_duration (24); - picture_asset->set_size (libdcp::Size (1998, 1080)); - - /* Now we can create the asset itself. Here using a function (video_frame) to obtain the name of the JPEG2000 file for each frame. - 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 */ + boost::shared_ptr<dcp::PictureMXFWriter> picture_writer = picture_mxf->start_write ("DCP/picture.mxf", dcp::SMPTE, false); - picture_asset->create (video_frame); + /* Write 24 frames of the same JPEG2000 file */ + dcp::File picture ("examples/help.j2c"); + for (int i = 0; i < 24; ++i) { + picture_writer->write (picture.data(), picture.size()); + } - /* 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. + /* And finish off */ + picture_writer->finalize (); - We could add more files here to use more channels; the file order is: - Left - Right - Centre - LFE (sub) - Left surround - Right surround + /* 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<boost::filesystem::path> 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 ("My Film DCP", "audio.mxf")); - sound_asset->set_edit_rate (24); - sound_asset->set_intrinsic_duration (48); - sound_asset->create (sound_files); - - /* 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. + boost::shared_ptr<dcp::SoundMXF> sound_mxf (new dcp::SoundMXF (dcp::Fraction (24, 1), 48000, 2)); + boost::shared_ptr<dcp::SoundMXFWriter> sound_writer = sound_mxf->start_write ("DCP/sound.mxf", dcp::SMPTE); + + /* 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 */ + boost::shared_ptr<dcp::Reel> reel (new dcp::Reel ()); + + /* Add picture and sound to it. The zeros are the `entry points', i.e. the first + (video) frame from the MXFs that the reel should play. */ - libdcp::XMLMetadata metadata; - dcp.write_xml (false, metadata); - + reel->add (boost::shared_ptr<dcp::ReelPictureAsset> (new dcp::ReelMonoPictureAsset (picture_mxf, 0))); + reel->add (boost::shared_ptr<dcp::ReelSoundAsset> (new dcp::ReelSoundAsset (sound_mxf, 0))); + + /* Make a CPL with this reel */ + boost::shared_ptr<dcp::CPL> cpl (new dcp::CPL ("My film", dcp::FEATURE)); + cpl->add (reel); + + /* Write the DCP */ + dcp::DCP dcp ("DCP"); + dcp.add (cpl); + dcp.add (picture_mxf); + dcp.add (sound_mxf); + dcp.write_xml (dcp::SMPTE); + return 0; } diff --git a/examples/read_dcp.cc b/examples/read_dcp.cc new file mode 100644 index 00000000..f3c47a3c --- /dev/null +++ b/examples/read_dcp.cc @@ -0,0 +1,90 @@ +/* + Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + + This program 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, + 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. + +*/ + +/* If you are using an installed libdcp, these #includes would need to be changed to +#include <libdcp/dcp.h> +#include <libdcp/picture_mxf.h> +... etc. ... +*/ + +#include "dcp.h" +#include "cpl.h" +#include "reel.h" +#include "reel_picture_asset.h" +#include "mono_picture_frame.h" +#include "mono_picture_mxf.h" +#include "stereo_picture_mxf.h" +#include "sound_mxf.h" +#include "subtitle_content.h" +#include "argb_frame.h" +#include <Magick++.h> + +/** @file examples/read_dcp.cc + * @brief Shows how to read a DCP. + */ + +int +main () +{ + /* Create a DCP, specifying where our existing data is */ + dcp::DCP dcp ("/home/carl/diagonal.com/APPASSIONATA_TLR_F_UK-DEFR_CH_51_2K_LOK_20121115_DGL_OV"); + /* Read the DCP to find out about it */ + dcp.read (); + + if (dcp.encrypted ()) { + std::cout << "DCP is encrypted.\n"; + } else { + std::cout << "DCP is not encrypted.\n"; + } + + std::cout << "DCP has " << dcp.cpls().size() << " CPLs.\n"; + std::list<boost::shared_ptr<dcp::Asset> > assets = dcp.assets (); + std::cout << "DCP has " << assets.size() << " assets.\n"; + for (std::list<boost::shared_ptr<dcp::Asset> >::const_iterator i = assets.begin(); i != assets.end(); ++i) { + if (boost::dynamic_pointer_cast<dcp::MonoPictureMXF> (*i)) { + std::cout << "2D picture\n"; + } else if (boost::dynamic_pointer_cast<dcp::StereoPictureMXF> (*i)) { + std::cout << "3D picture\n"; + } else if (boost::dynamic_pointer_cast<dcp::SoundMXF> (*i)) { + std::cout << "Sound\n"; + } else if (boost::dynamic_pointer_cast<dcp::SubtitleContent> (*i)) { + std::cout << "Subtitle\n"; + } else if (boost::dynamic_pointer_cast<dcp::CPL> (*i)) { + std::cout << "CPL\n"; + } + std::cout << "\t" << (*i)->file().leaf().string() << "\n"; + } + + /* Take the first CPL */ + boost::shared_ptr<dcp::CPL> cpl = dcp.cpls().front (); + + /* Get the MXF of the picture asset in the first reel */ + boost::shared_ptr<dcp::MonoPictureMXF> picture_mxf = boost::dynamic_pointer_cast<dcp::MonoPictureMXF> (cpl->reels().front()->main_picture()->mxf ()); + + /* Get the 1000th frame of it */ + boost::shared_ptr<const dcp::MonoPictureFrame> picture_frame_j2k = picture_mxf->get_frame(999); + + /* Get a ARGB copy of it */ + boost::shared_ptr<dcp::ARGBFrame> picture_frame_rgb = picture_frame_j2k->argb_frame (); + + Magick::Image image (picture_frame_rgb->size().width, picture_frame_rgb->size().height, "BGRA", Magick::CharPixel, picture_frame_rgb->data ()); + image.write ("frame.png"); + + return 0; +} diff --git a/examples/wscript b/examples/wscript index 05cca98f..abb0885c 100644 --- a/examples/wscript +++ b/examples/wscript @@ -1,8 +1,16 @@ def build(bld): obj = bld(features = 'cxx cxxprogram') - obj.name = 'examples' - obj.use = 'libdcp' + obj.name = 'make_dcp' + obj.use = 'libdcp%s' % bld.env.API_VERSION obj.uselib = 'OPENJPEG CXML' obj.source = 'make_dcp.cc' obj.target = 'make_dcp' obj.install_path = '' + + obj = bld(features = 'cxx cxxprogram') + obj.name = 'read_dcp' + obj.use = 'libdcp%s' % bld.env.API_VERSION + obj.uselib = 'OPENJPEG CXML MAGICK' + obj.source = 'read_dcp.cc' + obj.target = 'read_dcp' + obj.install_path = '' |
