2 Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
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.
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.
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.
21 #include <libavcodec/avcodec.h>
22 #include <libavformat/avformat.h>
23 #include <libswscale/swscale.h>
25 #include <libdcp/raw_convert.h>
27 #include "ffmpeg_content.h"
28 #include "exceptions.h"
35 using boost::shared_ptr;
36 using libdcp::raw_convert;
38 boost::mutex FFmpeg::_mutex;
40 FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> c)
43 , _avio_buffer_size (4096)
56 boost::mutex::scoped_lock lm (_mutex);
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);
65 av_frame_free (&_frame);
67 avformat_close_input (&_format_context);
71 avio_read_wrapper (void* data, uint8_t* buffer, int amount)
73 return reinterpret_cast<FFmpeg*>(data)->avio_read (buffer, amount);
77 avio_seek_wrapper (void* data, int64_t offset, int whence)
79 return reinterpret_cast<FFmpeg*>(data)->avio_seek (offset, whence);
83 FFmpeg::setup_general ()
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;
93 AVDictionary* options = 0;
94 /* These durations are in microseconds, and represent how far into the content file
95 we will look for streams.
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);
100 if (avformat_open_input (&_format_context, 0, 0, &options) < 0) {
101 throw OpenFileError (_ffmpeg_content->path(0).string ());
104 if (avformat_find_stream_info (_format_context, 0) < 0) {
105 throw DecodeError (_("could not find stream information"));
108 /* Find video stream */
110 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
111 AVStream* s = _format_context->streams[i];
112 /* Files from iTunes sometimes have two video streams, one with the avg_frame_rate.num and .den set
113 to zero. Ignore these streams.
115 if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO && s->avg_frame_rate.num > 0 && s->avg_frame_rate.den > 0) {
120 if (_video_stream < 0) {
121 throw DecodeError (N_("could not find video stream"));
124 /* Hack: if the AVStreams have zero IDs, put some in. We
125 use the IDs so that we can cope with VOBs, in which streams
126 move about in index but remain with the same ID in different
127 VOBs. However, some files have all-zero IDs, hence this hack.
131 while (i < _format_context->nb_streams && _format_context->streams[i]->id == 0) {
135 if (i == _format_context->nb_streams) {
136 /* Put in our own IDs */
137 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
138 _format_context->streams[i]->id = i;
142 _frame = av_frame_alloc ();
144 throw DecodeError (N_("could not allocate frame"));
149 FFmpeg::setup_video ()
151 boost::mutex::scoped_lock lm (_mutex);
153 assert (_video_stream >= 0);
154 AVCodecContext* context = _format_context->streams[_video_stream]->codec;
155 AVCodec* codec = avcodec_find_decoder (context->codec_id);
158 throw DecodeError (_("could not find video decoder"));
161 if (avcodec_open2 (context, codec, 0) < 0) {
162 throw DecodeError (N_("could not open video decoder"));
167 FFmpeg::setup_audio ()
169 boost::mutex::scoped_lock lm (_mutex);
171 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
172 AVCodecContext* context = _format_context->streams[i]->codec;
173 if (context->codec_type != AVMEDIA_TYPE_AUDIO) {
177 AVCodec* codec = avcodec_find_decoder (context->codec_id);
179 throw DecodeError (_("could not find audio decoder"));
182 if (avcodec_open2 (context, codec, 0) < 0) {
183 throw DecodeError (N_("could not open audio decoder"));
190 FFmpeg::video_codec_context () const
192 return _format_context->streams[_video_stream]->codec;
196 FFmpeg::audio_codec_context () const
198 return _ffmpeg_content->audio_stream()->stream(_format_context)->codec;
202 FFmpeg::avio_read (uint8_t* buffer, int const amount)
204 return _file_group.read (buffer, amount);
208 FFmpeg::avio_seek (int64_t const pos, int whence)
210 if (whence == AVSEEK_SIZE) {
211 return _file_group.length ();
214 return _file_group.seek (pos, whence);