X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fsubtitle.cc;h=0d18861c455f69f2d2649730f93d898d0ed66463;hb=e01961397fbf87c69da4c8a8e79cef3c16480d3a;hp=18dded02c9080a69ca730ea036fe773b0734d42c;hpb=b96ad1327c25d5de8d61ed73a1c0e207e67f1226;p=dcpomatic.git diff --git a/src/lib/subtitle.cc b/src/lib/subtitle.cc index 18dded02c..0d18861c4 100644 --- a/src/lib/subtitle.cc +++ b/src/lib/subtitle.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington + Copyright (C) 2013-2014 Carl Hetherington 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,53 +18,99 @@ */ #include "subtitle.h" +#include "subtitle_content.h" +#include "piece.h" #include "image.h" -#include "exceptions.h" +#include "scaler.h" +#include "film.h" -using namespace std; -using namespace boost; +using boost::shared_ptr; +using boost::dynamic_pointer_cast; +using boost::weak_ptr; -Subtitle::Subtitle (AVSubtitle const & sub) +Subtitle::Subtitle (shared_ptr film, libdcp::Size video_container_size, weak_ptr weak_piece, shared_ptr image, dcpomatic::Rect rect, Time from, Time to) + : _piece (weak_piece) + , _in_image (image) + , _in_rect (rect) + , _in_from (from) + , _in_to (to) { - /* subtitle PTS in seconds */ - float const packet_time = (sub.pts / AV_TIME_BASE) + float (sub.pts % AV_TIME_BASE) / 1e6; + update (film, video_container_size); +} + +void +Subtitle::update (shared_ptr film, libdcp::Size video_container_size) +{ + shared_ptr piece = _piece.lock (); + if (!piece) { + return; + } + + if (!_in_image) { + _out_image.reset (); + return; + } + + shared_ptr sc = dynamic_pointer_cast (piece->content); + assert (sc); + + dcpomatic::Rect in_rect = _in_rect; + libdcp::Size scaled_size; + + in_rect.x += sc->subtitle_x_offset (); + in_rect.y += sc->subtitle_y_offset (); + + /* We will scale the subtitle up to fit _video_container_size, and also by the additional subtitle_scale */ + scaled_size.width = in_rect.width * video_container_size.width * sc->subtitle_scale (); + scaled_size.height = in_rect.height * video_container_size.height * sc->subtitle_scale (); + + /* Then we need a corrective translation, consisting of two parts: + * + * 1. that which is the result of the scaling of the subtitle by _video_container_size; this will be + * rect.x * _video_container_size.width and rect.y * _video_container_size.height. + * + * 2. that to shift the origin of the scale by subtitle_scale to the centre of the subtitle; this will be + * (width_before_subtitle_scale * (1 - subtitle_scale) / 2) and + * (height_before_subtitle_scale * (1 - subtitle_scale) / 2). + * + * Combining these two translations gives these expressions. + */ - /* hence start time for this sub */ - _from = packet_time + (double (sub.start_display_time) / 1e3); - _to = packet_time + (double (sub.end_display_time) / 1e3); + _out_position.x = rint (video_container_size.width * (in_rect.x + (in_rect.width * (1 - sc->subtitle_scale ()) / 2))); + _out_position.y = rint (video_container_size.height * (in_rect.y + (in_rect.height * (1 - sc->subtitle_scale ()) / 2))); + + _out_image = _in_image->scale ( + scaled_size, + Scaler::from_id ("bicubic"), + _in_image->pixel_format (), + true + ); - for (unsigned int i = 0; i < sub.num_rects; ++i) { - _images.push_back (shared_ptr (new SubtitleImage (sub.rects[i]))); + /* XXX: hack */ + Time from = _in_from; + Time to = _in_to; + shared_ptr vc = dynamic_pointer_cast (piece->content); + if (vc) { + from = rint (from * vc->video_frame_rate() / film->video_frame_rate()); + to = rint (to * vc->video_frame_rate() / film->video_frame_rate()); } + + _out_from = from + piece->content->position (); + _out_to = to + piece->content->position (); + + check_out_to (); } -/** @param t Time in seconds from the start of the film */ bool -Subtitle::displayed_at (double t) +Subtitle::covers (Time t) const { - return t >= _from && t <= _to; + return _out_from <= t && t <= _out_to; } -SubtitleImage::SubtitleImage (AVSubtitleRect const * rect) - : _position (rect->x, rect->y) - , _image (new SimpleImage (PIX_FMT_RGBA, Size (rect->w, rect->h))) +void +Subtitle::check_out_to () { - if (rect->type != SUBTITLE_BITMAP) { - throw DecodeError ("non-bitmap subtitles not yet supported"); - } - - /* Start of the first line in the subtitle */ - uint8_t* sub_p = rect->pict.data[0]; - /* sub_p looks up into a RGB palette which is here */ - uint32_t const * palette = (uint32_t *) rect->pict.data[1]; - /* Start of the output data */ - uint32_t* out_p = (uint32_t *) _image->data()[0]; - - for (int y = 0; y < rect->h; ++y) { - uint8_t* sub_line_p = sub_p; - for (int x = 0; x < rect->w; ++x) { - *out_p++ = palette[*sub_line_p++]; - } - sub_p += rect->pict.linesize[0]; + if (_stop && _out_to > _stop.get ()) { + _out_to = _stop.get (); } }