+2014-03-07 Carl Hetherington <cth@carlh.net>
+
+ * Add subtitle view.
+
+ 2014-06-12 Carl Hetherington <cth@carlh.net>
+
+ * Version 1.69.26 released.
+
+ 2014-06-12 Carl Hetherington <cth@carlh.net>
+
+ * Fix bug where DCP-o-matic does not recreate video after
+ subtitles are turned on or off.
+
+ 2014-06-10 Carl Hetherington <cth@carlh.net>
+
+ * Support ISDCF naming convention version 9 (#257).
+
+ * Rename DCI to ISDCF when talking about the digital cinema
+ naming convention (#362).
+
+ * Fix crash when opening the timeline with no content (#369).
+
+ 2014-06-09 Carl Hetherington <cth@carlh.net>
+
+ * Fix server/client with non-RGB24 sources.
+
+ * Version 1.69.25 released.
+
+ 2014-06-09 Carl Hetherington <cth@carlh.net>
+
+ * Make audio gain a floating-point value in the UI (#367).
+
+ * Work-around out-of-memory crashes with large start trims (#252).
+
+ * Version 1.69.24 released.
+
+ 2014-06-06 Carl Hetherington <cth@carlh.net>
+
+ * Version 1.69.23 released.
+
+ 2014-06-05 Carl Hetherington <cth@carlh.net>
+
+ * Version 1.69.22 released.
+
+ 2014-06-05 Carl Hetherington <cth@carlh.net>
+
+ * Large speed-up to multi-image source file decoding.
+
+ * Back-port changes from v2 which work out how separate
+ audio files should be resampled by looking at the video
+ files which are present at the same time.
+
+ 2014-06-03 Carl Hetherington <cth@carlh.net>
+
+ * Version 1.69.21 released.
+
2014-06-03 Carl Hetherington <cth@carlh.net>
* Fix bad resampling of separate sound file sources that
void as_xml (xmlpp::Node *) const;
std::string technical_summary () const;
+ /** @return number of audio channels in the content */
virtual int audio_channels () const = 0;
- virtual AudioContent::Frame audio_length () const = 0;
- virtual int content_audio_frame_rate () const = 0;
+ /** @return the length of the audio in the content */
+ virtual ContentTime audio_length () const = 0;
+ /** @return the frame rate of the content */
+ virtual int audio_frame_rate () const = 0;
virtual AudioMapping audio_mapping () const = 0;
- virtual void set_audio_mapping (AudioMapping) = 0;
+ virtual void set_audio_mapping (AudioMapping);
virtual boost::filesystem::path audio_analysis_path () const;
- int output_audio_frame_rate () const;
-
+ int resampled_audio_frame_rate () const;
+
boost::signals2::connection analyse_audio (boost::function<void()>);
- void set_audio_gain (float);
+ void set_audio_gain (double);
void set_audio_delay (int);
- float audio_gain () const {
+ double audio_gain () const {
boost::mutex::scoped_lock lm (_mutex);
return _audio_gain;
}
#include <boost/shared_ptr.hpp>
#include <boost/signals2.hpp>
#include <boost/filesystem.hpp>
-#include <libdcp/metadata.h>
+#include <dcp/metadata.h>
- #include "dci_metadata.h"
+ #include "isdcf_metadata.h"
#include "colour_conversion.h"
#include "server.h"
using std::list;
using std::cout;
using std::vector;
+ using std::max;
using boost::shared_ptr;
-using libdcp::raw_convert;
+using dcp::raw_convert;
int const ContentProperty::PATH = 400;
int const ContentProperty::POSITION = 401;
string
Content::technical_summary () const
{
- return String::compose ("%1 %2 %3", path_summary(), digest(), position());
+ return String::compose ("%1 %2 %3", path_summary(), digest(), position().seconds());
}
-Time
+DCPTime
Content::length_after_trim () const
{
- return full_length() - trim_start() - trim_end();
- return max (int64_t (0), full_length() - trim_start() - trim_end());
-}
-
-/** @param t A time relative to the start of this content (not the position).
- * @return true if this time is trimmed by our trim settings.
- */
-bool
-Content::trimmed (Time t) const
-{
- return (t < trim_start() || t > (full_length() - trim_end ()));
++ return max (DCPTime (), full_length() - trim_start() - trim_end());
}
/** @return string which includes everything about how this content affects
vector<DCPContentType const *> DCPContentType::_dcp_content_types;
-DCPContentType::DCPContentType (string p, libdcp::ContentKind k, string d)
+DCPContentType::DCPContentType (string p, dcp::ContentKind k, string d)
: _pretty_name (p)
, _libdcp_kind (k)
- , _dci_name (d)
+ , _isdcf_name (d)
{
}
private:
std::string _pretty_name;
- libdcp::ContentKind _libdcp_kind;
+ dcp::ContentKind _libdcp_kind;
- std::string _dci_name;
+ std::string _isdcf_name;
/** All available DCP content types */
static std::vector<DCPContentType const *> _dcp_content_types;
p /= name;
return p;
}
+
+bool
+FFmpegContent::has_subtitle_during (ContentTimePeriod period) const
+{
+ shared_ptr<FFmpegSubtitleStream> stream = subtitle_stream ();
++ if (!stream) {
++ return false;
++ }
+
+ /* XXX: inefficient */
+ for (vector<ContentTimePeriod>::const_iterator i = stream->periods.begin(); i != stream->periods.end(); ++i) {
+ if (i->from <= period.to && i->to >= period.from) {
+ return true;
+ }
+ }
+
+ return false;
+}
* Subtitle offset changed to subtitle y offset, and subtitle x offset added.
* 7 -> 8
* Use <Scale> tag in <VideoContent> rather than <Ratio>.
+ * 8 -> 9
+ * DCI -> ISDCF
+ *
+ * Bumped to 32 for 2.0 branch; some times are expressed in Times rather
+ * than frames now.
*/
-int const Film::current_state_version = 9;
+int const Film::current_state_version = 32;
/** Construct a Film object in a given directory.
*
if (video_frame_rate() != 24) {
d << "-" << video_frame_rate();
}
-
+
if (container()) {
- d << "_" << container()->dci_name();
+ d << "_" << container()->isdcf_name();
}
- DCIMetadata const dm = dci_metadata ();
+ /* XXX: this only works for content which has been scaled to a given ratio,
+ and uses the first bit of content only.
+ */
+
+ /* The standard says we don't do this for trailers, for some strange reason */
- if (dcp_content_type() && dcp_content_type()->libdcp_kind() != libdcp::TRAILER) {
++ if (dcp_content_type() && dcp_content_type()->libdcp_kind() != dcp::TRAILER) {
+ ContentList cl = content ();
+ Ratio const * content_ratio = 0;
+ for (ContentList::const_iterator i = cl.begin(); i != cl.end(); ++i) {
+ shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (*i);
+ if (vc && (content_ratio == 0 || vc->scale().ratio() != content_ratio)) {
+ content_ratio = vc->scale().ratio();
+ }
+ }
+
+ if (content_ratio && content_ratio != container()) {
+ d << "-" << content_ratio->isdcf_name();
+ }
+ }
if (!dm.audio_language.empty ()) {
d << "_" << dm.audio_language;
#include <boost/signals2.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/filesystem.hpp>
-#include <libdcp/key.h>
-#include <libdcp/kdm.h>
+#include <dcp/key.h>
+#include <dcp/decrypted_kdm.h>
+#include <dcp/encrypted_kdm.h>
#include "util.h"
#include "types.h"
- #include "dci_metadata.h"
+ #include "isdcf_metadata.h"
+ #include "frame_rate_change.h"
class DCPContentType;
class Log;
RawImageProxy::add_metadata (xmlpp::Node* node) const
{
node->add_child("Type")->add_child_text (N_("Raw"));
- node->add_child("Width")->add_child_text (libdcp::raw_convert<string> (_image->size().width));
- node->add_child("Height")->add_child_text (libdcp::raw_convert<string> (_image->size().height));
- node->add_child("PixelFormat")->add_child_text (libdcp::raw_convert<string> (_image->pixel_format ()));
+ node->add_child("Width")->add_child_text (dcp::raw_convert<string> (_image->size().width));
+ node->add_child("Height")->add_child_text (dcp::raw_convert<string> (_image->size().height));
++ node->add_child("PixelFormat")->add_child_text (dcp::raw_convert<string> (_image->pixel_format ()));
}
void
throw DecodeError (_("Could not decode image file"));
}
+ dcp::Size size (magick_image->columns(), magick_image->rows());
LOG_TIMING ("[%1] MagickImageProxy decode finished", boost::this_thread::get_id ());
- libdcp::Size size (magick_image->columns(), magick_image->rows());
-
_image.reset (new Image (PIX_FMT_RGB24, size, true));
- using namespace MagickCore;
-
+ /* Write line-by-line here as _image must be aligned, and write() cannot be told about strides */
uint8_t* p = _image->data()[0];
- for (int y = 0; y < size.height; ++y) {
- uint8_t* q = p;
- for (int x = 0; x < size.width; ++x) {
- Magick::Color c = magick_image->pixelColor (x, y);
- *q++ = c.redQuantum() * 255 / QuantumRange;
- *q++ = c.greenQuantum() * 255 / QuantumRange;
- *q++ = c.blueQuantum() * 255 / QuantumRange;
- }
+ for (int i = 0; i < size.height; ++i) {
+ using namespace MagickCore;
+ magick_image->write (0, i, size.width, 1, "RGB", CharPixel, p);
p += _image->stride()[0];
}
--- /dev/null
-#include <libdcp/raw_convert.h>
+ /*
+ 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.
+
+ */
+
+ #include <iostream>
+ #include <libcxml/cxml.h>
-using libdcp::raw_convert;
++#include <dcp/raw_convert.h>
+ #include "isdcf_metadata.h"
+
+ #include "i18n.h"
+
+ using std::string;
+ using boost::shared_ptr;
-ISDCFMetadata::ISDCFMetadata (shared_ptr<const cxml::Node> node)
++using dcp::raw_convert;
+
++ISDCFMetadata::ISDCFMetadata (cxml::ConstNodePtr node)
+ {
+ content_version = node->number_child<int> ("ContentVersion");
+ audio_language = node->string_child ("AudioLanguage");
+ subtitle_language = node->string_child ("SubtitleLanguage");
+ territory = node->string_child ("Territory");
+ rating = node->string_child ("Rating");
+ studio = node->string_child ("Studio");
+ facility = node->string_child ("Facility");
+ package_type = node->string_child ("PackageType");
+
+ /* This stuff was added later */
+ temp_version = node->optional_bool_child ("TempVersion").get_value_or (false);
+ pre_release = node->optional_bool_child ("PreRelease").get_value_or (false);
+ red_band = node->optional_bool_child ("RedBand").get_value_or (false);
+ chain = node->optional_string_child ("Chain").get_value_or ("");
+ two_d_version_of_three_d = node->optional_bool_child ("TwoDVersionOfThreeD").get_value_or (false);
+ mastered_luminance = node->optional_string_child ("MasteredLuminance").get_value_or ("");
+ }
+
+ void
+ ISDCFMetadata::as_xml (xmlpp::Node* root) const
+ {
+ root->add_child("ContentVersion")->add_child_text (raw_convert<string> (content_version));
+ root->add_child("AudioLanguage")->add_child_text (audio_language);
+ root->add_child("SubtitleLanguage")->add_child_text (subtitle_language);
+ root->add_child("Territory")->add_child_text (territory);
+ root->add_child("Rating")->add_child_text (rating);
+ root->add_child("Studio")->add_child_text (studio);
+ root->add_child("Facility")->add_child_text (facility);
+ root->add_child("PackageType")->add_child_text (package_type);
+ root->add_child("TempVersion")->add_child_text (temp_version ? "1" : "0");
+ root->add_child("PreRelease")->add_child_text (pre_release ? "1" : "0");
+ root->add_child("RedBand")->add_child_text (red_band ? "1" : "0");
+ root->add_child("Chain")->add_child_text (chain);
+ root->add_child("TwoDVersionOfThreeD")->add_child_text (two_d_version_of_three_d ? "1" : "0");
+ root->add_child("MasteredLuminance")->add_child_text (mastered_luminance);
+ }
+
+ void
+ ISDCFMetadata::read_old_metadata (string k, string v)
+ {
+ if (k == N_("audio_language")) {
+ audio_language = v;
+ } else if (k == N_("subtitle_language")) {
+ subtitle_language = v;
+ } else if (k == N_("territory")) {
+ territory = v;
+ } else if (k == N_("rating")) {
+ rating = v;
+ } else if (k == N_("studio")) {
+ studio = v;
+ } else if (k == N_("facility")) {
+ facility = v;
+ } else if (k == N_("package_type")) {
+ package_type = v;
+ }
+ }
--- /dev/null
-
-namespace cxml {
- class Node;
-}
+ /*
+ 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 DCPOMATIC_ISDCF_METADATA_H
+ #define DCPOMATIC_ISDCF_METADATA_H
+
+ #include <string>
+ #include <libxml++/libxml++.h>
- ISDCFMetadata (boost::shared_ptr<const cxml::Node>);
++#include <libcxml/cxml.h>
+
+ class ISDCFMetadata
+ {
+ public:
+ ISDCFMetadata ()
+ : content_version (1)
+ , temp_version (false)
+ , pre_release (false)
+ , red_band (false)
+ , two_d_version_of_three_d (false)
+ {}
+
++ ISDCFMetadata (cxml::ConstNodePtr);
+
+ void as_xml (xmlpp::Node *) const;
+ void read_old_metadata (std::string, std::string);
+
+ int content_version;
+ std::string audio_language;
+ std::string subtitle_language;
+ std::string territory;
+ std::string rating;
+ std::string studio;
+ std::string facility;
+ std::string package_type;
+ /** true if this is a temporary version (without final picture or sound) */
+ bool temp_version;
+ /** true if this is a pre-release version (final picture and sound, but without accessibility features) */
+ bool pre_release;
+ /** true if this has adult content */
+ bool red_band;
+ /** specific theatre chain or event */
+ std::string chain;
+ /** true if this is a 2D version of content that also exists in 3D */
+ bool two_d_version_of_three_d;
+ /** mastered luminance if there are multiple versions distributed (e.g. 35, 4fl, 6fl etc.) */
+ std::string mastered_luminance;
+ };
+
+ #endif
#include "image.h"
#include "image_proxy.h"
#include "ratio.h"
-#include "resampler.h"
#include "log.h"
#include "scaler.h"
+#include "render_subtitles.h"
+#include "config.h"
+#include "content_video.h"
#include "player_video_frame.h"
+ #include "frame_rate_change.h"
#define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
#include <boost/enable_shared_from_this.hpp>
#include "ffmpeg_content.h"
#include "audio_mapping.h"
+#include "util.h"
+ #include "frame_rate_change.h"
class Content;
class FFmpegContent;
_audio_mapping = m;
}
- signal_changed (AudioContentProperty::AUDIO_MAPPING);
+ AudioContent::set_audio_mapping (m);
}
-
config.cc
content.cc
content_factory.cc
+ content_subtitle.cc
cross.cc
- dci_metadata.cc
dcp_content_type.cc
dcp_video_frame.cc
- decoder.cc
+ dcpomatic_time.cc
dolby_cp750.cc
encoder.cc
examine_content_job.cc
protected:
virtual void do_paint (wxGraphicsContext *) = 0;
- int time_x (Time t) const
+ int time_x (DCPTime t) const
{
- return _timeline.tracks_position().x + t.seconds() * _timeline.pixels_per_second ();
- return _timeline.tracks_position().x + t * _timeline.pixels_per_time_unit().get_value_or (0);
++ return _timeline.tracks_position().x + t.seconds() * _timeline.pixels_per_second().get_value_or (0);
}
Timeline& _timeline;
return dcpomatic::Rect<int> (
time_x (content->position ()) - 8,
y_pos (_track.get()) - 8,
- content->length_after_trim().seconds() * _timeline.pixels_per_second() + 16,
- content->length_after_trim () * _timeline.pixels_per_time_unit().get_value_or(0) + 16,
++ content->length_after_trim().seconds() * _timeline.pixels_per_second().get_value_or(0) + 16,
_timeline.track_height() + 16
);
}
wxDouble name_leading;
gc->GetTextExtent (name, &name_width, &name_height, &name_descent, &name_leading);
- gc->Clip (wxRegion (time_x (position), y_pos (_track.get()), len.seconds() * _timeline.pixels_per_second(), _timeline.track_height()));
- gc->Clip (wxRegion (time_x (position), y_pos (_track.get()), len * _timeline.pixels_per_time_unit().get_value_or(0), _timeline.track_height()));
++ gc->Clip (wxRegion (time_x (position), y_pos (_track.get()), len.seconds() * _timeline.pixels_per_second().get_value_or(0), _timeline.track_height()));
gc->DrawText (name, time_x (position) + 12, y_pos (_track.get() + 1) - name_height - 4);
gc->ResetClip ();
}
void do_paint (wxGraphicsContext* gc)
{
- if (!_timeline.pixels_per_time_unit()) {
++ if (!_timeline.pixels_per_second()) {
+ return;
+ }
+
- double const pptu = _timeline.pixels_per_time_unit().get ();
++ double const pps = _timeline.pixels_per_second().get ();
+
gc->SetPen (*wxThePenList->FindOrCreatePen (wxColour (0, 0, 0), 1, wxPENSTYLE_SOLID));
- double mark_interval = rint (128 / _timeline.pixels_per_second ());
- int mark_interval = rint (128 / (TIME_HZ * pptu));
++ double mark_interval = rint (128 / pps);
if (mark_interval > 5) {
- mark_interval -= mark_interval % 5;
+ mark_interval -= int (rint (mark_interval)) % 5;
}
if (mark_interval > 10) {
- mark_interval -= mark_interval % 10;
+ mark_interval -= int (rint (mark_interval)) % 10;
}
if (mark_interval > 60) {
- mark_interval -= mark_interval % 60;
+ mark_interval -= int (rint (mark_interval)) % 60;
}
if (mark_interval > 3600) {
- mark_interval -= mark_interval % 3600;
+ mark_interval -= int (rint (mark_interval)) % 3600;
}
if (mark_interval < 1) {
path.AddLineToPoint (_timeline.width(), _y);
gc->StrokePath (path);
- Time t = 0;
- while ((t * pptu) < _timeline.width()) {
+ /* Time in seconds */
+ DCPTime t;
- while ((t.seconds() * _timeline.pixels_per_second()) < _timeline.width()) {
++ while ((t.seconds() * pps) < _timeline.width()) {
wxGraphicsPath path = gc->CreatePath ();
path.MoveToPoint (time_x (t), _y - 4);
path.AddLineToPoint (time_x (t), _y + 4);
wxDouble str_leading;
gc->GetTextExtent (str, &str_width, &str_height, &str_descent, &str_leading);
- int const tx = _timeline.x_offset() + t.seconds() * _timeline.pixels_per_second();
- int const tx = _timeline.x_offset() + t * pptu;
++ int const tx = _timeline.x_offset() + t.seconds() * pps;
if ((tx + str_width) < _timeline.width()) {
gc->DrawText (str, time_x (t), _y + 16);
}
void
Timeline::set_position_from_event (wxMouseEvent& ev)
{
- if (!_pixels_per_time_unit) {
++ if (!_pixels_per_second) {
+ return;
+ }
+
- double const pptu = _pixels_per_time_unit.get ();
++ double const pps = _pixels_per_second.get ();
+
wxPoint const p = ev.GetPosition();
if (!_first_move) {
return;
}
- DCPTime new_position = _down_view_position + DCPTime::from_seconds ((p.x - _down_point.x) / _pixels_per_second);
- Time new_position = _down_view_position + (p.x - _down_point.x) / pptu;
++ DCPTime new_position = _down_view_position + DCPTime::from_seconds ((p.x - _down_point.x) / pps);
if (_snap) {
if (!first) {
/* Snap if it's close; `close' means within a proportion of the time on the timeline */
- if (nearest_distance < DCPTime::from_seconds ((width() / pixels_per_second()) / 32)) {
- if (nearest_distance < (width() / pptu) / 32) {
++ if (nearest_distance < DCPTime::from_seconds ((width() / pps) / 32)) {
new_position = nearest_new_position;
}
}
return 48;
}
- double pixels_per_second () const {
- boost::optional<double> pixels_per_time_unit () const {
- return _pixels_per_time_unit;
++ boost::optional<double> pixels_per_second () const {
+ return _pixels_per_second;
}
Position<int> tracks_position () const {
ViewList _views;
boost::shared_ptr<TimeAxisView> _time_axis_view;
int _tracks;
- double _pixels_per_second;
- boost::optional<double> _pixels_per_time_unit;
++ boost::optional<double> _pixels_per_second;
bool _left_down;
wxPoint _down_point;
boost::shared_ptr<ContentView> _down_view;
BOOST_CHECK (remotely_encoded);
BOOST_CHECK_EQUAL (locally_encoded->size(), remotely_encoded->size());
- BOOST_CHECK (memcmp (locally_encoded->data(), remotely_encoded->data(), locally_encoded->size()) == 0);
+ BOOST_CHECK_EQUAL (memcmp (locally_encoded->data(), remotely_encoded->data(), locally_encoded->size()), 0);
}
- BOOST_AUTO_TEST_CASE (client_server_test)
+ BOOST_AUTO_TEST_CASE (client_server_test_rgb)
{
- shared_ptr<Image> image (new Image (PIX_FMT_RGB24, libdcp::Size (1998, 1080), true));
+ shared_ptr<Image> image (new Image (PIX_FMT_RGB24, dcp::Size (1998, 1080), true));
uint8_t* p = image->data()[0];
for (int y = 0; y < 1080; ++y) {
p += sub_image->stride()[0];
}
- shared_ptr<FileLog> log (new FileLog ("build/test/client_server_test.log"));
+ shared_ptr<FileLog> log (new FileLog ("build/test/client_server_test_rgb.log"));
+
+ shared_ptr<PlayerVideoFrame> pvf (
+ new PlayerVideoFrame (
+ shared_ptr<ImageProxy> (new RawImageProxy (image, log)),
+ Crop (),
- libdcp::Size (1998, 1080),
- libdcp::Size (1998, 1080),
++ dcp::Size (1998, 1080),
++ dcp::Size (1998, 1080),
+ Scaler::from_id ("bicubic"),
+ EYES_BOTH,
+ PART_WHOLE,
+ ColourConversion ()
+ )
+ );
+
- pvf->set_subtitle (sub_image, Position<int> (50, 60));
++ pvf->set_subtitle (PositionImage (sub_image, Position<int> (50, 60)));
+
+ shared_ptr<DCPVideoFrame> frame (
+ new DCPVideoFrame (
+ pvf,
+ 0,
+ 24,
+ 200000000,
+ RESOLUTION_2K,
+ log
+ )
+ );
+
+ shared_ptr<EncodedData> locally_encoded = frame->encode_locally ();
+ BOOST_ASSERT (locally_encoded);
+
+ Server* server = new Server (log, true);
+
+ new thread (boost::bind (&Server::run, server, 2));
+
+ /* Let the server get itself ready */
+ dcpomatic_sleep (1);
+
+ ServerDescription description ("localhost", 2);
+
+ list<thread*> threads;
+ for (int i = 0; i < 8; ++i) {
+ threads.push_back (new thread (boost::bind (do_remote_encode, frame, description, locally_encoded)));
+ }
+
+ for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
+ (*i)->join ();
+ }
+
+ for (list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) {
+ delete *i;
+ }
+ }
+
+ BOOST_AUTO_TEST_CASE (client_server_test_yuv)
+ {
- shared_ptr<Image> image (new Image (PIX_FMT_YUV420P, libdcp::Size (1998, 1080), true));
++ shared_ptr<Image> image (new Image (PIX_FMT_YUV420P, dcp::Size (1998, 1080), true));
+ uint8_t* p = image->data()[0];
+
+ for (int i = 0; i < image->components(); ++i) {
+ uint8_t* p = image->data()[i];
+ for (int j = 0; j < image->line_size()[i]; ++j) {
+ *p++ = j % 256;
+ }
+ }
+
- shared_ptr<Image> sub_image (new Image (PIX_FMT_RGBA, libdcp::Size (100, 200), true));
++ shared_ptr<Image> sub_image (new Image (PIX_FMT_RGBA, dcp::Size (100, 200), true));
+ p = sub_image->data()[0];
+ for (int y = 0; y < 200; ++y) {
+ uint8_t* q = p;
+ for (int x = 0; x < 100; ++x) {
+ *q++ = y % 256;
+ *q++ = x % 256;
+ *q++ = (x + y) % 256;
+ *q++ = 1;
+ }
+ p += sub_image->stride()[0];
+ }
+
+ shared_ptr<FileLog> log (new FileLog ("build/test/client_server_test_yuv.log"));
shared_ptr<PlayerVideoFrame> pvf (
new PlayerVideoFrame (
using std::cout;
-/* Basic test of identifier() for ColourConversion (i.e. a hash of the numbers) */
BOOST_AUTO_TEST_CASE (colour_conversion_test)
{
- ColourConversion A (2.4, true, libdcp::colour_matrix::srgb_to_xyz, 2.6);
- ColourConversion B (2.4, false, libdcp::colour_matrix::srgb_to_xyz, 2.6);
+ ColourConversion A (2.4, true, dcp::colour_matrix::srgb_to_xyz, 2.6);
+ ColourConversion B (2.4, false, dcp::colour_matrix::srgb_to_xyz, 2.6);
- BOOST_CHECK_EQUAL (A.identifier(), "246ff9b7dc32c0488948a32a713924b3");
- BOOST_CHECK_EQUAL (B.identifier(), "a8d1da30f96a121d8db06a03409758b3");
+ BOOST_CHECK_EQUAL (A.identifier(), "1e720d2d99add654d7816f3b72da815e");
+ BOOST_CHECK_EQUAL (B.identifier(), "18751a247b22682b725bf9c4caf71522");
}
BOOST_AUTO_TEST_CASE (film_metadata_test)
{
- string const test_film = "build/test/film_metadata_test";
-
- if (boost::filesystem::exists (test_film)) {
- boost::filesystem::remove_all (test_film);
- }
+ shared_ptr<Film> f = new_test_film ("film_metadata_test");
+ boost::filesystem::path dir = test_film_dir ("film_metadata_test");
- f->_dci_date = boost::gregorian::from_undelimited_string ("20130211");
- shared_ptr<Film> f (new Film (test_film));
+ f->_isdcf_date = boost::gregorian::from_undelimited_string ("20130211");
BOOST_CHECK (f->container() == 0);
BOOST_CHECK (f->dcp_content_type() == 0);
#include "lib/config.h"
#include "lib/ffmpeg_content.h"
#include "lib/playlist.h"
+#include "lib/ffmpeg_audio_stream.h"
+ #include "lib/frame_rate_change.h"
#include "test.h"
using boost::shared_ptr;
Config::instance()->set_num_local_encoding_threads (1);
Config::instance()->set_server_port_base (61920);
- Config::instance()->set_default_dci_metadata (DCIMetadata ());
+ Config::instance()->set_default_isdcf_metadata (ISDCFMetadata ());
Config::instance()->set_default_container (static_cast<Ratio*> (0));
Config::instance()->set_default_dcp_content_type (static_cast<DCPContentType*> (0));
+ Config::instance()->set_default_audio_delay (0);
ServerFinder::instance()->disable ();
film_metadata_test.cc
frame_rate_test.cc
image_test.cc
+ isdcf_name_test.cc
job_test.cc
make_black_test.cc
+ player_test.cc
pixel_formats_test.cc
- play_test.cc
ratio_test.cc
+ repeat_frame_test.cc
recover_test.cc
resampler_test.cc
scaling_test.cc