bf9bafbfa8400a6c24a7386913e1bc0480e81e8b
[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                         DCPOMATIC_ASSERT (_format_context->duration != AV_NOPTS_VALUE);
65
66                         _audio_streams.push_back (
67                                 shared_ptr<FFmpegAudioStream> (
68                                         new FFmpegAudioStream (
69                                                 audio_stream_name (s),
70                                                 s->id,
71                                                 s->codec->sample_rate,
72                                                 (double (_format_context->duration) / AV_TIME_BASE) * s->codec->sample_rate,
73                                                 s->codec->channels
74                                                 )
75                                         )
76                                 );
77
78                 } else if (s->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
79                         _subtitle_streams.push_back (shared_ptr<FFmpegSubtitleStream> (new FFmpegSubtitleStream (subtitle_stream_name (s), s->id)));
80                 }
81         }
82
83         if (has_video ()) {
84                 /* See if the header has duration information in it */
85                 _need_video_length = _format_context->duration == AV_NOPTS_VALUE;
86                 if (!_need_video_length) {
87                         _video_length = (double (_format_context->duration) / AV_TIME_BASE) * video_frame_rate().get ();
88                 }
89         }
90
91         if (job) {
92                 if (_need_video_length) {
93                         job->sub (_("Finding length and subtitles"));
94                 } else {
95                         job->sub (_("Finding subtitles"));
96                 }
97         }
98
99         /* Run through until we find:
100          *   - the first video.
101          *   - the first audio for each stream.
102          *   - the subtitle periods for each stream.
103          *
104          * We have to note subtitle periods as otherwise we have no way of knowing
105          * where we should look for subtitles (video and audio are always present,
106          * so they are ok).
107          */
108
109         int64_t const len = _file_group.length ();
110         while (true) {
111                 int r = av_read_frame (_format_context, &_packet);
112                 if (r < 0) {
113                         break;
114                 }
115
116                 if (job) {
117                         if (len > 0) {
118                                 job->set_progress (float (_format_context->pb->pos) / len);
119                         } else {
120                                 job->set_progress_unknown ();
121                         }
122                 }
123
124                 AVCodecContext* context = _format_context->streams[_packet.stream_index]->codec;
125
126                 if (_video_stream && _packet.stream_index == _video_stream.get()) {
127                         video_packet (context);
128                 }
129
130                 bool got_all_audio = true;
131
132                 for (size_t i = 0; i < _audio_streams.size(); ++i) {
133                         if (_audio_streams[i]->uses_index (_format_context, _packet.stream_index)) {
134                                 audio_packet (context, _audio_streams[i]);
135                         }
136                         if (!_audio_streams[i]->first_audio) {
137                                 got_all_audio = false;
138                         }
139                 }
140
141                 for (size_t i = 0; i < _subtitle_streams.size(); ++i) {
142                         if (_subtitle_streams[i]->uses_index (_format_context, _packet.stream_index)) {
143                                 subtitle_packet (context, _subtitle_streams[i]);
144                         }
145                 }
146
147                 av_packet_unref (&_packet);
148
149                 if (_first_video && got_all_audio && _subtitle_streams.empty ()) {
150                         /* All done */
151                         break;
152                 }
153         }
154
155         /* Finish off any hanging subtitles at the end */
156         for (LastSubtitleMap::const_iterator i = _last_subtitle_start.begin(); i != _last_subtitle_start.end(); ++i) {
157                 if (i->second) {
158                         if (i->second->image) {
159                                 i->first->add_image_subtitle (
160                                         i->second->id,
161                                         ContentTimePeriod (
162                                                 i->second->time,
163                                                 ContentTime::from_frames (video_length(), video_frame_rate().get_value_or (24))
164                                                 )
165                                         );
166                         } else {
167                                 i->first->add_text_subtitle (
168                                         i->second->id,
169                                         ContentTimePeriod (
170                                                 i->second->time,
171                                                 ContentTime::from_frames (video_length(), video_frame_rate().get_value_or (24))
172                                                 )
173                                         );
174                         }
175                 }
176         }
177
178         /* We just added subtitles to our streams without taking the PTS offset into account;
179            this is because we might not know the PTS offset when the first subtitle is seen.
180            Now we know the PTS offset so we can apply it to those subtitles.
181         */
182         if (has_video() && video_frame_rate()) {
183                 BOOST_FOREACH (shared_ptr<FFmpegSubtitleStream> i, _subtitle_streams) {
184                         i->add_offset (pts_offset (_audio_streams, _first_video, video_frame_rate().get()));
185                 }
186         }
187 }
188
189 void
190 FFmpegExaminer::video_packet (AVCodecContext* context)
191 {
192         DCPOMATIC_ASSERT (_video_stream);
193
194         if (_first_video && !_need_video_length) {
195                 return;
196         }
197
198         int frame_finished;
199         if (avcodec_decode_video2 (context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
200                 if (!_first_video) {
201                         _first_video = frame_time (_format_context->streams[_video_stream.get()]);
202                 }
203                 if (_need_video_length) {
204                         _video_length = frame_time (
205                                 _format_context->streams[_video_stream.get()]
206                                 ).get_value_or (ContentTime ()).frames_round (video_frame_rate().get ());
207                 }
208         }
209 }
210
211 void
212 FFmpegExaminer::audio_packet (AVCodecContext* context, shared_ptr<FFmpegAudioStream> stream)
213 {
214         if (stream->first_audio) {
215                 return;
216         }
217
218         int frame_finished;
219         if (avcodec_decode_audio4 (context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) {
220                 stream->first_audio = frame_time (stream->stream (_format_context));
221         }
222 }
223
224 void
225 FFmpegExaminer::subtitle_packet (AVCodecContext* context, shared_ptr<FFmpegSubtitleStream> stream)
226 {
227         int frame_finished;
228         AVSubtitle sub;
229         if (avcodec_decode_subtitle2 (context, &sub, &frame_finished, &_packet) >= 0 && frame_finished) {
230                 string id = subtitle_id (sub);
231                 FFmpegSubtitlePeriod const period = subtitle_period (sub);
232                 bool const starts_image = subtitle_starts_image (sub);
233
234                 LastSubtitleMap::iterator last = _last_subtitle_start.find (stream);
235                 if (last != _last_subtitle_start.end() && last->second) {
236                         /* We have seen the start of a subtitle but not yet the end.  Whatever this is
237                            finishes the previous subtitle, so add it */
238                         if (last->second->image) {
239                                 stream->add_image_subtitle (last->second->id, ContentTimePeriod (last->second->time, period.from));
240                         } else {
241                                 stream->add_text_subtitle (last->second->id, ContentTimePeriod (last->second->time, period.from));
242                         }
243                         if (sub.num_rects == 0) {
244                                 /* This is a `proper' end-of-subtitle */
245                                 _last_subtitle_start[stream] = optional<SubtitleStart> ();
246                         } else {
247                                 /* This is just another subtitle, so we start again */
248                                 _last_subtitle_start[stream] = SubtitleStart (id, starts_image, period.from);
249                         }
250                 } else if (sub.num_rects == 1) {
251                         if (period.to) {
252                                 if (starts_image) {
253                                         stream->add_image_subtitle (id, ContentTimePeriod (period.from, period.to.get ()));
254                                 } else {
255                                         stream->add_text_subtitle (id, ContentTimePeriod (period.from, period.to.get ()));
256                                 }
257                         } else {
258                                 _last_subtitle_start[stream] = SubtitleStart (id, starts_image, period.from);
259                         }
260                 }
261
262                 for (unsigned int i = 0; i < sub.num_rects; ++i) {
263                         if (sub.rects[i]->type == SUBTITLE_BITMAP) {
264 #ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT
265                                 uint32_t* palette = (uint32_t *) sub.rects[i]->pict.data[1];
266                                 for (int j = 0; j < sub.rects[i]->nb_colors; ++j) {
267                                         RGBA rgba  (
268                                                 (palette[j] & 0x00ff0000) >> 16,
269                                                 (palette[j] & 0x0000ff00) >> 8,
270                                                 (palette[j] & 0x000000ff) >> 0,
271                                                 (palette[j] & 0xff000000) >> 24
272                                                 );
273
274                                         stream->set_colour (rgba, rgba);
275                                 }
276 #else
277                                 uint32_t* palette = (uint32_t *) sub.rects[i]->data[1];
278                                 for (int j = 0; j < sub.rects[i]->nb_colors; ++j) {
279                                         RGBA rgba  (
280                                                 (palette[j] & 0x00ff0000) >> 16,
281                                                 (palette[j] & 0x0000ff00) >> 8,
282                                                 (palette[j] & 0x000000ff) >> 0,
283                                                 (palette[j] & 0xff000000) >> 24
284                                                 );
285
286                                         stream->set_colour (rgba, rgba);
287                                 }
288 #endif
289                         }
290                 }
291
292                 avsubtitle_free (&sub);
293         }
294 }
295
296 optional<ContentTime>
297 FFmpegExaminer::frame_time (AVStream* s) const
298 {
299         optional<ContentTime> t;
300
301         int64_t const bet = av_frame_get_best_effort_timestamp (_frame);
302         if (bet != AV_NOPTS_VALUE) {
303                 t = ContentTime::from_seconds (bet * av_q2d (s->time_base));
304         }
305
306         return t;
307 }
308
309 optional<double>
310 FFmpegExaminer::video_frame_rate () const
311 {
312         DCPOMATIC_ASSERT (_video_stream);
313         /* This use of r_frame_rate is debateable; there's a few different
314          * frame rates in the format context, but this one seems to be the most
315          * reliable.
316          */
317         return av_q2d (av_stream_get_r_frame_rate (_format_context->streams[_video_stream.get()]));
318 }
319
320 dcp::Size
321 FFmpegExaminer::video_size () const
322 {
323         return dcp::Size (video_codec_context()->width, video_codec_context()->height);
324 }
325
326 /** @return Length according to our content's header */
327 Frame
328 FFmpegExaminer::video_length () const
329 {
330         return max (Frame (1), _video_length);
331 }
332
333 optional<double>
334 FFmpegExaminer::sample_aspect_ratio () const
335 {
336         DCPOMATIC_ASSERT (_video_stream);
337         AVRational sar = av_guess_sample_aspect_ratio (_format_context, _format_context->streams[_video_stream.get()], 0);
338         if (sar.num == 0) {
339                 /* I assume this means that we don't know */
340                 return optional<double> ();
341         }
342         return double (sar.num) / sar.den;
343 }
344
345 string
346 FFmpegExaminer::audio_stream_name (AVStream* s) const
347 {
348         SafeStringStream n;
349
350         n << stream_name (s);
351
352         if (!n.str().empty()) {
353                 n << "; ";
354         }
355
356         n << s->codec->channels << " channels";
357
358         return n.str ();
359 }
360
361 string
362 FFmpegExaminer::subtitle_stream_name (AVStream* s) const
363 {
364         SafeStringStream n;
365
366         n << stream_name (s);
367
368         if (n.str().empty()) {
369                 n << _("unknown");
370         }
371
372         return n.str ();
373 }
374
375 string
376 FFmpegExaminer::stream_name (AVStream* s) const
377 {
378         SafeStringStream n;
379
380         if (s->metadata) {
381                 AVDictionaryEntry const * lang = av_dict_get (s->metadata, "language", 0, 0);
382                 if (lang) {
383                         n << lang->value;
384                 }
385
386                 AVDictionaryEntry const * title = av_dict_get (s->metadata, "title", 0, 0);
387                 if (title) {
388                         if (!n.str().empty()) {
389                                 n << " ";
390                         }
391                         n << title->value;
392                 }
393         }
394
395         return n.str ();
396 }
397
398 int
399 FFmpegExaminer::bits_per_pixel () const
400 {
401         if (video_codec_context()->pix_fmt == -1) {
402                 throw DecodeError (_("Could not find pixel format for video."));
403         }
404
405         AVPixFmtDescriptor const * d = av_pix_fmt_desc_get (video_codec_context()->pix_fmt);
406         DCPOMATIC_ASSERT (d);
407         return av_get_bits_per_pixel (d);
408 }
409
410 bool
411 FFmpegExaminer::yuv () const
412 {
413         switch (video_codec_context()->pix_fmt) {
414         case AV_PIX_FMT_YUV420P:
415         case AV_PIX_FMT_YUYV422:
416         case AV_PIX_FMT_YUV422P:
417         case AV_PIX_FMT_YUV444P:
418         case AV_PIX_FMT_YUV410P:
419         case AV_PIX_FMT_YUV411P:
420         case AV_PIX_FMT_YUVJ420P:
421         case AV_PIX_FMT_YUVJ422P:
422         case AV_PIX_FMT_YUVJ444P:
423         case AV_PIX_FMT_UYVY422:
424         case AV_PIX_FMT_UYYVYY411:
425         case AV_PIX_FMT_NV12:
426         case AV_PIX_FMT_NV21:
427         case AV_PIX_FMT_YUV440P:
428         case AV_PIX_FMT_YUVJ440P:
429         case AV_PIX_FMT_YUVA420P:
430         case AV_PIX_FMT_YUV420P16LE:
431         case AV_PIX_FMT_YUV420P16BE:
432         case AV_PIX_FMT_YUV422P16LE:
433         case AV_PIX_FMT_YUV422P16BE:
434         case AV_PIX_FMT_YUV444P16LE:
435         case AV_PIX_FMT_YUV444P16BE:
436         case AV_PIX_FMT_YUV420P9BE:
437         case AV_PIX_FMT_YUV420P9LE:
438         case AV_PIX_FMT_YUV420P10BE:
439         case AV_PIX_FMT_YUV420P10LE:
440         case AV_PIX_FMT_YUV422P10BE:
441         case AV_PIX_FMT_YUV422P10LE:
442         case AV_PIX_FMT_YUV444P9BE:
443         case AV_PIX_FMT_YUV444P9LE:
444         case AV_PIX_FMT_YUV444P10BE:
445         case AV_PIX_FMT_YUV444P10LE:
446         case AV_PIX_FMT_YUV422P9BE:
447         case AV_PIX_FMT_YUV422P9LE:
448         case AV_PIX_FMT_YUVA420P9BE:
449         case AV_PIX_FMT_YUVA420P9LE:
450         case AV_PIX_FMT_YUVA422P9BE:
451         case AV_PIX_FMT_YUVA422P9LE:
452         case AV_PIX_FMT_YUVA444P9BE:
453         case AV_PIX_FMT_YUVA444P9LE:
454         case AV_PIX_FMT_YUVA420P10BE:
455         case AV_PIX_FMT_YUVA420P10LE:
456         case AV_PIX_FMT_YUVA422P10BE:
457         case AV_PIX_FMT_YUVA422P10LE:
458         case AV_PIX_FMT_YUVA444P10BE:
459         case AV_PIX_FMT_YUVA444P10LE:
460         case AV_PIX_FMT_YUVA420P16BE:
461         case AV_PIX_FMT_YUVA420P16LE:
462         case AV_PIX_FMT_YUVA422P16BE:
463         case AV_PIX_FMT_YUVA422P16LE:
464         case AV_PIX_FMT_YUVA444P16BE:
465         case AV_PIX_FMT_YUVA444P16LE:
466         case AV_PIX_FMT_NV16:
467         case AV_PIX_FMT_NV20LE:
468         case AV_PIX_FMT_NV20BE:
469         case AV_PIX_FMT_YVYU422:
470         case AV_PIX_FMT_YUVA444P:
471         case AV_PIX_FMT_YUVA422P:
472         case AV_PIX_FMT_YUV420P12BE:
473         case AV_PIX_FMT_YUV420P12LE:
474         case AV_PIX_FMT_YUV420P14BE:
475         case AV_PIX_FMT_YUV420P14LE:
476         case AV_PIX_FMT_YUV422P12BE:
477         case AV_PIX_FMT_YUV422P12LE:
478         case AV_PIX_FMT_YUV422P14BE:
479         case AV_PIX_FMT_YUV422P14LE:
480         case AV_PIX_FMT_YUV444P12BE:
481         case AV_PIX_FMT_YUV444P12LE:
482         case AV_PIX_FMT_YUV444P14BE:
483         case AV_PIX_FMT_YUV444P14LE:
484         case AV_PIX_FMT_YUVJ411P:
485                 return true;
486         default:
487                 return false;
488         }
489 }
490
491 bool
492 FFmpegExaminer::has_video () const
493 {
494         return static_cast<bool> (_video_stream);
495 }