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 "exceptions.h"
25 #include "raw_convert.h"
27 #include "ffmpeg_subtitle_stream.h"
28 #include "compose.hpp"
30 #include <libavcodec/avcodec.h>
31 #include <libavformat/avformat.h>
32 #include <libswscale/swscale.h>
34 #include <boost/algorithm/string.hpp>
42 using boost::shared_ptr;
44 boost::mutex FFmpeg::_mutex;
45 boost::weak_ptr<Log> FFmpeg::_ffmpeg_log;
47 FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> c)
50 , _avio_buffer_size (4096)
62 boost::mutex::scoped_lock lm (_mutex);
64 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
65 avcodec_close (_format_context->streams[i]->codec);
68 av_frame_free (&_frame);
69 avformat_close_input (&_format_context);
73 avio_read_wrapper (void* data, uint8_t* buffer, int amount)
75 return reinterpret_cast<FFmpeg*>(data)->avio_read (buffer, amount);
79 avio_seek_wrapper (void* data, int64_t offset, int whence)
81 return reinterpret_cast<FFmpeg*>(data)->avio_seek (offset, whence);
85 FFmpeg::ffmpeg_log_callback (void* ptr, int level, const char* fmt, va_list vl)
87 if (level > AV_LOG_WARNING) {
92 static int prefix = 0;
93 av_log_format_line (ptr, level, fmt, vl, line, sizeof (line), &prefix);
94 shared_ptr<Log> log = _ffmpeg_log.lock ();
97 boost::algorithm::trim (str);
98 log->log (String::compose ("FFmpeg: %1", str), Log::TYPE_GENERAL);
105 FFmpeg::setup_general ()
109 /* This might not work too well in some cases of multiple FFmpeg decoders,
110 but it's probably good enough.
112 _ffmpeg_log = _ffmpeg_content->film()->log ();
113 av_log_set_callback (FFmpeg::ffmpeg_log_callback);
115 _file_group.set_paths (_ffmpeg_content->paths ());
116 _avio_buffer = static_cast<uint8_t*> (wrapped_av_malloc (_avio_buffer_size));
117 _avio_context = avio_alloc_context (_avio_buffer, _avio_buffer_size, 0, this, avio_read_wrapper, 0, avio_seek_wrapper);
118 _format_context = avformat_alloc_context ();
119 _format_context->pb = _avio_context;
121 AVDictionary* options = 0;
122 /* These durations are in microseconds, and represent how far into the content file
123 we will look for streams.
125 av_dict_set (&options, "analyzeduration", raw_convert<string> (5 * 60 * 1000000).c_str(), 0);
126 av_dict_set (&options, "probesize", raw_convert<string> (5 * 60 * 1000000).c_str(), 0);
128 if (avformat_open_input (&_format_context, 0, 0, &options) < 0) {
129 throw OpenFileError (_ffmpeg_content->path(0).string ());
132 if (avformat_find_stream_info (_format_context, 0) < 0) {
133 throw DecodeError (_("could not find stream information"));
136 /* Find video stream */
138 int video_stream_undefined_frame_rate = -1;
140 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
141 AVStream* s = _format_context->streams[i];
142 if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
143 if (s->avg_frame_rate.num > 0 && s->avg_frame_rate.den > 0) {
144 /* This is definitely our video stream */
147 /* This is our video stream if we don't get a better offer */
148 video_stream_undefined_frame_rate = i;
153 /* Files from iTunes sometimes have two video streams, one with the avg_frame_rate.num and .den set
154 to zero. Only use such a stream if there is no alternative.
156 if (_video_stream == -1 && video_stream_undefined_frame_rate != -1) {
157 _video_stream = video_stream_undefined_frame_rate;
160 if (_video_stream < 0) {
161 throw DecodeError (N_("could not find video stream"));
164 /* Hack: if the AVStreams have duplicate IDs, replace them with our
165 own. We use the IDs so that we can cope with VOBs, in which streams
166 move about in index but remain with the same ID in different
167 VOBs. However, some files have duplicate IDs, hence this hack.
170 bool duplicates = false;
171 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
172 for (uint32_t j = i + 1; j < _format_context->nb_streams; ++j) {
173 if (_format_context->streams[i]->id == _format_context->streams[j]->id) {
180 /* Put in our own IDs */
181 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
182 _format_context->streams[i]->id = i;
186 _frame = av_frame_alloc ();
188 throw DecodeError (N_("could not allocate frame"));
193 FFmpeg::setup_decoders ()
195 boost::mutex::scoped_lock lm (_mutex);
197 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
198 AVCodecContext* context = _format_context->streams[i]->codec;
200 AVCodec* codec = avcodec_find_decoder (context->codec_id);
203 /* This option disables decoding of DCA frame footers in our patched version
204 of FFmpeg. I believe these footers are of no use to us, and they can cause
205 problems when FFmpeg fails to decode them (mantis #352).
207 AVDictionary* options = 0;
208 av_dict_set (&options, "disable_footer", "1", 0);
210 if (avcodec_open2 (context, codec, &options) < 0) {
211 throw DecodeError (N_("could not open decoder"));
215 /* We are silently ignoring any failures to find suitable decoders here */
220 FFmpeg::video_codec_context () const
222 return _format_context->streams[_video_stream]->codec;
226 FFmpeg::subtitle_codec_context () const
228 if (!_ffmpeg_content->subtitle_stream ()) {
232 return _ffmpeg_content->subtitle_stream()->stream(_format_context)->codec;
236 FFmpeg::avio_read (uint8_t* buffer, int const amount)
238 return _file_group.read (buffer, amount);
242 FFmpeg::avio_seek (int64_t const pos, int whence)
244 if (whence == AVSEEK_SIZE) {
245 return _file_group.length ();
248 return _file_group.seek (pos, whence);
252 FFmpeg::subtitle_period (AVSubtitle const & sub)
254 ContentTime const packet_time = ContentTime::from_seconds (static_cast<double> (sub.pts) / AV_TIME_BASE);
256 if (sub.end_display_time == static_cast<uint32_t> (-1)) {
257 /* End time is not known */
258 return FFmpegSubtitlePeriod (packet_time + ContentTime::from_seconds (sub.start_display_time / 1e3));
261 return FFmpegSubtitlePeriod (
262 packet_time + ContentTime::from_seconds (sub.start_display_time / 1e3),
263 packet_time + ContentTime::from_seconds (sub.end_display_time / 1e3)