Only do long probes of FFmpeg content with the examiner, not the decoder.
[dcpomatic.git] / src / lib / ffmpeg.cc
1 /*
2     Copyright (C) 2013 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 <libswscale/swscale.h>
24 #include <libpostproc/postprocess.h>
25 }
26 #include "ffmpeg.h"
27 #include "ffmpeg_content.h"
28 #include "exceptions.h"
29
30 #include "i18n.h"
31
32 using std::string;
33 using std::cout;
34 using std::stringstream;
35 using boost::shared_ptr;
36 using boost::lexical_cast;
37
38 boost::mutex FFmpeg::_mutex;
39
40 /** @param long_probe true to do a long probe of the file looking for streams */
41 FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> c, bool long_probe)
42         : _ffmpeg_content (c)
43         , _format_context (0)
44         , _frame (0)
45         , _video_stream (-1)
46 {
47         setup_general (long_probe);
48         setup_video ();
49         setup_audio ();
50 }
51
52 FFmpeg::~FFmpeg ()
53 {
54         boost::mutex::scoped_lock lm (_mutex);
55
56         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
57                 AVCodecContext* context = _format_context->streams[i]->codec;
58                 if (context->codec_type == AVMEDIA_TYPE_VIDEO || context->codec_type == AVMEDIA_TYPE_AUDIO) {
59                         avcodec_close (context);
60                 }
61         }
62
63         avcodec_free_frame (&_frame);
64         
65         avformat_close_input (&_format_context);
66 }
67
68 void
69 FFmpeg::setup_general (bool long_probe)
70 {
71         av_register_all ();
72
73         AVDictionary* options = 0;
74         if (long_probe) {
75                 /* These durations are in microseconds, and represent how far into the content file
76                    we will look for streams.
77                 */
78                 av_dict_set (&options, "analyzeduration", lexical_cast<string> (5 * 60 * 1e6).c_str(), 0);
79                 av_dict_set (&options, "probesize", lexical_cast<string> (5 * 60 * 1e6).c_str(), 0);
80         }
81         
82         if (avformat_open_input (&_format_context, _ffmpeg_content->path().string().c_str(), 0, &options) < 0) {
83                 throw OpenFileError (_ffmpeg_content->path().string ());
84         }
85
86         if (avformat_find_stream_info (_format_context, 0) < 0) {
87                 throw DecodeError (_("could not find stream information"));
88         }
89
90         /* Find video stream */
91
92         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
93                 AVStream* s = _format_context->streams[i];
94                 if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
95                         _video_stream = i;
96                 }
97         }
98
99         if (_video_stream < 0) {
100                 throw DecodeError (N_("could not find video stream"));
101         }
102
103         _frame = avcodec_alloc_frame ();
104         if (_frame == 0) {
105                 throw DecodeError (N_("could not allocate frame"));
106         }
107 }
108
109 void
110 FFmpeg::setup_video ()
111 {
112         boost::mutex::scoped_lock lm (_mutex);
113         
114         AVCodecContext* context = _format_context->streams[_video_stream]->codec;
115         AVCodec* codec = avcodec_find_decoder (context->codec_id);
116
117         if (codec == 0) {
118                 throw DecodeError (_("could not find video decoder"));
119         }
120
121         if (avcodec_open2 (context, codec, 0) < 0) {
122                 throw DecodeError (N_("could not open video decoder"));
123         }
124 }
125
126 void
127 FFmpeg::setup_audio ()
128 {
129         boost::mutex::scoped_lock lm (_mutex);
130
131         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
132                 AVCodecContext* context = _format_context->streams[i]->codec;
133                 if (context->codec_type != AVMEDIA_TYPE_AUDIO) {
134                         continue;
135                 }
136                 
137                 AVCodec* codec = avcodec_find_decoder (context->codec_id);
138                 if (codec == 0) {
139                         throw DecodeError (_("could not find audio decoder"));
140                 }
141                 
142                 if (avcodec_open2 (context, codec, 0) < 0) {
143                         throw DecodeError (N_("could not open audio decoder"));
144                 }
145         }
146 }
147
148
149 AVCodecContext *
150 FFmpeg::video_codec_context () const
151 {
152         return _format_context->streams[_video_stream]->codec;
153 }
154
155 AVCodecContext *
156 FFmpeg::audio_codec_context () const
157 {
158         return _format_context->streams[_ffmpeg_content->audio_stream()->id]->codec;
159 }