Properly remove JSON server; remove some unused usings; remove some unnecessary uses...
[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 }
25 #include <libdcp/raw_convert.h>
26 #include "ffmpeg.h"
27 #include "ffmpeg_content.h"
28 #include "exceptions.h"
29 #include "util.h"
30
31 #include "i18n.h"
32
33 using std::string;
34 using std::cout;
35 using boost::shared_ptr;
36 using libdcp::raw_convert;
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*> (wrapped_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", raw_convert<string> (5 * 60 * 1000000).c_str(), 0);
98         av_dict_set (&options, "probesize", raw_convert<string> (5 * 60 * 1000000).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         assert (_video_stream >= 0);
151         AVCodecContext* context = _format_context->streams[_video_stream]->codec;
152         AVCodec* codec = avcodec_find_decoder (context->codec_id);
153
154         if (codec == 0) {
155                 throw DecodeError (_("could not find video decoder"));
156         }
157
158         if (avcodec_open2 (context, codec, 0) < 0) {
159                 throw DecodeError (N_("could not open video decoder"));
160         }
161 }
162
163 void
164 FFmpeg::setup_audio ()
165 {
166         boost::mutex::scoped_lock lm (_mutex);
167
168         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
169                 AVCodecContext* context = _format_context->streams[i]->codec;
170                 if (context->codec_type != AVMEDIA_TYPE_AUDIO) {
171                         continue;
172                 }
173                 
174                 AVCodec* codec = avcodec_find_decoder (context->codec_id);
175                 if (codec == 0) {
176                         throw DecodeError (_("could not find audio decoder"));
177                 }
178                 
179                 if (avcodec_open2 (context, codec, 0) < 0) {
180                         throw DecodeError (N_("could not open audio decoder"));
181                 }
182         }
183 }
184
185
186 AVCodecContext *
187 FFmpeg::video_codec_context () const
188 {
189         return _format_context->streams[_video_stream]->codec;
190 }
191
192 AVCodecContext *
193 FFmpeg::audio_codec_context () const
194 {
195         return _ffmpeg_content->audio_stream()->stream(_format_context)->codec;
196 }
197
198 int
199 FFmpeg::avio_read (uint8_t* buffer, int const amount)
200 {
201         return _file_group.read (buffer, amount);
202 }
203
204 int64_t
205 FFmpeg::avio_seek (int64_t const pos, int whence)
206 {
207         if (whence == AVSEEK_SIZE) {
208                 return _file_group.length ();
209         }
210         
211         return _file_group.seek (pos, whence);
212 }