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>
26 #include "ffmpeg_content.h"
27 #include "ffmpeg_audio_stream.h"
28 #include "ffmpeg_subtitle_stream.h"
29 #include "exceptions.h"
31 #include "raw_convert.h"
37 using boost::shared_ptr;
39 boost::mutex FFmpeg::_mutex;
41 FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> c)
44 , _avio_buffer_size (4096)
56 boost::mutex::scoped_lock lm (_mutex);
58 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
59 avcodec_close (_format_context->streams[i]->codec);
62 av_frame_free (&_frame);
63 avformat_close_input (&_format_context);
67 avio_read_wrapper (void* data, uint8_t* buffer, int amount)
69 return reinterpret_cast<FFmpeg*>(data)->avio_read (buffer, amount);
73 avio_seek_wrapper (void* data, int64_t offset, int whence)
75 return reinterpret_cast<FFmpeg*>(data)->avio_seek (offset, whence);
79 FFmpeg::setup_general ()
83 _file_group.set_paths (_ffmpeg_content->paths ());
84 _avio_buffer = static_cast<uint8_t*> (wrapped_av_malloc (_avio_buffer_size));
85 _avio_context = avio_alloc_context (_avio_buffer, _avio_buffer_size, 0, this, avio_read_wrapper, 0, avio_seek_wrapper);
86 _format_context = avformat_alloc_context ();
87 _format_context->pb = _avio_context;
89 AVDictionary* options = 0;
90 /* These durations are in microseconds, and represent how far into the content file
91 we will look for streams.
93 av_dict_set (&options, "analyzeduration", raw_convert<string> (5 * 60 * 1000000).c_str(), 0);
94 av_dict_set (&options, "probesize", raw_convert<string> (5 * 60 * 1000000).c_str(), 0);
96 if (avformat_open_input (&_format_context, 0, 0, &options) < 0) {
97 throw OpenFileError (_ffmpeg_content->path(0).string ());
100 if (avformat_find_stream_info (_format_context, 0) < 0) {
101 throw DecodeError (_("could not find stream information"));
104 /* Find video stream */
106 int video_stream_undefined_frame_rate = -1;
108 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
109 AVStream* s = _format_context->streams[i];
110 /* Files from iTunes sometimes have two video streams, one with the avg_frame_rate.num and .den set
111 to zero. Ignore these streams.
113 if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
114 if (s->avg_frame_rate.num > 0 && s->avg_frame_rate.den > 0) {
115 /* This is definitely our video stream */
118 /* This is our video stream if we don't get a better offer */
119 video_stream_undefined_frame_rate = i;
124 /* Files from iTunes sometimes have two video streams, one with the avg_frame_rate.num and .den set
125 to zero. Only use such a stream if there is no alternative.
127 if (_video_stream == -1 && video_stream_undefined_frame_rate != -1) {
128 _video_stream = video_stream_undefined_frame_rate;
131 if (_video_stream < 0) {
132 throw DecodeError (N_("could not find video stream"));
135 /* Hack: if the AVStreams have duplicate IDs, replace them with our
136 own. We use the IDs so that we can cope with VOBs, in which streams
137 move about in index but remain with the same ID in different
138 VOBs. However, some files have duplicate IDs, hence this hack.
141 bool duplicates = false;
142 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
143 for (uint32_t j = i + 1; j < _format_context->nb_streams; ++j) {
144 if (_format_context->streams[i]->id == _format_context->streams[j]->id) {
151 /* Put in our own IDs */
152 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
153 _format_context->streams[i]->id = i;
157 _frame = av_frame_alloc ();
159 throw DecodeError (N_("could not allocate frame"));
164 FFmpeg::setup_decoders ()
166 boost::mutex::scoped_lock lm (_mutex);
168 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
169 AVCodecContext* context = _format_context->streams[i]->codec;
171 AVCodec* codec = avcodec_find_decoder (context->codec_id);
174 /* This option disables decoding of DCA frame footers in our patched version
175 of FFmpeg. I believe these footers are of no use to us, and they can cause
176 problems when FFmpeg fails to decode them (mantis #352).
178 AVDictionary* options = 0;
179 av_dict_set (&options, "disable_footer", "1", 0);
181 if (avcodec_open2 (context, codec, &options) < 0) {
182 throw DecodeError (N_("could not open decoder"));
186 /* We are silently ignoring any failures to find suitable decoders here */
191 FFmpeg::video_codec_context () const
193 return _format_context->streams[_video_stream]->codec;
197 FFmpeg::subtitle_codec_context () const
199 if (!_ffmpeg_content->subtitle_stream ()) {
203 return _ffmpeg_content->subtitle_stream()->stream(_format_context)->codec;
207 FFmpeg::avio_read (uint8_t* buffer, int const amount)
209 return _file_group.read (buffer, amount);
213 FFmpeg::avio_seek (int64_t const pos, int whence)
215 if (whence == AVSEEK_SIZE) {
216 return _file_group.length ();
219 return _file_group.seek (pos, whence);