list<shared_ptr<Image> > images = graph->process (frame);
+ SourceFrame const sf = av_q2d (_format_context->streams[_video_stream]->time_base)
+ * av_frame_get_best_effort_timestamp(_frame) * frames_per_second();
+
for (list<shared_ptr<Image> >::iterator i = images.begin(); i != images.end(); ++i) {
- emit_video (*i);
+ emit_video (*i, sf);
}
}
int64_t const t = static_cast<int64_t>(f) / (av_q2d (_format_context->streams[_video_stream]->time_base) * frames_per_second());
int const r = av_seek_frame (_format_context, _video_stream, t, 0);
avcodec_flush_buffers (_video_codec_context);
-
- if (r >= 0) {
- OutputChanged ();
- }
-
return r < 0;
}
delete magick_image;
- emit_video (image);
+ emit_video (image, 0);
++_iter;
return false;
VideoDecoder::VideoDecoder (shared_ptr<Film> f, shared_ptr<const DecodeOptions> o, Job* j)
: Decoder (f, o, j)
, _video_frame (0)
+ , _last_source_frame (0)
{
}
/** Called by subclasses to tell the world that some video data is ready.
* We find a subtitle then emit it for listeners.
- * @param frame to decode; caller manages memory.
+ * @param frame to emit.
*/
void
-VideoDecoder::emit_video (shared_ptr<Image> image)
+VideoDecoder::emit_video (shared_ptr<Image> image, SourceFrame f)
{
shared_ptr<Subtitle> sub;
if (_timed_subtitle && _timed_subtitle->displayed_at (double (video_frame()) / _film->frames_per_second())) {
}
signal_video (image, sub);
+ _last_source_frame = f;
}
void
return _subtitle_streams;
}
+ SourceFrame last_source_frame () const {
+ return _last_source_frame;
+ }
+
protected:
virtual PixelFormat pixel_format () const = 0;
- void emit_video (boost::shared_ptr<Image>);
+ void emit_video (boost::shared_ptr<Image>, SourceFrame);
void emit_subtitle (boost::shared_ptr<TimedSubtitle>);
void repeat_last_video ();
void signal_video (boost::shared_ptr<Image>, boost::shared_ptr<Subtitle>);
SourceFrame _video_frame;
-
+ SourceFrame _last_source_frame;
+
boost::shared_ptr<TimedSubtitle> _timed_subtitle;
boost::shared_ptr<Image> _last_image;
void
FilmViewer::decoder_changed ()
{
- shared_ptr<Image> last = _display;
- while (last == _display) {
- _decoders.video->pass ();
- }
- _panel->Refresh ();
- _panel->Update ();
+ seek_and_update (_decoders.video->last_source_frame ());
}
void
_decoders.video->pass ();
}
-#if 0
- if (_last_frame_in_seconds) {
- double const video_length_in_seconds = static_cast<double>(_format_context->duration) / AV_TIME_BASE;
- int const new_slider_position = 4096 * _last_frame_in_seconds / video_length_in_seconds;
- if (new_slider_position != _slider->GetValue()) {
- _slider->SetValue (new_slider_position);
- }
+ int const new_slider_position = 4096 * _decoders.video->last_source_frame() / _film->length().get();
+ if (new_slider_position != _slider->GetValue()) {
+ _slider->SetValue (new_slider_position);
}
-#endif
}
void
FilmViewer::slider_moved (wxCommandEvent& ev)
{
- _decoders.video->seek (_slider->GetValue() * _film->length().get() / 4096);
+ seek_and_update (_slider->GetValue() * _film->length().get() / 4096);
+}
+
+void
+FilmViewer::seek_and_update (SourceFrame f)
+{
+ _decoders.video->seek (f);
+
+ shared_ptr<Image> last = _display;
+ while (last == _display) {
+ _decoders.video->pass ();
+ }
+ _panel->Refresh ();
+ _panel->Update ();
}
void
void check_play_state ();
void update_from_raw ();
void decoder_changed ();
+ void seek_and_update (SourceFrame);
boost::shared_ptr<Film> _film;