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