2 Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
22 #include <libavcodec/avcodec.h>
23 #include <libavformat/avformat.h>
24 #include <libavutil/pixfmt.h>
25 #include <libavutil/pixdesc.h>
27 #include "ffmpeg_examiner.h"
28 #include "ffmpeg_content.h"
30 #include "ffmpeg_audio_stream.h"
31 #include "ffmpeg_subtitle_stream.h"
33 #include "safe_stringstream.h"
34 #include <boost/foreach.hpp>
35 #include <boost/make_shared.hpp>
43 using boost::shared_ptr;
44 using boost::make_shared;
45 using boost::optional;
47 /** @param job job that the examiner is operating in, or 0 */
48 FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> c, shared_ptr<Job> job)
51 , _need_video_length (false)
53 /* Find audio and subtitle streams */
55 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
56 AVStream* s = _format_context->streams[i];
57 if (s->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
59 /* This is a hack; sometimes it seems that _audio_codec_context->channel_layout isn't set up,
60 so bodge it here. No idea why we should have to do this.
63 if (s->codec->channel_layout == 0) {
64 s->codec->channel_layout = av_get_default_channel_layout (s->codec->channels);
67 DCPOMATIC_ASSERT (_format_context->duration != AV_NOPTS_VALUE);
68 DCPOMATIC_ASSERT (s->codec->codec);
69 DCPOMATIC_ASSERT (s->codec->codec->name);
71 _audio_streams.push_back (
72 shared_ptr<FFmpegAudioStream> (
73 new FFmpegAudioStream (
75 s->codec->codec->name,
77 s->codec->sample_rate,
78 (double (_format_context->duration) / AV_TIME_BASE) * s->codec->sample_rate,
84 } else if (s->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
85 _subtitle_streams.push_back (boost::make_shared<FFmpegSubtitleStream> (subtitle_stream_name (s), s->id));
90 /* See if the header has duration information in it */
91 _need_video_length = _format_context->duration == AV_NOPTS_VALUE;
92 if (!_need_video_length) {
93 _video_length = (double (_format_context->duration) / AV_TIME_BASE) * video_frame_rate().get ();
98 if (_need_video_length) {
99 job->sub (_("Finding length and subtitles"));
100 } else if (!_subtitle_streams.empty()) {
101 job->sub (_("Finding subtitles"));
103 job->sub (_("Finding length"));
107 /* Run through until we find:
109 * - the first audio for each stream.
110 * - the subtitle periods for each stream.
112 * We have to note subtitle periods as otherwise we have no way of knowing
113 * where we should look for subtitles (video and audio are always present,
117 int64_t const len = _file_group.length ();
119 int r = av_read_frame (_format_context, &_packet);
126 job->set_progress (float (_format_context->pb->pos) / len);
128 job->set_progress_unknown ();
132 AVCodecContext* context = _format_context->streams[_packet.stream_index]->codec;
134 if (_video_stream && _packet.stream_index == _video_stream.get()) {
135 video_packet (context);
138 bool got_all_audio = true;
140 for (size_t i = 0; i < _audio_streams.size(); ++i) {
141 if (_audio_streams[i]->uses_index (_format_context, _packet.stream_index)) {
142 audio_packet (context, _audio_streams[i]);
144 if (!_audio_streams[i]->first_audio) {
145 got_all_audio = false;
149 for (size_t i = 0; i < _subtitle_streams.size(); ++i) {
150 if (_subtitle_streams[i]->uses_index (_format_context, _packet.stream_index)) {
151 subtitle_packet (context, _subtitle_streams[i]);
155 av_packet_unref (&_packet);
157 if (_first_video && got_all_audio && _subtitle_streams.empty ()) {
163 /* Finish off any hanging subtitles at the end */
164 for (LastSubtitleMap::const_iterator i = _last_subtitle_start.begin(); i != _last_subtitle_start.end(); ++i) {
166 if (i->second->image) {
167 i->first->add_image_subtitle (
171 ContentTime::from_frames (video_length(), video_frame_rate().get_value_or (24))
175 i->first->add_text_subtitle (
179 ContentTime::from_frames (video_length(), video_frame_rate().get_value_or (24))
186 /* We just added subtitles to our streams without taking the PTS offset into account;
187 this is because we might not know the PTS offset when the first subtitle is seen.
188 Now we know the PTS offset so we can apply it to those subtitles.
190 if (has_video() && video_frame_rate()) {
191 BOOST_FOREACH (shared_ptr<FFmpegSubtitleStream> i, _subtitle_streams) {
192 i->add_offset (pts_offset (_audio_streams, _first_video, video_frame_rate().get()));
198 FFmpegExaminer::video_packet (AVCodecContext* context)
200 DCPOMATIC_ASSERT (_video_stream);
202 if (_first_video && !_need_video_length) {
207 if (avcodec_decode_video2 (context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
209 _first_video = frame_time (_format_context->streams[_video_stream.get()]);
211 if (_need_video_length) {
212 _video_length = frame_time (
213 _format_context->streams[_video_stream.get()]
214 ).get_value_or (ContentTime ()).frames_round (video_frame_rate().get ());
220 FFmpegExaminer::audio_packet (AVCodecContext* context, shared_ptr<FFmpegAudioStream> stream)
222 if (stream->first_audio) {
227 if (avcodec_decode_audio4 (context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
228 stream->first_audio = frame_time (stream->stream (_format_context));
233 FFmpegExaminer::subtitle_packet (AVCodecContext* context, shared_ptr<FFmpegSubtitleStream> stream)
237 if (avcodec_decode_subtitle2 (context, &sub, &frame_finished, &_packet) >= 0 && frame_finished) {
238 string id = subtitle_id (sub);
239 FFmpegSubtitlePeriod const period = subtitle_period (sub);
240 bool const starts_image = subtitle_starts_image (sub);
242 LastSubtitleMap::iterator last = _last_subtitle_start.find (stream);
243 if (last != _last_subtitle_start.end() && last->second) {
244 /* We have seen the start of a subtitle but not yet the end. Whatever this is
245 finishes the previous subtitle, so add it */
246 if (last->second->image) {
247 stream->add_image_subtitle (last->second->id, ContentTimePeriod (last->second->time, period.from));
249 stream->add_text_subtitle (last->second->id, ContentTimePeriod (last->second->time, period.from));
251 if (sub.num_rects == 0) {
252 /* This is a `proper' end-of-subtitle */
253 _last_subtitle_start[stream] = optional<SubtitleStart> ();
255 /* This is just another subtitle, so we start again */
256 _last_subtitle_start[stream] = SubtitleStart (id, starts_image, period.from);
258 } else if (sub.num_rects == 1) {
261 stream->add_image_subtitle (id, ContentTimePeriod (period.from, period.to.get ()));
263 stream->add_text_subtitle (id, ContentTimePeriod (period.from, period.to.get ()));
266 _last_subtitle_start[stream] = SubtitleStart (id, starts_image, period.from);
270 for (unsigned int i = 0; i < sub.num_rects; ++i) {
271 if (sub.rects[i]->type == SUBTITLE_BITMAP) {
272 #ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT
273 uint32_t* palette = (uint32_t *) sub.rects[i]->pict.data[1];
274 for (int j = 0; j < sub.rects[i]->nb_colors; ++j) {
276 (palette[j] & 0x00ff0000) >> 16,
277 (palette[j] & 0x0000ff00) >> 8,
278 (palette[j] & 0x000000ff) >> 0,
279 (palette[j] & 0xff000000) >> 24
282 stream->set_colour (rgba, rgba);
285 uint32_t* palette = (uint32_t *) sub.rects[i]->data[1];
286 for (int j = 0; j < sub.rects[i]->nb_colors; ++j) {
288 (palette[j] & 0x00ff0000) >> 16,
289 (palette[j] & 0x0000ff00) >> 8,
290 (palette[j] & 0x000000ff) >> 0,
291 (palette[j] & 0xff000000) >> 24
294 stream->set_colour (rgba, rgba);
300 avsubtitle_free (&sub);
304 optional<ContentTime>
305 FFmpegExaminer::frame_time (AVStream* s) const
307 optional<ContentTime> t;
309 int64_t const bet = av_frame_get_best_effort_timestamp (_frame);
310 if (bet != AV_NOPTS_VALUE) {
311 t = ContentTime::from_seconds (bet * av_q2d (s->time_base));
318 FFmpegExaminer::video_frame_rate () const
320 DCPOMATIC_ASSERT (_video_stream);
321 /* This use of r_frame_rate is debateable; there's a few different
322 * frame rates in the format context, but this one seems to be the most
325 return av_q2d (av_stream_get_r_frame_rate (_format_context->streams[_video_stream.get()]));
329 FFmpegExaminer::video_size () const
331 return dcp::Size (video_codec_context()->width, video_codec_context()->height);
334 /** @return Length according to our content's header */
336 FFmpegExaminer::video_length () const
338 return max (Frame (1), _video_length);
342 FFmpegExaminer::sample_aspect_ratio () const
344 DCPOMATIC_ASSERT (_video_stream);
345 AVRational sar = av_guess_sample_aspect_ratio (_format_context, _format_context->streams[_video_stream.get()], 0);
347 /* I assume this means that we don't know */
348 return optional<double> ();
350 return double (sar.num) / sar.den;
354 FFmpegExaminer::subtitle_stream_name (AVStream* s) const
358 n << stream_name (s);
360 if (n.str().empty()) {
368 FFmpegExaminer::stream_name (AVStream* s) const
373 AVDictionaryEntry const * lang = av_dict_get (s->metadata, "language", 0, 0);
378 AVDictionaryEntry const * title = av_dict_get (s->metadata, "title", 0, 0);
380 if (!n.str().empty()) {
391 FFmpegExaminer::bits_per_pixel () const
393 if (video_codec_context()->pix_fmt == -1) {
394 throw DecodeError (_("Could not find pixel format for video."));
397 AVPixFmtDescriptor const * d = av_pix_fmt_desc_get (video_codec_context()->pix_fmt);
398 DCPOMATIC_ASSERT (d);
399 return av_get_bits_per_pixel (d);
403 FFmpegExaminer::yuv () const
405 switch (video_codec_context()->pix_fmt) {
406 case AV_PIX_FMT_YUV420P:
407 case AV_PIX_FMT_YUYV422:
408 case AV_PIX_FMT_YUV422P:
409 case AV_PIX_FMT_YUV444P:
410 case AV_PIX_FMT_YUV410P:
411 case AV_PIX_FMT_YUV411P:
412 case AV_PIX_FMT_YUVJ420P:
413 case AV_PIX_FMT_YUVJ422P:
414 case AV_PIX_FMT_YUVJ444P:
415 case AV_PIX_FMT_UYVY422:
416 case AV_PIX_FMT_UYYVYY411:
417 case AV_PIX_FMT_NV12:
418 case AV_PIX_FMT_NV21:
419 case AV_PIX_FMT_YUV440P:
420 case AV_PIX_FMT_YUVJ440P:
421 case AV_PIX_FMT_YUVA420P:
422 case AV_PIX_FMT_YUV420P16LE:
423 case AV_PIX_FMT_YUV420P16BE:
424 case AV_PIX_FMT_YUV422P16LE:
425 case AV_PIX_FMT_YUV422P16BE:
426 case AV_PIX_FMT_YUV444P16LE:
427 case AV_PIX_FMT_YUV444P16BE:
428 case AV_PIX_FMT_YUV420P9BE:
429 case AV_PIX_FMT_YUV420P9LE:
430 case AV_PIX_FMT_YUV420P10BE:
431 case AV_PIX_FMT_YUV420P10LE:
432 case AV_PIX_FMT_YUV422P10BE:
433 case AV_PIX_FMT_YUV422P10LE:
434 case AV_PIX_FMT_YUV444P9BE:
435 case AV_PIX_FMT_YUV444P9LE:
436 case AV_PIX_FMT_YUV444P10BE:
437 case AV_PIX_FMT_YUV444P10LE:
438 case AV_PIX_FMT_YUV422P9BE:
439 case AV_PIX_FMT_YUV422P9LE:
440 case AV_PIX_FMT_YUVA420P9BE:
441 case AV_PIX_FMT_YUVA420P9LE:
442 case AV_PIX_FMT_YUVA422P9BE:
443 case AV_PIX_FMT_YUVA422P9LE:
444 case AV_PIX_FMT_YUVA444P9BE:
445 case AV_PIX_FMT_YUVA444P9LE:
446 case AV_PIX_FMT_YUVA420P10BE:
447 case AV_PIX_FMT_YUVA420P10LE:
448 case AV_PIX_FMT_YUVA422P10BE:
449 case AV_PIX_FMT_YUVA422P10LE:
450 case AV_PIX_FMT_YUVA444P10BE:
451 case AV_PIX_FMT_YUVA444P10LE:
452 case AV_PIX_FMT_YUVA420P16BE:
453 case AV_PIX_FMT_YUVA420P16LE:
454 case AV_PIX_FMT_YUVA422P16BE:
455 case AV_PIX_FMT_YUVA422P16LE:
456 case AV_PIX_FMT_YUVA444P16BE:
457 case AV_PIX_FMT_YUVA444P16LE:
458 case AV_PIX_FMT_NV16:
459 case AV_PIX_FMT_NV20LE:
460 case AV_PIX_FMT_NV20BE:
461 case AV_PIX_FMT_YVYU422:
462 case AV_PIX_FMT_YUVA444P:
463 case AV_PIX_FMT_YUVA422P:
464 case AV_PIX_FMT_YUV420P12BE:
465 case AV_PIX_FMT_YUV420P12LE:
466 case AV_PIX_FMT_YUV420P14BE:
467 case AV_PIX_FMT_YUV420P14LE:
468 case AV_PIX_FMT_YUV422P12BE:
469 case AV_PIX_FMT_YUV422P12LE:
470 case AV_PIX_FMT_YUV422P14BE:
471 case AV_PIX_FMT_YUV422P14LE:
472 case AV_PIX_FMT_YUV444P12BE:
473 case AV_PIX_FMT_YUV444P12LE:
474 case AV_PIX_FMT_YUV444P14BE:
475 case AV_PIX_FMT_YUV444P14LE:
476 case AV_PIX_FMT_YUVJ411P:
484 FFmpegExaminer::has_video () const
486 return static_cast<bool> (_video_stream);