Merge master.
[dcpomatic.git] / src / lib / ffmpeg.cc
1 /*
2     Copyright (C) 2013-2014 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 }
25 #include <dcp/raw_convert.h>
26 #include "ffmpeg.h"
27 #include "ffmpeg_content.h"
28 #include "ffmpeg_audio_stream.h"
29 #include "ffmpeg_subtitle_stream.h"
30 #include "exceptions.h"
31 #include "util.h"
32
33 #include "i18n.h"
34
35 using std::string;
36 using std::cout;
37 using boost::shared_ptr;
38 using dcp::raw_convert;
39
40 boost::mutex FFmpeg::_mutex;
41
42 FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> c)
43         : _ffmpeg_content (c)
44         , _avio_buffer (0)
45         , _avio_buffer_size (4096)
46         , _avio_context (0)
47         , _format_context (0)
48         , _frame (0)
49         , _video_stream (-1)
50 {
51         setup_general ();
52         setup_decoders ();
53 }
54
55 FFmpeg::~FFmpeg ()
56 {
57         boost::mutex::scoped_lock lm (_mutex);
58
59         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
60                 avcodec_close (_format_context->streams[i]->codec);
61         }
62
63         av_frame_free (&_frame);
64         avformat_close_input (&_format_context);
65 }
66
67 static int
68 avio_read_wrapper (void* data, uint8_t* buffer, int amount)
69 {
70         return reinterpret_cast<FFmpeg*>(data)->avio_read (buffer, amount);
71 }
72
73 static int64_t
74 avio_seek_wrapper (void* data, int64_t offset, int whence)
75 {
76         return reinterpret_cast<FFmpeg*>(data)->avio_seek (offset, whence);
77 }
78
79 void
80 FFmpeg::setup_general ()
81 {
82         av_register_all ();
83
84         _file_group.set_paths (_ffmpeg_content->paths ());
85         _avio_buffer = static_cast<uint8_t*> (wrapped_av_malloc (_avio_buffer_size));
86         _avio_context = avio_alloc_context (_avio_buffer, _avio_buffer_size, 0, this, avio_read_wrapper, 0, avio_seek_wrapper);
87         _format_context = avformat_alloc_context ();
88         _format_context->pb = _avio_context;
89         
90         AVDictionary* options = 0;
91         /* These durations are in microseconds, and represent how far into the content file
92            we will look for streams.
93         */
94         av_dict_set (&options, "analyzeduration", raw_convert<string> (5 * 60 * 1000000).c_str(), 0);
95         av_dict_set (&options, "probesize", raw_convert<string> (5 * 60 * 1000000).c_str(), 0);
96         
97         if (avformat_open_input (&_format_context, 0, 0, &options) < 0) {
98                 throw OpenFileError (_ffmpeg_content->path(0).string ());
99         }
100
101         if (avformat_find_stream_info (_format_context, 0) < 0) {
102                 throw DecodeError (_("could not find stream information"));
103         }
104
105         /* Find video stream */
106
107         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
108                 AVStream* s = _format_context->streams[i];
109                 /* Files from iTunes sometimes have two video streams, one with the avg_frame_rate.num and .den set
110                    to zero.  Ignore these streams.
111                 */
112                 if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO && s->avg_frame_rate.num > 0 && s->avg_frame_rate.den > 0) {
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_decoders ()
147 {
148         boost::mutex::scoped_lock lm (_mutex);
149
150         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
151                 AVCodecContext* context = _format_context->streams[i]->codec;
152                 
153                 AVCodec* codec = avcodec_find_decoder (context->codec_id);
154                 if (codec) {
155                         if (avcodec_open2 (context, codec, 0) < 0) {
156                                 throw DecodeError (N_("could not open decoder"));
157                         }
158                 }
159
160                 /* We are silently ignoring any failures to find suitable decoders here */
161         }
162 }
163
164 AVCodecContext *
165 FFmpeg::video_codec_context () const
166 {
167         return _format_context->streams[_video_stream]->codec;
168 }
169
170 AVCodecContext *
171 FFmpeg::audio_codec_context () const
172 {
173         if (!_ffmpeg_content->audio_stream ()) {
174                 return 0;
175         }
176         
177         return _ffmpeg_content->audio_stream()->stream(_format_context)->codec;
178 }
179
180 AVCodecContext *
181 FFmpeg::subtitle_codec_context () const
182 {
183         if (!_ffmpeg_content->subtitle_stream ()) {
184                 return 0;
185         }
186         
187         return _ffmpeg_content->subtitle_stream()->stream(_format_context)->codec;
188 }
189
190 int
191 FFmpeg::avio_read (uint8_t* buffer, int const amount)
192 {
193         return _file_group.read (buffer, amount);
194 }
195
196 int64_t
197 FFmpeg::avio_seek (int64_t const pos, int whence)
198 {
199         if (whence == AVSEEK_SIZE) {
200                 return _file_group.length ();
201         }
202         
203         return _file_group.seek (pos, whence);
204 }