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