Disable YUV->RGB conversion controls with non-YUV sources (#649).
[dcpomatic.git] / src / lib / ffmpeg_examiner.cc
1 /*
2     Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
3
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.
8
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.
13
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.
17
18 */
19
20 extern "C" {
21 #include <libavcodec/avcodec.h>
22 #include <libavformat/avformat.h>
23 #include <libavutil/pixfmt.h>
24 #include <libavutil/pixdesc.h>
25 }
26 #include "ffmpeg_examiner.h"
27 #include "ffmpeg_content.h"
28 #include "job.h"
29 #include "ffmpeg_audio_stream.h"
30 #include "ffmpeg_subtitle_stream.h"
31 #include "util.h"
32 #include "safe_stringstream.h"
33 #include <boost/foreach.hpp>
34 #include <iostream>
35
36 #include "i18n.h"
37
38 using std::string;
39 using std::cout;
40 using std::max;
41 using boost::shared_ptr;
42 using boost::optional;
43
44 /** @param job job that the examiner is operating in, or 0 */
45 FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> c, shared_ptr<Job> job)
46         : FFmpeg (c)
47         , _video_length (0)
48         , _need_video_length (false)
49 {
50         /* Find audio and subtitle streams */
51
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) {
55
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.
58                         */
59
60                         if (s->codec->channel_layout == 0) {
61                                 s->codec->channel_layout = av_get_default_channel_layout (s->codec->channels);
62                         }
63
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)
67                                         )
68                                 );
69
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)));
72                 }
73         }
74
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 ();
79         }
80
81         if (job) {
82                 if (_need_video_length) {
83                         job->sub (_("Finding length and subtitles"));
84                 } else {
85                         job->sub (_("Finding subtitles"));
86                 }
87         }
88
89         /* Run through until we find:
90          *   - the first video.
91          *   - the first audio for each stream.
92          *   - the subtitle periods for each stream.
93          *
94          * We have to note subtitle periods as otherwise we have no way of knowing
95          * where we should look for subtitles (video and audio are always present,
96          * so they are ok).
97          */
98
99         int64_t const len = _file_group.length ();
100         while (true) {
101                 int r = av_read_frame (_format_context, &_packet);
102                 if (r < 0) {
103                         break;
104                 }
105
106                 if (job) {
107                         if (len > 0) {
108                                 job->set_progress (float (_format_context->pb->pos) / len);
109                         } else {
110                                 job->set_progress_unknown ();
111                         }
112                 }
113
114                 AVCodecContext* context = _format_context->streams[_packet.stream_index]->codec;
115
116                 if (_packet.stream_index == _video_stream) {
117                         video_packet (context);
118                 }
119
120                 bool got_all_audio = true;
121
122                 for (size_t i = 0; i < _audio_streams.size(); ++i) {
123                         if (_audio_streams[i]->uses_index (_format_context, _packet.stream_index)) {
124                                 audio_packet (context, _audio_streams[i]);
125                         }
126                         if (!_audio_streams[i]->first_audio) {
127                                 got_all_audio = false;
128                         }
129                 }
130
131                 for (size_t i = 0; i < _subtitle_streams.size(); ++i) {
132                         if (_subtitle_streams[i]->uses_index (_format_context, _packet.stream_index)) {
133                                 subtitle_packet (context, _subtitle_streams[i]);
134                         }
135                 }
136
137                 av_free_packet (&_packet);
138
139                 if (_first_video && got_all_audio && _subtitle_streams.empty ()) {
140                         /* All done */
141                         break;
142                 }
143         }
144
145         for (LastSubtitleMap::const_iterator i = _last_subtitle_start.begin(); i != _last_subtitle_start.end(); ++i) {
146                 if (i->second) {
147                         i->first->add_subtitle (
148                                 ContentTimePeriod (
149                                         i->second.get (),
150                                         ContentTime::from_frames (video_length(), video_frame_rate().get_value_or (24))
151                                         )
152                                 );
153                 }
154         }
155
156         /* We just added subtitles to our streams without taking the PTS offset into account;
157            this is because we might not know the PTS offset when the first subtitle is seen.
158            Now we know the PTS offset so we can apply it to those subtitles.
159         */
160         if (video_frame_rate()) {
161                 BOOST_FOREACH (shared_ptr<FFmpegSubtitleStream> i, _subtitle_streams) {
162                         i->add_offset (pts_offset (_audio_streams, _first_video, video_frame_rate().get()));
163                 }
164         }
165 }
166
167 void
168 FFmpegExaminer::video_packet (AVCodecContext* context)
169 {
170         if (_first_video && !_need_video_length) {
171                 return;
172         }
173
174         int frame_finished;
175         if (avcodec_decode_video2 (context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
176                 if (!_first_video) {
177                         _first_video = frame_time (_format_context->streams[_video_stream]);
178                 }
179                 if (_need_video_length) {
180                         _video_length = frame_time (
181                                 _format_context->streams[_video_stream]
182                                 ).get_value_or (ContentTime ()).frames_round (video_frame_rate().get ());
183                 }
184         }
185 }
186
187 void
188 FFmpegExaminer::audio_packet (AVCodecContext* context, shared_ptr<FFmpegAudioStream> stream)
189 {
190         if (stream->first_audio) {
191                 return;
192         }
193
194         int frame_finished;
195         if (avcodec_decode_audio4 (context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
196                 stream->first_audio = frame_time (stream->stream (_format_context));
197         }
198 }
199
200 void
201 FFmpegExaminer::subtitle_packet (AVCodecContext* context, shared_ptr<FFmpegSubtitleStream> stream)
202 {
203         int frame_finished;
204         AVSubtitle sub;
205         if (avcodec_decode_subtitle2 (context, &sub, &frame_finished, &_packet) >= 0 && frame_finished) {
206                 FFmpegSubtitlePeriod const period = subtitle_period (sub);
207                 LastSubtitleMap::iterator last = _last_subtitle_start.find (stream);
208                 if (last != _last_subtitle_start.end() && last->second) {
209                         /* We have seen the start of a subtitle but not yet the end.  Whatever this is
210                            finishes the previous subtitle, so add it */
211                         stream->add_subtitle (ContentTimePeriod (last->second.get (), period.from));
212                         if (sub.num_rects == 0) {
213                                 /* This is a `proper' end-of-subtitle */
214                                 _last_subtitle_start[stream] = optional<ContentTime> ();
215                         } else {
216                                 /* This is just another subtitle, so we start again */
217                                 _last_subtitle_start[stream] = period.from;
218                         }
219                 } else if (sub.num_rects == 1) {
220                         if (period.to) {
221                                 stream->add_subtitle (ContentTimePeriod (period.from, period.to.get ()));
222                         } else {
223                                 _last_subtitle_start[stream] = period.from;
224                         }
225                 }
226                 avsubtitle_free (&sub);
227         }
228 }
229
230 optional<ContentTime>
231 FFmpegExaminer::frame_time (AVStream* s) const
232 {
233         optional<ContentTime> t;
234
235         int64_t const bet = av_frame_get_best_effort_timestamp (_frame);
236         if (bet != AV_NOPTS_VALUE) {
237                 t = ContentTime::from_seconds (bet * av_q2d (s->time_base));
238         }
239
240         return t;
241 }
242
243 optional<double>
244 FFmpegExaminer::video_frame_rate () const
245 {
246         /* This use of r_frame_rate is debateable; there's a few different
247          * frame rates in the format context, but this one seems to be the most
248          * reliable.
249          */
250         return av_q2d (av_stream_get_r_frame_rate (_format_context->streams[_video_stream]));
251 }
252
253 dcp::Size
254 FFmpegExaminer::video_size () const
255 {
256         return dcp::Size (video_codec_context()->width, video_codec_context()->height);
257 }
258
259 /** @return Length according to our content's header */
260 Frame
261 FFmpegExaminer::video_length () const
262 {
263         return max (Frame (1), _video_length);
264 }
265
266 optional<double>
267 FFmpegExaminer::sample_aspect_ratio () const
268 {
269         AVRational sar = av_guess_sample_aspect_ratio (_format_context, _format_context->streams[_video_stream], 0);
270         if (sar.num == 0) {
271                 /* I assume this means that we don't know */
272                 return optional<double> ();
273         }
274         return double (sar.num) / sar.den;
275 }
276
277 string
278 FFmpegExaminer::audio_stream_name (AVStream* s) const
279 {
280         SafeStringStream n;
281
282         n << stream_name (s);
283
284         if (!n.str().empty()) {
285                 n << "; ";
286         }
287
288         n << s->codec->channels << " channels";
289
290         return n.str ();
291 }
292
293 string
294 FFmpegExaminer::subtitle_stream_name (AVStream* s) const
295 {
296         SafeStringStream n;
297
298         n << stream_name (s);
299
300         if (n.str().empty()) {
301                 n << _("unknown");
302         }
303
304         return n.str ();
305 }
306
307 string
308 FFmpegExaminer::stream_name (AVStream* s) const
309 {
310         SafeStringStream n;
311
312         if (s->metadata) {
313                 AVDictionaryEntry const * lang = av_dict_get (s->metadata, "language", 0, 0);
314                 if (lang) {
315                         n << lang->value;
316                 }
317
318                 AVDictionaryEntry const * title = av_dict_get (s->metadata, "title", 0, 0);
319                 if (title) {
320                         if (!n.str().empty()) {
321                                 n << " ";
322                         }
323                         n << title->value;
324                 }
325         }
326
327         return n.str ();
328 }
329
330 int
331 FFmpegExaminer::bits_per_pixel () const
332 {
333         return av_get_bits_per_pixel (av_pix_fmt_desc_get (video_codec_context()->pix_fmt));
334 }
335
336 bool
337 FFmpegExaminer::yuv () const
338 {
339         switch (video_codec_context()->pix_fmt) {
340         case AV_PIX_FMT_YUV420P:
341         case AV_PIX_FMT_YUYV422:
342         case AV_PIX_FMT_YUV422P:
343         case AV_PIX_FMT_YUV444P:
344         case AV_PIX_FMT_YUV410P:
345         case AV_PIX_FMT_YUV411P:
346         case AV_PIX_FMT_YUVJ420P:
347         case AV_PIX_FMT_YUVJ422P:
348         case AV_PIX_FMT_YUVJ444P:
349         case AV_PIX_FMT_UYVY422:
350         case AV_PIX_FMT_UYYVYY411:
351         case AV_PIX_FMT_NV12:
352         case AV_PIX_FMT_NV21:
353         case AV_PIX_FMT_YUV440P:
354         case AV_PIX_FMT_YUVJ440P:
355         case AV_PIX_FMT_YUVA420P:
356         case AV_PIX_FMT_YUV420P16LE:
357         case AV_PIX_FMT_YUV420P16BE:
358         case AV_PIX_FMT_YUV422P16LE:
359         case AV_PIX_FMT_YUV422P16BE:
360         case AV_PIX_FMT_YUV444P16LE:
361         case AV_PIX_FMT_YUV444P16BE:
362         case AV_PIX_FMT_YUV420P9BE:
363         case AV_PIX_FMT_YUV420P9LE:
364         case AV_PIX_FMT_YUV420P10BE:
365         case AV_PIX_FMT_YUV420P10LE:
366         case AV_PIX_FMT_YUV422P10BE:
367         case AV_PIX_FMT_YUV422P10LE:
368         case AV_PIX_FMT_YUV444P9BE:
369         case AV_PIX_FMT_YUV444P9LE:
370         case AV_PIX_FMT_YUV444P10BE:
371         case AV_PIX_FMT_YUV444P10LE:
372         case AV_PIX_FMT_YUV422P9BE:
373         case AV_PIX_FMT_YUV422P9LE:
374         case AV_PIX_FMT_YUVA422P_LIBAV:
375         case AV_PIX_FMT_YUVA444P_LIBAV:
376         case AV_PIX_FMT_YUVA420P9BE:
377         case AV_PIX_FMT_YUVA420P9LE:
378         case AV_PIX_FMT_YUVA422P9BE:
379         case AV_PIX_FMT_YUVA422P9LE:
380         case AV_PIX_FMT_YUVA444P9BE:
381         case AV_PIX_FMT_YUVA444P9LE:
382         case AV_PIX_FMT_YUVA420P10BE:
383         case AV_PIX_FMT_YUVA420P10LE:
384         case AV_PIX_FMT_YUVA422P10BE:
385         case AV_PIX_FMT_YUVA422P10LE:
386         case AV_PIX_FMT_YUVA444P10BE:
387         case AV_PIX_FMT_YUVA444P10LE:
388         case AV_PIX_FMT_YUVA420P16BE:
389         case AV_PIX_FMT_YUVA420P16LE:
390         case AV_PIX_FMT_YUVA422P16BE:
391         case AV_PIX_FMT_YUVA422P16LE:
392         case AV_PIX_FMT_YUVA444P16BE:
393         case AV_PIX_FMT_YUVA444P16LE:
394         case AV_PIX_FMT_NV16:
395         case AV_PIX_FMT_NV20LE:
396         case AV_PIX_FMT_NV20BE:
397         case AV_PIX_FMT_YVYU422:
398         case AV_PIX_FMT_YUVA444P:
399         case AV_PIX_FMT_YUVA422P:
400         case AV_PIX_FMT_YUV420P12BE:
401         case AV_PIX_FMT_YUV420P12LE:
402         case AV_PIX_FMT_YUV420P14BE:
403         case AV_PIX_FMT_YUV420P14LE:
404         case AV_PIX_FMT_YUV422P12BE:
405         case AV_PIX_FMT_YUV422P12LE:
406         case AV_PIX_FMT_YUV422P14BE:
407         case AV_PIX_FMT_YUV422P14LE:
408         case AV_PIX_FMT_YUV444P12BE:
409         case AV_PIX_FMT_YUV444P12LE:
410         case AV_PIX_FMT_YUV444P14BE:
411         case AV_PIX_FMT_YUV444P14LE:
412         case AV_PIX_FMT_YUVJ411P:
413                 return true;
414         default:
415                 return false;
416         }
417 }