#include "player.h"
#include "film.h"
#include "ffmpeg_decoder.h"
+#include "video_decoder.h"
+#include "audio_decoder.h"
#include "audio_buffers.h"
#include "audio_content.h"
#include "ffmpeg_content.h"
#include "image_decoder.h"
+#include "content_audio.h"
#include "image_content.h"
-#include "sndfile_decoder.h"
-#include "sndfile_content.h"
#include "subtitle_content.h"
#include "text_subtitle_decoder.h"
#include "text_subtitle_content.h"
+#include "video_mxf_decoder.h"
+#include "video_mxf_content.h"
#include "dcp_content.h"
#include "job.h"
#include "image.h"
static bool
has_video (Content* c)
{
- return c->video;
+ return static_cast<bool>(c->video);
}
static bool
has_audio (Content* c)
{
- return c->audio;
+ return static_cast<bool>(c->audio);
}
static bool
has_subtitle (Content* c)
{
- return c->subtitle;
+ return static_cast<bool>(c->subtitle);
}
Player::Player (shared_ptr<const Film> film, shared_ptr<const Playlist> playlist)
shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (i);
if (fc) {
decoder.reset (new FFmpegDecoder (fc, _film->log(), _fast));
- frc = FrameRateChange (fc->video->frame_rate(), _film->video_frame_rate());
+ frc = FrameRateChange (fc->active_video_frame_rate(), _film->video_frame_rate());
}
shared_ptr<const DCPContent> dc = dynamic_pointer_cast<const DCPContent> (i);
if (dc) {
decoder.reset (new DCPDecoder (dc, _film->log(), _fast));
- frc = FrameRateChange (dc->video->frame_rate(), _film->video_frame_rate());
+ frc = FrameRateChange (dc->active_video_frame_rate(), _film->video_frame_rate());
}
/* ImageContent */
decoder.reset (new ImageDecoder (ic, _film->log()));
}
- frc = FrameRateChange (ic->video->frame_rate(), _film->video_frame_rate());
- }
-
- /* SndfileContent */
- shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (i);
- if (sc) {
- decoder.reset (new SndfileDecoder (sc, _fast, _film->log()));
-
- /* Work out a FrameRateChange for the best overlap video for this content */
- DCPTime best_overlap_t;
- shared_ptr<Content> best_overlap;
- BOOST_FOREACH (shared_ptr<Content> j, _playlist->content ()) {
- if (!j->video) {
- continue;
- }
-
- DCPTime const overlap = min (j->end(), i->end()) - max (j->position(), i->position());
- if (overlap > best_overlap_t) {
- best_overlap = j;
- best_overlap_t = overlap;
- }
- }
-
- if (best_overlap) {
- frc = FrameRateChange (best_overlap->video->frame_rate(), _film->video_frame_rate ());
- } else {
- /* No video overlap; e.g. if the DCP is just audio */
- frc = FrameRateChange (_film->video_frame_rate(), _film->video_frame_rate ());
- }
+ frc = FrameRateChange (ic->active_video_frame_rate(), _film->video_frame_rate());
}
/* It's questionable whether subtitle content should have a video frame rate; perhaps
shared_ptr<const TextSubtitleContent> rc = dynamic_pointer_cast<const TextSubtitleContent> (i);
if (rc) {
decoder.reset (new TextSubtitleDecoder (rc));
- frc = FrameRateChange (rc->subtitle->video_frame_rate(), _film->video_frame_rate());
+ frc = FrameRateChange (rc->active_video_frame_rate(), _film->video_frame_rate());
}
/* DCPSubtitleContent */
shared_ptr<const DCPSubtitleContent> dsc = dynamic_pointer_cast<const DCPSubtitleContent> (i);
if (dsc) {
decoder.reset (new DCPSubtitleDecoder (dsc));
- frc = FrameRateChange (dsc->subtitle->video_frame_rate(), _film->video_frame_rate());
+ frc = FrameRateChange (dsc->active_video_frame_rate(), _film->video_frame_rate());
+ }
+
+ /* VideoMXFContent */
+ shared_ptr<const VideoMXFContent> vmc = dynamic_pointer_cast<const VideoMXFContent> (i);
+ if (vmc) {
+ decoder.reset (new VideoMXFDecoder (vmc, _film->log()));
+ frc = FrameRateChange (vmc->active_video_frame_rate(), _film->video_frame_rate());
}
- shared_ptr<VideoDecoder> vd = dynamic_pointer_cast<VideoDecoder> (decoder);
- if (vd && _ignore_video) {
- vd->set_ignore_video ();
+ DCPOMATIC_ASSERT (decoder);
+
+ if (decoder->video && _ignore_video) {
+ decoder->video->set_ignore ();
}
- shared_ptr<AudioDecoder> ad = dynamic_pointer_cast<AudioDecoder> (decoder);
- if (ad && _ignore_audio) {
- ad->set_ignore_audio ();
+ if (decoder->audio && _ignore_audio) {
+ decoder->audio->set_ignore ();
}
_pieces.push_back (shared_ptr<Piece> (new Piece (i, decoder, frc.get ())));
Changed (frequent);
} else if (
+ property == ContentProperty::VIDEO_FRAME_RATE ||
property == SubtitleContentProperty::USE ||
property == SubtitleContentProperty::X_OFFSET ||
property == SubtitleContentProperty::Y_OFFSET ||
property == SubtitleContentProperty::FONTS ||
property == VideoContentProperty::CROP ||
property == VideoContentProperty::SCALE ||
- property == VideoContentProperty::FRAME_RATE ||
property == VideoContentProperty::FADE_IN ||
property == VideoContentProperty::FADE_OUT ||
property == VideoContentProperty::COLOUR_CONVERSION
/* Get video from appropriate piece(s) */
BOOST_FOREACH (shared_ptr<Piece> piece, ov) {
- shared_ptr<VideoDecoder> decoder = dynamic_pointer_cast<VideoDecoder> (piece->decoder);
+ shared_ptr<VideoDecoder> decoder = piece->decoder->video;
DCPOMATIC_ASSERT (decoder);
shared_ptr<DCPContent> dcp_content = dynamic_pointer_cast<DCPContent> (piece->content);
if (use) {
/* We want to use this piece */
- list<ContentVideo> content_video = decoder->get_video (dcp_to_content_video (piece, time), accurate);
+ list<ContentVideo> content_video = decoder->get (dcp_to_content_video (piece, time), accurate);
if (content_video.empty ()) {
pvf.push_back (black_player_video_frame (time));
} else {
}
} else {
/* Discard unused video */
- decoder->get_video (dcp_to_content_video (piece, time), accurate);
+ decoder->get (dcp_to_content_video (piece, time), accurate);
}
}
}
BOOST_FOREACH (shared_ptr<Piece> i, ov) {
DCPOMATIC_ASSERT (i->content->audio);
- shared_ptr<AudioDecoder> decoder = dynamic_pointer_cast<AudioDecoder> (i->decoder);
+ shared_ptr<AudioDecoder> decoder = i->decoder->audio;
DCPOMATIC_ASSERT (decoder);
/* The time that we should request from the content */
}
/* Audio from this piece's decoder stream (which might be more or less than what we asked for) */
- ContentAudio all = decoder->get_audio (j, content_frame, request_frames, accurate);
+ ContentAudio all = decoder->get (j, content_frame, request_frames, accurate);
/* Gain */
if (i->content->audio->gain() != 0) {
continue;
}
- shared_ptr<SubtitleDecoder> subtitle_decoder = dynamic_pointer_cast<SubtitleDecoder> ((*j)->decoder);
+ shared_ptr<SubtitleDecoder> subtitle_decoder = (*j)->decoder->subtitle;
ContentTime const from = dcp_to_content_subtitle (*j, time);
/* XXX: this video_frame_rate() should be the rate that the subtitle content has been prepared for */
ContentTime const to = from + ContentTime::from_frames (1, _film->video_frame_rate ());
- list<ContentImageSubtitle> image = subtitle_decoder->get_image_subtitles (ContentTimePeriod (from, to), starting, accurate);
+ list<ContentImageSubtitle> image = subtitle_decoder->get_image (ContentTimePeriod (from, to), starting, accurate);
for (list<ContentImageSubtitle>::iterator i = image.begin(); i != image.end(); ++i) {
/* Apply content's subtitle offsets */
ps.image.push_back (i->sub);
}
- list<ContentTextSubtitle> text = subtitle_decoder->get_text_subtitles (ContentTimePeriod (from, to), starting, accurate);
+ list<ContentTextSubtitle> text = subtitle_decoder->get_text (ContentTimePeriod (from, to), starting, accurate);
BOOST_FOREACH (ContentTextSubtitle& ts, text) {
BOOST_FOREACH (dcp::SubtitleString s, ts.subs) {
s.set_h_position (s.h_position() + (*j)->content->subtitle->x_offset ());