}
void
-DCP::add_sound_asset (list<string> const & files)
+DCP::add_sound_asset (vector<string> const & files)
{
filesystem::path p;
p /= _directory;
}
void
-DCP::add_picture_asset (list<string> const & files, int w, int h)
+DCP::add_sound_asset (sigc::slot<string, Channel> get_path, int channels)
+{
+ filesystem::path p;
+ p /= _directory;
+ p /= "audio.mxf";
+ _assets.push_back (shared_ptr<SoundAsset> (new SoundAsset (get_path, p.string(), &Progress, _fps, _length, channels)));
+}
+
+void
+DCP::add_picture_asset (vector<string> const & files, int width, int height)
+{
+ filesystem::path p;
+ p /= _directory;
+ p /= "video.mxf";
+ _assets.push_back (shared_ptr<PictureAsset> (new PictureAsset (files, p.string(), &Progress, _fps, _length, width, height)));
+}
+
+void
+DCP::add_picture_asset (sigc::slot<string, int> get_path, int width, int height)
{
filesystem::path p;
p /= _directory;
p /= "video.mxf";
- _assets.push_back (shared_ptr<PictureAsset> (new PictureAsset (files, p.string(), &Progress, _fps, _length, w, h)));
+ _assets.push_back (shared_ptr<PictureAsset> (new PictureAsset (get_path, p.string(), &Progress, _fps, _length, width, height)));
}
void
#include <list>
#include <boost/shared_ptr.hpp>
#include <sigc++/sigc++.h>
+#include "types.h"
/** @brief Namespace for everything in libdcp */
namespace libdcp
*
* libdcp::DCP dcp ("My Film DCP", "My Film", libdcp::DCP::FEATURE, 24, 50000);
*
- * list<string> j2k_files;
+ * vector<string> j2k_files;
* j2k_files.push_back ("1.j2c");
* ...
* j2k_files.push_back ("50000.j2c");
* // These images are 1998x1080 pixels (DCI Flat)
* dcp.add_picture_asset (j2k_files, 1998, 1080);
*
- * list<string> wav_files;
+ * vector<string> wav_files;
* wav_files.push_back ("L.wav");
* wav_files.push_back ("R.wav");
* wav_files.push_back ("C.wav");
/** Add a sound asset.
* @param files Pathnames of WAV files to use in the order Left, Right,
- * Centre, Lfe (sub), Left surround, Right surround.
+ * Centre, Lfe (sub), Left surround, Right surround; not all files need
+ * to be present.
*/
- void add_sound_asset (std::list<std::string> const & files);
+ void add_sound_asset (std::vector<std::string> const & files);
+
+ /** Add a sound asset.
+ * @param get_path Functor to get the path to the WAV for a given channel.
+ * @param channels Number of channels.
+ */
+ void add_sound_asset (sigc::slot<std::string, Channel> get_path, int channels);
/** Add a picture asset.
* @param files Pathnames of JPEG2000 files, in frame order.
* @param width Width of images in pixels.
* @param height Height of images in pixels.
*/
- void add_picture_asset (std::list<std::string> const & files, int width, int height);
+ void add_picture_asset (std::vector<std::string> const & files, int width, int height);
+
+ /** Add a picture asset.
+ * @param get_path Functor to get path to the JPEG2000 for a given frame.
+ * @param width Width of images in pixels.
+ * @param height Height of images in pixels.
+ */
+ void add_picture_asset (sigc::slot<std::string, int> get_path, int width, int height);
/** Write the required XML files to the directory that was
* passed into the constructor.
using namespace libdcp;
PictureAsset::PictureAsset (
- list<string> const & files,
+ sigc::slot<string, int> get_path,
string mxf_path,
sigc::signal1<void, float>* progress,
int fps,
: Asset (mxf_path, progress, fps, length)
, _width (width)
, _height (height)
+{
+ construct (get_path);
+}
+
+PictureAsset::PictureAsset (
+ vector<string> const & files,
+ string mxf_path,
+ sigc::signal1<void, float>* progress,
+ int fps,
+ int length,
+ int width,
+ int height)
+ : Asset (mxf_path, progress, fps, length)
+ , _width (width)
+ , _height (height)
+{
+ construct (sigc::bind (sigc::mem_fun (*this, &PictureAsset::path_from_list), files));
+}
+
+string
+PictureAsset::path_from_list (int f, vector<string> const & files) const
+{
+ return files[f];
+}
+
+void
+PictureAsset::construct (sigc::slot<string, int> get_path)
{
ASDCP::JP2K::CodestreamParser j2k_parser;
ASDCP::JP2K::FrameBuffer frame_buffer (4 * Kumu::Megabyte);
- if (ASDCP_FAILURE (j2k_parser.OpenReadFrame (files.front().c_str(), frame_buffer))) {
+ if (ASDCP_FAILURE (j2k_parser.OpenReadFrame (get_path(0).c_str(), frame_buffer))) {
stringstream s;
- s << "could not open " << files.front() << " for reading";
+ s << "could not open " << get_path(0) << " for reading";
throw runtime_error (s.str());
}
throw runtime_error ("could not open MXF for writing");
}
- int j = 0;
- for (list<string>::const_iterator i = files.begin(); i != files.end(); ++i) {
- if (ASDCP_FAILURE (j2k_parser.OpenReadFrame (i->c_str(), frame_buffer))) {
+ for (int i = 0; i < _length; ++i) {
+
+ string const path = get_path (i);
+
+ if (ASDCP_FAILURE (j2k_parser.OpenReadFrame (path.c_str(), frame_buffer))) {
stringstream s;
- s << "could not open " << *i << " for reading";
+ s << "could not open " << path << " for reading";
throw runtime_error (s.str());
}
throw runtime_error ("error in writing video MXF");
}
- ++j;
- (*_progress) (0.5 * float (j) / files.size ());
+ (*_progress) (0.5 * float (i) / _length);
}
if (ASDCP_FAILURE (mxf_writer.Finalize())) {
* @param height Height of images in pixels.
*/
PictureAsset (
- std::list<std::string> const & files,
+ std::vector<std::string> const & files,
std::string mxf_path,
sigc::signal1<void, float>* progress,
int fps,
int height
);
+ /** Construct a PictureAsset, generating the MXF from the JPEG2000 files.
+ * This may take some time; progress is indicated by emission of the Progress signal.
+ * @param files Pathnames of JPEG2000 files, in frame order.
+ * @param mxf_path Pathname of MXF file to create.
+ * @param progress Signal to inform of progress.
+ * @param fps Frames per second.
+ * @param length Length in frames.
+ * @param width Width of images in pixels.
+ * @param height Height of images in pixels.
+ */
+ PictureAsset (
+ sigc::slot<std::string, int> get_path,
+ std::string mxf_path,
+ sigc::signal1<void, float>* progress,
+ int fps,
+ int length,
+ int width,
+ int height
+ );
+
/** Write details of this asset to a CPL stream.
* @param s Stream.
*/
void write_to_cpl (std::ostream& s) const;
private:
+ std::string path_from_list (int f, std::vector<std::string> const & files) const;
+ void construct (sigc::slot<std::string, int>);
+
/** picture width in pixels */
int _width;
/** picture height in pixels */
using namespace boost;
using namespace libdcp;
-SoundAsset::SoundAsset (list<string> const & files, string mxf_path, sigc::signal1<void, float>* progress, int fps, int length)
+SoundAsset::SoundAsset (
+ vector<string> const & files, string mxf_path, sigc::signal1<void, float>* progress, int fps, int length
+ )
: Asset (mxf_path, progress, fps, length)
+ , _channels (files.size ())
+{
+ construct (sigc::bind (sigc::mem_fun (*this, &SoundAsset::path_from_channel), files));
+}
+
+SoundAsset::SoundAsset (
+ sigc::slot<string, Channel> get_path, string mxf_path, sigc::signal1<void, float>* progress, int fps, int length, int channels
+ )
+ : Asset (mxf_path, progress, fps, length)
+ , _channels (channels)
+{
+ construct (get_path);
+}
+
+string
+SoundAsset::path_from_channel (Channel channel, vector<string> const & files)
+{
+ unsigned int const c = int (channel);
+ assert (c < files.size ());
+ return files[c];
+}
+
+void
+SoundAsset::construct (sigc::slot<string, Channel> get_path)
{
ASDCP::Rational asdcp_fps (_fps, 1);
- ASDCP::PCM::WAVParser pcm_parser_channel[files.size()];
- if (pcm_parser_channel[0].OpenRead (files.front().c_str(), asdcp_fps)) {
+ ASDCP::PCM::WAVParser pcm_parser_channel[_channels];
+ if (pcm_parser_channel[0].OpenRead (get_path(LEFT).c_str(), asdcp_fps)) {
throw runtime_error ("could not open WAV file for reading");
}
audio_desc.ChannelCount = 0;
audio_desc.BlockAlign = 0;
audio_desc.EditRate = asdcp_fps;
- audio_desc.AvgBps = audio_desc.AvgBps * files.size ();
+ audio_desc.AvgBps = audio_desc.AvgBps * _channels;
- ASDCP::PCM::FrameBuffer frame_buffer_channel[files.size()];
- ASDCP::PCM::AudioDescriptor audio_desc_channel[files.size()];
-
- int j = 0;
- for (list<string>::const_iterator i = files.begin(); i != files.end(); ++i) {
+ Channel channels[] = {
+ LEFT,
+ RIGHT,
+ CENTRE,
+ LFE,
+ LS,
+ RS
+ };
+
+ ASDCP::PCM::FrameBuffer frame_buffer_channel[_channels];
+ ASDCP::PCM::AudioDescriptor audio_desc_channel[_channels];
+
+ for (int i = 0; i < _channels; ++i) {
+
+ string const path = get_path (channels[i]);
- if (ASDCP_FAILURE (pcm_parser_channel[j].OpenRead (i->c_str(), asdcp_fps))) {
+ if (ASDCP_FAILURE (pcm_parser_channel[i].OpenRead (path.c_str(), asdcp_fps))) {
throw runtime_error ("could not open WAV file for reading");
}
- pcm_parser_channel[j].FillAudioDescriptor (audio_desc_channel[j]);
- frame_buffer_channel[j].Capacity (ASDCP::PCM::CalcFrameBufferSize (audio_desc_channel[j]));
+ pcm_parser_channel[i].FillAudioDescriptor (audio_desc_channel[i]);
+ frame_buffer_channel[i].Capacity (ASDCP::PCM::CalcFrameBufferSize (audio_desc_channel[i]));
- audio_desc.ChannelCount += audio_desc_channel[j].ChannelCount;
- audio_desc.BlockAlign += audio_desc_channel[j].BlockAlign;
- ++j;
+ audio_desc.ChannelCount += audio_desc_channel[i].ChannelCount;
+ audio_desc.BlockAlign += audio_desc_channel[i].BlockAlign;
}
ASDCP::PCM::FrameBuffer frame_buffer;
byte_t sample_size = ASDCP::PCM::CalcSampleSize (audio_desc_channel[0]);
int offset = 0;
- for (list<string>::size_type j = 0; j < files.size(); ++j) {
+ for (int j = 0; j < _channels; ++j) {
memset (frame_buffer_channel[j].Data(), 0, frame_buffer_channel[j].Capacity());
if (ASDCP_FAILURE (pcm_parser_channel[j].ReadFrame (frame_buffer_channel[j]))) {
throw runtime_error ("could not read audio frame");
}
while (data_s < data_e) {
- for (list<string>::size_type j = 0; j < files.size(); ++j) {
+ for (int j = 0; j < _channels; ++j) {
byte_t* frame = frame_buffer_channel[j].Data() + offset;
memcpy (data_s, frame, sample_size);
data_s += sample_size;
*/
+#ifndef LIBDCP_SOUND_ASSET_H
+#define LIBDCP_SOUND_ASSET_H
+
/** @file src/sound_asset.h
* @brief An asset made up of WAV files
*/
#include "asset.h"
+#include "types.h"
namespace libdcp
{
* @param progress Signal to inform of progress.
* @param fps Frames per second.
* @param length Length in frames.
+ * @param channels Number of audio channels.
*/
- SoundAsset (std::list<std::string> const & files, std::string mxf_path, sigc::signal1<void, float>* progress, int fps, int length);
+ SoundAsset (
+ std::vector<std::string> const & files,
+ std::string mxf_path,
+ sigc::signal1<void, float>* progress,
+ int fps,
+ int length
+ );
+ /** Construct a SoundAsset, generating the MXF from the WAV files.
+ * This may take some time; progress is indicated by emission of the Progress signal.
+ * @param files Pathnames of sound files, in the order Left, Right, Centre, Lfe (sub), Left surround, Right surround.
+ * @param mxf_path Pathname of MXF file to create.
+ * @param progress Signal to inform of progress.
+ * @param fps Frames per second.
+ * @param length Length in frames.
+ * @param channels Number of audio channels.
+ */
+ SoundAsset (
+ sigc::slot<std::string, Channel>,
+ std::string mxf_path,
+ sigc::signal1<void, float>* progress,
+ int fps,
+ int length,
+ int channels
+ );
+
/** Write details of this asset to a CPL stream.
* @param s Stream.
*/
void write_to_cpl (std::ostream& s) const;
+
+private:
+ void construct (sigc::slot<std::string, Channel> get_path);
+ std::string path_from_channel (Channel channel, std::vector<std::string> const & files);
+
+ /** Number of channels in the asset */
+ int _channels;
};
}
+
+#endif
--- /dev/null
+/*
+ Copyright (C) 2012 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.
+
+*/
+
+#ifndef LIBDCP_CHANNEL_H
+#define LIBDCP_CHANNEL_H
+
+namespace libdcp
+{
+
+/** Identifier for a sound channel */
+enum Channel {
+ LEFT = 0, ///< left
+ RIGHT = 1, ///< right
+ CENTRE = 2, ///< centre
+ LFE = 3, ///< low-frequency effects (sub)
+ LS = 4, ///< left surround
+ RS = 5 ///< right surround
+};
+
+}
+
+#endif
headers = """
dcp.h
metadata.h
+ types.h
"""
bld.install_files('${PREFIX}/include/libdcp', headers)
#include "dcp.h"
#include "util.h"
#include "metadata.h"
+#include "types.h"
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE libdcp_test
using namespace std;
using namespace boost;
+string
+j2c (int)
+{
+ return "test/data/32x32_red_square.j2c";
+}
+
+string
+wav (libdcp::Channel)
+{
+ return "test/data/1s_24-bit_48k_silence.wav";
+}
+
+
BOOST_AUTO_TEST_CASE (dcp_test)
{
Kumu::libdcp_test = true;
filesystem::create_directories ("build/test/foo");
libdcp::DCP d ("build/test/foo", "A Test DCP", libdcp::DCP::FEATURE, 24, 24);
- list<string> j2cs;
- for (int i = 0; i < 24; ++i) {
- j2cs.push_back ("test/data/32x32_red_square.j2c");
- }
- d.add_picture_asset (j2cs, 32, 32);
-
- list<string> wavs;
- for (int i = 0; i < 2; ++i) {
- wavs.push_back ("test/data/1s_24-bit_48k_silence.wav");
- }
- d.add_sound_asset (wavs);
+ d.add_picture_asset (sigc::ptr_fun (&j2c), 32, 32);
+ d.add_sound_asset (sigc::ptr_fun (&wav), 2);
d.write_xml ();
}