diff options
| author | Carl Hetherington <cth@carlh.net> | 2012-10-10 15:47:06 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2012-10-10 15:47:06 +0100 |
| commit | cc4a67b7eb8ecaed076e261960848f70e3e741af (patch) | |
| tree | a41a122341543aee630d6842785d90830298a297 /src | |
| parent | d382f34db155ddaf4bb61538c18b87c7564e00b2 (diff) | |
Subs successfully exported with thumbs.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/ab_transcoder.cc | 4 | ||||
| -rw-r--r-- | src/lib/ab_transcoder.h | 3 | ||||
| -rw-r--r-- | src/lib/dcp_video_frame.cc | 7 | ||||
| -rw-r--r-- | src/lib/dcp_video_frame.h | 4 | ||||
| -rw-r--r-- | src/lib/decoder.cc | 6 | ||||
| -rw-r--r-- | src/lib/decoder.h | 7 | ||||
| -rw-r--r-- | src/lib/encoder.h | 4 | ||||
| -rw-r--r-- | src/lib/ffmpeg_decoder.cc | 132 | ||||
| -rw-r--r-- | src/lib/ffmpeg_decoder.h | 5 | ||||
| -rw-r--r-- | src/lib/image.cc | 57 | ||||
| -rw-r--r-- | src/lib/image.h | 3 | ||||
| -rw-r--r-- | src/lib/imagemagick_decoder.cc | 22 | ||||
| -rw-r--r-- | src/lib/imagemagick_decoder.h | 19 | ||||
| -rw-r--r-- | src/lib/j2k_still_encoder.cc | 4 | ||||
| -rw-r--r-- | src/lib/j2k_still_encoder.h | 2 | ||||
| -rw-r--r-- | src/lib/j2k_wav_encoder.cc | 4 | ||||
| -rw-r--r-- | src/lib/j2k_wav_encoder.h | 3 | ||||
| -rw-r--r-- | src/lib/job_manager.cc | 5 | ||||
| -rw-r--r-- | src/lib/options.h | 8 | ||||
| -rw-r--r-- | src/lib/server.cc | 12 | ||||
| -rw-r--r-- | src/lib/tiff_decoder.cc | 2 | ||||
| -rw-r--r-- | src/lib/tiff_encoder.cc | 56 | ||||
| -rw-r--r-- | src/lib/tiff_encoder.h | 2 | ||||
| -rw-r--r-- | src/lib/wscript | 1 |
24 files changed, 203 insertions, 169 deletions
diff --git a/src/lib/ab_transcoder.cc b/src/lib/ab_transcoder.cc index 1c20ae477..a32d82c54 100644 --- a/src/lib/ab_transcoder.cc +++ b/src/lib/ab_transcoder.cc @@ -70,7 +70,7 @@ ABTranscoder::~ABTranscoder () } void -ABTranscoder::process_video (shared_ptr<Image> yuv, int frame, int index) +ABTranscoder::process_video (shared_ptr<Image> yuv, int frame, shared_ptr<Subtitle> sub, int index) { if (index == 0) { /* Keep this image around until we get the other half */ @@ -92,7 +92,7 @@ ABTranscoder::process_video (shared_ptr<Image> yuv, int frame, int index) } /* And pass it to the encoder */ - _encoder->process_video (_image, frame); + _encoder->process_video (_image, frame, sub); _image.reset (); } diff --git a/src/lib/ab_transcoder.h b/src/lib/ab_transcoder.h index 0310bb923..491205ef7 100644 --- a/src/lib/ab_transcoder.h +++ b/src/lib/ab_transcoder.h @@ -32,6 +32,7 @@ class FilmState; class Options; class Image; class Log; +class Subtitle; /** @class ABTranscoder * @brief A transcoder which uses one FilmState for the left half of the screen, and a different one @@ -54,7 +55,7 @@ public: void go (); private: - void process_video (boost::shared_ptr<Image>, int, int); + void process_video (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>, int); boost::shared_ptr<const FilmState> _fs_a; boost::shared_ptr<const FilmState> _fs_b; diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index 90826a99f..13d3efcbf 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -72,8 +72,9 @@ using namespace boost; * @param l Log to write to. */ DCPVideoFrame::DCPVideoFrame ( - shared_ptr<Image> yuv, Size out, int p, Scaler const * s, int f, float fps, string pp, int clut, int bw, Log* l) + shared_ptr<Image> yuv, shared_ptr<Subtitle> sub, Size out, int p, Scaler const * s, int f, float fps, string pp, int clut, int bw, Log* l) : _input (yuv) + , _subtitle (sub) , _out_size (out) , _padding (p) , _scaler (s) @@ -296,10 +297,6 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv) << Config::instance()->colour_lut_index () << " " << Config::instance()->j2k_bandwidth () << " "; - for (int i = 0; i < _input->components(); ++i) { - s << _input->line_size()[i] << " "; - } - socket.write ((uint8_t *) s.str().c_str(), s.str().length() + 1, 30); for (int i = 0; i < _input->components(); ++i) { diff --git a/src/lib/dcp_video_frame.h b/src/lib/dcp_video_frame.h index 72f885e45..fe2e27966 100644 --- a/src/lib/dcp_video_frame.h +++ b/src/lib/dcp_video_frame.h @@ -31,6 +31,7 @@ class ServerDescription; class Scaler; class Image; class Log; +class Subtitle; /** @class EncodedData * @brief Container for J2K-encoded data. @@ -105,7 +106,7 @@ public: class DCPVideoFrame { public: - DCPVideoFrame (boost::shared_ptr<Image>, Size, int, Scaler const *, int, float, std::string, int, int, Log *); + DCPVideoFrame (boost::shared_ptr<Image>, boost::shared_ptr<Subtitle>, Size, int, Scaler const *, int, float, std::string, int, int, Log *); virtual ~DCPVideoFrame (); boost::shared_ptr<EncodedData> encode_locally (); @@ -120,6 +121,7 @@ private: void write_encoded (boost::shared_ptr<const Options>, uint8_t *, int); boost::shared_ptr<Image> _input; ///< the input image + boost::shared_ptr<Subtitle> _subtitle; ///< any subtitle that should be on the image Size _out_size; ///< the required size of the output, in pixels int _padding; Scaler const * _scaler; ///< scaler to use diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index 15d74022c..e4b892ea4 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -228,7 +228,7 @@ Decoder::process_audio (uint8_t* data, int size) * @param frame to decode; caller manages memory. */ void -Decoder::process_video (AVFrame* frame) +Decoder::process_video (AVFrame* frame, shared_ptr<Subtitle> sub) { if (_minimal) { ++_video_frame; @@ -303,10 +303,8 @@ Decoder::process_video (AVFrame* frame) image->make_black (); } - overlay (image); - TIMING ("Decoder emits %1", _video_frame); - Video (image, _video_frame); + Video (image, _video_frame, sub); ++_video_frame; } } diff --git a/src/lib/decoder.h b/src/lib/decoder.h index 9a4c7695e..5cb44b8d9 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -37,6 +37,7 @@ class Options; class Image; class Log; class DelayLine; +class Subtitle; /** @class Decoder. * @brief Parent class for decoders of content. @@ -81,8 +82,9 @@ public: /** Emitted when a video frame is ready. * First parameter is the frame. * Second parameter is its index within the content. + * Third parameter is either 0 or a subtitle that should be on this frame. */ - sigc::signal<void, boost::shared_ptr<Image>, int> Video; + sigc::signal<void, boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle> > Video; /** Emitted when some audio data is ready. * First parameter is the interleaved sample data, format is given in the FilmState. @@ -98,9 +100,8 @@ protected: virtual int time_base_denominator () const = 0; virtual int sample_aspect_ratio_numerator () const = 0; virtual int sample_aspect_ratio_denominator () const = 0; - virtual void overlay (boost::shared_ptr<Image> image) const {} - void process_video (AVFrame *); + void process_video (AVFrame *, boost::shared_ptr<Subtitle>); void process_audio (uint8_t *, int); /** our FilmState */ diff --git a/src/lib/encoder.h b/src/lib/encoder.h index ea356cec4..02a2d7723 100644 --- a/src/lib/encoder.h +++ b/src/lib/encoder.h @@ -36,6 +36,7 @@ class FilmState; class Options; class Image; class Log; +class Subtitle; /** @class Encoder * @brief Parent class for classes which can encode video and audio frames. @@ -58,8 +59,9 @@ public: /** Called with a frame of video. * @param i Video frame image. * @param f Frame number within the film. + * @param s A subtitle that should be on this frame, or 0. */ - virtual void process_video (boost::shared_ptr<Image> i, int f) = 0; + virtual void process_video (boost::shared_ptr<Image> i, int f, boost::shared_ptr<Subtitle> s) = 0; /** Called with some audio data. * @param d Data. diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index ca35c6e81..c2ee9297b 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -48,6 +48,7 @@ extern "C" { #include "util.h" #include "log.h" #include "ffmpeg_decoder.h" +#include "subtitle.h" using namespace std; using namespace boost; @@ -65,7 +66,6 @@ FFmpegDecoder::FFmpegDecoder (boost::shared_ptr<const FilmState> s, boost::share , _audio_codec (0) , _subtitle_codec_context (0) , _subtitle_codec (0) - , _have_subtitle (false) { setup_general (); setup_video (); @@ -83,10 +83,6 @@ FFmpegDecoder::~FFmpegDecoder () avcodec_close (_video_codec_context); } - if (_have_subtitle) { - avsubtitle_free (&_subtitle); - } - if (_subtitle_codec_context) { avcodec_close (_subtitle_codec_context); } @@ -209,7 +205,12 @@ FFmpegDecoder::do_pass () int frame_finished; while (avcodec_decode_video2 (_video_codec_context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) { - process_video (_frame); + shared_ptr<Subtitle> s; + if (_subtitle && _subtitle->displayed_at (double (last_video_frame()) / rint (_fs->frames_per_second))) { + s = _subtitle; + } + + process_video (_frame, s); } if (_audio_stream >= 0 && _opt->decode_audio) { @@ -230,7 +231,12 @@ FFmpegDecoder::do_pass () int frame_finished; if (avcodec_decode_video2 (_video_codec_context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) { - process_video (_frame); + shared_ptr<Subtitle> s; + if (_subtitle && _subtitle->displayed_at (double (last_video_frame()) / rint (_fs->frames_per_second))) { + s = _subtitle; + } + + process_video (_frame, s); } } else if (_audio_stream >= 0 && _packet.stream_index == _audio_stream && _opt->decode_audio) { @@ -247,16 +253,13 @@ FFmpegDecoder::do_pass () process_audio (_frame->data[0], data_size); } - } else if (_subtitle_stream >= 0 && _packet.stream_index == _subtitle_stream && _fs->with_subtitles) { - - if (_have_subtitle) { - avsubtitle_free (&_subtitle); - _have_subtitle = false; - } + } else if (_subtitle_stream >= 0 && _packet.stream_index == _subtitle_stream) { int got_subtitle; - if (avcodec_decode_subtitle2 (_subtitle_codec_context, &_subtitle, &got_subtitle, &_packet) && got_subtitle) { - _have_subtitle = true; + AVSubtitle sub; + if (avcodec_decode_subtitle2 (_subtitle_codec_context, &sub, &got_subtitle, &_packet) && got_subtitle) { + _subtitle.reset (new Subtitle (sub)); + avsubtitle_free (&sub); } } @@ -358,105 +361,6 @@ FFmpegDecoder::sample_aspect_ratio_denominator () const return _video_codec_context->sample_aspect_ratio.den; } -void -FFmpegDecoder::overlay (shared_ptr<Image> image) const -{ - if (!_have_subtitle) { - return; - } - - /* subtitle PTS in seconds */ - float const packet_time = (_subtitle.pts / AV_TIME_BASE) + float (_subtitle.pts % AV_TIME_BASE) / 1e6; - /* hence start time for this sub */ - float const from = packet_time + (float (_subtitle.start_display_time) / 1e3); - float const to = packet_time + (float (_subtitle.end_display_time) / 1e3); - - float const video_frame_time = float (last_video_frame ()) / rint (_fs->frames_per_second); - - if (from > video_frame_time || video_frame_time < to) { - return; - } - - for (unsigned int i = 0; i < _subtitle.num_rects; ++i) { - AVSubtitleRect* rect = _subtitle.rects[i]; - if (rect->type != SUBTITLE_BITMAP) { - throw DecodeError ("non-bitmap subtitles not yet supported"); - } - - /* XXX: all this assumes YUV420 in image */ - - assert (rect->pict.data[0]); - - /* Start of the first line in the target image */ - uint8_t* frame_y_p = image->data()[0] + rect->y * image->line_size()[0]; - uint8_t* frame_u_p = image->data()[1] + (rect->y / 2) * image->line_size()[1]; - uint8_t* frame_v_p = image->data()[2] + (rect->y / 2) * image->line_size()[2]; - - int const hlim = min (rect->y + rect->h, image->size().height) - rect->y; - - /* 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]; - - for (int sub_y = 0; sub_y < hlim; ++sub_y) { - /* Pointers to the start of this line */ - uint8_t* sub_line_p = sub_p; - uint8_t* frame_line_y_p = frame_y_p + rect->x; - uint8_t* frame_line_u_p = frame_u_p + (rect->x / 2); - uint8_t* frame_line_v_p = frame_v_p + (rect->x / 2); - - /* U and V are subsampled */ - uint8_t next_u = 0; - uint8_t next_v = 0; - int subsample_step = 0; - - for (int sub_x = 0; sub_x < rect->w; ++sub_x) { - - /* RGB value for this subtitle pixel */ - uint32_t const val = palette[*sub_line_p++]; - - int const red = (val & 0xff); - int const green = (val & 0xff00) >> 8; - int const blue = (val & 0xff0000) >> 16; - float const alpha = ((val & 0xff000000) >> 24) / 255.0; - - /* Alpha-blend Y */ - int const cy = *frame_line_y_p; - *frame_line_y_p++ = int (cy * (1 - alpha)) + int (RGB_TO_Y_CCIR (red, green, blue) * alpha); - - /* Store up U and V */ - next_u |= ((RGB_TO_U_CCIR (red, green, blue, 0) & 0xf0) >> 4) << (4 * subsample_step); - next_v |= ((RGB_TO_V_CCIR (red, green, blue, 0) & 0xf0) >> 4) << (4 * subsample_step); - - if (subsample_step == 1 && (sub_y % 2) == 0) { - int const cu = *frame_line_u_p; - int const cv = *frame_line_v_p; - - *frame_line_u_p++ = - int (((cu & 0x0f) * (1 - alpha) + (next_u & 0x0f) * alpha)) | - int (((cu & 0xf0) * (1 - alpha) + (next_u & 0xf0) * alpha)); - - *frame_line_v_p++ = - int (((cv & 0x0f) * (1 - alpha) + (next_v & 0x0f) * alpha)) | - int (((cv & 0xf0) * (1 - alpha) + (next_v & 0xf0) * alpha)); - - next_u = next_v = 0; - } - - subsample_step = (subsample_step + 1) % 2; - } - - sub_p += rect->pict.linesize[0]; - frame_y_p += image->line_size()[0]; - if ((sub_y % 2) == 0) { - frame_u_p += image->line_size()[1]; - frame_v_p += image->line_size()[2]; - } - } - } -} - bool FFmpegDecoder::has_subtitles () const { diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 59ec7573d..e92b326b8 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -44,6 +44,7 @@ class FilmState; class Options; class Image; class Log; +class Subtitle; /** @class FFmpegDecoder * @brief A decoder using FFmpeg to decode content. @@ -73,7 +74,6 @@ private: int time_base_denominator () const; int sample_aspect_ratio_numerator () const; int sample_aspect_ratio_denominator () const; - void overlay (boost::shared_ptr<Image> image) const; void setup_general (); void setup_video (); @@ -96,6 +96,5 @@ private: AVCodec* _subtitle_codec; ///< may be 0 if there is no subtitle AVPacket _packet; - AVSubtitle _subtitle; - bool _have_subtitle; + boost::shared_ptr<Subtitle> _subtitle; }; diff --git a/src/lib/image.cc b/src/lib/image.cc index 2df7636af..8fd43093d 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -57,6 +57,7 @@ Image::lines (int n) const } break; case PIX_FMT_RGB24: + case PIX_FMT_RGBA: return size().height; default: assert (false); @@ -73,6 +74,7 @@ Image::components () const case PIX_FMT_YUV420P: return 3; case PIX_FMT_RGB24: + case PIX_FMT_RGBA: return 1; default: assert (false); @@ -81,6 +83,31 @@ Image::components () const return 0; } +shared_ptr<Image> +Image::scale (Size out_size, Scaler const * scaler) const +{ + assert (scaler); + + shared_ptr<SimpleImage> scaled (new SimpleImage (pixel_format(), out_size)); + + struct SwsContext* scale_context = sws_getContext ( + size().width, size().height, pixel_format(), + out_size.width, out_size.height, pixel_format(), + scaler->ffmpeg_id (), 0, 0, 0 + ); + + sws_scale ( + scale_context, + data(), line_size(), + 0, size().height, + scaled->data (), scaled->line_size () + ); + + sws_freeContext (scale_context); + + return scaled; +} + /** Scale this image to a given size and convert it to RGB. * @param out_size Output image size in pixels. * @param scaler Scaler to use. @@ -192,10 +219,25 @@ SimpleImage::SimpleImage (PixelFormat p, Size s) { _data = (uint8_t **) av_malloc (components() * sizeof (uint8_t *)); _line_size = (int *) av_malloc (components() * sizeof (int)); + + switch (p) { + case PIX_FMT_RGB24: + _line_size[0] = s.width * 3; + break; + case PIX_FMT_RGBA: + _line_size[0] = s.width * 4; + break; + case PIX_FMT_YUV420P: + _line_size[0] = s.width; + _line_size[1] = s.width / 2; + _line_size[2] = s.width / 2; + break; + default: + assert (false); + } for (int i = 0; i < components(); ++i) { - _data[i] = 0; - _line_size[i] = 0; + _data[i] = (uint8_t *) av_malloc (_line_size[i] * lines (i)); } } @@ -210,17 +252,6 @@ SimpleImage::~SimpleImage () av_free (_line_size); } -/** Set the size in bytes of each horizontal line of a given component. - * @param i Component index. - * @param s Size of line in bytes. - */ -void -SimpleImage::set_line_size (int i, int s) -{ - _line_size[i] = s; - _data[i] = (uint8_t *) av_malloc (s * lines (i)); -} - uint8_t ** SimpleImage::data () const { diff --git a/src/lib/image.h b/src/lib/image.h index 0161d2b01..d10bcae9e 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -66,6 +66,7 @@ public: int components () const; int lines (int) const; boost::shared_ptr<RGBFrameImage> scale_and_convert_to_rgb (Size, int, Scaler const *) const; + boost::shared_ptr<Image> scale (Size, Scaler const *) const; boost::shared_ptr<PostProcessImage> post_process (std::string) const; void make_black (); @@ -108,8 +109,6 @@ public: int * line_size () const; Size size () const; - void set_line_size (int, int); - private: Size _size; ///< size in pixels uint8_t** _data; ///< array of pointers to components diff --git a/src/lib/imagemagick_decoder.cc b/src/lib/imagemagick_decoder.cc index 7cee01ec5..df20479c9 100644 --- a/src/lib/imagemagick_decoder.cc +++ b/src/lib/imagemagick_decoder.cc @@ -1,3 +1,22 @@ +/* + 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. + +*/ + #include <iostream> #include <Magick++/Image.h> #include "imagemagick_decoder.h" @@ -5,6 +24,7 @@ #include "image.h" using namespace std; +using namespace boost; ImageMagickDecoder::ImageMagickDecoder ( boost::shared_ptr<const FilmState> s, boost::shared_ptr<const Options> o, Job* j, Log* l, bool minimal, bool ignore_length) @@ -41,7 +61,7 @@ ImageMagickDecoder::do_pass () } - process_video (image.frame ()); + process_video (image.frame (), shared_ptr<Subtitle> ()); _done = true; return false; diff --git a/src/lib/imagemagick_decoder.h b/src/lib/imagemagick_decoder.h index 05dc7f113..809f3aecd 100644 --- a/src/lib/imagemagick_decoder.h +++ b/src/lib/imagemagick_decoder.h @@ -1,3 +1,22 @@ +/* + 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. + +*/ + #include "decoder.h" namespace Magick { diff --git a/src/lib/j2k_still_encoder.cc b/src/lib/j2k_still_encoder.cc index d218d08fe..a241dd6e3 100644 --- a/src/lib/j2k_still_encoder.cc +++ b/src/lib/j2k_still_encoder.cc @@ -48,11 +48,11 @@ J2KStillEncoder::J2KStillEncoder (shared_ptr<const FilmState> s, shared_ptr<cons } void -J2KStillEncoder::process_video (shared_ptr<Image> yuv, int frame) +J2KStillEncoder::process_video (shared_ptr<Image> yuv, int frame, shared_ptr<Subtitle> sub) { pair<string, string> const s = Filter::ffmpeg_strings (_fs->filters); DCPVideoFrame* f = new DCPVideoFrame ( - yuv, _opt->out_size, _opt->padding, _fs->scaler, 0, _fs->frames_per_second, s.second, + yuv, sub, _opt->out_size, _opt->padding, _fs->scaler, 0, _fs->frames_per_second, s.second, Config::instance()->colour_lut_index(), Config::instance()->j2k_bandwidth(), _log ); diff --git a/src/lib/j2k_still_encoder.h b/src/lib/j2k_still_encoder.h index 7a03e1195..c48b9e69c 100644 --- a/src/lib/j2k_still_encoder.h +++ b/src/lib/j2k_still_encoder.h @@ -37,7 +37,7 @@ public: J2KStillEncoder (boost::shared_ptr<const FilmState>, boost::shared_ptr<const Options>, Log *); void process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format) {} - void process_video (boost::shared_ptr<Image>, int); + void process_video (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>); void process_audio (uint8_t *, int) {} void process_end () {} }; diff --git a/src/lib/j2k_wav_encoder.cc b/src/lib/j2k_wav_encoder.cc index a1f70a08a..7bcac483b 100644 --- a/src/lib/j2k_wav_encoder.cc +++ b/src/lib/j2k_wav_encoder.cc @@ -105,7 +105,7 @@ J2KWAVEncoder::close_sound_files () } void -J2KWAVEncoder::process_video (shared_ptr<Image> yuv, int frame) +J2KWAVEncoder::process_video (shared_ptr<Image> yuv, int frame, shared_ptr<Subtitle> sub) { boost::mutex::scoped_lock lock (_worker_mutex); @@ -126,7 +126,7 @@ J2KWAVEncoder::process_video (shared_ptr<Image> yuv, int frame) TIMING ("adding to queue of %1", _queue.size ()); _queue.push_back (boost::shared_ptr<DCPVideoFrame> ( new DCPVideoFrame ( - yuv, _opt->out_size, _opt->padding, _fs->scaler, frame, _fs->frames_per_second, s.second, + yuv, sub, _opt->out_size, _opt->padding, _fs->scaler, frame, _fs->frames_per_second, s.second, Config::instance()->colour_lut_index (), Config::instance()->j2k_bandwidth (), _log ) diff --git a/src/lib/j2k_wav_encoder.h b/src/lib/j2k_wav_encoder.h index e11358c2c..87068ad3d 100644 --- a/src/lib/j2k_wav_encoder.h +++ b/src/lib/j2k_wav_encoder.h @@ -38,6 +38,7 @@ class ServerDescription; class DCPVideoFrame; class Image; class Log; +class Subtitle; /** @class J2KWAVEncoder * @brief An encoder which writes JPEG2000 and WAV files. @@ -49,7 +50,7 @@ public: ~J2KWAVEncoder (); void process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format); - void process_video (boost::shared_ptr<Image>, int); + void process_video (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>); void process_audio (uint8_t *, int); void process_end (); diff --git a/src/lib/job_manager.cc b/src/lib/job_manager.cc index 562c887de..2db91a177 100644 --- a/src/lib/job_manager.cc +++ b/src/lib/job_manager.cc @@ -95,6 +95,11 @@ JobManager::scheduler () { boost::mutex::scoped_lock lm (_mutex); for (list<shared_ptr<Job> >::iterator i = _jobs.begin(); i != _jobs.end(); ++i) { + if ((*i)->running ()) { + /* Something is already happening */ + break; + } + if ((*i)->is_new()) { shared_ptr<Job> r = (*i)->required (); if (!r || r->finished_ok ()) { diff --git a/src/lib/options.h b/src/lib/options.h index 39068c24f..2fc5f77ff 100644 --- a/src/lib/options.h +++ b/src/lib/options.h @@ -56,11 +56,15 @@ public: * @param t true to return a temporary file path, otherwise a permanent one. * @return The path to write this video frame to. */ - std::string frame_out_path (int f, bool t) const { + std::string frame_out_path (int f, bool t, std::string e = "") const { + if (e.empty ()) { + e = _frame_out_extension; + } + std::stringstream s; s << _frame_out_path << "/"; s.width (8); - s << std::setfill('0') << f << _frame_out_extension; + s << std::setfill('0') << f << e; if (t) { s << ".tmp"; diff --git a/src/lib/server.cc b/src/lib/server.cc index 28236e3e0..76989d078 100644 --- a/src/lib/server.cc +++ b/src/lib/server.cc @@ -115,16 +115,14 @@ Server::process (shared_ptr<Socket> socket) shared_ptr<SimpleImage> image (new SimpleImage (pixel_format, in_size)); for (int i = 0; i < image->components(); ++i) { - int line_size; - s >> line_size; - image->set_line_size (i, line_size); - } - - for (int i = 0; i < image->components(); ++i) { socket->read_definite_and_consume (image->data()[i], image->line_size()[i] * image->lines(i), 30); } + + /* XXX: subtitle */ + DCPVideoFrame dcp_video_frame ( + image, shared_ptr<Subtitle> (), out_size, padding, scaler, frame, frames_per_second, post_process, colour_lut_index, j2k_bandwidth, _log + ); - DCPVideoFrame dcp_video_frame (image, out_size, padding, 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); diff --git a/src/lib/tiff_decoder.cc b/src/lib/tiff_decoder.cc index 101e0c047..116c65f7b 100644 --- a/src/lib/tiff_decoder.cc +++ b/src/lib/tiff_decoder.cc @@ -179,7 +179,7 @@ TIFFDecoder::do_pass () _TIFFfree (raster); TIFFClose (t); - process_video (image.frame ()); + process_video (image.frame (), shared_ptr<Subtitle> ()); ++_iter; return false; diff --git a/src/lib/tiff_encoder.cc b/src/lib/tiff_encoder.cc index 19e34741d..9aa7b68c3 100644 --- a/src/lib/tiff_encoder.cc +++ b/src/lib/tiff_encoder.cc @@ -26,6 +26,7 @@ #include <sstream> #include <iomanip> #include <iostream> +#include <fstream> #include <boost/filesystem.hpp> #include <tiffio.h> #include "tiff_encoder.h" @@ -34,6 +35,7 @@ #include "options.h" #include "exceptions.h" #include "image.h" +#include "subtitle.h" using namespace std; using namespace boost; @@ -49,7 +51,7 @@ TIFFEncoder::TIFFEncoder (shared_ptr<const FilmState> s, shared_ptr<const Option } void -TIFFEncoder::process_video (shared_ptr<Image> image, int frame) +TIFFEncoder::process_video (shared_ptr<Image> image, int frame, shared_ptr<Subtitle> sub) { shared_ptr<Image> scaled = image->scale_and_convert_to_rgb (_opt->out_size, _opt->padding, _fs->scaler); string tmp_file = _opt->frame_out_path (frame, true); @@ -72,6 +74,56 @@ TIFFEncoder::process_video (shared_ptr<Image> image, int frame) TIFFClose (output); - boost::filesystem::rename (tmp_file, _opt->frame_out_path (frame, false)); + filesystem::rename (tmp_file, _opt->frame_out_path (frame, false)); + + if (sub) { + float const x_scale = float (_opt->out_size.width) / _fs->size.width; + float const y_scale = float (_opt->out_size.height) / _fs->size.height; + + 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 << ".tiff"; + + string tmp_sub_file = _opt->frame_out_path (frame, true, ext.str ()); + output = TIFFOpen (tmp_sub_file.c_str(), "w"); + if (output == 0) { + throw CreateFileError (tmp_file); + } + + 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); + + TIFFSetField (output, TIFFTAG_IMAGEWIDTH, scaled->size().width); + TIFFSetField (output, TIFFTAG_IMAGELENGTH, scaled->size().height); + TIFFSetField (output, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + TIFFSetField (output, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField (output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + TIFFSetField (output, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField (output, TIFFTAG_SAMPLESPERPIXEL, 4); + + if (TIFFWriteEncodedStrip (output, 0, scaled->data()[0], scaled->size().width * scaled->size().height * 4) == 0) { + throw WriteFileError (tmp_file, 0); + } + + TIFFClose (output); + 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"; + + metadata.close (); + filesystem::rename (tmp_metadata_file, _opt->frame_out_path (frame, false, ".sub")); + } + + } + frame_done (frame); } diff --git a/src/lib/tiff_encoder.h b/src/lib/tiff_encoder.h index ef1ce25d2..1c9f33f4a 100644 --- a/src/lib/tiff_encoder.h +++ b/src/lib/tiff_encoder.h @@ -37,7 +37,7 @@ public: TIFFEncoder (boost::shared_ptr<const FilmState> s, boost::shared_ptr<const Options> o, Log* l); void process_begin (int64_t audio_channel_layout, AVSampleFormat audio_sample_format) {} - void process_video (boost::shared_ptr<Image>, int); + void process_video (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>); void process_audio (uint8_t *, int) {} void process_end () {} }; diff --git a/src/lib/wscript b/src/lib/wscript index c809226ce..67292047c 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -42,6 +42,7 @@ def build(bld): screen.cc server.cc sound_processor.cc + subtitle.cc thumbs_job.cc tiff_decoder.cc tiff_encoder.cc |
