#include "ffmpeg_subtitle_stream.h"
#include "util.h"
#include "safe_stringstream.h"
+#include <boost/foreach.hpp>
+#include <iostream>
#include "i18n.h"
_need_video_length = _format_context->duration == AV_NOPTS_VALUE;
if (!_need_video_length) {
_video_length = (double (_format_context->duration) / AV_TIME_BASE) * video_frame_rate().get ();
- } else if (job) {
- job->sub (_("Finding length"));
- job->set_progress_unknown ();
}
if (job) {
- job->sub (_("Finding subtitles"));
+ if (_need_video_length) {
+ job->sub (_("Finding length and subtitles"));
+ } else {
+ job->sub (_("Finding subtitles"));
+ }
}
/* Run through until we find:
* where we should look for subtitles (video and audio are always present,
* so they are ok).
*/
+
+ int64_t const len = _file_group.length ();
while (true) {
int r = av_read_frame (_format_context, &_packet);
if (r < 0) {
}
if (job) {
- job->set_progress_unknown ();
+ if (len > 0) {
+ job->set_progress (float (_format_context->pb->pos) / len);
+ } else {
+ job->set_progress_unknown ();
+ }
}
AVCodecContext* context = _format_context->streams[_packet.stream_index]->codec;
video_packet (context);
}
+ bool got_all_audio = true;
+
for (size_t i = 0; i < _audio_streams.size(); ++i) {
if (_audio_streams[i]->uses_index (_format_context, _packet.stream_index)) {
audio_packet (context, _audio_streams[i]);
}
+ if (!_audio_streams[i]->first_audio) {
+ got_all_audio = false;
+ }
}
for (size_t i = 0; i < _subtitle_streams.size(); ++i) {
}
av_free_packet (&_packet);
+
+ if (_first_video && got_all_audio && _subtitle_streams.empty ()) {
+ /* All done */
+ break;
+ }
+ }
+
+ for (LastSubtitleMap::const_iterator i = _last_subtitle_start.begin(); i != _last_subtitle_start.end(); ++i) {
+ if (i->second) {
+ i->first->add_subtitle (
+ ContentTimePeriod (
+ i->second.get (),
+ ContentTime::from_frames (video_length(), video_frame_rate().get_value_or (24))
+ )
+ );
+ }
+ }
+
+ /* We just added subtitles to our streams without taking the PTS offset into account;
+ this is because we might not know the PTS offset when the first subtitle is seen.
+ Now we know the PTS offset so we can apply it to those subtitles.
+ */
+ if (video_frame_rate()) {
+ BOOST_FOREACH (shared_ptr<FFmpegSubtitleStream> i, _subtitle_streams) {
+ i->add_offset (pts_offset (_audio_streams, _first_video, video_frame_rate().get()));
+ }
}
}
AVSubtitle sub;
if (avcodec_decode_subtitle2 (context, &sub, &frame_finished, &_packet) >= 0 && frame_finished) {
FFmpegSubtitlePeriod const period = subtitle_period (sub);
- if (sub.num_rects <= 0 && _last_subtitle_start) {
- stream->add_subtitle (ContentTimePeriod (_last_subtitle_start.get (), period.from));
- _last_subtitle_start = optional<ContentTime> ();
+ LastSubtitleMap::iterator last = _last_subtitle_start.find (stream);
+ if (last != _last_subtitle_start.end() && last->second) {
+ /* We have seen the start of a subtitle but not yet the end. Whatever this is
+ finishes the previous subtitle, so add it */
+ stream->add_subtitle (ContentTimePeriod (last->second.get (), period.from));
+ if (sub.num_rects == 0) {
+ /* This is a `proper' end-of-subtitle */
+ _last_subtitle_start[stream] = optional<ContentTime> ();
+ } else {
+ /* This is just another subtitle, so we start again */
+ _last_subtitle_start[stream] = period.from;
+ }
} else if (sub.num_rects == 1) {
if (period.to) {
stream->add_subtitle (ContentTimePeriod (period.from, period.to.get ()));
} else {
- _last_subtitle_start = period.from;
+ _last_subtitle_start[stream] = period.from;
}
}
avsubtitle_free (&sub);