Merge branch 'warnings' into v2.15.x.
[dcpomatic.git] / src / lib / ffmpeg.cc
1 /*
2     Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
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.
10
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.
15
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/>.
18
19 */
20
21 #include "ffmpeg.h"
22 #include "ffmpeg_content.h"
23 #include "film.h"
24 #include "exceptions.h"
25 #include "util.h"
26 #include "log.h"
27 #include "dcpomatic_log.h"
28 #include "ffmpeg_subtitle_stream.h"
29 #include "ffmpeg_audio_stream.h"
30 #include "decrypted_ecinema_kdm.h"
31 #include "digester.h"
32 #include "compose.hpp"
33 #include "config.h"
34 #include <dcp/raw_convert.h>
35 extern "C" {
36 #include <libavcodec/avcodec.h>
37 #include <libavformat/avformat.h>
38 #include <libswscale/swscale.h>
39 }
40 #include <boost/algorithm/string.hpp>
41 #include <boost/foreach.hpp>
42 #include <iostream>
43
44 #include "i18n.h"
45
46 using std::string;
47 using std::cout;
48 using std::cerr;
49 using std::vector;
50 using boost::shared_ptr;
51 using boost::optional;
52 using dcp::raw_convert;
53 using namespace dcpomatic;
54
55 boost::mutex FFmpeg::_mutex;
56
57 FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> c)
58         : _ffmpeg_content (c)
59         , _avio_buffer (0)
60         , _avio_buffer_size (4096)
61         , _avio_context (0)
62         , _format_context (0)
63         , _frame (0)
64 {
65         setup_general ();
66         setup_decoders ();
67 }
68
69 FFmpeg::~FFmpeg ()
70 {
71         boost::mutex::scoped_lock lm (_mutex);
72
73 DCPOMATIC_DISABLE_WARNINGS
74         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
75                 avcodec_close (_format_context->streams[i]->codec);
76         }
77 DCPOMATIC_ENABLE_WARNINGS
78
79         av_frame_free (&_frame);
80         avformat_close_input (&_format_context);
81 }
82
83 static int
84 avio_read_wrapper (void* data, uint8_t* buffer, int amount)
85 {
86         return reinterpret_cast<FFmpeg*>(data)->avio_read (buffer, amount);
87 }
88
89 static int64_t
90 avio_seek_wrapper (void* data, int64_t offset, int whence)
91 {
92         return reinterpret_cast<FFmpeg*>(data)->avio_seek (offset, whence);
93 }
94
95 void
96 FFmpeg::ffmpeg_log_callback (void* ptr, int level, const char* fmt, va_list vl)
97 {
98         if (level > AV_LOG_WARNING) {
99                 return;
100         }
101
102         char line[1024];
103         static int prefix = 0;
104         av_log_format_line (ptr, level, fmt, vl, line, sizeof (line), &prefix);
105         string str (line);
106         boost::algorithm::trim (str);
107         dcpomatic_log->log (String::compose ("FFmpeg: %1", str), LogEntry::TYPE_GENERAL);
108 }
109
110 void
111 FFmpeg::setup_general ()
112 {
113         /* This might not work too well in some cases of multiple FFmpeg decoders,
114            but it's probably good enough.
115         */
116         av_log_set_callback (FFmpeg::ffmpeg_log_callback);
117
118         _file_group.set_paths (_ffmpeg_content->paths ());
119         _avio_buffer = static_cast<uint8_t*> (wrapped_av_malloc (_avio_buffer_size));
120         _avio_context = avio_alloc_context (_avio_buffer, _avio_buffer_size, 0, this, avio_read_wrapper, 0, avio_seek_wrapper);
121         if (!_avio_context) {
122                 throw std::bad_alloc ();
123         }
124         _format_context = avformat_alloc_context ();
125         if (!_format_context) {
126                 throw std::bad_alloc ();
127         }
128         _format_context->pb = _avio_context;
129
130         AVDictionary* options = 0;
131 #ifdef DCPOMATIC_VARIANT_SWAROOP
132         if (_ffmpeg_content->kdm()) {
133                 DecryptedECinemaKDM kdm (_ffmpeg_content->kdm().get(), Config::instance()->decryption_chain()->key().get());
134                 av_dict_set (&options, "decryption_key", kdm.key().hex().c_str(), 0);
135         }
136 #endif
137
138         int e = avformat_open_input (&_format_context, 0, 0, &options);
139         if (e < 0) {
140                 throw OpenFileError (_ffmpeg_content->path(0).string(), e, OpenFileError::READ);
141         }
142
143         if (avformat_find_stream_info (_format_context, 0) < 0) {
144                 throw DecodeError (_("could not find stream information"));
145         }
146
147         /* Find video stream */
148
149         optional<int> video_stream_undefined_frame_rate;
150
151 DCPOMATIC_DISABLE_WARNINGS
152         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
153                 AVStream* s = _format_context->streams[i];
154                 if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO && avcodec_find_decoder(s->codec->codec_id)) {
155                         if (s->avg_frame_rate.num > 0 && s->avg_frame_rate.den > 0) {
156                                 /* This is definitely our video stream */
157                                 _video_stream = i;
158                         } else {
159                                 /* This is our video stream if we don't get a better offer */
160                                 video_stream_undefined_frame_rate = i;
161                         }
162                 }
163         }
164 DCPOMATIC_ENABLE_WARNINGS
165
166         /* Files from iTunes sometimes have two video streams, one with the avg_frame_rate.num and .den set
167            to zero.  Only use such a stream if there is no alternative.
168         */
169         if (!_video_stream && video_stream_undefined_frame_rate) {
170                 _video_stream = video_stream_undefined_frame_rate.get();
171         }
172
173         /* Ignore video streams with crazy frame rates.  These are usually things like album art on MP3s. */
174         if (_video_stream && av_q2d(av_guess_frame_rate(_format_context, _format_context->streams[_video_stream.get()], 0)) > 1000) {
175                 _video_stream = optional<int>();
176         }
177
178         /* Hack: if the AVStreams have duplicate IDs, replace them with our
179            own.  We use the IDs so that we can cope with VOBs, in which streams
180            move about in index but remain with the same ID in different
181            VOBs.  However, some files have duplicate IDs, hence this hack.
182         */
183
184         bool duplicates = false;
185         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
186                 for (uint32_t j = i + 1; j < _format_context->nb_streams; ++j) {
187                         if (_format_context->streams[i]->id == _format_context->streams[j]->id) {
188                                 duplicates = true;
189                         }
190                 }
191         }
192
193         if (duplicates) {
194                 /* Put in our own IDs */
195                 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
196                         _format_context->streams[i]->id = i;
197                 }
198         }
199
200         _frame = av_frame_alloc ();
201         if (_frame == 0) {
202                 throw DecodeError (N_("could not allocate frame"));
203         }
204 }
205
206 void
207 FFmpeg::setup_decoders ()
208 {
209         boost::mutex::scoped_lock lm (_mutex);
210
211 DCPOMATIC_DISABLE_WARNINGS
212         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
213                 AVCodecContext* context = _format_context->streams[i]->codec;
214
215                 AVCodec* codec = avcodec_find_decoder (context->codec_id);
216                 if (codec) {
217
218                         AVDictionary* options = 0;
219                         /* This option disables decoding of DCA frame footers in our patched version
220                            of FFmpeg.  I believe these footers are of no use to us, and they can cause
221                            problems when FFmpeg fails to decode them (mantis #352).
222                         */
223                         av_dict_set (&options, "disable_footer", "1", 0);
224                         /* This allows decoding of some DNxHR 444 and HQX files; see
225                            https://trac.ffmpeg.org/ticket/5681
226                         */
227                         av_dict_set_int (&options, "strict", FF_COMPLIANCE_EXPERIMENTAL, 0);
228                         /* Enable following of links in files */
229                         av_dict_set_int (&options, "enable_drefs", 1, 0);
230
231                         if (avcodec_open2 (context, codec, &options) < 0) {
232                                 throw DecodeError (N_("could not open decoder"));
233                         }
234                 } else {
235                         dcpomatic_log->log (String::compose ("No codec found for stream %1", i), LogEntry::TYPE_WARNING);
236                 }
237         }
238 DCPOMATIC_ENABLE_WARNINGS
239 }
240
241 DCPOMATIC_DISABLE_WARNINGS
242 AVCodecContext *
243 FFmpeg::video_codec_context () const
244 {
245         if (!_video_stream) {
246                 return 0;
247         }
248
249         return _format_context->streams[_video_stream.get()]->codec;
250 }
251
252 AVCodecContext *
253 FFmpeg::subtitle_codec_context () const
254 {
255         if (!_ffmpeg_content->subtitle_stream ()) {
256                 return 0;
257         }
258
259         return _ffmpeg_content->subtitle_stream()->stream(_format_context)->codec;
260 }
261 DCPOMATIC_ENABLE_WARNINGS
262
263 int
264 FFmpeg::avio_read (uint8_t* buffer, int const amount)
265 {
266         return _file_group.read (buffer, amount);
267 }
268
269 int64_t
270 FFmpeg::avio_seek (int64_t const pos, int whence)
271 {
272         if (whence == AVSEEK_SIZE) {
273                 return _file_group.length ();
274         }
275
276         return _file_group.seek (pos, whence);
277 }
278
279 FFmpegSubtitlePeriod
280 FFmpeg::subtitle_period (AVSubtitle const & sub)
281 {
282         ContentTime const packet_time = ContentTime::from_seconds (static_cast<double> (sub.pts) / AV_TIME_BASE);
283
284         if (sub.end_display_time == static_cast<uint32_t> (-1)) {
285                 /* End time is not known */
286                 return FFmpegSubtitlePeriod (packet_time + ContentTime::from_seconds (sub.start_display_time / 1e3));
287         }
288
289         return FFmpegSubtitlePeriod (
290                 packet_time + ContentTime::from_seconds (sub.start_display_time / 1e3),
291                 packet_time + ContentTime::from_seconds (sub.end_display_time / 1e3)
292                 );
293 }
294
295 /** Compute the pts offset to use given a set of audio streams and some video details.
296  *  Sometimes these parameters will have just been determined by an Examiner, sometimes
297  *  they will have been retrieved from a piece of Content, hence the need for this method
298  *  in FFmpeg.
299  */
300 ContentTime
301 FFmpeg::pts_offset (vector<shared_ptr<FFmpegAudioStream> > audio_streams, optional<ContentTime> first_video, double video_frame_rate) const
302 {
303         /* Audio and video frame PTS values may not start with 0.  We want
304            to fiddle them so that:
305
306            1.  One of them starts at time 0.
307            2.  The first video PTS value ends up on a frame boundary.
308
309            Then we remove big initial gaps in PTS and we allow our
310            insertion of black frames to work.
311
312            We will do:
313              audio_pts_to_use = audio_pts_from_ffmpeg + pts_offset;
314              video_pts_to_use = video_pts_from_ffmpeg + pts_offset;
315         */
316
317         /* First, make one of them start at 0 */
318
319         ContentTime po = ContentTime::min ();
320
321         if (first_video) {
322                 po = - first_video.get ();
323         }
324
325         BOOST_FOREACH (shared_ptr<FFmpegAudioStream> i, audio_streams) {
326                 if (i->first_audio) {
327                         po = max (po, - i->first_audio.get ());
328                 }
329         }
330
331         /* If the offset is positive we would be pushing things from a -ve PTS to be played.
332            I don't think we ever want to do that, as it seems things at -ve PTS are not meant
333            to be seen (use for alignment bars etc.); see mantis #418.
334         */
335         if (po > ContentTime ()) {
336                 po = ContentTime ();
337         }
338
339         /* Now adjust so that the video pts starts on a frame */
340         if (first_video) {
341                 ContentTime const fvc = first_video.get() + po;
342                 po += fvc.ceil (video_frame_rate) - fvc;
343         }
344
345         return po;
346 }