2 Copyright (C) 2013-2015 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 "ffmpeg_content.h"
23 #include "ffmpeg_audio_stream.h"
24 #include "ffmpeg_subtitle_stream.h"
25 #include "exceptions.h"
27 #include "raw_convert.h"
30 #include <libavcodec/avcodec.h>
31 #include <libavformat/avformat.h>
32 #include <libswscale/swscale.h>
34 #include <boost/algorithm/string.hpp>
41 using boost::shared_ptr;
43 boost::mutex FFmpeg::_mutex;
44 boost::weak_ptr<Log> FFmpeg::_ffmpeg_log;
46 FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> c)
49 , _avio_buffer_size (4096)
61 boost::mutex::scoped_lock lm (_mutex);
63 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
64 avcodec_close (_format_context->streams[i]->codec);
67 av_frame_free (&_frame);
68 avformat_close_input (&_format_context);
72 avio_read_wrapper (void* data, uint8_t* buffer, int amount)
74 return reinterpret_cast<FFmpeg*>(data)->avio_read (buffer, amount);
78 avio_seek_wrapper (void* data, int64_t offset, int whence)
80 return reinterpret_cast<FFmpeg*>(data)->avio_seek (offset, whence);
84 FFmpeg::ffmpeg_log_callback (void* ptr, int level, const char* fmt, va_list vl)
86 if (level > AV_LOG_WARNING) {
91 static int prefix = 0;
92 av_log_format_line (ptr, level, fmt, vl, line, sizeof (line), &prefix);
93 shared_ptr<Log> log = _ffmpeg_log.lock ();
96 boost::algorithm::trim (str);
97 log->log (String::compose ("FFmpeg: %1", str), Log::TYPE_GENERAL);
104 FFmpeg::setup_general ()
108 /* This might not work too well in some cases of multiple FFmpeg decoders,
109 but it's probably good enough.
111 _ffmpeg_log = _ffmpeg_content->film()->log ();
112 av_log_set_callback (FFmpeg::ffmpeg_log_callback);
114 _file_group.set_paths (_ffmpeg_content->paths ());
115 _avio_buffer = static_cast<uint8_t*> (wrapped_av_malloc (_avio_buffer_size));
116 _avio_context = avio_alloc_context (_avio_buffer, _avio_buffer_size, 0, this, avio_read_wrapper, 0, avio_seek_wrapper);
117 _format_context = avformat_alloc_context ();
118 _format_context->pb = _avio_context;
120 AVDictionary* options = 0;
121 /* These durations are in microseconds, and represent how far into the content file
122 we will look for streams.
124 av_dict_set (&options, "analyzeduration", raw_convert<string> (5 * 60 * 1000000).c_str(), 0);
125 av_dict_set (&options, "probesize", raw_convert<string> (5 * 60 * 1000000).c_str(), 0);
127 if (avformat_open_input (&_format_context, 0, 0, &options) < 0) {
128 throw OpenFileError (_ffmpeg_content->path(0).string ());
131 if (avformat_find_stream_info (_format_context, 0) < 0) {
132 throw DecodeError (_("could not find stream information"));
135 /* Find video stream */
137 int video_stream_undefined_frame_rate = -1;
139 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
140 AVStream* s = _format_context->streams[i];
141 /* Files from iTunes sometimes have two video streams, one with the avg_frame_rate.num and .den set
142 to zero. Ignore these streams.
144 if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
145 if (s->avg_frame_rate.num > 0 && s->avg_frame_rate.den > 0) {
146 /* This is definitely our video stream */
149 /* This is our video stream if we don't get a better offer */
150 video_stream_undefined_frame_rate = i;
155 /* Files from iTunes sometimes have two video streams, one with the avg_frame_rate.num and .den set
156 to zero. Only use such a stream if there is no alternative.
158 if (_video_stream == -1 && video_stream_undefined_frame_rate != -1) {
159 _video_stream = video_stream_undefined_frame_rate;
162 if (_video_stream < 0) {
163 throw DecodeError (N_("could not find video stream"));
166 /* Hack: if the AVStreams have duplicate IDs, replace them with our
167 own. We use the IDs so that we can cope with VOBs, in which streams
168 move about in index but remain with the same ID in different
169 VOBs. However, some files have duplicate IDs, hence this hack.
172 bool duplicates = false;
173 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
174 for (uint32_t j = i + 1; j < _format_context->nb_streams; ++j) {
175 if (_format_context->streams[i]->id == _format_context->streams[j]->id) {
182 /* Put in our own IDs */
183 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
184 _format_context->streams[i]->id = i;
188 _frame = av_frame_alloc ();
190 throw DecodeError (N_("could not allocate frame"));
195 FFmpeg::setup_decoders ()
197 boost::mutex::scoped_lock lm (_mutex);
199 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
200 AVCodecContext* context = _format_context->streams[i]->codec;
202 AVCodec* codec = avcodec_find_decoder (context->codec_id);
205 /* This option disables decoding of DCA frame footers in our patched version
206 of FFmpeg. I believe these footers are of no use to us, and they can cause
207 problems when FFmpeg fails to decode them (mantis #352).
209 AVDictionary* options = 0;
210 av_dict_set (&options, "disable_footer", "1", 0);
212 if (avcodec_open2 (context, codec, &options) < 0) {
213 throw DecodeError (N_("could not open decoder"));
217 /* We are silently ignoring any failures to find suitable decoders here */
222 FFmpeg::video_codec_context () const
224 return _format_context->streams[_video_stream]->codec;
228 FFmpeg::subtitle_codec_context () const
230 if (!_ffmpeg_content->subtitle_stream ()) {
234 return _ffmpeg_content->subtitle_stream()->stream(_format_context)->codec;
238 FFmpeg::avio_read (uint8_t* buffer, int const amount)
240 return _file_group.read (buffer, amount);
244 FFmpeg::avio_seek (int64_t const pos, int whence)
246 if (whence == AVSEEK_SIZE) {
247 return _file_group.length ();
250 return _file_group.seek (pos, whence);