using boost::dynamic_pointer_cast;
using dcp::Size;
-FFmpegDecoder::FFmpegDecoder (shared_ptr<const FFmpegContent> c, shared_ptr<Log> log)
+FFmpegDecoder::FFmpegDecoder (shared_ptr<const FFmpegContent> c, shared_ptr<Log> log, bool fast)
: FFmpeg (c)
, _log (log)
, _have_current_subtitle (false)
}
if (c->audio) {
- audio.reset (new AudioDecoder (this, c->audio, log));
+ audio.reset (new AudioDecoder (this, c->audio, log, fast));
}
if (c->subtitle) {
- subtitle.reset (new SubtitleDecoder (this, c->subtitle, log));
+ /* XXX: this time here should be the time of the first subtitle, not 0 */
+ subtitle.reset (new SubtitleDecoder (this, c->subtitle, log, ContentTime()));
}
_next_time.resize (_format_context->nb_streams);
if (video) {
double const vfr = _ffmpeg_content->video_frame_rate().get();
Frame const f = full_length.frames_round (vfr);
- Frame v = video->position().frames_round (vfr);
+ Frame v = video->position().frames_round (vfr) + 1;
while (v < f) {
video->emit (shared_ptr<const ImageProxy> (new RawImageProxy (_black_image)), v);
++v;
BOOST_FOREACH (shared_ptr<FFmpegAudioStream> i, _ffmpeg_content->ffmpeg_audio_streams ()) {
ContentTime a = audio->stream_position(i);
- while (a < full_length) {
- ContentTime to_do = min (full_length - a, ContentTime::from_seconds (0.1));
- shared_ptr<AudioBuffers> silence (new AudioBuffers (i->channels(), to_do.frames_ceil (i->frame_rate())));
- silence->make_silent ();
- audio->emit (i, silence, a);
- a += to_do;
+ /* Unfortunately if a is 0 that really means that we don't know the stream position since
+ there has been no data on it since the last seek. In this case we'll just do nothing
+ here. I'm not sure if that's the right idea.
+ */
+ if (a > ContentTime()) {
+ while (a < full_length) {
+ ContentTime to_do = min (full_length - a, ContentTime::from_seconds (0.1));
+ shared_ptr<AudioBuffers> silence (new AudioBuffers (i->channels(), to_do.frames_ceil (i->frame_rate())));
+ silence->make_silent ();
+ audio->emit (i, silence, a);
+ a += to_do;
+ }
}
}
_have_current_subtitle = true;
if (sub_period.to) {
_current_subtitle_to = *sub_period.to + _pts_offset;
+ } else {
+ _current_subtitle_to = optional<ContentTime>();
}
for (unsigned int i = 0; i < sub.num_rects; ++i) {
}
}
+ if (_current_subtitle_to) {
+ subtitle->emit_stop (*_current_subtitle_to);
+ }
+
avsubtitle_free (&sub);
}
void
FFmpegDecoder::decode_bitmap_subtitle (AVSubtitleRect const * rect, ContentTime from)
{
- /* Note RGBA is expressed little-endian, so the first byte in the word is R, second
- G, third B, fourth A.
+ /* Note BGRA is expressed little-endian, so the first byte in the word is B, second
+ G, third R, fourth A.
*/
- shared_ptr<Image> image (new Image (AV_PIX_FMT_RGBA, dcp::Size (rect->w, rect->h), true));
+ shared_ptr<Image> image (new Image (AV_PIX_FMT_BGRA, dcp::Size (rect->w, rect->h), true));
#ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT
/* Start of the first line in the subtitle */
uint32_t* out_line_p = out_p;
for (int x = 0; x < rect->w; ++x) {
RGBA const p = mapped_palette[*sub_line_p++];
- /* XXX: this seems to be wrong to me (isn't the output image RGBA?) but it looks right on screen */
- *out_line_p++ = (p.a << 24) | (p.r << 16) | (p.g << 8) | p.b;
+ /* XXX: this seems to be wrong to me (isn't the output image BGRA?) but it looks right on screen */
+ *out_line_p++ = (p.a << 24) | (p.b << 16) | (p.g << 8) | p.r;
}
#ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT
sub_p += rect->pict.linesize[0];