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