summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-10-22 16:48:45 +0100
committerCarl Hetherington <cth@carlh.net>2013-10-22 16:48:45 +0100
commit0e2c7f060529d93035e89b06d4aa687830a5e0ad (patch)
tree4a4e95373532ed6557d0fabd7c4fd989d9dbc87b /src
parentdb67e0d5c855127862bb8dd579d41e4a11f84798 (diff)
Hacks.
Diffstat (limited to 'src')
-rw-r--r--src/lib/audio_decoder.cc12
-rw-r--r--src/lib/audio_decoder.h5
-rw-r--r--src/lib/ffmpeg_decoder.cc2
-rw-r--r--src/lib/player.cc103
-rw-r--r--src/lib/player.h21
-rw-r--r--src/lib/sndfile_decoder.cc2
-rw-r--r--src/lib/util.cc2
-rw-r--r--src/wx/film_viewer.cc26
-rw-r--r--src/wx/film_viewer.h2
9 files changed, 121 insertions, 54 deletions
diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc
index 1f5868583..c9fbddda1 100644
--- a/src/lib/audio_decoder.cc
+++ b/src/lib/audio_decoder.cc
@@ -32,8 +32,9 @@ using std::cout;
using boost::optional;
using boost::shared_ptr;
-AudioDecoder::AudioDecoder (shared_ptr<const Film> film)
+AudioDecoder::AudioDecoder (shared_ptr<const Film> film, shared_ptr<const AudioContent> content)
: Decoder (film)
+ , _audio_content (content)
, _audio_position (0)
{
@@ -45,3 +46,12 @@ AudioDecoder::audio (shared_ptr<const AudioBuffers> data, AudioContent::Frame fr
Audio (data, frame);
_audio_position = frame + data->frames ();
}
+
+/** This is a bit odd, but necessary when we have (e.g.) FFmpegDecoders with no audio.
+ * The player needs to know that there is no audio otherwise it will keep prompting the XXX
+ */
+bool
+AudioDecoder::has_audio () const
+{
+ return _audio_content->channels () > 0;
+}
diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h
index 2ad53da8b..ab6c4b8a9 100644
--- a/src/lib/audio_decoder.h
+++ b/src/lib/audio_decoder.h
@@ -36,7 +36,9 @@ class AudioBuffers;
class AudioDecoder : public virtual Decoder
{
public:
- AudioDecoder (boost::shared_ptr<const Film>);
+ AudioDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const AudioContent>);
+
+ bool has_audio () const;
/** Emitted when some audio data is ready */
boost::signals2::signal<void (boost::shared_ptr<const AudioBuffers>, AudioContent::Frame)> Audio;
@@ -44,6 +46,7 @@ public:
protected:
void audio (boost::shared_ptr<const AudioBuffers>, AudioContent::Frame);
+ boost::shared_ptr<const AudioContent> _audio_content;
AudioContent::Frame _audio_position;
};
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index 8da607e7e..45c242237 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -61,7 +61,7 @@ using libdcp::Size;
FFmpegDecoder::FFmpegDecoder (shared_ptr<const Film> f, shared_ptr<const FFmpegContent> c, bool video, bool audio)
: Decoder (f)
, VideoDecoder (f, c)
- , AudioDecoder (f)
+ , AudioDecoder (f, c)
, SubtitleDecoder (f)
, FFmpeg (c)
, _subtitle_codec_context (0)
diff --git a/src/lib/player.cc b/src/lib/player.cc
index 8f6a8bb35..73c873c59 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -55,6 +55,8 @@ public:
: content (c)
, video_position (c->position ())
, audio_position (c->position ())
+ , repeat_to_do (0)
+ , repeat_done (0)
{}
Piece (shared_ptr<Content> c, shared_ptr<Decoder> d)
@@ -63,11 +65,50 @@ public:
, video_position (c->position ())
, audio_position (c->position ())
{}
+
+ void set_repeat (IncomingVideo video, int num)
+ {
+ cout << "Set repeat " << num << "\n";
+ repeat_video = video;
+ repeat_to_do = num;
+ repeat_done = 0;
+ }
+
+ void reset_repeat ()
+ {
+ repeat_video.image.reset ();
+ repeat_to_do = 0;
+ repeat_done = 0;
+ }
+
+ bool repeating () const
+ {
+ return repeat_done != repeat_to_do;
+ }
+
+ void repeat (Player* player)
+ {
+ cout << "repeating; " << repeat_done << "\n";
+ player->process_video (
+ repeat_video.weak_piece,
+ repeat_video.image,
+ repeat_video.eyes,
+ repeat_video.same,
+ repeat_video.frame,
+ (repeat_done + 1) * (TIME_HZ / player->_film->video_frame_rate ())
+ );
+
+ ++repeat_done;
+ }
shared_ptr<Content> content;
shared_ptr<Decoder> decoder;
Time video_position;
Time audio_position;
+
+ IncomingVideo repeat_video;
+ int repeat_to_do;
+ int repeat_done;
};
Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
@@ -116,6 +157,7 @@ Player::pass ()
for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
if ((*i)->decoder->done ()) {
+ cout << "Scan: done.\n";
continue;
}
@@ -137,20 +179,31 @@ Player::pass ()
}
if (!earliest) {
+ cout << "No earliest: out.\n";
flush ();
return true;
}
+ cout << "Earliest: " << earliest_t << "\n";
+
switch (type) {
case VIDEO:
+ cout << "VIDEO.\n";
if (earliest_t > _video_position) {
emit_black ();
} else {
- earliest->decoder->pass ();
+ if (earliest->repeating ()) {
+ cout << "-repeating.\n";
+ earliest->repeat (this);
+ } else {
+ cout << "-passing.\n";
+ earliest->decoder->pass ();
+ }
}
break;
case AUDIO:
+ cout << "SOUND.\n";
if (earliest_t > _audio_position) {
emit_silence (_film->time_to_audio_frames (earliest_t - _audio_position));
} else {
@@ -188,14 +241,16 @@ Player::pass ()
}
void
-Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image, Eyes eyes, bool same, VideoContent::Frame frame)
+Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image, Eyes eyes, bool same, VideoContent::Frame frame, Time extra)
{
+ cout << "PLAYER RECEIVES A VIDEO FRAME, extra " << extra << "\n";
+
/* Keep a note of what came in so that we can repeat it if required */
- _last_process_video.weak_piece = weak_piece;
- _last_process_video.image = image;
- _last_process_video.eyes = eyes;
- _last_process_video.same = same;
- _last_process_video.frame = frame;
+ _last_incoming_video.weak_piece = weak_piece;
+ _last_incoming_video.image = image;
+ _last_incoming_video.eyes = eyes;
+ _last_incoming_video.same = same;
+ _last_incoming_video.frame = frame;
shared_ptr<Piece> piece = weak_piece.lock ();
if (!piece) {
@@ -225,7 +280,7 @@ Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image
work_image = work_image->scale (image_size, _film->scaler(), PIX_FMT_RGB24, true);
- Time time = content->position() + relative_time - content->trim_start ();
+ Time time = content->position() + relative_time + extra - content->trim_start ();
if (_film->with_subtitles () && _out_subtitle.image && time >= _out_subtitle.from && time <= _out_subtitle.to) {
work_image->alpha_blend (_out_subtitle.image, _out_subtitle.position);
@@ -245,11 +300,16 @@ Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image
#endif
Video (work_image, eyes, content->colour_conversion(), same, time);
- time += TIME_HZ / _film->video_frame_rate();
+ time += TIME_HZ / _film->video_frame_rate();
_last_emit_was_black = false;
-
_video_position = piece->video_position = time;
+
+ cout << "frc.repeat=" << frc.repeat << "; vp now " << _video_position << "\n";
+
+ if (frc.repeat > 1 && !piece->repeating ()) {
+ piece->set_repeat (_last_incoming_video, frc.repeat - 1);
+ }
}
void
@@ -370,10 +430,12 @@ Player::seek (Time t, bool accurate)
*/
VideoContent::Frame f = (s + vc->trim_start ()) * _film->video_frame_rate() / (frc.factor() * TIME_HZ);
dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (f, accurate);
+
+ (*i)->reset_repeat ();
}
_video_position = _audio_position = t;
-
+
/* XXX: don't seek audio because we don't need to... */
}
@@ -397,7 +459,7 @@ Player::setup_pieces ()
if (fc) {
shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio));
- fd->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4));
+ fd->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4, 0));
fd->Audio.connect (bind (&Player::process_audio, this, piece, _1, _2));
fd->Subtitle.connect (bind (&Player::process_subtitle, this, piece, _1, _2, _3, _4));
@@ -418,7 +480,7 @@ Player::setup_pieces ()
if (!id) {
id.reset (new StillImageDecoder (_film, ic));
- id->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4));
+ id->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4, 0));
}
piece->decoder = id;
@@ -430,7 +492,7 @@ Player::setup_pieces ()
if (!md) {
md.reset (new MovingImageDecoder (_film, mc));
- md->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4));
+ md->Video.connect (bind (&Player::process_video, this, piece, _1, _2, _3, _4, 0));
}
piece->decoder = md;
@@ -617,16 +679,17 @@ Player::update_subtitle ()
bool
Player::repeat_last_video ()
{
- if (!_last_process_video.image) {
+ if (!_last_incoming_video.image) {
return false;
}
process_video (
- _last_process_video.weak_piece,
- _last_process_video.image,
- _last_process_video.eyes,
- _last_process_video.same,
- _last_process_video.frame
+ _last_incoming_video.weak_piece,
+ _last_incoming_video.image,
+ _last_incoming_video.eyes,
+ _last_incoming_video.same,
+ _last_incoming_video.frame,
+ 0
);
return true;
diff --git a/src/lib/player.h b/src/lib/player.h
index 7cce7e723..424a39216 100644
--- a/src/lib/player.h
+++ b/src/lib/player.h
@@ -41,6 +41,16 @@ class Resampler;
/** @class Player
* @brief A class which can `play' a Playlist; emitting its audio and video.
*/
+
+struct IncomingVideo
+{
+public:
+ boost::weak_ptr<Piece> weak_piece;
+ boost::shared_ptr<const Image> image;
+ Eyes eyes;
+ bool same;
+ VideoContent::Frame frame;
+};
class Player : public boost::enable_shared_from_this<Player>, public boost::noncopyable
{
@@ -83,8 +93,9 @@ public:
private:
friend class PlayerWrapper;
+ friend class Piece;
- void process_video (boost::weak_ptr<Piece>, boost::shared_ptr<const Image>, Eyes, bool, VideoContent::Frame);
+ void process_video (boost::weak_ptr<Piece>, boost::shared_ptr<const Image>, Eyes, bool, VideoContent::Frame, Time);
void process_audio (boost::weak_ptr<Piece>, boost::shared_ptr<const AudioBuffers>, AudioContent::Frame);
void process_subtitle (boost::weak_ptr<Piece>, boost::shared_ptr<Image>, dcpomatic::Rect<double>, Time, Time);
void setup_pieces ();
@@ -140,13 +151,7 @@ private:
bool _last_emit_was_black;
- struct {
- boost::weak_ptr<Piece> weak_piece;
- boost::shared_ptr<const Image> image;
- Eyes eyes;
- bool same;
- VideoContent::Frame frame;
- } _last_process_video;
+ IncomingVideo _last_incoming_video;
boost::signals2::scoped_connection _playlist_changed_connection;
boost::signals2::scoped_connection _playlist_content_changed_connection;
diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc
index 1fc1ecaf2..09ccf4fbc 100644
--- a/src/lib/sndfile_decoder.cc
+++ b/src/lib/sndfile_decoder.cc
@@ -35,7 +35,7 @@ using boost::shared_ptr;
SndfileDecoder::SndfileDecoder (shared_ptr<const Film> f, shared_ptr<const SndfileContent> c)
: Decoder (f)
- , AudioDecoder (f)
+ , AudioDecoder (f, c)
, _sndfile_content (c)
, _deinterleave_buffer (0)
{
diff --git a/src/lib/util.cc b/src/lib/util.cc
index 4880e5ced..15efcc099 100644
--- a/src/lib/util.cc
+++ b/src/lib/util.cc
@@ -768,7 +768,7 @@ FrameRateConversion::FrameRateConversion (float source, int dcp)
}
if (source < dcp) {
- repeat = floor (source / dcp);
+ repeat = floor (dcp / source);
}
change_speed = !about_equal (source * factor(), dcp);
diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc
index 945644fb1..a1a47a943 100644
--- a/src/wx/film_viewer.cc
+++ b/src/wx/film_viewer.cc
@@ -120,8 +120,7 @@ FilmViewer::set_film (shared_ptr<Film> f)
_film = f;
_frame.reset ();
- _queue.clear ();
-
+
_slider->SetValue (0);
set_position_text (0);
@@ -286,12 +285,6 @@ FilmViewer::process_video (shared_ptr<const Image> image, Eyes eyes, Time t)
return;
}
- if (_got_frame) {
- /* This is an additional frame emitted by a single pass. Store it. */
- _queue.push_front (make_pair (image, t));
- return;
- }
-
_frame = image;
_got_frame = true;
@@ -335,17 +328,12 @@ FilmViewer::fetch_next_frame ()
_got_frame = false;
- if (!_queue.empty ()) {
- process_video (_queue.back().first, EYES_BOTH, _queue.back().second);
- _queue.pop_back ();
- } else {
- try {
- while (!_got_frame && !_player->pass ()) {}
- } catch (DecodeError& e) {
- _play_button->SetValue (false);
- check_play_state ();
- error_dialog (this, wxString::Format (_("Could not decode video for view (%s)"), std_to_wx(e.what()).data()));
- }
+ try {
+ while (!_got_frame && !_player->pass ()) {}
+ } catch (DecodeError& e) {
+ _play_button->SetValue (false);
+ check_play_state ();
+ error_dialog (this, wxString::Format (_("Could not decode video for view (%s)"), std_to_wx(e.what()).data()));
}
_panel->Refresh ();
diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h
index 7bda9617e..2337da6b0 100644
--- a/src/wx/film_viewer.h
+++ b/src/wx/film_viewer.h
@@ -89,6 +89,4 @@ private:
libdcp::Size _out_size;
/** Size of the panel that we have available */
libdcp::Size _panel_size;
-
- std::list<std::pair<boost::shared_ptr<const Image>, Time> > _queue;
};