Rename TYPE_DEBUG_PLAYER to TYPE_DEBUG_VIDEO_VIEW.
[dcpomatic.git] / src / lib / ffmpeg.cc
index 5171166d5f0e9aeea6ea9ae60cbe5dd391cf79df..8eb19816c0828b44b1dfc82bc030f19d37378ea5 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 #include "exceptions.h"
 #include "util.h"
 #include "log.h"
+#include "dcpomatic_log.h"
 #include "ffmpeg_subtitle_stream.h"
 #include "ffmpeg_audio_stream.h"
+#include "decrypted_ecinema_kdm.h"
 #include "digester.h"
 #include "compose.hpp"
+#include "config.h"
 #include <dcp/raw_convert.h>
 extern "C" {
 #include <libavcodec/avcodec.h>
@@ -47,9 +50,9 @@ using std::vector;
 using boost::shared_ptr;
 using boost::optional;
 using dcp::raw_convert;
+using namespace dcpomatic;
 
 boost::mutex FFmpeg::_mutex;
-boost::weak_ptr<Log> FFmpeg::_ffmpeg_log;
 
 FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> c)
        : _ffmpeg_content (c)
@@ -97,14 +100,9 @@ FFmpeg::ffmpeg_log_callback (void* ptr, int level, const char* fmt, va_list vl)
        char line[1024];
        static int prefix = 0;
        av_log_format_line (ptr, level, fmt, vl, line, sizeof (line), &prefix);
-       shared_ptr<Log> log = _ffmpeg_log.lock ();
-       if (log) {
-               string str (line);
-               boost::algorithm::trim (str);
-               log->log (String::compose ("FFmpeg: %1", str), LogEntry::TYPE_GENERAL);
-       } else {
-               cerr << line;
-       }
+       string str (line);
+       boost::algorithm::trim (str);
+       dcpomatic_log->log (String::compose ("FFmpeg: %1", str), LogEntry::TYPE_GENERAL);
 }
 
 void
@@ -113,25 +111,31 @@ FFmpeg::setup_general ()
        /* This might not work too well in some cases of multiple FFmpeg decoders,
           but it's probably good enough.
        */
-       _ffmpeg_log = _ffmpeg_content->film()->log ();
        av_log_set_callback (FFmpeg::ffmpeg_log_callback);
 
        _file_group.set_paths (_ffmpeg_content->paths ());
        _avio_buffer = static_cast<uint8_t*> (wrapped_av_malloc (_avio_buffer_size));
        _avio_context = avio_alloc_context (_avio_buffer, _avio_buffer_size, 0, this, avio_read_wrapper, 0, avio_seek_wrapper);
+       if (!_avio_context) {
+               throw std::bad_alloc ();
+       }
        _format_context = avformat_alloc_context ();
+       if (!_format_context) {
+               throw std::bad_alloc ();
+       }
        _format_context->pb = _avio_context;
 
        AVDictionary* options = 0;
-       /* These durations are in microseconds, and represent how far into the content file
-          we will look for streams.
-       */
-       av_dict_set (&options, "analyzeduration", raw_convert<string> (5 * 60 * 1000000).c_str(), 0);
-       av_dict_set (&options, "probesize", raw_convert<string> (5 * 60 * 1000000).c_str(), 0);
+#ifdef DCPOMATIC_VARIANT_SWAROOP
+       if (_ffmpeg_content->kdm()) {
+               DecryptedECinemaKDM kdm (_ffmpeg_content->kdm().get(), Config::instance()->decryption_chain()->key().get());
+               av_dict_set (&options, "decryption_key", kdm.key().hex().c_str(), 0);
+       }
+#endif
 
        int e = avformat_open_input (&_format_context, 0, 0, &options);
        if (e < 0) {
-               throw OpenFileError (_ffmpeg_content->path(0).string(), e, true);
+               throw OpenFileError (_ffmpeg_content->path(0).string(), e, OpenFileError::READ);
        }
 
        if (avformat_find_stream_info (_format_context, 0) < 0) {
@@ -162,6 +166,11 @@ FFmpeg::setup_general ()
                _video_stream = video_stream_undefined_frame_rate.get();
        }
 
+       /* Ignore video streams with crazy frame rates.  These are usually things like album art on MP3s. */
+       if (_video_stream && av_q2d(av_guess_frame_rate(_format_context, _format_context->streams[_video_stream.get()], 0)) > 1000) {
+               _video_stream = optional<int>();
+       }
+
        /* Hack: if the AVStreams have duplicate IDs, replace them with our
           own.  We use the IDs so that we can cope with VOBs, in which streams
           move about in index but remain with the same ID in different
@@ -211,15 +220,14 @@ FFmpeg::setup_decoders ()
                           https://trac.ffmpeg.org/ticket/5681
                        */
                        av_dict_set_int (&options, "strict", FF_COMPLIANCE_EXPERIMENTAL, 0);
+                       /* Enable following of links in files */
+                       av_dict_set_int (&options, "enable_drefs", 1, 0);
 
                        if (avcodec_open2 (context, codec, &options) < 0) {
                                throw DecodeError (N_("could not open decoder"));
                        }
                } else {
-                       shared_ptr<Log> log = _ffmpeg_log.lock ();
-                       if (log) {
-                               log->log (String::compose ("No codec found for stream %1", i), LogEntry::TYPE_WARNING);
-                       }
+                       dcpomatic_log->log (String::compose ("No codec found for stream %1", i), LogEntry::TYPE_WARNING);
                }
        }
 }