diff options
| author | Carl Hetherington <cth@carlh.net> | 2012-10-15 23:19:27 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2012-10-15 23:19:27 +0100 |
| commit | e946a66554185459043af2a8bdae575e255c743d (patch) | |
| tree | 42d7ee7da6f6646f91b5429ed20fe84db92387d8 /src | |
| parent | 43990add893eccf350f280e2dd3f947a94f3e9aa (diff) | |
Unholy melange of stuff; setup a standard test config; send / receive subs to / from servers; various other image stride-related fixes.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/dcp_video_frame.cc | 43 | ||||
| -rw-r--r-- | src/lib/decoder.cc | 7 | ||||
| -rw-r--r-- | src/lib/film.cc | 21 | ||||
| -rw-r--r-- | src/lib/film.h | 2 | ||||
| -rw-r--r-- | src/lib/image.cc | 24 | ||||
| -rw-r--r-- | src/lib/image.h | 3 | ||||
| -rw-r--r-- | src/lib/imagemagick_encoder.cc | 39 | ||||
| -rw-r--r-- | src/lib/server.cc | 31 | ||||
| -rw-r--r-- | src/lib/subtitle.cc | 39 | ||||
| -rw-r--r-- | src/lib/subtitle.h | 38 | ||||
| -rw-r--r-- | src/lib/util.h | 2 | ||||
| -rw-r--r-- | src/wx/film_viewer.cc | 39 |
12 files changed, 154 insertions, 134 deletions
diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index 04735269c..e074b1cd1 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -161,17 +161,14 @@ DCPVideoFrame::encode_locally () shared_ptr<Image> prepared = _input->scale_and_convert_to_rgb (_out_size, _padding, _scaler); if (_subtitle) { - list<shared_ptr<SubtitleImage> > subs = _subtitle->images (); - for (list<shared_ptr<SubtitleImage> >::iterator i = subs.begin(); i != subs.end(); ++i) { - Rectangle tx = transformed_subtitle_area ( - float (_out_size.width) / _input->size().width, - float (_out_size.height) / _input->size().height, - (*i)->area(), _subtitle_offset, _subtitle_scale - ); - - shared_ptr<Image> im = (*i)->image()->scale (Size (tx.w, tx.h), _scaler); - prepared->alpha_blend (im, Position (tx.x, tx.y)); - } + Rectangle tx = subtitle_transformed_area ( + float (_out_size.width) / _input->size().width, + float (_out_size.height) / _input->size().height, + _subtitle->area(), _subtitle_offset, _subtitle_scale + ); + + shared_ptr<Image> im = _subtitle->image()->scale (Size (tx.w, tx.h), _scaler); + prepared->alpha_blend (im, Position (tx.x, tx.y)); } create_openjpeg_container (); @@ -310,9 +307,9 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv) asio::ip::tcp::resolver::query query (serv->host_name(), boost::lexical_cast<string> (Config::instance()->server_port ())); asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve (query); - Socket socket; + shared_ptr<Socket> socket (new Socket); - socket.connect (*endpoint_iterator, 30); + socket->connect (*endpoint_iterator, 30); stringstream s; s << "encode " @@ -329,19 +326,27 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv) << Config::instance()->colour_lut_index () << " " << Config::instance()->j2k_bandwidth () << " "; - socket.write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30); + if (_subtitle) { + s << _subtitle->position().x << " " << _subtitle->position().y << " " + << _subtitle->image()->size().width << " " << _subtitle->image()->size().height; + } else { + s << "-1 -1 0 0"; + } + + socket->write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30); - for (int i = 0; i < _input->components(); ++i) { - socket.write (_input->data()[i], _input->stride()[i] * _input->lines(i), 30); + _input->write_to_socket (socket); + if (_subtitle) { + _subtitle->image()->write_to_socket (socket); } char buffer[32]; - socket.read_indefinite ((uint8_t *) buffer, sizeof (buffer), 30); - socket.consume (strlen (buffer) + 1); + socket->read_indefinite ((uint8_t *) buffer, sizeof (buffer), 30); + socket->consume (strlen (buffer) + 1); shared_ptr<EncodedData> e (new RemotelyEncodedData (atoi (buffer))); /* now read the rest */ - socket.read_definite_and_consume (e->data(), e->size(), 30); + socket->read_definite_and_consume (e->data(), e->size(), 30); _log->log (String::compose ("Finished remotely-encoded frame %1", _frame)); diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index 1f771da2d..8989a938b 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -417,10 +417,7 @@ Decoder::process_subtitle (shared_ptr<Subtitle> s) _subtitle = s; if (_opt->apply_crop) { - list<shared_ptr<SubtitleImage> > im = _subtitle->images (); - for (list<shared_ptr<SubtitleImage> >::iterator i = im.begin(); i != im.end(); ++i) { - Position const p = (*i)->position (); - (*i)->set_position (Position (p.x - _fs->crop.left, p.y - _fs->crop.top)); - } + Position const p = _subtitle->position (); + _subtitle->set_position (Position (p.x - _fs->crop.left, p.y - _fs->crop.top)); } } diff --git a/src/lib/film.cc b/src/lib/film.cc index 31af2f1c2..636e2d546 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -685,20 +685,18 @@ Film::set_subtitle_scale (float s) signal_changed (SUBTITLE_SCALE); } -list<pair<Position, string> > -Film::thumb_subtitles (int n) const +pair<Position, string> +Film::thumb_subtitle (int n) const { string sub_file = _state.thumb_base(n) + ".sub"; if (!filesystem::exists (sub_file)) { - return list<pair<Position, string> > (); + return pair<Position, string> (); } ifstream f (sub_file.c_str ()); string line; - int sub_number; - int sub_x; - list<pair<Position, string> > subs; + pair<Position, string> sub; while (getline (f, line)) { if (line.empty ()) { @@ -717,14 +715,13 @@ Film::thumb_subtitles (int n) const string const k = line.substr (0, s); int const v = lexical_cast<int> (line.substr(s + 1)); - if (k == "image") { - sub_number = v; - } else if (k == "x") { - sub_x = v; + if (k == "x") { + sub.first.x = v; } else if (k == "y") { - subs.push_back (make_pair (Position (sub_x, v), String::compose ("%1.sub.%2.png", _state.thumb_base(n), sub_number))); + sub.first.y = v; + sub.second = String::compose ("%1.sub.png", _state.thumb_base(n)); } } - return subs; + return sub; } diff --git a/src/lib/film.h b/src/lib/film.h index c006eae36..46c67ad19 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -203,7 +203,7 @@ public: int num_thumbs () const; int thumb_frame (int) const; std::string thumb_file (int) const; - std::list<std::pair<Position, std::string> > thumb_subtitles (int) const; + std::pair<Position, std::string> thumb_subtitle (int) const; void copy_from_dvd_post_gui (); void examine_content (); diff --git a/src/lib/image.cc b/src/lib/image.cc index f5aef8444..30dc4292f 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -244,6 +244,30 @@ Image::alpha_blend (shared_ptr<Image> other, Position position) } } +void +Image::read_from_socket (shared_ptr<Socket> socket) +{ + for (int i = 0; i < components(); ++i) { + uint8_t* p = data()[i]; + for (int y = 0; y < lines(i); ++y) { + socket->read_definite_and_consume (p, line_size()[i], 30); + p += stride()[i]; + } + } +} + +void +Image::write_to_socket (shared_ptr<Socket> socket) const +{ + for (int i = 0; i < components(); ++i) { + uint8_t* p = data()[i]; + for (int y = 0; y < lines(i); ++y) { + socket->write (p, line_size()[i], 30); + p += stride()[i]; + } + } +} + /** Construct a SimpleImage of a given size and format, allocating memory * as required. * diff --git a/src/lib/image.h b/src/lib/image.h index 30c8519e7..6c3c9109e 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -75,6 +75,9 @@ public: void alpha_blend (boost::shared_ptr<Image> image, Position pos); void make_black (); + + void read_from_socket (boost::shared_ptr<Socket>); + void write_to_socket (boost::shared_ptr<Socket>) const; PixelFormat pixel_format () const { return _pixel_format; diff --git a/src/lib/imagemagick_encoder.cc b/src/lib/imagemagick_encoder.cc index 9bd8162f8..d0feb1893 100644 --- a/src/lib/imagemagick_encoder.cc +++ b/src/lib/imagemagick_encoder.cc @@ -69,32 +69,23 @@ ImageMagickEncoder::process_video (shared_ptr<Image> image, int frame, shared_pt string tmp_metadata_file = _opt->frame_out_path (frame, false, ".sub"); ofstream metadata (tmp_metadata_file.c_str ()); - list<shared_ptr<SubtitleImage> > images = sub->images (); - int n = 0; - for (list<shared_ptr<SubtitleImage> >::iterator i = images.begin(); i != images.end(); ++i) { - stringstream ext; - ext << ".sub." << n << ".png"; - - Size new_size = (*i)->image()->size (); - new_size.width *= x_scale; - new_size.height *= y_scale; - shared_ptr<Image> scaled = (*i)->image()->scale (new_size, _fs->scaler); - shared_ptr<Image> compact (new CompactImage (scaled)); - - string tmp_sub_file = _opt->frame_out_path (frame, true, ext.str ()); - Magick::Image sub_thumb (compact->size().width, compact->size().height, "RGBA", MagickCore::CharPixel, compact->data()[0]); - sub_thumb.magick ("PNG"); - sub_thumb.write (tmp_sub_file); - filesystem::rename (tmp_sub_file, _opt->frame_out_path (frame, false, ext.str ())); - - metadata << "image " << n << "\n" - << "x " << (*i)->position().x << "\n" - << "y " << (*i)->position().y << "\n"; + Size new_size = sub->image()->size (); + new_size.width *= x_scale; + new_size.height *= y_scale; + shared_ptr<Image> scaled = sub->image()->scale (new_size, _fs->scaler); + shared_ptr<Image> compact (new CompactImage (scaled)); + + string tmp_sub_file = _opt->frame_out_path (frame, true, ".sub.png"); + Magick::Image sub_thumb (compact->size().width, compact->size().height, "RGBA", MagickCore::CharPixel, compact->data()[0]); + sub_thumb.magick ("PNG"); + sub_thumb.write (tmp_sub_file); + filesystem::rename (tmp_sub_file, _opt->frame_out_path (frame, false, ".sub.png")); - metadata.close (); - filesystem::rename (tmp_metadata_file, _opt->frame_out_path (frame, false, ".sub")); - } + metadata << "x " << sub->position().x << "\n" + << "y " << sub->position().y << "\n"; + metadata.close (); + filesystem::rename (tmp_metadata_file, _opt->frame_out_path (frame, false, ".sub.png")); } frame_done (frame); diff --git a/src/lib/server.cc b/src/lib/server.cc index b5eda2eb8..2d19d06be 100644 --- a/src/lib/server.cc +++ b/src/lib/server.cc @@ -33,6 +33,7 @@ #include "image.h" #include "dcp_video_frame.h" #include "config.h" +#include "subtitle.h" using namespace std; using namespace boost; @@ -72,18 +73,18 @@ Server::Server (Log* log) int Server::process (shared_ptr<Socket> socket) { - char buffer[128]; + char buffer[256]; socket->read_indefinite ((uint8_t *) buffer, sizeof (buffer), 30); socket->consume (strlen (buffer) + 1); stringstream s (buffer); - + string command; s >> command; if (command != "encode") { return -1; } - + Size in_size; int pixel_format_int; Size out_size; @@ -96,6 +97,8 @@ Server::process (shared_ptr<Socket> socket) string post_process; int colour_lut_index; int j2k_bandwidth; + Position subtitle_position; + Size subtitle_size; s >> in_size.width >> in_size.height >> pixel_format_int @@ -108,8 +111,10 @@ Server::process (shared_ptr<Socket> socket) >> frames_per_second >> post_process >> colour_lut_index - >> j2k_bandwidth; - + >> j2k_bandwidth + >> subtitle_position.x >> subtitle_position.y + >> subtitle_size.width >> subtitle_size.height; + PixelFormat pixel_format = (PixelFormat) pixel_format_int; Scaler const * scaler = Scaler::from_id (scaler_id); if (post_process == "none") { @@ -117,20 +122,24 @@ Server::process (shared_ptr<Socket> socket) } shared_ptr<Image> image (new AlignedImage (pixel_format, in_size)); - - for (int i = 0; i < image->components(); ++i) { - socket->read_definite_and_consume (image->data()[i], image->stride()[i] * image->lines(i), 30); + + image->read_from_socket (socket); + + shared_ptr<Subtitle> sub; + if (subtitle_position.x != -1) { + shared_ptr<Image> subtitle_image (new AlignedImage (pixel_format, subtitle_size)); + subtitle_image->read_from_socket (socket); + sub.reset (new Subtitle (subtitle_position, subtitle_image)); } - /* XXX: subtitle */ DCPVideoFrame dcp_video_frame ( - image, shared_ptr<Subtitle> (), out_size, padding, subtitle_offset, subtitle_scale, + image, sub, out_size, padding, subtitle_offset, subtitle_scale, scaler, frame, frames_per_second, post_process, colour_lut_index, j2k_bandwidth, _log ); shared_ptr<EncodedData> encoded = dcp_video_frame.encode_locally (); encoded->send (socket); - + return frame; } diff --git a/src/lib/subtitle.cc b/src/lib/subtitle.cc index 0eb40b14e..2e9a89088 100644 --- a/src/lib/subtitle.cc +++ b/src/lib/subtitle.cc @@ -34,25 +34,18 @@ Subtitle::Subtitle (AVSubtitle const & sub) _from = packet_time + (double (sub.start_display_time) / 1e3); _to = packet_time + (double (sub.end_display_time) / 1e3); - for (unsigned int i = 0; i < sub.num_rects; ++i) { - _images.push_back (shared_ptr<SubtitleImage> (new SubtitleImage (sub.rects[i]))); + if (sub.num_rects > 1) { + throw DecodeError ("multi-part subtitles not yet supported"); } -} -/** @param t Time in seconds from the start of the film */ -bool -Subtitle::displayed_at (double t) -{ - return t >= _from && t <= _to; -} + AVSubtitleRect const * rect = sub.rects[0]; -SubtitleImage::SubtitleImage (AVSubtitleRect const * rect) - : _position (rect->x, rect->y) - , _image (new AlignedImage (PIX_FMT_RGBA, Size (rect->w, rect->h))) -{ if (rect->type != SUBTITLE_BITMAP) { throw DecodeError ("non-bitmap subtitles not yet supported"); } + + _position = Position (rect->x, rect->y); + _image.reset (new AlignedImage (PIX_FMT_RGBA, Size (rect->w, rect->h))); /* Start of the first line in the subtitle */ uint8_t* sub_p = rect->pict.data[0]; @@ -72,8 +65,24 @@ SubtitleImage::SubtitleImage (AVSubtitleRect const * rect) } } +Subtitle::Subtitle (Position p, shared_ptr<Image> i) + : _from (0) + , _to (0) + , _position (p) + , _image (i) +{ + +} + +/** @param t Time in seconds from the start of the film */ +bool +Subtitle::displayed_at (double t) +{ + return t >= _from && t <= _to; +} + Rectangle -transformed_subtitle_area ( +subtitle_transformed_area ( float target_x_scale, float target_y_scale, Rectangle sub_area, int subtitle_offset, float subtitle_scale ) @@ -107,7 +116,7 @@ transformed_subtitle_area ( } Rectangle -SubtitleImage::area () const +Subtitle::area () const { return Rectangle (_position.x, _position.y, _image->size().width, _image->size().height); } diff --git a/src/lib/subtitle.h b/src/lib/subtitle.h index 6fd0d8772..ef9571ad4 100644 --- a/src/lib/subtitle.h +++ b/src/lib/subtitle.h @@ -22,39 +22,16 @@ #include "util.h" struct AVSubtitle; -class SubtitleImage; class Image; -class FilmState; class Subtitle { public: Subtitle (AVSubtitle const &); + Subtitle (Position p, boost::shared_ptr<Image> i); bool displayed_at (double t); - std::list<boost::shared_ptr<SubtitleImage> > images () const { - return _images; - } - -private: - /** display from time in seconds from the start of the film */ - double _from; - /** display to time in seconds from the start of the film */ - double _to; - std::list<boost::shared_ptr<SubtitleImage> > _images; -}; - -extern Rectangle transformed_subtitle_area ( - float target_x_scale, float target_y_scale, - Rectangle sub_area, int subtitle_offset, float subtitle_scale - ); - -class SubtitleImage -{ -public: - SubtitleImage (AVSubtitleRect const *); - void set_position (Position p) { _position = p; } @@ -68,8 +45,19 @@ public: } Rectangle area () const; - + private: + /** display from time in seconds from the start of the film */ + double _from; + /** display to time in seconds from the start of the film */ + double _to; Position _position; boost::shared_ptr<Image> _image; }; + +Rectangle +subtitle_transformed_area ( + float target_x_scale, float target_y_scale, + Rectangle sub_area, int subtitle_offset, float subtitle_scale + ); + diff --git a/src/lib/util.h b/src/lib/util.h index bd7675a8a..916f47cdb 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -186,7 +186,7 @@ private: boost::asio::deadline_timer _deadline; boost::asio::ip::tcp::socket _socket; /** a buffer for small reads */ - uint8_t _buffer[256]; + uint8_t _buffer[512]; /** amount of valid data in the buffer */ int _buffer_data; }; diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index bf082adc2..34140d16c 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -58,21 +58,18 @@ public: if (_frame_rebuild_needed) { _image.reset (new wxImage (std_to_wx (_film->thumb_file (_index)))); - _subtitles.clear (); - list<pair<Position, string> > s = _film->thumb_subtitles (_index); - for (list<pair<Position, string> >::iterator i = s.begin(); i != s.end(); ++i) { - _subtitles.push_back (SubtitleView (i->first, std_to_wx (i->second))); + _subtitle.reset (); + pair<Position, string> s = _film->thumb_subtitle (_index); + if (!s.second.empty ()) { + _subtitle.reset (new SubtitleView (s.first, std_to_wx (s.second))); } _frame_rebuild_needed = false; - compose (); - _composition_needed = false; } if (_composition_needed) { compose (); - _composition_needed = false; } wxPaintDC dc (this); @@ -80,10 +77,8 @@ public: dc.DrawBitmap (*_bitmap, 0, 0, false); } - if (_film->with_subtitles ()) { - for (list<SubtitleView>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) { - dc.DrawBitmap (*i->bitmap, i->transformed_area.x, i->transformed_area.y, true); - } + if (_film->with_subtitles() && _subtitle) { + dc.DrawBitmap (*_subtitle->bitmap, _subtitle->transformed_area.x, _subtitle->transformed_area.y, true); } } @@ -123,7 +118,7 @@ public: { _bitmap.reset (); _image.reset (); - _subtitles.clear (); + _subtitle.reset (); } void recompose () @@ -138,6 +133,8 @@ private: void compose () { + _composition_needed = false; + if (!_film || !_image) { return; } @@ -176,17 +173,17 @@ private: _bitmap.reset (new wxBitmap (_transformed_image)); - for (list<SubtitleView>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) { + if (_subtitle) { - i->transformed_area = transformed_subtitle_area ( - x_scale, y_scale, i->base_area, _film->subtitle_offset(), _film->subtitle_scale() + _subtitle->transformed_area = subtitle_transformed_area ( + x_scale, y_scale, _subtitle->base_area, _film->subtitle_offset(), _film->subtitle_scale() ); - i->transformed_image = i->base_image; - i->transformed_image.Rescale (i->transformed_area.w, i->transformed_area.h, wxIMAGE_QUALITY_HIGH); - i->transformed_area.x -= _film->crop().left; - i->transformed_area.y -= _film->crop().top; - i->bitmap.reset (new wxBitmap (i->transformed_image)); + _subtitle->transformed_image = _subtitle->base_image; + _subtitle->transformed_image.Rescale (_subtitle->transformed_area.w, _subtitle->transformed_area.h, wxIMAGE_QUALITY_HIGH); + _subtitle->transformed_area.x -= _film->crop().left; + _subtitle->transformed_area.y -= _film->crop().top; + _subtitle->bitmap.reset (new wxBitmap (_subtitle->transformed_image)); } } @@ -217,7 +214,7 @@ private: shared_ptr<wxBitmap> bitmap; }; - list<SubtitleView> _subtitles; + shared_ptr<SubtitleView> _subtitle; }; BEGIN_EVENT_TABLE (ThumbPanel, wxPanel) |
