2 Copyright (C) 2013-2014 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 <dcp/raw_convert.h>
27 #include "ffmpeg_content.h"
28 #include "ffmpeg_audio_stream.h"
29 #include "ffmpeg_subtitle_stream.h"
30 #include "exceptions.h"
37 using boost::shared_ptr;
38 using dcp::raw_convert;
40 boost::mutex FFmpeg::_mutex;
42 FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> c)
45 , _avio_buffer_size (4096)
57 boost::mutex::scoped_lock lm (_mutex);
59 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
60 avcodec_close (_format_context->streams[i]->codec);
63 av_frame_free (&_frame);
64 avformat_close_input (&_format_context);
68 avio_read_wrapper (void* data, uint8_t* buffer, int amount)
70 return reinterpret_cast<FFmpeg*>(data)->avio_read (buffer, amount);
74 avio_seek_wrapper (void* data, int64_t offset, int whence)
76 return reinterpret_cast<FFmpeg*>(data)->avio_seek (offset, whence);
80 FFmpeg::setup_general ()
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;
90 AVDictionary* options = 0;
91 /* These durations are in microseconds, and represent how far into the content file
92 we will look for streams.
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);
97 if (avformat_open_input (&_format_context, 0, 0, &options) < 0) {
98 throw OpenFileError (_ffmpeg_content->path(0).string ());
101 if (avformat_find_stream_info (_format_context, 0) < 0) {
102 throw DecodeError (_("could not find stream information"));
105 /* Find video stream */
107 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
108 AVStream* s = _format_context->streams[i];
109 if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
114 if (_video_stream < 0) {
115 throw DecodeError (N_("could not find video stream"));
118 /* Hack: if the AVStreams have zero IDs, put some in. We
119 use the IDs so that we can cope with VOBs, in which streams
120 move about in index but remain with the same ID in different
121 VOBs. However, some files have all-zero IDs, hence this hack.
125 while (i < _format_context->nb_streams && _format_context->streams[i]->id == 0) {
129 if (i == _format_context->nb_streams) {
130 /* Put in our own IDs */
131 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
132 _format_context->streams[i]->id = i;
136 _frame = av_frame_alloc ();
138 throw DecodeError (N_("could not allocate frame"));
143 FFmpeg::setup_decoders ()
145 boost::mutex::scoped_lock lm (_mutex);
147 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
148 AVCodecContext* context = _format_context->streams[i]->codec;
150 AVCodec* codec = avcodec_find_decoder (context->codec_id);
152 if (avcodec_open2 (context, codec, 0) < 0) {
153 throw DecodeError (N_("could not open decoder"));
157 /* We are silently ignoring any failures to find suitable decoders here */
162 FFmpeg::video_codec_context () const
164 return _format_context->streams[_video_stream]->codec;
168 FFmpeg::audio_codec_context () const
170 if (!_ffmpeg_content->audio_stream ()) {
174 return _ffmpeg_content->audio_stream()->stream(_format_context)->codec;
178 FFmpeg::subtitle_codec_context () const
180 if (!_ffmpeg_content->subtitle_stream ()) {
184 return _ffmpeg_content->subtitle_stream()->stream(_format_context)->codec;
188 FFmpeg::avio_read (uint8_t* buffer, int const amount)
190 return _file_group.read (buffer, amount);
194 FFmpeg::avio_seek (int64_t const pos, int whence)
196 if (whence == AVSEEK_SIZE) {
197 return _file_group.length ();
200 return _file_group.seek (pos, whence);