summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-07-10 15:04:57 +0100
committerCarl Hetherington <cth@carlh.net>2013-07-10 15:04:57 +0100
commit611f2241c6732c2c38d87e129e51cf9d8d7a08b8 (patch)
tree0c00420654d322856aecb5c6bbaeb483b3db7211 /src/lib
parentade36b7e120838840d0f645763b8e0814eaf9ee4 (diff)
Basic return of subtitles.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ffmpeg_decoder.cc48
-rw-r--r--src/lib/ffmpeg_decoder.h4
-rw-r--r--src/lib/player.cc44
-rw-r--r--src/lib/player.h5
-rw-r--r--src/lib/subtitle.h1
-rw-r--r--src/lib/subtitle_decoder.cc41
-rw-r--r--src/lib/subtitle_decoder.h35
-rw-r--r--src/lib/video_decoder.cc18
-rw-r--r--src/lib/wscript1
9 files changed, 141 insertions, 56 deletions
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index d8ee278b3..3714c1542 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -61,6 +61,7 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr<const Film> f, shared_ptr<const FFmpegC
: Decoder (f)
, VideoDecoder (f)
, AudioDecoder (f)
+ , SubtitleDecoder (f)
, FFmpeg (c)
, _subtitle_codec_context (0)
, _subtitle_codec (0)
@@ -142,27 +143,7 @@ FFmpegDecoder::pass ()
} else if (_ffmpeg_content->audio_stream() && _packet.stream_index == _ffmpeg_content->audio_stream()->id && _decode_audio) {
decode_audio_packet ();
} else if (_ffmpeg_content->subtitle_stream() && _packet.stream_index == _ffmpeg_content->subtitle_stream()->id) {
-#if 0
-
- int got_subtitle;
- AVSubtitle sub;
- if (avcodec_decode_subtitle2 (_subtitle_codec_context, &sub, &got_subtitle, &_packet) && got_subtitle) {
- /* Sometimes we get an empty AVSubtitle, which is used by some codecs to
- indicate that the previous subtitle should stop.
- */
- if (sub.num_rects > 0) {
- shared_ptr<TimedSubtitle> ts;
- try {
- subtitle (shared_ptr<TimedSubtitle> (new TimedSubtitle (sub)));
- } catch (...) {
- /* some problem with the subtitle; we probably didn't understand it */
- }
- } else {
- subtitle (shared_ptr<TimedSubtitle> ());
- }
- avsubtitle_free (&sub);
- }
-#endif
+ decode_subtitle_packet ();
}
av_free_packet (&_packet);
@@ -489,3 +470,28 @@ FFmpegDecoder::done () const
return vd && ad;
}
+void
+FFmpegDecoder::decode_subtitle_packet ()
+{
+ int got_subtitle;
+ AVSubtitle sub;
+ if (avcodec_decode_subtitle2 (_subtitle_codec_context, &sub, &got_subtitle, &_packet) < 0 || !got_subtitle) {
+ return;
+ }
+
+ /* Sometimes we get an empty AVSubtitle, which is used by some codecs to
+ indicate that the previous subtitle should stop.
+ */
+ if (sub.num_rects > 0) {
+ shared_ptr<TimedSubtitle> ts;
+ try {
+ subtitle (shared_ptr<TimedSubtitle> (new TimedSubtitle (sub)));
+ } catch (...) {
+ /* some problem with the subtitle; we probably didn't understand it */
+ }
+ } else {
+ subtitle (shared_ptr<TimedSubtitle> ());
+ }
+
+ avsubtitle_free (&sub);
+}
diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h
index eebf75445..8819954db 100644
--- a/src/lib/ffmpeg_decoder.h
+++ b/src/lib/ffmpeg_decoder.h
@@ -35,6 +35,7 @@ extern "C" {
#include "decoder.h"
#include "video_decoder.h"
#include "audio_decoder.h"
+#include "subtitle_decoder.h"
#include "ffmpeg.h"
class Film;
@@ -43,7 +44,7 @@ class ffmpeg_pts_offset_test;
/** @class FFmpegDecoder
* @brief A decoder using FFmpeg to decode content.
*/
-class FFmpegDecoder : public VideoDecoder, public AudioDecoder, public FFmpeg
+class FFmpegDecoder : public VideoDecoder, public AudioDecoder, public SubtitleDecoder, public FFmpeg
{
public:
FFmpegDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const FFmpegContent>, bool video, bool audio);
@@ -69,6 +70,7 @@ private:
bool decode_video_packet ();
void decode_audio_packet ();
+ void decode_subtitle_packet ();
void maybe_add_subtitle ();
boost::shared_ptr<AudioBuffers> deinterleave_audio (uint8_t** data, int size);
diff --git a/src/lib/player.cc b/src/lib/player.cc
index 6b7dc2722..2bafbdcd5 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -31,6 +31,7 @@
#include "image.h"
#include "ratio.h"
#include "resampler.h"
+#include "subtitle.h"
using std::list;
using std::cout;
@@ -215,48 +216,46 @@ Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image
return;
}
- image = image->crop (content->crop(), true);
+ shared_ptr<Image> work_image = image->crop (content->crop(), true);
libdcp::Size const image_size = content->ratio()->size (_video_container_size);
- image = image->scale_and_convert_to_rgb (image_size, _film->scaler(), true);
+ work_image = work_image->scale_and_convert_to_rgb (image_size, _film->scaler(), true);
-#if 0
- if (film->with_subtitles ()) {
+ Time time = content->start() + (frame * frc.factor() * TIME_HZ / _film->dcp_video_frame_rate());
+
+ if (_film->with_subtitles ()) {
shared_ptr<Subtitle> sub;
- if (_timed_subtitle && _timed_subtitle->displayed_at (t)) {
- sub = _timed_subtitle->subtitle ();
+ if (_subtitle && _subtitle->displayed_at (time - _subtitle_offset)) {
+ sub = _subtitle->subtitle ();
}
if (sub) {
dcpomatic::Rect const tx = subtitle_transformed_area (
float (image_size.width) / content->video_size().width,
float (image_size.height) / content->video_size().height,
- sub->area(), film->subtitle_offset(), film->subtitle_scale()
+ sub->area(), _film->subtitle_offset(), _film->subtitle_scale()
);
- shared_ptr<Image> im = sub->image()->scale (tx.size(), film->scaler(), true);
- image->alpha_blend (im, tx.position());
+ shared_ptr<Image> im = sub->image()->scale (tx.size(), _film->scaler(), true);
+ work_image->alpha_blend (im, tx.position());
}
}
-#endif
if (image_size != _video_container_size) {
assert (image_size.width <= _video_container_size.width);
assert (image_size.height <= _video_container_size.height);
shared_ptr<Image> im (new SimpleImage (PIX_FMT_RGB24, _video_container_size, true));
im->make_black ();
- im->copy (image, Position ((_video_container_size.width - image_size.width) / 2, (_video_container_size.height - image_size.height) / 2));
- image = im;
+ im->copy (work_image, Position ((_video_container_size.width - image_size.width) / 2, (_video_container_size.height - image_size.height) / 2));
+ work_image = im;
}
- Time time = content->start() + (frame * frc.factor() * TIME_HZ / _film->dcp_video_frame_rate());
-
- Video (image, same, time);
+ Video (work_image, same, time);
time += TIME_HZ / _film->dcp_video_frame_rate();
if (frc.repeat) {
- Video (image, true, time);
+ Video (work_image, true, time);
time += TIME_HZ / _film->dcp_video_frame_rate();
}
@@ -390,6 +389,7 @@ Player::setup_pieces ()
fd->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3));
fd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
+ fd->Subtitle.connect (bind (&Player::process_subtitle, this, piece, _1));
piece->decoder = fd;
}
@@ -514,3 +514,15 @@ Player::film_changed (Film::Property p)
Changed ();
}
}
+
+void
+Player::process_subtitle (weak_ptr<Piece> weak_piece, shared_ptr<TimedSubtitle> sub)
+{
+ shared_ptr<Piece> piece = weak_piece.lock ();
+ if (!piece) {
+ return;
+ }
+
+ _subtitle = sub;
+ _subtitle_offset = piece->content->start ();
+}
diff --git a/src/lib/player.h b/src/lib/player.h
index 15fa4dbd6..f96d5ac69 100644
--- a/src/lib/player.h
+++ b/src/lib/player.h
@@ -35,6 +35,7 @@ class AudioContent;
class Piece;
class Image;
class Resampler;
+class TimedSubtitle;
/** @class Player
* @brief A class which can `play' a Playlist; emitting its audio and video.
@@ -77,6 +78,7 @@ private:
void process_video (boost::weak_ptr<Piece>, boost::shared_ptr<const Image>, bool, VideoContent::Frame);
void process_audio (boost::weak_ptr<Piece>, boost::shared_ptr<const AudioBuffers>, AudioContent::Frame);
+ void process_subtitle (boost::weak_ptr<Piece>, boost::shared_ptr<TimedSubtitle>);
void setup_pieces ();
void playlist_changed ();
void content_changed (boost::weak_ptr<Content>, int);
@@ -107,6 +109,9 @@ private:
libdcp::Size _video_container_size;
boost::shared_ptr<Image> _black_frame;
std::map<boost::shared_ptr<AudioContent>, boost::shared_ptr<Resampler> > _resamplers;
+
+ boost::shared_ptr<TimedSubtitle> _subtitle;
+ Time _subtitle_offset;
};
#endif
diff --git a/src/lib/subtitle.h b/src/lib/subtitle.h
index 1020397cc..47735c453 100644
--- a/src/lib/subtitle.h
+++ b/src/lib/subtitle.h
@@ -60,6 +60,7 @@ subtitle_transformed_area (
);
/** A Subtitle class with details of the time over which it should be shown */
+/** XXX: merge with Subtitle? */
class TimedSubtitle
{
public:
diff --git a/src/lib/subtitle_decoder.cc b/src/lib/subtitle_decoder.cc
new file mode 100644
index 000000000..0ffe5e501
--- /dev/null
+++ b/src/lib/subtitle_decoder.cc
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 2013 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 <boost/shared_ptr.hpp>
+#include "subtitle_decoder.h"
+#include "subtitle.h"
+
+using boost::shared_ptr;
+
+SubtitleDecoder::SubtitleDecoder (shared_ptr<const Film> f)
+ : Decoder (f)
+{
+
+}
+
+
+/** Called by subclasses when a subtitle is ready.
+ * s may be 0 to say that there is no current subtitle.
+ * @param s New current subtitle, or 0.
+ */
+void
+SubtitleDecoder::subtitle (shared_ptr<TimedSubtitle> s)
+{
+ Subtitle (s);
+}
diff --git a/src/lib/subtitle_decoder.h b/src/lib/subtitle_decoder.h
new file mode 100644
index 000000000..0c299f61f
--- /dev/null
+++ b/src/lib/subtitle_decoder.h
@@ -0,0 +1,35 @@
+/*
+ Copyright (C) 2013 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 <boost/signals2.hpp>
+#include "decoder.h"
+
+class Film;
+class TimedSubtitle;
+
+class SubtitleDecoder : public virtual Decoder
+{
+public:
+ SubtitleDecoder (boost::shared_ptr<const Film>);
+
+ boost::signals2::signal<void (boost::shared_ptr<TimedSubtitle>)> Subtitle;
+
+protected:
+ void subtitle (boost::shared_ptr<TimedSubtitle>);
+};
diff --git a/src/lib/video_decoder.cc b/src/lib/video_decoder.cc
index f61e63d4d..0616cd437 100644
--- a/src/lib/video_decoder.cc
+++ b/src/lib/video_decoder.cc
@@ -42,21 +42,3 @@ VideoDecoder::video (shared_ptr<const Image> image, bool same, VideoContent::Fra
_video_position = frame + 1;
}
-#if 0
-
-/** Called by subclasses when a subtitle is ready.
- * s may be 0 to say that there is no current subtitle.
- * @param s New current subtitle, or 0.
- */
-void
-VideoDecoder::subtitle (shared_ptr<TimedSubtitle> s)
-{
- _timed_subtitle = s;
-
- if (_timed_subtitle) {
- Position const p = _timed_subtitle->subtitle()->position ();
- _timed_subtitle->subtitle()->set_position (Position (p.x - _video_content->crop().left, p.y - _video_content->crop().top));
- }
-}
-#endif
-
diff --git a/src/lib/wscript b/src/lib/wscript
index 2f8653984..34d44ec5b 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -44,6 +44,7 @@ sources = """
sndfile_content.cc
sndfile_decoder.cc
sound_processor.cc
+ subtitle_decoder.cc
subtitle.cc
timer.cc
transcode_job.cc