2 Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <libavcodec/avcodec.h>
22 #include <libavformat/avformat.h>
23 #include <libavutil/pixfmt.h>
24 #include <libavutil/pixdesc.h>
26 #include "ffmpeg_examiner.h"
27 #include "ffmpeg_content.h"
29 #include "ffmpeg_audio_stream.h"
30 #include "ffmpeg_subtitle_stream.h"
32 #include "safe_stringstream.h"
33 #include <boost/foreach.hpp>
41 using boost::shared_ptr;
42 using boost::optional;
44 /** @param job job that the examiner is operating in, or 0 */
45 FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> c, shared_ptr<Job> job)
48 , _need_video_length (false)
50 /* Find audio and subtitle streams */
52 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
53 AVStream* s = _format_context->streams[i];
54 if (s->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
56 /* This is a hack; sometimes it seems that _audio_codec_context->channel_layout isn't set up,
57 so bodge it here. No idea why we should have to do this.
60 if (s->codec->channel_layout == 0) {
61 s->codec->channel_layout = av_get_default_channel_layout (s->codec->channels);
64 _audio_streams.push_back (
65 shared_ptr<FFmpegAudioStream> (
66 new FFmpegAudioStream (audio_stream_name (s), s->id, s->codec->sample_rate, s->codec->channels)
70 } else if (s->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
71 _subtitle_streams.push_back (shared_ptr<FFmpegSubtitleStream> (new FFmpegSubtitleStream (subtitle_stream_name (s), s->id)));
75 /* See if the header has duration information in it */
76 _need_video_length = _format_context->duration == AV_NOPTS_VALUE;
77 if (!_need_video_length) {
78 _video_length = (double (_format_context->duration) / AV_TIME_BASE) * video_frame_rate().get ();
80 job->sub (_("Finding length"));
81 job->set_progress_unknown ();
85 job->sub (_("Finding subtitles"));
88 /* Run through until we find:
90 * - the first audio for each stream.
91 * - the subtitle periods for each stream.
93 * We have to note subtitle periods as otherwise we have no way of knowing
94 * where we should look for subtitles (video and audio are always present,
99 int r = av_read_frame (_format_context, &_packet);
105 job->set_progress_unknown ();
108 AVCodecContext* context = _format_context->streams[_packet.stream_index]->codec;
110 if (_packet.stream_index == _video_stream) {
111 video_packet (context);
114 bool got_all_audio = true;
116 for (size_t i = 0; i < _audio_streams.size(); ++i) {
117 if (_audio_streams[i]->uses_index (_format_context, _packet.stream_index)) {
118 audio_packet (context, _audio_streams[i]);
120 if (!_audio_streams[i]->first_audio) {
121 got_all_audio = false;
125 for (size_t i = 0; i < _subtitle_streams.size(); ++i) {
126 if (_subtitle_streams[i]->uses_index (_format_context, _packet.stream_index)) {
127 subtitle_packet (context, _subtitle_streams[i]);
131 av_free_packet (&_packet);
133 if (_first_video && got_all_audio && _subtitle_streams.empty ()) {
139 for (LastSubtitleMap::const_iterator i = _last_subtitle_start.begin(); i != _last_subtitle_start.end(); ++i) {
141 i->first->add_subtitle (
144 ContentTime::from_frames (video_length(), video_frame_rate().get_value_or (24))
150 /* We just added subtitles to our streams without taking the PTS offset into account;
151 this is because we might not know the PTS offset when the first subtitle is seen.
152 Now we know the PTS offset so we can apply it to those subtitles.
154 if (video_frame_rate()) {
155 BOOST_FOREACH (shared_ptr<FFmpegSubtitleStream> i, _subtitle_streams) {
156 i->add_offset (pts_offset (_audio_streams, _first_video, video_frame_rate().get()));
162 FFmpegExaminer::video_packet (AVCodecContext* context)
164 if (_first_video && !_need_video_length) {
169 if (avcodec_decode_video2 (context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
171 _first_video = frame_time (_format_context->streams[_video_stream]);
173 if (_need_video_length) {
174 _video_length = frame_time (
175 _format_context->streams[_video_stream]
176 ).get_value_or (ContentTime ()).frames_round (video_frame_rate().get ());
182 FFmpegExaminer::audio_packet (AVCodecContext* context, shared_ptr<FFmpegAudioStream> stream)
184 if (stream->first_audio) {
189 if (avcodec_decode_audio4 (context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
190 stream->first_audio = frame_time (stream->stream (_format_context));
195 FFmpegExaminer::subtitle_packet (AVCodecContext* context, shared_ptr<FFmpegSubtitleStream> stream)
199 if (avcodec_decode_subtitle2 (context, &sub, &frame_finished, &_packet) >= 0 && frame_finished) {
200 FFmpegSubtitlePeriod const period = subtitle_period (sub);
201 LastSubtitleMap::iterator last = _last_subtitle_start.find (stream);
202 if (last != _last_subtitle_start.end() && last->second) {
203 /* We have seen the start of a subtitle but not yet the end. Whatever this is
204 finishes the previous subtitle, so add it */
205 stream->add_subtitle (ContentTimePeriod (last->second.get (), period.from));
206 if (sub.num_rects == 0) {
207 /* This is a `proper' end-of-subtitle */
208 _last_subtitle_start[stream] = optional<ContentTime> ();
210 /* This is just another subtitle, so we start again */
211 _last_subtitle_start[stream] = period.from;
213 } else if (sub.num_rects == 1) {
215 stream->add_subtitle (ContentTimePeriod (period.from, period.to.get ()));
217 _last_subtitle_start[stream] = period.from;
220 avsubtitle_free (&sub);
224 optional<ContentTime>
225 FFmpegExaminer::frame_time (AVStream* s) const
227 optional<ContentTime> t;
229 int64_t const bet = av_frame_get_best_effort_timestamp (_frame);
230 if (bet != AV_NOPTS_VALUE) {
231 t = ContentTime::from_seconds (bet * av_q2d (s->time_base));
238 FFmpegExaminer::video_frame_rate () const
240 /* This use of r_frame_rate is debateable; there's a few different
241 * frame rates in the format context, but this one seems to be the most
244 return av_q2d (av_stream_get_r_frame_rate (_format_context->streams[_video_stream]));
248 FFmpegExaminer::video_size () const
250 return dcp::Size (video_codec_context()->width, video_codec_context()->height);
253 /** @return Length according to our content's header */
255 FFmpegExaminer::video_length () const
257 return max (Frame (1), _video_length);
261 FFmpegExaminer::sample_aspect_ratio () const
263 AVRational sar = av_guess_sample_aspect_ratio (_format_context, _format_context->streams[_video_stream], 0);
265 /* I assume this means that we don't know */
266 return optional<double> ();
268 return double (sar.num) / sar.den;
272 FFmpegExaminer::audio_stream_name (AVStream* s) const
276 n << stream_name (s);
278 if (!n.str().empty()) {
282 n << s->codec->channels << " channels";
288 FFmpegExaminer::subtitle_stream_name (AVStream* s) const
292 n << stream_name (s);
294 if (n.str().empty()) {
302 FFmpegExaminer::stream_name (AVStream* s) const
307 AVDictionaryEntry const * lang = av_dict_get (s->metadata, "language", 0, 0);
312 AVDictionaryEntry const * title = av_dict_get (s->metadata, "title", 0, 0);
314 if (!n.str().empty()) {
325 FFmpegExaminer::bits_per_pixel () const
327 return av_get_bits_per_pixel (av_pix_fmt_desc_get (video_codec_context()->pix_fmt));