/*
- Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
#include "util.h"
#include "log.h"
#include "ffmpeg_decoder.h"
-#include "subtitle_decoder.h"
+#include "text_decoder.h"
#include "ffmpeg_audio_stream.h"
#include "ffmpeg_subtitle_stream.h"
#include "video_filter_graph.h"
#include "film.h"
#include "audio_decoder.h"
#include "compose.hpp"
-#include "subtitle_content.h"
+#include "text_content.h"
#include "audio_content.h"
#include <dcp/subtitle_string.h>
#include <sub/ssa_reader.h>
audio.reset (new AudioDecoder (this, c->audio, log, fast));
}
- if (c->subtitle) {
+ if (c->only_text()) {
/* XXX: this time here should be the time of the first subtitle, not 0 */
- subtitle.reset (new SubtitleDecoder (this, c->subtitle, log, ContentTime()));
+ text.push_back (shared_ptr<TextDecoder> (new TextDecoder (this, c->only_text(), log, ContentTime())));
}
_next_time.resize (_format_context->nb_streams);
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;
+ }
}
}
if (_video_stream && si == _video_stream.get() && !video->ignore()) {
decode_video_packet ();
- } else if (fc->subtitle_stream() && fc->subtitle_stream()->uses_index(_format_context, si) && !subtitle->ignore()) {
+ } else if (fc->subtitle_stream() && fc->subtitle_stream()->uses_index(_format_context, si) && !only_text()->ignore()) {
decode_subtitle_packet ();
} else {
decode_audio_packet ();
}
if (i == _filter_graphs.end ()) {
- graph.reset (new VideoFilterGraph (dcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format));
+ dcp::Fraction vfr (lrint(_ffmpeg_content->video_frame_rate().get() * 1000), 1000);
+ graph.reset (new VideoFilterGraph (dcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format, vfr));
graph->setup (_ffmpeg_content->filters ());
_filter_graphs.push_back (graph);
LOG_GENERAL (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format);
if (i->second != AV_NOPTS_VALUE) {
double const pts = i->second * av_q2d (_format_context->streams[_video_stream.get()]->time_base) + _pts_offset.seconds ();
+
video->emit (
shared_ptr<ImageProxy> (new RawImageProxy (image)),
- llrint (pts * _ffmpeg_content->active_video_frame_rate ())
+ llrint(pts * _ffmpeg_content->active_video_frame_rate())
);
} else {
LOG_WARNING_NC ("Dropping frame without PTS");
/* Stop any current subtitle, either at the time it was supposed to stop, or now if now is sooner */
if (_have_current_subtitle) {
if (_current_subtitle_to) {
- subtitle->emit_stop (min(*_current_subtitle_to, subtitle_period(sub).from + _pts_offset));
+ only_text()->emit_stop (min(*_current_subtitle_to, subtitle_period(sub).from + _pts_offset));
} else {
- subtitle->emit_stop (subtitle_period(sub).from + _pts_offset);
+ only_text()->emit_stop (subtitle_period(sub).from + _pts_offset);
}
_have_current_subtitle = false;
}
FFmpegSubtitlePeriod sub_period = subtitle_period (sub);
ContentTime from;
from = sub_period.from + _pts_offset;
- _have_current_subtitle = true;
if (sub_period.to) {
_current_subtitle_to = *sub_period.to + _pts_offset;
} else {
_current_subtitle_to = optional<ContentTime>();
+ _have_current_subtitle = true;
}
for (unsigned int i = 0; i < sub.num_rects; ++i) {
}
if (_current_subtitle_to) {
- subtitle->emit_stop (*_current_subtitle_to);
+ only_text()->emit_stop (*_current_subtitle_to);
}
avsubtitle_free (&sub);
static_cast<double> (rect->h) / target_height
);
- subtitle->emit_image_start (from, image, scaled_rect);
+ only_text()->emit_bitmap_start (from, image, scaled_rect);
}
void
produces a single format of Dialogue: lines...
*/
- vector<string> bits;
- split (bits, ass, is_any_of (","));
- if (bits.size() < 10) {
+ int commas = 0;
+ string text;
+ for (size_t i = 0; i < ass.length(); ++i) {
+ if (commas < 9 && ass[i] == ',') {
+ ++commas;
+ } else if (commas == 9) {
+ text += ass[i];
+ }
+ }
+
+ if (text.empty ()) {
return;
}
sub::RawSubtitle base;
list<sub::RawSubtitle> raw = sub::SSAReader::parse_line (
base,
- bits[9],
+ text,
_ffmpeg_content->video->size().width,
_ffmpeg_content->video->size().height
);
BOOST_FOREACH (sub::Subtitle const & i, sub::collect<list<sub::Subtitle> > (raw)) {
- subtitle->emit_text_start (from, i);
+ only_text()->emit_plain_start (from, i);
}
}