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>
24 #include <libpostproc/postprocess.h>
27 #include "ffmpeg_content.h"
28 #include "exceptions.h"
34 using std::stringstream;
35 using boost::shared_ptr;
36 using boost::lexical_cast;
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 avcodec_free_frame (&_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*> (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", lexical_cast<string> (5 * 60 * 1e6).c_str(), 0);
98 av_dict_set (&options, "probesize", lexical_cast<string> (5 * 60 * 1e6).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 if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
117 if (_video_stream < 0) {
118 throw DecodeError (N_("could not find video stream"));
121 /* Hack: if the AVStreams have zero IDs, put some in. We
122 use the IDs so that we can cope with VOBs, in which streams
123 move about in index but remain with the same ID in different
124 VOBs. However, some files have all-zero IDs, hence this hack.
128 while (i < _format_context->nb_streams && _format_context->streams[i]->id == 0) {
132 if (i == _format_context->nb_streams) {
133 /* Put in our own IDs */
134 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
135 _format_context->streams[i]->id = i;
139 _frame = avcodec_alloc_frame ();
141 throw DecodeError (N_("could not allocate frame"));
146 FFmpeg::setup_video ()
148 boost::mutex::scoped_lock lm (_mutex);
150 AVCodecContext* context = _format_context->streams[_video_stream]->codec;
151 AVCodec* codec = avcodec_find_decoder (context->codec_id);
154 throw DecodeError (_("could not find video decoder"));
157 if (avcodec_open2 (context, codec, 0) < 0) {
158 throw DecodeError (N_("could not open video decoder"));
163 FFmpeg::setup_audio ()
165 boost::mutex::scoped_lock lm (_mutex);
167 for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
168 AVCodecContext* context = _format_context->streams[i]->codec;
169 if (context->codec_type != AVMEDIA_TYPE_AUDIO) {
173 AVCodec* codec = avcodec_find_decoder (context->codec_id);
175 throw DecodeError (_("could not find audio decoder"));
178 if (avcodec_open2 (context, codec, 0) < 0) {
179 throw DecodeError (N_("could not open audio decoder"));
186 FFmpeg::video_codec_context () const
188 return _format_context->streams[_video_stream]->codec;
192 FFmpeg::audio_codec_context () const
194 return _ffmpeg_content->audio_stream()->stream(_format_context)->codec;
198 FFmpeg::avio_read (uint8_t* buffer, int const amount)
200 return _file_group.read (buffer, amount);
204 FFmpeg::avio_seek (int64_t const pos, int whence)
206 if (whence == AVSEEK_SIZE) {
207 return _file_group.length ();
210 return _file_group.seek (pos, whence);