Merge branch 'master' into 2.0
[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 FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> c)
41         : _ffmpeg_content (c)
42         , _avio_buffer (0)
43         , _avio_buffer_size (4096)
44         , _avio_context (0)
45         , _format_context (0)
46         , _frame (0)
47         , _video_stream (-1)
48 {
49         setup_general ();
50         setup_video ();
51         setup_audio ();
52 }
53
54 FFmpeg::~FFmpeg ()
55 {
56         boost::mutex::scoped_lock lm (_mutex);
57
58         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
59                 AVCodecContext* context = _format_context->streams[i]->codec;
60                 if (context->codec_type == AVMEDIA_TYPE_VIDEO || context->codec_type == AVMEDIA_TYPE_AUDIO) {
61                         avcodec_close (context);
62                 }
63         }
64
65         av_frame_free (&_frame);
66         
67         avformat_close_input (&_format_context);
68 }
69
70 static int
71 avio_read_wrapper (void* data, uint8_t* buffer, int amount)
72 {
73         return reinterpret_cast<FFmpeg*>(data)->avio_read (buffer, amount);
74 }
75
76 static int64_t
77 avio_seek_wrapper (void* data, int64_t offset, int whence)
78 {
79         return reinterpret_cast<FFmpeg*>(data)->avio_seek (offset, whence);
80 }
81
82 void
83 FFmpeg::setup_general ()
84 {
85         av_register_all ();
86
87         _file_group.set_paths (_ffmpeg_content->paths ());
88         _avio_buffer = static_cast<uint8_t*> (av_malloc (_avio_buffer_size));
89         _avio_context = avio_alloc_context (_avio_buffer, _avio_buffer_size, 0, this, avio_read_wrapper, 0, avio_seek_wrapper);
90         _format_context = avformat_alloc_context ();
91         _format_context->pb = _avio_context;
92         
93         AVDictionary* options = 0;
94         /* These durations are in microseconds, and represent how far into the content file
95            we will look for streams.
96         */
97         av_dict_set (&options, "analyzeduration", lexical_cast<string> (5 * 60 * 1e6).c_str(), 0);
98         av_dict_set (&options, "probesize", lexical_cast<string> (5 * 60 * 1e6).c_str(), 0);
99         
100         if (avformat_open_input (&_format_context, 0, 0, &options) < 0) {
101                 throw OpenFileError (_ffmpeg_content->path(0).string ());
102         }
103
104         if (avformat_find_stream_info (_format_context, 0) < 0) {
105                 throw DecodeError (_("could not find stream information"));
106         }
107
108         /* Find video stream */
109
110         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
111                 AVStream* s = _format_context->streams[i];
112                 if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
113                         _video_stream = i;
114                 }
115         }
116
117         if (_video_stream < 0) {
118                 throw DecodeError (N_("could not find video stream"));
119         }
120
121         /* Hack: if the AVStreams have zero IDs, put some in.  We
122            use the IDs so that we can cope with VOBs, in which streams
123            move about in index but remain with the same ID in different
124            VOBs.  However, some files have all-zero IDs, hence this hack.
125         */
126            
127         uint32_t i = 0;
128         while (i < _format_context->nb_streams && _format_context->streams[i]->id == 0) {
129                 ++i;
130         }
131
132         if (i == _format_context->nb_streams) {
133                 /* Put in our own IDs */
134                 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
135                         _format_context->streams[i]->id = i;
136                 }
137         }
138
139         _frame = av_frame_alloc ();
140         if (_frame == 0) {
141                 throw DecodeError (N_("could not allocate frame"));
142         }
143 }
144
145 void
146 FFmpeg::setup_video ()
147 {
148         boost::mutex::scoped_lock lm (_mutex);
149         
150         AVCodecContext* context = _format_context->streams[_video_stream]->codec;
151         AVCodec* codec = avcodec_find_decoder (context->codec_id);
152
153         if (codec == 0) {
154                 throw DecodeError (_("could not find video decoder"));
155         }
156
157         if (avcodec_open2 (context, codec, 0) < 0) {
158                 throw DecodeError (N_("could not open video decoder"));
159         }
160 }
161
162 void
163 FFmpeg::setup_audio ()
164 {
165         boost::mutex::scoped_lock lm (_mutex);
166
167         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
168                 AVCodecContext* context = _format_context->streams[i]->codec;
169                 if (context->codec_type != AVMEDIA_TYPE_AUDIO) {
170                         continue;
171                 }
172                 
173                 AVCodec* codec = avcodec_find_decoder (context->codec_id);
174                 if (codec == 0) {
175                         throw DecodeError (_("could not find audio decoder"));
176                 }
177                 
178                 if (avcodec_open2 (context, codec, 0) < 0) {
179                         throw DecodeError (N_("could not open audio decoder"));
180                 }
181         }
182 }
183
184
185 AVCodecContext *
186 FFmpeg::video_codec_context () const
187 {
188         return _format_context->streams[_video_stream]->codec;
189 }
190
191 AVCodecContext *
192 FFmpeg::audio_codec_context () const
193 {
194         if (!_ffmpeg_content->audio_stream ()) {
195                 return 0;
196         }
197         
198         return _ffmpeg_content->audio_stream()->stream(_format_context)->codec;
199 }
200
201 int
202 FFmpeg::avio_read (uint8_t* buffer, int const amount)
203 {
204         return _file_group.read (buffer, amount);
205 }
206
207 int64_t
208 FFmpeg::avio_seek (int64_t const pos, int whence)
209 {
210         if (whence == AVSEEK_SIZE) {
211                 return _file_group.length ();
212         }
213         
214         return _file_group.seek (pos, whence);
215 }