--- /dev/null
+/*
+ Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+extern "C" {
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+#include <libswscale/swscale.h>
+#include <libpostproc/postprocess.h>
+}
+#include "ffmpeg.h"
+#include "ffmpeg_content.h"
+#include "exceptions.h"
+
+#include "i18n.h"
+
+using std::string;
+using std::stringstream;
+using boost::shared_ptr;
+
+boost::mutex FFmpeg::_mutex;
+
+FFmpeg::FFmpeg (boost::shared_ptr<const FFmpegContent> c)
+ : _ffmpeg_content (c)
+ , _format_context (0)
+ , _frame (0)
+ , _video_stream (-1)
+ , _video_codec_context (0)
+ , _video_codec (0)
+ , _audio_codec_context (0)
+ , _audio_codec (0)
+{
+ setup_general ();
+ setup_video ();
+ setup_audio ();
+}
+
+FFmpeg::~FFmpeg ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+
+ if (_audio_codec_context) {
+ avcodec_close (_audio_codec_context);
+ }
+
+ if (_video_codec_context) {
+ avcodec_close (_video_codec_context);
+ }
+
+ av_free (_frame);
+
+ avformat_close_input (&_format_context);
+}
+
+void
+FFmpeg::setup_general ()
+{
+ av_register_all ();
+
+ if (avformat_open_input (&_format_context, _ffmpeg_content->file().string().c_str(), 0, 0) < 0) {
+ throw OpenFileError (_ffmpeg_content->file().string ());
+ }
+
+ if (avformat_find_stream_info (_format_context, 0) < 0) {
+ throw DecodeError (_("could not find stream information"));
+ }
+
+ /* Find video stream */
+
+ for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
+ AVStream* s = _format_context->streams[i];
+ if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ _video_stream = i;
+ }
+ }
+
+ if (_video_stream < 0) {
+ throw DecodeError (N_("could not find video stream"));
+ }
+
+ _frame = avcodec_alloc_frame ();
+ if (_frame == 0) {
+ throw DecodeError (N_("could not allocate frame"));
+ }
+}
+
+void
+FFmpeg::setup_video ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+
+ _video_codec_context = _format_context->streams[_video_stream]->codec;
+ _video_codec = avcodec_find_decoder (_video_codec_context->codec_id);
+
+ if (_video_codec == 0) {
+ throw DecodeError (_("could not find video decoder"));
+ }
+
+ if (avcodec_open2 (_video_codec_context, _video_codec, 0) < 0) {
+ throw DecodeError (N_("could not open video decoder"));
+ }
+}
+
+void
+FFmpeg::setup_audio ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+
+ if (!_ffmpeg_content->audio_stream ()) {
+ return;
+ }
+
+ _audio_codec_context = _format_context->streams[_ffmpeg_content->audio_stream()->id]->codec;
+ _audio_codec = avcodec_find_decoder (_audio_codec_context->codec_id);
+
+ if (_audio_codec == 0) {
+ throw DecodeError (_("could not find audio decoder"));
+ }
+
+ if (avcodec_open2 (_audio_codec_context, _audio_codec, 0) < 0) {
+ throw DecodeError (N_("could not open audio decoder"));
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <vector>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/mutex.hpp>
+extern "C" {
+#include <libavcodec/avcodec.h>
+}
+
+struct AVFilterGraph;
+struct AVCodecContext;
+struct AVFilterContext;
+struct AVFormatContext;
+struct AVFrame;
+struct AVBufferContext;
+struct AVCodec;
+struct AVStream;
+
+class FFmpegContent;
+
+class FFmpeg
+{
+public:
+ FFmpeg (boost::shared_ptr<const FFmpegContent>);
+ virtual ~FFmpeg ();
+
+ boost::shared_ptr<const FFmpegContent> ffmpeg_content () const {
+ return _ffmpeg_content;
+ }
+
+protected:
+ boost::shared_ptr<const FFmpegContent> _ffmpeg_content;
+ AVFormatContext* _format_context;
+ AVPacket _packet;
+ AVFrame* _frame;
+ int _video_stream;
+
+ AVCodecContext* _video_codec_context;
+ AVCodec* _video_codec;
+ AVCodecContext* _audio_codec_context; ///< may be 0 if there is no audio
+ AVCodec* _audio_codec; ///< may be 0 if there is no audio
+
+ /* It would appear (though not completely verified) that one must have
+ a mutex around calls to avcodec_open* and avcodec_close... and here
+ it is.
+ */
+ static boost::mutex _mutex;
+
+private:
+ void setup_general ();
+ void setup_video ();
+ void setup_audio ();
+};
#include <libcxml/cxml.h>
#include "ffmpeg_content.h"
-#include "ffmpeg_decoder.h"
+#include "ffmpeg_examiner.h"
#include "compose.hpp"
#include "job.h"
#include "util.h"
#include "filter.h"
+#include "film.h"
#include "log.h"
#include "i18n.h"
shared_ptr<const Film> film = _film.lock ();
assert (film);
- shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (film, shared_from_this (), true, false));
+ shared_ptr<FFmpegExaminer> examiner (new FFmpegExaminer (shared_from_this ()));
ContentVideoFrame video_length = 0;
- video_length = decoder->video_length ();
- film->log()->log (String::compose ("Video length obtained from header as %1 frames", decoder->video_length ()));
+ video_length = examiner->video_length ();
+ film->log()->log (String::compose ("Video length obtained from header as %1 frames", examiner->video_length ()));
{
boost::mutex::scoped_lock lm (_mutex);
_video_length = video_length;
- _subtitle_streams = decoder->subtitle_streams ();
+ _subtitle_streams = examiner->subtitle_streams ();
if (!_subtitle_streams.empty ()) {
_subtitle_stream = _subtitle_streams.front ();
}
- _audio_streams = decoder->audio_streams ();
+ _audio_streams = examiner->audio_streams ();
if (!_audio_streams.empty ()) {
_audio_stream = _audio_streams.front ();
}
}
- take_from_video_decoder (decoder);
+ take_from_video_examiner (examiner);
signal_changed (ContentProperty::LENGTH);
signal_changed (FFmpegContentProperty::SUBTITLE_STREAMS);
#include <iostream>
#include <stdint.h>
#include <boost/lexical_cast.hpp>
+#include <sndfile.h>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
-#include <libswscale/swscale.h>
-#include <libpostproc/postprocess.h>
}
-#include <sndfile.h>
#include "film.h"
#include "filter.h"
#include "exceptions.h"
using boost::dynamic_pointer_cast;
using libdcp::Size;
-boost::mutex FFmpegDecoder::_mutex;
-
FFmpegDecoder::FFmpegDecoder (shared_ptr<const Film> f, shared_ptr<const FFmpegContent> c, bool video, bool audio)
: Decoder (f)
, VideoDecoder (f, c)
, AudioDecoder (f, c)
- , _ffmpeg_content (c)
- , _format_context (0)
- , _video_stream (-1)
- , _frame (0)
- , _video_codec_context (0)
- , _video_codec (0)
- , _audio_codec_context (0)
- , _audio_codec (0)
+ , FFmpeg (c)
, _subtitle_codec_context (0)
, _subtitle_codec (0)
, _decode_video (video)
, _decode_audio (audio)
{
- setup_general ();
- setup_video ();
- setup_audio ();
setup_subtitle ();
}
FFmpegDecoder::~FFmpegDecoder ()
{
- boost::mutex::scoped_lock lm (_mutex);
-
- if (_audio_codec_context) {
- avcodec_close (_audio_codec_context);
- }
-
- if (_video_codec_context) {
- avcodec_close (_video_codec_context);
- }
-
if (_subtitle_codec_context) {
avcodec_close (_subtitle_codec_context);
}
-
- av_free (_frame);
-
- avformat_close_input (&_format_context);
}
-void
-FFmpegDecoder::setup_general ()
-{
- av_register_all ();
-
- if (avformat_open_input (&_format_context, _ffmpeg_content->file().string().c_str(), 0, 0) < 0) {
- throw OpenFileError (_ffmpeg_content->file().string ());
- }
-
- if (avformat_find_stream_info (_format_context, 0) < 0) {
- throw DecodeError (_("could not find stream information"));
- }
-
- /* Find video, audio and subtitle streams */
-
- for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
- AVStream* s = _format_context->streams[i];
- if (s->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- _video_stream = i;
- } else if (s->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-
- /* This is a hack; sometimes it seems that _audio_codec_context->channel_layout isn't set up,
- so bodge it here. No idea why we should have to do this.
- */
-
- if (s->codec->channel_layout == 0) {
- s->codec->channel_layout = av_get_default_channel_layout (s->codec->channels);
- }
-
- _audio_streams.push_back (
- shared_ptr<FFmpegAudioStream> (
- new FFmpegAudioStream (stream_name (s), i, s->codec->sample_rate, s->codec->channels)
- )
- );
-
- } else if (s->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
- _subtitle_streams.push_back (shared_ptr<FFmpegSubtitleStream> (new FFmpegSubtitleStream (stream_name (s), i)));
- }
- }
-
- if (_video_stream < 0) {
- throw DecodeError (N_("could not find video stream"));
- }
-
- _frame = avcodec_alloc_frame ();
- if (_frame == 0) {
- throw DecodeError (N_("could not allocate frame"));
- }
-}
-
-void
-FFmpegDecoder::setup_video ()
-{
- boost::mutex::scoped_lock lm (_mutex);
-
- _video_codec_context = _format_context->streams[_video_stream]->codec;
- _video_codec = avcodec_find_decoder (_video_codec_context->codec_id);
-
- if (_video_codec == 0) {
- throw DecodeError (_("could not find video decoder"));
- }
-
- if (avcodec_open2 (_video_codec_context, _video_codec, 0) < 0) {
- throw DecodeError (N_("could not open video decoder"));
- }
-}
-
-void
-FFmpegDecoder::setup_audio ()
-{
- boost::mutex::scoped_lock lm (_mutex);
-
- if (!_ffmpeg_content->audio_stream ()) {
- return;
- }
-
- _audio_codec_context = _format_context->streams[_ffmpeg_content->audio_stream()->id]->codec;
- _audio_codec = avcodec_find_decoder (_audio_codec_context->codec_id);
-
- if (_audio_codec == 0) {
- throw DecodeError (_("could not find audio decoder"));
- }
-
- if (avcodec_open2 (_audio_codec_context, _audio_codec, 0) < 0) {
- throw DecodeError (N_("could not open audio decoder"));
- }
-}
-
-void
-FFmpegDecoder::setup_subtitle ()
-{
- boost::mutex::scoped_lock lm (_mutex);
-
- if (!_ffmpeg_content->subtitle_stream() || _ffmpeg_content->subtitle_stream()->id >= int (_format_context->nb_streams)) {
- return;
- }
-
- _subtitle_codec_context = _format_context->streams[_ffmpeg_content->subtitle_stream()->id]->codec;
- _subtitle_codec = avcodec_find_decoder (_subtitle_codec_context->codec_id);
-
- if (_subtitle_codec == 0) {
- throw DecodeError (_("could not find subtitle decoder"));
- }
-
- if (avcodec_open2 (_subtitle_codec_context, _subtitle_codec, 0) < 0) {
- throw DecodeError (N_("could not open subtitle decoder"));
- }
-}
-
-
void
FFmpegDecoder::pass ()
{
return audio;
}
-float
-FFmpegDecoder::video_frame_rate () const
-{
- AVStream* s = _format_context->streams[_video_stream];
-
- if (s->avg_frame_rate.num && s->avg_frame_rate.den) {
- return av_q2d (s->avg_frame_rate);
- }
-
- return av_q2d (s->r_frame_rate);
-}
-
AVSampleFormat
FFmpegDecoder::audio_sample_format () const
{
return _audio_codec_context->sample_fmt;
}
-libdcp::Size
-FFmpegDecoder::video_size () const
-{
- return libdcp::Size (_video_codec_context->width, _video_codec_context->height);
-}
-
-string
-FFmpegDecoder::stream_name (AVStream* s) const
-{
- stringstream n;
-
- if (s->metadata) {
- AVDictionaryEntry const * lang = av_dict_get (s->metadata, N_("language"), 0, 0);
- if (lang) {
- n << lang->value;
- }
-
- AVDictionaryEntry const * title = av_dict_get (s->metadata, N_("title"), 0, 0);
- if (title) {
- if (!n.str().empty()) {
- n << N_(" ");
- }
- n << title->value;
- }
- }
-
- if (n.str().empty()) {
- n << N_("unknown");
- }
-
- return n.str ();
-}
-
int
FFmpegDecoder::bytes_per_audio_sample () const
{
void
FFmpegDecoder::seek_back ()
{
- if (position() < (2.5 * TIME_HZ / video_frame_rate())) {
+ if (position() < (2.5 * TIME_HZ / _ffmpeg_content->video_frame_rate())) {
return;
}
- do_seek (position() - 2.5 * TIME_HZ / video_frame_rate(), true, true);
+ do_seek (position() - 2.5 * TIME_HZ / _ffmpeg_content->video_frame_rate(), true, true);
VideoDecoder::seek_back ();
}
void
FFmpegDecoder::seek_forward ()
{
- if (position() >= (_ffmpeg_content->length() - 0.5 * TIME_HZ / video_frame_rate())) {
+ if (position() >= (_ffmpeg_content->length() - 0.5 * TIME_HZ / _ffmpeg_content->video_frame_rate())) {
return;
}
- do_seek (position() - 0.5 * TIME_HZ / video_frame_rate(), true, true);
+ do_seek (position() - 0.5 * TIME_HZ / _ffmpeg_content->video_frame_rate(), true, true);
VideoDecoder::seek_forward ();
}
return;
}
-/** @return Length (in video frames) according to our content's header */
-ContentVideoFrame
-FFmpegDecoder::video_length () const
-{
- return (double(_format_context->duration) / AV_TIME_BASE) * video_frame_rate();
-}
-
void
FFmpegDecoder::decode_audio_packet ()
{
return (!_decode_audio || !_audio_codec_context || audio_done()) && (!_decode_video || video_done());
}
+void
+FFmpegDecoder::setup_subtitle ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+
+ if (!_ffmpeg_content->subtitle_stream() || _ffmpeg_content->subtitle_stream()->id >= int (_format_context->nb_streams)) {
+ return;
+ }
+
+ _subtitle_codec_context = _format_context->streams[_ffmpeg_content->subtitle_stream()->id]->codec;
+ _subtitle_codec = avcodec_find_decoder (_subtitle_codec_context->codec_id);
+
+ if (_subtitle_codec == 0) {
+ throw DecodeError (_("could not find subtitle decoder"));
+ }
+
+ if (avcodec_open2 (_subtitle_codec_context, _subtitle_codec, 0) < 0) {
+ throw DecodeError (N_("could not open subtitle decoder"));
+ }
+}
#include "decoder.h"
#include "video_decoder.h"
#include "audio_decoder.h"
+#include "ffmpeg.h"
-struct AVFilterGraph;
-struct AVCodecContext;
-struct AVFilterContext;
-struct AVFormatContext;
-struct AVFrame;
-struct AVBufferContext;
-struct AVCodec;
-struct AVStream;
-class Job;
-class Options;
-class Image;
-class Log;
-class FFmpegContent;
class Film;
/** @class FFmpegDecoder
* @brief A decoder using FFmpeg to decode content.
*/
-class FFmpegDecoder : public VideoDecoder, public AudioDecoder
+class FFmpegDecoder : public VideoDecoder, public AudioDecoder, public FFmpeg
{
public:
FFmpegDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const FFmpegContent>, bool video, bool audio);
~FFmpegDecoder ();
- /* Decoder */
-
void pass ();
void seek (Time);
void seek_back ();
Time position () const;
bool done () const;
- /* VideoDecoder */
-
- float video_frame_rate () const;
- libdcp::Size video_size () const;
- ContentVideoFrame video_length () const;
-
- /* FFmpegDecoder */
-
- std::vector<boost::shared_ptr<FFmpegSubtitleStream> > subtitle_streams () const {
- return _subtitle_streams;
- }
-
- std::vector<boost::shared_ptr<FFmpegAudioStream> > audio_streams () const {
- return _audio_streams;
- }
-
- boost::shared_ptr<const FFmpegContent> ffmpeg_content () const {
- return _ffmpeg_content;
- }
-
private:
/* No copy construction */
FFmpegDecoder (FFmpegDecoder const &);
FFmpegDecoder& operator= (FFmpegDecoder const &);
- PixelFormat pixel_format () const;
+ void setup_subtitle ();
+
AVSampleFormat audio_sample_format () const;
int bytes_per_audio_sample () const;
void do_seek (Time, bool, bool);
- void setup_general ();
- void setup_video ();
- void setup_audio ();
- void setup_subtitle ();
-
bool decode_video_packet ();
void decode_audio_packet ();
void maybe_add_subtitle ();
boost::shared_ptr<AudioBuffers> deinterleave_audio (uint8_t** data, int size);
- std::string stream_name (AVStream* s) const;
-
- boost::shared_ptr<const FFmpegContent> _ffmpeg_content;
-
- AVFormatContext* _format_context;
- int _video_stream;
-
- AVFrame* _frame;
-
- AVCodecContext* _video_codec_context;
- AVCodec* _video_codec;
- AVCodecContext* _audio_codec_context; ///< may be 0 if there is no audio
- AVCodec* _audio_codec; ///< may be 0 if there is no audio
AVCodecContext* _subtitle_codec_context; ///< may be 0 if there is no subtitle
AVCodec* _subtitle_codec; ///< may be 0 if there is no subtitle
-
- AVPacket _packet;
-
+
std::list<boost::shared_ptr<FilterGraph> > _filter_graphs;
boost::mutex _filter_graphs_mutex;
- std::vector<boost::shared_ptr<FFmpegSubtitleStream> > _subtitle_streams;
- std::vector<boost::shared_ptr<FFmpegAudioStream> > _audio_streams;
-
bool _decode_video;
bool _decode_audio;
-
- /* It would appear (though not completely verified) that one must have
- a mutex around calls to avcodec_open* and avcodec_close... and here
- it is.
- */
- static boost::mutex _mutex;
};
--- /dev/null
+/*
+ Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+extern "C" {
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+}
+#include "ffmpeg_examiner.h"
+#include "ffmpeg_content.h"
+
+using std::string;
+using std::stringstream;
+using boost::shared_ptr;
+
+FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> c)
+ : FFmpeg (c)
+{
+ /* Find audio and subtitle streams */
+
+ for (uint32_t i = 0; i < _format_context->nb_streams; ++i) {
+ AVStream* s = _format_context->streams[i];
+ if (s->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+
+ /* This is a hack; sometimes it seems that _audio_codec_context->channel_layout isn't set up,
+ so bodge it here. No idea why we should have to do this.
+ */
+
+ if (s->codec->channel_layout == 0) {
+ s->codec->channel_layout = av_get_default_channel_layout (s->codec->channels);
+ }
+
+ _audio_streams.push_back (
+ shared_ptr<FFmpegAudioStream> (
+ new FFmpegAudioStream (stream_name (s), i, s->codec->sample_rate, s->codec->channels)
+ )
+ );
+
+ } else if (s->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+ _subtitle_streams.push_back (shared_ptr<FFmpegSubtitleStream> (new FFmpegSubtitleStream (stream_name (s), i)));
+ }
+ }
+
+}
+
+float
+FFmpegExaminer::video_frame_rate () const
+{
+ AVStream* s = _format_context->streams[_video_stream];
+
+ if (s->avg_frame_rate.num && s->avg_frame_rate.den) {
+ return av_q2d (s->avg_frame_rate);
+ }
+
+ return av_q2d (s->r_frame_rate);
+}
+
+libdcp::Size
+FFmpegExaminer::video_size () const
+{
+ return libdcp::Size (_video_codec_context->width, _video_codec_context->height);
+}
+
+/** @return Length (in video frames) according to our content's header */
+ContentVideoFrame
+FFmpegExaminer::video_length () const
+{
+ return (double (_format_context->duration) / AV_TIME_BASE) * video_frame_rate();
+}
+
+string
+FFmpegExaminer::stream_name (AVStream* s) const
+{
+ stringstream n;
+
+ if (s->metadata) {
+ AVDictionaryEntry const * lang = av_dict_get (s->metadata, "language", 0, 0);
+ if (lang) {
+ n << lang->value;
+ }
+
+ AVDictionaryEntry const * title = av_dict_get (s->metadata, "title", 0, 0);
+ if (title) {
+ if (!n.str().empty()) {
+ n << " ";
+ }
+ n << title->value;
+ }
+ }
+
+ if (n.str().empty()) {
+ n << "unknown";
+ }
+
+ return n.str ();
+}
--- /dev/null
+/*
+ Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "ffmpeg.h"
+#include "video_examiner.h"
+
+class FFmpegAudioStream;
+class FFmpegSubtitleStream;
+
+class FFmpegExaminer : public FFmpeg, public VideoExaminer
+{
+public:
+ FFmpegExaminer (boost::shared_ptr<const FFmpegContent>);
+
+ float video_frame_rate () const;
+ libdcp::Size video_size () const;
+ ContentVideoFrame video_length () const;
+
+ std::vector<boost::shared_ptr<FFmpegSubtitleStream> > subtitle_streams () const {
+ return _subtitle_streams;
+ }
+
+ std::vector<boost::shared_ptr<FFmpegAudioStream> > audio_streams () const {
+ return _audio_streams;
+ }
+
+private:
+ std::string stream_name (AVStream* s) const;
+
+ std::vector<boost::shared_ptr<FFmpegSubtitleStream> > _subtitle_streams;
+ std::vector<boost::shared_ptr<FFmpegAudioStream> > _audio_streams;
+};
#include "filter.h"
#include "exceptions.h"
#include "image.h"
-#include "ffmpeg_decoder.h"
#include "i18n.h"
--- /dev/null
+/*
+ Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+class ImageMagickContent;
+
+class ImageMagick
+{
+public:
+ ImageMagick (boost::shared_ptr<const ImageMagickContent> c)
+ : _imagemagick_content (c)
+ {}
+
+ boost::shared_ptr<const ImageMagickContent> content () const {
+ return _imagemagick_content;
+ }
+
+protected:
+ boost::shared_ptr<const ImageMagickContent> _imagemagick_content;
+};
#include <libcxml/cxml.h>
#include "imagemagick_content.h"
-#include "imagemagick_decoder.h"
+#include "imagemagick_examiner.h"
#include "config.h"
#include "compose.hpp"
+#include "film.h"
#include "i18n.h"
shared_ptr<const Film> film = _film.lock ();
assert (film);
- shared_ptr<ImageMagickDecoder> decoder (new ImageMagickDecoder (film, shared_from_this()));
+ shared_ptr<ImageMagickExaminer> examiner (new ImageMagickExaminer (film, shared_from_this()));
set_video_length (Config::instance()->default_still_length() * 24);
- take_from_video_decoder (decoder);
+ take_from_video_examiner (examiner);
}
shared_ptr<Content>
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
ImageMagickDecoder::ImageMagickDecoder (shared_ptr<const Film> f, shared_ptr<const ImageMagickContent> c)
: Decoder (f)
, VideoDecoder (f, c)
- , _imagemagick_content (c)
+ , ImageMagick (c)
{
}
-libdcp::Size
-ImageMagickDecoder::video_size () const
-{
- if (!_video_size) {
- using namespace MagickCore;
- Magick::Image* image = new Magick::Image (_imagemagick_content->file().string());
- _video_size = libdcp::Size (image->columns(), image->rows());
- delete image;
- }
-
- return _video_size.get ();
-}
-
-int
-ImageMagickDecoder::video_length () const
-{
- return _imagemagick_content->video_length ();
-}
-
-float
-ImageMagickDecoder::video_frame_rate () const
-{
- boost::shared_ptr<const Film> f = _film.lock ();
- if (!f) {
- return 24;
- }
-
- return f->dcp_video_frame_rate ();
-}
-
void
ImageMagickDecoder::pass ()
{
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
#include "video_decoder.h"
+#include "imagemagick.h"
namespace Magick {
class Image;
class ImageMagickContent;
-class ImageMagickDecoder : public VideoDecoder
+class ImageMagickDecoder : public VideoDecoder, public ImageMagick
{
public:
ImageMagickDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const ImageMagickContent>);
Time position () const;
bool done () const;
- /* VideoDecoder */
-
- float video_frame_rate () const;
- libdcp::Size video_size () const;
- ContentVideoFrame video_length () const;
-
- /* ImageMagickDecoder */
-
- boost::shared_ptr<const ImageMagickContent> content () const {
- return _imagemagick_content;
- }
-
private:
- boost::shared_ptr<const ImageMagickContent> _imagemagick_content;
boost::shared_ptr<Image> _image;
mutable boost::optional<libdcp::Size> _video_size;
};
--- /dev/null
+/*
+ Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <iostream>
+#include <Magick++.h>
+#include "imagemagick_content.h"
+#include "imagemagick_examiner.h"
+#include "film.h"
+
+#include "i18n.h"
+
+using std::cout;
+using boost::shared_ptr;
+
+ImageMagickExaminer::ImageMagickExaminer (shared_ptr<const Film> f, shared_ptr<const ImageMagickContent> c)
+ : ImageMagick (c)
+ , _film (f)
+{
+ using namespace MagickCore;
+ Magick::Image* image = new Magick::Image (_imagemagick_content->file().string());
+ _video_size = libdcp::Size (image->columns(), image->rows());
+ delete image;
+}
+
+libdcp::Size
+ImageMagickExaminer::video_size () const
+{
+ return _video_size;
+}
+
+int
+ImageMagickExaminer::video_length () const
+{
+ return _imagemagick_content->video_length ();
+}
+
+float
+ImageMagickExaminer::video_frame_rate () const
+{
+ boost::shared_ptr<const Film> f = _film.lock ();
+ if (!f) {
+ return 24;
+ }
+
+ return f->dcp_video_frame_rate ();
+}
+
--- /dev/null
+/*
+ Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "imagemagick.h"
+#include "video_examiner.h"
+
+namespace Magick {
+ class Image;
+}
+
+class ImageMagickContent;
+
+class ImageMagickExaminer : public ImageMagick, public VideoExaminer
+{
+public:
+ ImageMagickExaminer (boost::shared_ptr<const Film>, boost::shared_ptr<const ImageMagickContent>);
+
+ float video_frame_rate () const;
+ libdcp::Size video_size () const;
+ ContentVideoFrame video_length () const;
+
+private:
+ boost::weak_ptr<const Film> _film;
+ libdcp::Size _video_size;
+};
*/
+#include <iomanip>
#include <libcxml/cxml.h>
#include "video_content.h"
-#include "video_decoder.h"
+#include "video_examiner.h"
#include "ratio.h"
#include "i18n.h"
}
void
-VideoContent::take_from_video_decoder (shared_ptr<VideoDecoder> d)
+VideoContent::take_from_video_examiner (shared_ptr<VideoExaminer> d)
{
- /* These decoder calls could call other content methods which take a lock on the mutex */
+ /* These examiner calls could call other content methods which take a lock on the mutex */
libdcp::Size const vs = d->video_size ();
float const vfr = d->video_frame_rate ();
#include "content.h"
#include "util.h"
-class VideoDecoder;
+class VideoExaminer;
class Ratio;
class VideoContentProperty
}
protected:
- void take_from_video_decoder (boost::shared_ptr<VideoDecoder>);
+ void take_from_video_examiner (boost::shared_ptr<VideoExaminer>);
ContentVideoFrame _video_length;
if (sub) {
dcpomatic::Rect const tx = subtitle_transformed_area (
- float (image_size.width) / video_size().width,
- float (image_size.height) / video_size().height,
+ float (image_size.width) / _video_content->video_size().width,
+ float (image_size.height) / _video_content->video_size().height,
sub->area(), film->subtitle_offset(), film->subtitle_scale()
);
virtual void seek_back ();
virtual void seek_forward ();
- /* Calls for VideoContent to find out about itself */
-
- /** @return video frame rate second, or 0 if unknown */
- virtual float video_frame_rate () const = 0;
- /** @return video size in pixels */
- virtual libdcp::Size video_size () const = 0;
- /** @return length according to our content's header */
- virtual ContentVideoFrame video_length () const = 0;
-
void set_video_container_size (libdcp::Size);
protected:
--- /dev/null
+/*
+ Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <libdcp/types.h>
+#include "types.h"
+
+class VideoExaminer
+{
+public:
+ virtual float video_frame_rate () const = 0;
+ virtual libdcp::Size video_size () const = 0;
+ virtual ContentVideoFrame video_length () const = 0;
+};
examine_content_job.cc
exceptions.cc
filter_graph.cc
+ ffmpeg.cc
ffmpeg_content.cc
ffmpeg_decoder.cc
+ ffmpeg_examiner.cc
film.cc
filter.cc
image.cc
imagemagick_content.cc
imagemagick_decoder.cc
+ imagemagick_examiner.cc
job.cc
job_manager.cc
log.cc