diff options
| author | Carl Hetherington <cth@carlh.net> | 2014-05-14 19:27:04 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2014-05-14 19:27:04 +0100 |
| commit | 21e8238484af35ac207b01defe406e73445632be (patch) | |
| tree | 8985d03f7b5641fd4e160d5ca4cac253976d51ff /src/lib | |
| parent | 5c09a82e483593fb37da0cad20679be735887613 (diff) | |
Make DCPVideoFrame use PlayerVideoFrame to store its image.
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/colour_conversion.cc | 1 | ||||
| -rw-r--r-- | src/lib/dcp_video_frame.cc | 114 | ||||
| -rw-r--r-- | src/lib/dcp_video_frame.h | 23 | ||||
| -rw-r--r-- | src/lib/encoder.cc | 18 | ||||
| -rw-r--r-- | src/lib/image.cc | 23 | ||||
| -rw-r--r-- | src/lib/image.h | 2 | ||||
| -rw-r--r-- | src/lib/player_video_frame.cc | 64 | ||||
| -rw-r--r-- | src/lib/player_video_frame.h | 7 | ||||
| -rw-r--r-- | src/lib/server.cc | 22 | ||||
| -rw-r--r-- | src/lib/types.cc | 22 | ||||
| -rw-r--r-- | src/lib/types.h | 13 | ||||
| -rw-r--r-- | src/lib/video_content.cc | 5 | ||||
| -rw-r--r-- | src/lib/writer.h | 2 |
13 files changed, 212 insertions, 104 deletions
diff --git a/src/lib/colour_conversion.cc b/src/lib/colour_conversion.cc index cd1a81b25..5f17f9184 100644 --- a/src/lib/colour_conversion.cc +++ b/src/lib/colour_conversion.cc @@ -29,6 +29,7 @@ using std::list; using std::string; +using std::stringstream; using std::cout; using std::vector; using boost::shared_ptr; diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index 1c12eb7fd..5cd6a118e 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -42,6 +42,7 @@ #include <boost/array.hpp> #include <boost/asio.hpp> #include <boost/filesystem.hpp> +#include <openssl/md5.h> #include <libdcp/rec709_linearised_gamma_lut.h> #include <libdcp/srgb_linearised_gamma_lut.h> #include <libdcp/gamma_lut.h> @@ -60,6 +61,7 @@ #include "image.h" #include "log.h" #include "cross.h" +#include "player_video_frame.h" #include "i18n.h" @@ -73,18 +75,16 @@ using libdcp::raw_convert; #define DCI_COEFFICENT (48.0 / 52.37) /** Construct a DCP video frame. - * @param input Input image. - * @param f Index of the frame within the DCP. + * @param frame Input frame. + * @param index Index of the frame within the DCP. * @param bw J2K bandwidth to use (see Config::j2k_bandwidth ()) * @param l Log to write to. */ DCPVideoFrame::DCPVideoFrame ( - shared_ptr<const Image> image, int f, Eyes eyes, ColourConversion c, int dcp_fps, int bw, Resolution r, shared_ptr<Log> l + shared_ptr<const PlayerVideoFrame> frame, int index, int dcp_fps, int bw, Resolution r, shared_ptr<Log> l ) - : _image (image) - , _frame (f) - , _eyes (eyes) - , _conversion (c) + : _frame (frame) + , _index (index) , _frames_per_second (dcp_fps) , _j2k_bandwidth (bw) , _resolution (r) @@ -93,22 +93,11 @@ DCPVideoFrame::DCPVideoFrame ( } -DCPVideoFrame::DCPVideoFrame (shared_ptr<const Image> image, shared_ptr<const cxml::Node> node, shared_ptr<Log> log) - : _image (image) +DCPVideoFrame::DCPVideoFrame (shared_ptr<const PlayerVideoFrame> frame, shared_ptr<const cxml::Node> node, shared_ptr<Log> log) + : _frame (frame) , _log (log) { - _frame = node->number_child<int> ("Frame"); - string const eyes = node->string_child ("Eyes"); - if (eyes == "Both") { - _eyes = EYES_BOTH; - } else if (eyes == "Left") { - _eyes = EYES_LEFT; - } else if (eyes == "Right") { - _eyes = EYES_RIGHT; - } else { - assert (false); - } - _conversion = ColourConversion (node->node_child ("ColourConversion")); + _index = node->number_child<int> ("Index"); _frames_per_second = node->number_child<int> ("FramesPerSecond"); _j2k_bandwidth = node->number_child<int> ("J2KBandwidth"); _resolution = Resolution (node->optional_number_child<int>("Resolution").get_value_or (RESOLUTION_2K)); @@ -121,10 +110,10 @@ shared_ptr<EncodedData> DCPVideoFrame::encode_locally () { shared_ptr<libdcp::LUT> in_lut; - if (_conversion.input_gamma_linearised) { - in_lut = libdcp::SRGBLinearisedGammaLUT::cache.get (12, _conversion.input_gamma); + if (_frame->colour_conversion().input_gamma_linearised) { + in_lut = libdcp::SRGBLinearisedGammaLUT::cache.get (12, _frame->colour_conversion().input_gamma); } else { - in_lut = libdcp::GammaLUT::cache.get (12, _conversion.input_gamma); + in_lut = libdcp::GammaLUT::cache.get (12, _frame->colour_conversion().input_gamma); } /* XXX: libdcp should probably use boost */ @@ -132,20 +121,35 @@ DCPVideoFrame::encode_locally () double matrix[3][3]; for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { - matrix[i][j] = _conversion.matrix (i, j); + matrix[i][j] = _frame->colour_conversion().matrix (i, j); } } - + shared_ptr<libdcp::XYZFrame> xyz = libdcp::rgb_to_xyz ( - _image, + _frame->image(), in_lut, - libdcp::GammaLUT::cache.get (16, 1 / _conversion.output_gamma), + libdcp::GammaLUT::cache.get (16, 1 / _frame->colour_conversion().output_gamma), matrix ); + + { + MD5_CTX md5_context; + MD5_Init (&md5_context); + MD5_Update (&md5_context, xyz->data(0), 1998 * 1080 * 4); + MD5_Update (&md5_context, xyz->data(1), 1998 * 1080 * 4); + MD5_Update (&md5_context, xyz->data(2), 1998 * 1080 * 4); + unsigned char digest[MD5_DIGEST_LENGTH]; + MD5_Final (digest, &md5_context); + stringstream s; + for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) { + s << std::hex << std::setfill('0') << std::setw(2) << ((int) digest[i]); + } + } + /* Set the max image and component sizes based on frame_rate */ int max_cs_len = ((float) _j2k_bandwidth) / 8 / _frames_per_second; - if (_eyes == EYES_LEFT || _eyes == EYES_RIGHT) { + if (_frame->eyes() == EYES_LEFT || _frame->eyes() == EYES_RIGHT) { /* In 3D we have only half the normal bandwidth per eye */ max_cs_len /= 2; } @@ -244,15 +248,15 @@ DCPVideoFrame::encode_locally () throw EncodeError (N_("JPEG2000 encoding failed")); } - switch (_eyes) { + switch (_frame->eyes()) { case EYES_BOTH: - _log->log (String::compose (N_("Finished locally-encoded frame %1 for mono"), _frame)); + _log->log (String::compose (N_("Finished locally-encoded frame %1 for mono"), _index)); break; case EYES_LEFT: - _log->log (String::compose (N_("Finished locally-encoded frame %1 for L"), _frame)); + _log->log (String::compose (N_("Finished locally-encoded frame %1 for L"), _index)); break; case EYES_RIGHT: - _log->log (String::compose (N_("Finished locally-encoded frame %1 for R"), _frame)); + _log->log (String::compose (N_("Finished locally-encoded frame %1 for R"), _index)); break; default: break; @@ -283,28 +287,30 @@ DCPVideoFrame::encode_remotely (ServerDescription serv) socket->connect (*endpoint_iterator); + /* Collect all XML metadata */ xmlpp::Document doc; xmlpp::Element* root = doc.create_root_node ("EncodingRequest"); - root->add_child("Version")->add_child_text (raw_convert<string> (SERVER_LINK_VERSION)); - root->add_child("Width")->add_child_text (raw_convert<string> (_image->size().width)); - root->add_child("Height")->add_child_text (raw_convert<string> (_image->size().height)); add_metadata (root); + _log->log (String::compose (N_("Sending frame %1 to remote"), _index)); + + /* Send XML metadata */ stringstream xml; doc.write_to_stream (xml, "UTF-8"); - - _log->log (String::compose (N_("Sending frame %1 to remote"), _frame)); - socket->write (xml.str().length() + 1); socket->write ((uint8_t *) xml.str().c_str(), xml.str().length() + 1); - _image->write_to_socket (socket); + /* Send binary data */ + _frame->send_binary (socket); + /* Read the response (JPEG2000-encoded data); this blocks until the data + is ready and sent back. + */ shared_ptr<EncodedData> e (new RemotelyEncodedData (socket->read_uint32 ())); socket->read (e->data(), e->size()); - _log->log (String::compose (N_("Finished remotely-encoded frame %1"), _frame)); + _log->log (String::compose (N_("Finished remotely-encoded frame %1"), _index)); return e; } @@ -312,27 +318,17 @@ DCPVideoFrame::encode_remotely (ServerDescription serv) void DCPVideoFrame::add_metadata (xmlpp::Element* el) const { - el->add_child("Frame")->add_child_text (raw_convert<string> (_frame)); - - switch (_eyes) { - case EYES_BOTH: - el->add_child("Eyes")->add_child_text ("Both"); - break; - case EYES_LEFT: - el->add_child("Eyes")->add_child_text ("Left"); - break; - case EYES_RIGHT: - el->add_child("Eyes")->add_child_text ("Right"); - break; - default: - assert (false); - } - - _conversion.as_xml (el->add_child("ColourConversion")); - + el->add_child("Index")->add_child_text (raw_convert<string> (_index)); el->add_child("FramesPerSecond")->add_child_text (raw_convert<string> (_frames_per_second)); el->add_child("J2KBandwidth")->add_child_text (raw_convert<string> (_j2k_bandwidth)); el->add_child("Resolution")->add_child_text (raw_convert<string> (int (_resolution))); + _frame->add_metadata (el); +} + +Eyes +DCPVideoFrame::eyes () const +{ + return _frame->eyes (); } EncodedData::EncodedData (int s) diff --git a/src/lib/dcp_video_frame.h b/src/lib/dcp_video_frame.h index 40f758c74..e4006d986 100644 --- a/src/lib/dcp_video_frame.h +++ b/src/lib/dcp_video_frame.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> Taken from code Copyright (C) 2010-2011 Terrence Meiczinger This program is free software; you can redistribute it and/or modify @@ -33,6 +33,7 @@ class Scaler; class Image; class Log; class Subtitle; +class PlayerVideoFrame; /** @class EncodedData * @brief Container for J2K-encoded data. @@ -102,28 +103,24 @@ public: class DCPVideoFrame : public boost::noncopyable { public: - DCPVideoFrame (boost::shared_ptr<const Image>, int, Eyes, ColourConversion, int, int, Resolution, boost::shared_ptr<Log>); - DCPVideoFrame (boost::shared_ptr<const Image>, boost::shared_ptr<const cxml::Node>, boost::shared_ptr<Log>); + DCPVideoFrame (boost::shared_ptr<const PlayerVideoFrame>, int, int, int, Resolution, boost::shared_ptr<Log>); + DCPVideoFrame (boost::shared_ptr<const PlayerVideoFrame>, boost::shared_ptr<const cxml::Node>, boost::shared_ptr<Log>); boost::shared_ptr<EncodedData> encode_locally (); boost::shared_ptr<EncodedData> encode_remotely (ServerDescription); - Eyes eyes () const { - return _eyes; - } - - int frame () const { - return _frame; + int index () const { + return _index; } + + Eyes eyes () const; private: void add_metadata (xmlpp::Element *) const; - boost::shared_ptr<const Image> _image; - int _frame; ///< frame index within the DCP's intrinsic duration - Eyes _eyes; - ColourConversion _conversion; + boost::shared_ptr<const PlayerVideoFrame> _frame; + int _index; ///< frame index within the DCP's intrinsic duration int _frames_per_second; ///< Frames per second that we will use for the DCP int _j2k_bandwidth; ///< J2K bandwidth to use Resolution _resolution; ///< Resolution (2K or 4K) diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index 8ae402797..4fc2d7f81 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -125,9 +125,9 @@ Encoder::process_end () */ for (list<shared_ptr<DCPVideoFrame> >::iterator i = _queue.begin(); i != _queue.end(); ++i) { - _film->log()->log (String::compose (N_("Encode left-over frame %1"), (*i)->frame ())); + _film->log()->log (String::compose (N_("Encode left-over frame %1"), (*i)->index ())); try { - _writer->write ((*i)->encode_locally(), (*i)->frame (), (*i)->eyes ()); + _writer->write ((*i)->encode_locally(), (*i)->index (), (*i)->eyes ()); frame_done (); } catch (std::exception& e) { _film->log()->log (String::compose (N_("Local encode failed (%1)"), e.what ())); @@ -219,7 +219,7 @@ Encoder::process_video (shared_ptr<PlayerVideoFrame> pvf, bool same) TIMING ("adding to queue of %1", _queue.size ()); _queue.push_back (shared_ptr<DCPVideoFrame> ( new DCPVideoFrame ( - pvf->image(), _video_frames_out, pvf->eyes(), pvf->colour_conversion(), _film->video_frame_rate(), + pvf, _video_frames_out, _film->video_frame_rate(), _film->j2k_bandwidth(), _film->resolution(), _film->log() ) )); @@ -282,7 +282,7 @@ try TIMING ("encoder thread %1 wakes with queue of %2", boost::this_thread::get_id(), _queue.size()); shared_ptr<DCPVideoFrame> vf = _queue.front (); - TIMING ("encoder thread %1 pops frame %2 (%3) from queue", boost::this_thread::get_id(), vf->frame(), vf->eyes ()); + TIMING ("encoder thread %1 pops frame %2 (%3) from queue", boost::this_thread::get_id(), vf->index(), vf->eyes ()); _queue.pop_front (); lock.unlock (); @@ -308,27 +308,27 @@ try _film->log()->log ( String::compose ( N_("Remote encode of %1 on %2 failed (%3); thread sleeping for %4s"), - vf->frame(), server->host_name(), e.what(), remote_backoff) + vf->index(), server->host_name(), e.what(), remote_backoff) ); } } else { try { - TIMING ("encoder thread %1 begins local encode of %2", boost::this_thread::get_id(), vf->frame()); + TIMING ("encoder thread %1 begins local encode of %2", boost::this_thread::get_id(), vf->index()); encoded = vf->encode_locally (); - TIMING ("encoder thread %1 finishes local encode of %2", boost::this_thread::get_id(), vf->frame()); + TIMING ("encoder thread %1 finishes local encode of %2", boost::this_thread::get_id(), vf->index()); } catch (std::exception& e) { _film->log()->log (String::compose (N_("Local encode failed (%1)"), e.what ())); } } if (encoded) { - _writer->write (encoded, vf->frame (), vf->eyes ()); + _writer->write (encoded, vf->index (), vf->eyes ()); frame_done (); } else { lock.lock (); _film->log()->log ( - String::compose (N_("Encoder thread %1 pushes frame %2 back onto queue after failure"), boost::this_thread::get_id(), vf->frame()) + String::compose (N_("Encoder thread %1 pushes frame %2 back onto queue after failure"), boost::this_thread::get_id(), vf->index()) ); _queue.push_front (vf); lock.unlock (); diff --git a/src/lib/image.cc b/src/lib/image.cc index d083cf3f6..1fa55e242 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -22,6 +22,7 @@ */ #include <iostream> +#include <openssl/md5.h> extern "C" { #include <libswscale/swscale.h> #include <libavutil/pixfmt.h> @@ -37,6 +38,7 @@ using std::string; using std::min; using std::cout; using std::cerr; +using std::stringstream; using boost::shared_ptr; using libdcp::Size; @@ -619,3 +621,24 @@ Image::aligned () const return _aligned; } +string +Image::digest () const +{ + MD5_CTX md5_context; + MD5_Init (&md5_context); + + for (int i = 0; i < components(); ++i) { + MD5_Update (&md5_context, data()[i], line_size()[i]); + } + + unsigned char digest[MD5_DIGEST_LENGTH]; + MD5_Final (digest, &md5_context); + + stringstream s; + for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) { + s << std::hex << std::setfill('0') << std::setw(2) << ((int) digest[i]); + } + + return s.str (); +} + diff --git a/src/lib/image.h b/src/lib/image.h index 2d9f32231..f83bf6998 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -73,6 +73,8 @@ public: return _pixel_format; } + std::string digest () const; + private: friend class pixel_formats_test; diff --git a/src/lib/player_video_frame.cc b/src/lib/player_video_frame.cc index 571c18b6e..cbe879d10 100644 --- a/src/lib/player_video_frame.cc +++ b/src/lib/player_video_frame.cc @@ -17,10 +17,15 @@ */ +#include <libdcp/raw_convert.h> #include "player_video_frame.h" #include "image.h" +#include "scaler.h" +using std::string; +using std::cout; using boost::shared_ptr; +using libdcp::raw_convert; PlayerVideoFrame::PlayerVideoFrame ( shared_ptr<const Image> in, @@ -42,6 +47,33 @@ PlayerVideoFrame::PlayerVideoFrame ( } +PlayerVideoFrame::PlayerVideoFrame (shared_ptr<cxml::Node> node, shared_ptr<Socket> socket) +{ + _crop = Crop (node); + + _inter_size = libdcp::Size (node->number_child<int> ("InterWidth"), node->number_child<int> ("InterHeight")); + _out_size = libdcp::Size (node->number_child<int> ("OutWidth"), node->number_child<int> ("OutHeight")); + _scaler = Scaler::from_id (node->string_child ("Scaler")); + _eyes = (Eyes) node->number_child<int> ("Eyes"); + _colour_conversion = ColourConversion (node); + + shared_ptr<Image> image (new Image (PIX_FMT_RGB24, libdcp::Size (node->number_child<int> ("InWidth"), node->number_child<int> ("InHeight")), true)); + image->read_from_socket (socket); + _in = image; + + if (node->optional_number_child<int> ("SubtitleX")) { + + _subtitle_position = Position<int> (node->number_child<int> ("SubtitleX"), node->number_child<int> ("SubtitleY")); + + shared_ptr<Image> image ( + new Image (PIX_FMT_RGBA, libdcp::Size (node->number_child<int> ("SubtitleWidth"), node->number_child<int> ("SubtitleHeight")), true) + ); + + image->read_from_socket (socket); + _subtitle_image = image; + } +} + void PlayerVideoFrame::set_subtitle (shared_ptr<const Image> image, Position<int> pos) { @@ -50,7 +82,7 @@ PlayerVideoFrame::set_subtitle (shared_ptr<const Image> image, Position<int> pos } shared_ptr<Image> -PlayerVideoFrame::image () +PlayerVideoFrame::image () const { shared_ptr<Image> out = _in->crop_scale_window (_crop, _inter_size, _out_size, _scaler, PIX_FMT_RGB24, false); @@ -62,3 +94,33 @@ PlayerVideoFrame::image () return out; } + +void +PlayerVideoFrame::add_metadata (xmlpp::Element* node) const +{ + _crop.as_xml (node); + node->add_child("InWidth")->add_child_text (raw_convert<string> (_in->size().width)); + node->add_child("InHeight")->add_child_text (raw_convert<string> (_in->size().height)); + node->add_child("InterWidth")->add_child_text (raw_convert<string> (_inter_size.width)); + node->add_child("InterHeight")->add_child_text (raw_convert<string> (_inter_size.height)); + node->add_child("OutWidth")->add_child_text (raw_convert<string> (_out_size.width)); + node->add_child("OutHeight")->add_child_text (raw_convert<string> (_out_size.height)); + node->add_child("Scaler")->add_child_text (_scaler->id ()); + node->add_child("Eyes")->add_child_text (raw_convert<string> (_eyes)); + _colour_conversion.as_xml (node); + if (_subtitle_image) { + node->add_child ("SubtitleWidth")->add_child_text (raw_convert<string> (_subtitle_image->size().width)); + node->add_child ("SubtitleHeight")->add_child_text (raw_convert<string> (_subtitle_image->size().height)); + node->add_child ("SubtitleX")->add_child_text (raw_convert<string> (_subtitle_position.x)); + node->add_child ("SubtitleY")->add_child_text (raw_convert<string> (_subtitle_position.y)); + } +} + +void +PlayerVideoFrame::send_binary (shared_ptr<Socket> socket) const +{ + _in->write_to_socket (socket); + if (_subtitle_image) { + _subtitle_image->write_to_socket (socket); + } +} diff --git a/src/lib/player_video_frame.h b/src/lib/player_video_frame.h index 42d345c9a..ea7e54481 100644 --- a/src/lib/player_video_frame.h +++ b/src/lib/player_video_frame.h @@ -24,6 +24,7 @@ class Image; class Scaler; +class Socket; /** Everything needed to describe a video frame coming out of the player, but with the * bits still their raw form. We may want to combine the bits on a remote machine, @@ -33,10 +34,14 @@ class PlayerVideoFrame { public: PlayerVideoFrame (boost::shared_ptr<const Image>, Crop, libdcp::Size, libdcp::Size, Scaler const *, Eyes, ColourConversion); + PlayerVideoFrame (boost::shared_ptr<cxml::Node>, boost::shared_ptr<Socket>); void set_subtitle (boost::shared_ptr<const Image>, Position<int>); - boost::shared_ptr<Image> image (); + boost::shared_ptr<Image> image () const; + + void add_metadata (xmlpp::Element* node) const; + void send_binary (boost::shared_ptr<Socket> socket) const; Eyes eyes () const { return _eyes; diff --git a/src/lib/server.cc b/src/lib/server.cc index 0c5792ae0..b9bb825ee 100644 --- a/src/lib/server.cc +++ b/src/lib/server.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 @@ -37,6 +37,7 @@ #include "dcp_video_frame.h" #include "config.h" #include "cross.h" +#include "player_video_frame.h" #include "i18n.h" @@ -75,7 +76,7 @@ Server::process (shared_ptr<Socket> socket, struct timeval& after_read, struct t uint32_t length = socket->read_uint32 (); scoped_array<char> buffer (new char[length]); socket->read (reinterpret_cast<uint8_t*> (buffer.get()), length); - + stringstream s (buffer.get()); shared_ptr<cxml::Document> xml (new cxml::Document ("EncodingRequest")); xml->read_stream (s); @@ -85,14 +86,9 @@ Server::process (shared_ptr<Socket> socket, struct timeval& after_read, struct t return -1; } - libdcp::Size size ( - xml->number_child<int> ("Width"), xml->number_child<int> ("Height") - ); - - shared_ptr<Image> image (new Image (PIX_FMT_RGB24, size, true)); + shared_ptr<PlayerVideoFrame> pvf (new PlayerVideoFrame (xml, socket)); - image->read_from_socket (socket); - DCPVideoFrame dcp_video_frame (image, xml, _log); + DCPVideoFrame dcp_video_frame (pvf, xml, _log); gettimeofday (&after_read, 0); @@ -103,15 +99,11 @@ Server::process (shared_ptr<Socket> socket, struct timeval& after_read, struct t try { encoded->send (socket); } catch (std::exception& e) { - _log->log (String::compose ( - "Send failed; frame %1, data size %2, pixel format %3, image size %4x%5, %6 components", - dcp_video_frame.frame(), encoded->size(), image->pixel_format(), image->size().width, image->size().height, image->components() - ) - ); + _log->log (String::compose ("Send failed; frame %1", dcp_video_frame.index())); throw; } - return dcp_video_frame.frame (); + return dcp_video_frame.index (); } void diff --git a/src/lib/types.cc b/src/lib/types.cc index bc4f5f8d9..83bbf41e4 100644 --- a/src/lib/types.cc +++ b/src/lib/types.cc @@ -17,11 +17,16 @@ */ +#include <libxml++/libxml++.h> +#include <libcxml/cxml.h> +#include <libdcp/raw_convert.h> #include "types.h" using std::max; using std::min; using std::string; +using boost::shared_ptr; +using libdcp::raw_convert; bool operator== (Crop const & a, Crop const & b) { @@ -65,3 +70,20 @@ string_to_resolution (string s) assert (false); return RESOLUTION_2K; } + +Crop::Crop (shared_ptr<cxml::Node> node) +{ + left = node->number_child<int> ("LeftCrop"); + right = node->number_child<int> ("RightCrop"); + top = node->number_child<int> ("TopCrop"); + bottom = node->number_child<int> ("BottomCrop"); +} + +void +Crop::as_xml (xmlpp::Node* node) const +{ + node->add_child("LeftCrop")->add_child_text (raw_convert<string> (left)); + node->add_child("RightCrop")->add_child_text (raw_convert<string> (right)); + node->add_child("TopCrop")->add_child_text (raw_convert<string> (top)); + node->add_child("BottomCrop")->add_child_text (raw_convert<string> (bottom)); +} diff --git a/src/lib/types.h b/src/lib/types.h index c255bd0d8..8e2384d80 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -32,11 +32,19 @@ class SubtitleContent; class FFmpegContent; class AudioBuffers; +namespace cxml { + class Node; +} + +namespace xmlpp { + class Node; +} + /** The version number of the protocol used to communicate * with servers. Intended to be bumped when incompatibilities * are introduced. */ -#define SERVER_LINK_VERSION 1 +#define SERVER_LINK_VERSION 2 typedef int64_t Time; #define TIME_MAX INT64_MAX @@ -92,6 +100,7 @@ struct Crop { Crop () : left (0), right (0), top (0), bottom (0) {} Crop (int l, int r, int t, int b) : left (l), right (r), top (t), bottom (b) {} + Crop (boost::shared_ptr<cxml::Node>); /** Number of pixels to remove from the left-hand side */ int left; @@ -116,6 +125,8 @@ struct Crop return s; } + + void as_xml (xmlpp::Node *) const; }; extern bool operator== (Crop const & a, Crop const & b); diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc index 783cddafa..40772980f 100644 --- a/src/lib/video_content.cc +++ b/src/lib/video_content.cc @@ -161,10 +161,7 @@ VideoContent::as_xml (xmlpp::Node* node) const node->add_child("VideoHeight")->add_child_text (raw_convert<string> (_video_size.height)); node->add_child("VideoFrameRate")->add_child_text (raw_convert<string> (_video_frame_rate)); node->add_child("VideoFrameType")->add_child_text (raw_convert<string> (static_cast<int> (_video_frame_type))); - node->add_child("LeftCrop")->add_child_text (raw_convert<string> (_crop.left)); - node->add_child("RightCrop")->add_child_text (raw_convert<string> (_crop.right)); - node->add_child("TopCrop")->add_child_text (raw_convert<string> (_crop.top)); - node->add_child("BottomCrop")->add_child_text (raw_convert<string> (_crop.bottom)); + _crop.as_xml (node); _scale.as_xml (node->add_child("Scale")); _colour_conversion.as_xml (node->add_child("ColourConversion")); } diff --git a/src/lib/writer.h b/src/lib/writer.h index 7af79a417..c0699ad44 100644 --- a/src/lib/writer.h +++ b/src/lib/writer.h @@ -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 |
