Split examiner parts off 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::stringstream;
34 using boost::shared_ptr;
35
36 boost::mutex FFmpeg::_mutex;
37
38 FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> c)
39         : _ffmpeg_content (c)
40         , _format_context (0)
41         , _frame (0)
42         , _video_stream (-1)
43         , _video_codec_context (0)
44         , _video_codec (0)
45         , _audio_codec_context (0)
46         , _audio_codec (0)
47 {
48         setup_general ();
49         setup_video ();
50         setup_audio ();
51 }
52
53 FFmpeg::~FFmpeg ()
54 {
55         boost::mutex::scoped_lock lm (_mutex);
56         
57         if (_audio_codec_context) {
58                 avcodec_close (_audio_codec_context);
59         }
60
61         if (_video_codec_context) {
62                 avcodec_close (_video_codec_context);
63         }
64
65         av_free (_frame);
66         
67         avformat_close_input (&_format_context);
68 }
69
70 void
71 FFmpeg::setup_general ()
72 {
73         av_register_all ();
74
75         if (avformat_open_input (&_format_context, _ffmpeg_content->file().string().c_str(), 0, 0) < 0) {
76                 throw OpenFileError (_ffmpeg_content->file().string ());
77         }
78
79         if (avformat_find_stream_info (_format_context, 0) < 0) {
80                 throw DecodeError (_("could not find stream information"));
81         }
82
83         /* Find video stream */
84
85         for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
86                 AVStream* s = _format_context->streams[i];
87                 if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
88                         _video_stream = i;
89                 }
90         }
91
92         if (_video_stream < 0) {
93                 throw DecodeError (N_("could not find video stream"));
94         }
95
96         _frame = avcodec_alloc_frame ();
97         if (_frame == 0) {
98                 throw DecodeError (N_("could not allocate frame"));
99         }
100 }
101
102 void
103 FFmpeg::setup_video ()
104 {
105         boost::mutex::scoped_lock lm (_mutex);
106         
107         _video_codec_context = _format_context->streams[_video_stream]->codec;
108         _video_codec = avcodec_find_decoder (_video_codec_context->codec_id);
109
110         if (_video_codec == 0) {
111                 throw DecodeError (_("could not find video decoder"));
112         }
113
114         if (avcodec_open2 (_video_codec_context, _video_codec, 0) < 0) {
115                 throw DecodeError (N_("could not open video decoder"));
116         }
117 }
118
119 void
120 FFmpeg::setup_audio ()
121 {
122         boost::mutex::scoped_lock lm (_mutex);
123         
124         if (!_ffmpeg_content->audio_stream ()) {
125                 return;
126         }
127
128         _audio_codec_context = _format_context->streams[_ffmpeg_content->audio_stream()->id]->codec;
129         _audio_codec = avcodec_find_decoder (_audio_codec_context->codec_id);
130
131         if (_audio_codec == 0) {
132                 throw DecodeError (_("could not find audio decoder"));
133         }
134
135         if (avcodec_open2 (_audio_codec_context, _audio_codec, 0) < 0) {
136                 throw DecodeError (N_("could not open audio decoder"));
137         }
138 }