finished merge of viewer and footage
This commit is contained in:
@@ -36,18 +36,25 @@ const uint64_t ViewerOutput::kVideoParamEditMask = VideoParamEdit::kWidthHeight
|
||||
|
||||
#define super Node
|
||||
|
||||
ViewerOutput::ViewerOutput() :
|
||||
ViewerOutput::ViewerOutput(bool create_default_streams) :
|
||||
video_frame_cache_(this),
|
||||
audio_playback_cache_(this),
|
||||
operation_stack_(0)
|
||||
{
|
||||
AddInput(kVideoParamsInput, NodeValue::kVideoParams, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
AddInput(kVideoParamsInput, NodeValue::kVideoParams, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable | kInputFlagArray));
|
||||
SetInputProperty(kVideoParamsInput, QStringLiteral("mask"), QVariant::fromValue(kVideoParamEditMask));
|
||||
|
||||
AddInput(kAudioParamsInput, NodeValue::kAudioParams, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
|
||||
AddInput(kAudioParamsInput, NodeValue::kAudioParams, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable | kInputFlagArray));
|
||||
|
||||
connect(this, &Node::InputArraySizeChanged, this, &ViewerOutput::InputResized);
|
||||
|
||||
AddInput(kTextureInput, NodeValue::kTexture, InputFlags(kInputFlagNotKeyframable));
|
||||
AddInput(kSamplesInput, NodeValue::kSamples, InputFlags(kInputFlagNotKeyframable));
|
||||
|
||||
if (create_default_streams) {
|
||||
AddStream(Track::kVideo, QVariant());
|
||||
AddStream(Track::kAudio, QVariant());
|
||||
}
|
||||
}
|
||||
|
||||
ViewerOutput::~ViewerOutput()
|
||||
@@ -85,16 +92,116 @@ QString ViewerOutput::Description() const
|
||||
|
||||
QString ViewerOutput::duration() const
|
||||
{
|
||||
rational timeline_length = GetLength();
|
||||
/*rational timeline_length = GetLength();
|
||||
|
||||
int64_t timestamp = Timecode::time_to_timestamp(timeline_length, video_params().time_base());
|
||||
rational timebase = GetVideoParams().time_base();
|
||||
|
||||
return Timecode::timestamp_to_timecode(timestamp, video_params().time_base(), Core::instance()->GetTimecodeDisplay());
|
||||
int64_t timestamp = Timecode::time_to_timestamp(timeline_length, timebase);
|
||||
|
||||
return Timecode::timestamp_to_timecode(timestamp, timebase, Core::instance()->GetTimecodeDisplay());*/
|
||||
// Try video first
|
||||
VideoParams video = GetFirstEnabledVideoStream();
|
||||
|
||||
if (video.is_valid() && video.video_type() != VideoParams::kVideoTypeStill) {
|
||||
int64_t duration = video.duration();
|
||||
|
||||
rational frame_rate_timebase = video.frame_rate().flipped();
|
||||
if (frame_rate_timebase.isNull()) {
|
||||
frame_rate_timebase = video.time_base();
|
||||
}
|
||||
|
||||
if (video.time_base() != frame_rate_timebase) {
|
||||
// Convert from timebase to frame rate
|
||||
duration = Timecode::rescale_timestamp_ceil(duration, video.time_base(), frame_rate_timebase);
|
||||
}
|
||||
|
||||
return Timecode::timestamp_to_timecode(duration,
|
||||
frame_rate_timebase,
|
||||
Core::instance()->GetTimecodeDisplay());
|
||||
}
|
||||
|
||||
// Try audio second
|
||||
AudioParams audio = GetFirstEnabledAudioStream();
|
||||
|
||||
if (audio.is_valid()) {
|
||||
// If we're showing in a timecode, we prefer showing audio in seconds instead
|
||||
Timecode::Display display = Core::instance()->GetTimecodeDisplay();
|
||||
if (display == Timecode::kTimecodeDropFrame
|
||||
|| display == Timecode::kTimecodeNonDropFrame) {
|
||||
display = Timecode::kTimecodeSeconds;
|
||||
}
|
||||
|
||||
return Timecode::timestamp_to_timecode(audio.duration(),
|
||||
audio.time_base(),
|
||||
display);
|
||||
}
|
||||
|
||||
// Otherwise, return nothing
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString ViewerOutput::rate() const
|
||||
{
|
||||
return tr("%1 FPS").arg(video_params().time_base().flipped().toDouble());
|
||||
if (HasEnabledVideoStreams()) {
|
||||
// This is a video editor, prioritize video streams
|
||||
VideoParams video_stream = GetFirstEnabledVideoStream();
|
||||
|
||||
if (video_stream.video_type() != VideoParams::kVideoTypeStill) {
|
||||
rational using_tb = video_stream.frame_rate();
|
||||
|
||||
if (using_tb.isNull()) {
|
||||
using_tb = video_stream.time_base().flipped();
|
||||
}
|
||||
|
||||
return tr("%1 FPS").arg(using_tb.toDouble());
|
||||
}
|
||||
} else if (HasEnabledAudioStreams()) {
|
||||
// No video streams, return audio
|
||||
AudioParams audio_stream = GetFirstEnabledAudioStream();
|
||||
return tr("%1 Hz").arg(audio_stream.sample_rate());
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool ViewerOutput::HasEnabledVideoStreams() const
|
||||
{
|
||||
return GetFirstEnabledVideoStream().is_valid();
|
||||
}
|
||||
|
||||
bool ViewerOutput::HasEnabledAudioStreams() const
|
||||
{
|
||||
return GetFirstEnabledAudioStream().is_valid();
|
||||
}
|
||||
|
||||
VideoParams ViewerOutput::GetFirstEnabledVideoStream() const
|
||||
{
|
||||
int sz = GetVideoStreamCount();
|
||||
|
||||
for (int i=0; i<sz; i++) {
|
||||
VideoParams vp = GetVideoParams(i);
|
||||
|
||||
if (vp.enabled()) {
|
||||
return vp;
|
||||
}
|
||||
}
|
||||
|
||||
return VideoParams();
|
||||
}
|
||||
|
||||
AudioParams ViewerOutput::GetFirstEnabledAudioStream() const
|
||||
{
|
||||
int sz = GetAudioStreamCount();
|
||||
|
||||
for (int i=0; i<sz; i++) {
|
||||
AudioParams ap = GetAudioParams(i);
|
||||
|
||||
if (ap.enabled()) {
|
||||
return ap;
|
||||
}
|
||||
}
|
||||
|
||||
return AudioParams();
|
||||
}
|
||||
|
||||
void ViewerOutput::set_default_parameters()
|
||||
@@ -102,17 +209,21 @@ void ViewerOutput::set_default_parameters()
|
||||
int width = Config::Current()["DefaultSequenceWidth"].toInt();
|
||||
int height = Config::Current()["DefaultSequenceHeight"].toInt();
|
||||
|
||||
set_video_params(VideoParams(width,
|
||||
height,
|
||||
Config::Current()["DefaultSequenceFrameRate"].value<rational>(),
|
||||
static_cast<VideoParams::Format>(Config::Current()["OfflinePixelFormat"].toInt()),
|
||||
VideoParams::kInternalChannelCount,
|
||||
Config::Current()["DefaultSequencePixelAspect"].value<rational>(),
|
||||
Config::Current()["DefaultSequenceInterlacing"].value<VideoParams::Interlacing>(),
|
||||
VideoParams::generate_auto_divider(width, height)));
|
||||
set_audio_params(AudioParams(Config::Current()["DefaultSequenceAudioFrequency"].toInt(),
|
||||
Config::Current()["DefaultSequenceAudioLayout"].toULongLong(),
|
||||
AudioParams::kInternalFormat));
|
||||
SetVideoParams(VideoParams(
|
||||
width,
|
||||
height,
|
||||
Config::Current()["DefaultSequenceFrameRate"].value<rational>(),
|
||||
static_cast<VideoParams::Format>(Config::Current()["OfflinePixelFormat"].toInt()),
|
||||
VideoParams::kInternalChannelCount,
|
||||
Config::Current()["DefaultSequencePixelAspect"].value<rational>(),
|
||||
Config::Current()["DefaultSequenceInterlacing"].value<VideoParams::Interlacing>(),
|
||||
VideoParams::generate_auto_divider(width, height)
|
||||
));
|
||||
SetAudioParams(AudioParams(
|
||||
Config::Current()["DefaultSequenceAudioFrequency"].toInt(),
|
||||
Config::Current()["DefaultSequenceAudioLayout"].toULongLong(),
|
||||
AudioParams::kInternalFormat
|
||||
));
|
||||
}
|
||||
|
||||
void ViewerOutput::ShiftVideoCache(const rational &from, const rational &to)
|
||||
@@ -165,6 +276,33 @@ const rational& ViewerOutput::GetLength() const
|
||||
return last_length_;
|
||||
}
|
||||
|
||||
QVector<Track::Reference> ViewerOutput::GetEnabledStreamsAsReferences() const
|
||||
{
|
||||
QVector<Track::Reference> refs;
|
||||
|
||||
{
|
||||
int vp_sz = GetVideoStreamCount();
|
||||
|
||||
for (int i=0; i<vp_sz; i++) {
|
||||
if (GetVideoParams(i).enabled()) {
|
||||
refs.append(Track::Reference(Track::kVideo, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int ap_sz = GetAudioStreamCount();
|
||||
|
||||
for (int i=0; i<ap_sz; i++) {
|
||||
if (GetAudioParams(i).enabled()) {
|
||||
refs.append(Track::Reference(Track::kAudio, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return refs;
|
||||
}
|
||||
|
||||
void ViewerOutput::Retranslate()
|
||||
{
|
||||
super::Retranslate();
|
||||
@@ -258,44 +396,56 @@ void ViewerOutput::EndOperation()
|
||||
super::EndOperation();
|
||||
}
|
||||
|
||||
NodeOutput ViewerOutput::GetConnectedTextureOutput()
|
||||
{
|
||||
return GetConnectedOutput(kTextureInput);
|
||||
}
|
||||
|
||||
NodeOutput ViewerOutput::GetConnectedSampleOutput()
|
||||
{
|
||||
return GetConnectedOutput(kSamplesInput);
|
||||
}
|
||||
|
||||
void ViewerOutput::InputValueChangedEvent(const QString &input, int element)
|
||||
{
|
||||
if (input == kVideoParamsInput) {
|
||||
if (element == 0) {
|
||||
if (input == kVideoParamsInput) {
|
||||
|
||||
VideoParams new_video_params = video_params();
|
||||
VideoParams new_video_params = GetVideoParams();
|
||||
|
||||
bool size_changed = cached_video_params_.width() != new_video_params.width() || cached_video_params_.height() != new_video_params.height();
|
||||
bool timebase_changed = cached_video_params_.time_base() != new_video_params.time_base();
|
||||
bool pixel_aspect_changed = cached_video_params_.pixel_aspect_ratio() != new_video_params.pixel_aspect_ratio();
|
||||
bool interlacing_changed = cached_video_params_.interlacing() != new_video_params.interlacing();
|
||||
bool size_changed = cached_video_params_.width() != new_video_params.width() || cached_video_params_.height() != new_video_params.height();
|
||||
bool timebase_changed = cached_video_params_.time_base() != new_video_params.time_base();
|
||||
bool pixel_aspect_changed = cached_video_params_.pixel_aspect_ratio() != new_video_params.pixel_aspect_ratio();
|
||||
bool interlacing_changed = cached_video_params_.interlacing() != new_video_params.interlacing();
|
||||
|
||||
if (size_changed) {
|
||||
emit SizeChanged(new_video_params.width(), new_video_params.height());
|
||||
}
|
||||
|
||||
if (pixel_aspect_changed) {
|
||||
emit PixelAspectChanged(new_video_params.pixel_aspect_ratio());
|
||||
}
|
||||
|
||||
if (interlacing_changed) {
|
||||
emit InterlacingChanged(new_video_params.interlacing());
|
||||
}
|
||||
|
||||
if (timebase_changed) {
|
||||
video_frame_cache_.SetTimebase(new_video_params.time_base());
|
||||
emit TimebaseChanged(new_video_params.time_base());
|
||||
}
|
||||
|
||||
emit VideoParamsChanged();
|
||||
|
||||
cached_video_params_ = new_video_params;
|
||||
|
||||
} else if (input == kAudioParamsInput) {
|
||||
|
||||
emit AudioParamsChanged();
|
||||
|
||||
audio_playback_cache_.SetParameters(GetAudioParams());
|
||||
|
||||
if (size_changed) {
|
||||
emit SizeChanged(new_video_params.width(), new_video_params.height());
|
||||
}
|
||||
|
||||
if (pixel_aspect_changed) {
|
||||
emit PixelAspectChanged(new_video_params.pixel_aspect_ratio());
|
||||
}
|
||||
|
||||
if (interlacing_changed) {
|
||||
emit InterlacingChanged(new_video_params.interlacing());
|
||||
}
|
||||
|
||||
if (timebase_changed) {
|
||||
video_frame_cache_.SetTimebase(new_video_params.time_base());
|
||||
emit TimebaseChanged(new_video_params.time_base());
|
||||
}
|
||||
|
||||
emit VideoParamsChanged();
|
||||
|
||||
cached_video_params_ = video_params();
|
||||
|
||||
} else if (input == kAudioParamsInput) {
|
||||
|
||||
emit AudioParamsChanged();
|
||||
|
||||
audio_playback_cache_.SetParameters(audio_params());
|
||||
|
||||
}
|
||||
|
||||
super::InputValueChangedEvent(input, element);
|
||||
@@ -313,9 +463,9 @@ void ViewerOutput::ShiftAudioEvent(const rational &from, const rational &to)
|
||||
Q_UNUSED(to)
|
||||
}
|
||||
|
||||
void ViewerOutput::set_parameters_from_footage(const QVector<Footage *> footage)
|
||||
void ViewerOutput::set_parameters_from_footage(const QVector<ViewerOutput *> footage)
|
||||
{
|
||||
foreach (Footage* f, footage) {
|
||||
foreach (ViewerOutput* f, footage) {
|
||||
QVector<VideoParams> video_streams = f->GetEnabledVideoStreams();
|
||||
QVector<AudioParams> audio_streams = f->GetEnabledAudioStreams();
|
||||
|
||||
@@ -327,20 +477,20 @@ void ViewerOutput::set_parameters_from_footage(const QVector<Footage *> footage)
|
||||
// If this is a still image, we'll use it's resolution but won't set
|
||||
// `found_video_params` in case something with a frame rate comes along which we'll
|
||||
// prioritize
|
||||
using_timebase = video_params().time_base();
|
||||
using_timebase = GetVideoParams().time_base();
|
||||
} else {
|
||||
using_timebase = s.frame_rate().flipped();
|
||||
found_video_params = true;
|
||||
}
|
||||
|
||||
set_video_params(VideoParams(s.width(),
|
||||
SetVideoParams(VideoParams(s.width(),
|
||||
s.height(),
|
||||
using_timebase,
|
||||
static_cast<VideoParams::Format>(Config::Current()[QStringLiteral("OfflinePixelFormat")].toInt()),
|
||||
VideoParams::kInternalChannelCount,
|
||||
s.pixel_aspect_ratio(),
|
||||
s.interlacing(),
|
||||
VideoParams::generate_auto_divider(s.width(), s.height())));
|
||||
VideoParams::kInternalChannelCount,
|
||||
s.pixel_aspect_ratio(),
|
||||
s.interlacing(),
|
||||
VideoParams::generate_auto_divider(s.width(), s.height())));
|
||||
|
||||
if (found_video_params) {
|
||||
break;
|
||||
@@ -349,7 +499,7 @@ void ViewerOutput::set_parameters_from_footage(const QVector<Footage *> footage)
|
||||
|
||||
if (!audio_streams.isEmpty()) {
|
||||
const AudioParams& s = audio_streams.first();
|
||||
set_audio_params(AudioParams(s.sample_rate(), s.channel_layout(), AudioParams::kInternalFormat));
|
||||
SetAudioParams(AudioParams(s.sample_rate(), s.channel_layout(), AudioParams::kInternalFormat));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -372,4 +522,76 @@ void ViewerOutput::SaveCustom(QXmlStreamWriter *writer) const
|
||||
writer->writeEndElement(); // points
|
||||
}
|
||||
|
||||
int ViewerOutput::AddStream(Track::Type type, const QVariant& value)
|
||||
{
|
||||
QString id;
|
||||
|
||||
if (type == Track::kVideo) {
|
||||
id = kVideoParamsInput;
|
||||
} else if (type == Track::kAudio) {
|
||||
id = kAudioParamsInput;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Add another video/audio param to the array for this stream
|
||||
int index = InputArraySize(id);
|
||||
InputArrayAppend(id);
|
||||
|
||||
SetStandardValue(id, value, index);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void ViewerOutput::InputResized(const QString &input, int old_size, int new_size)
|
||||
{
|
||||
if (input == kVideoParamsInput || input == kAudioParamsInput) {
|
||||
Track::Type type = (input == kVideoParamsInput) ? Track::kVideo : Track::kAudio;
|
||||
|
||||
if (new_size > old_size) {
|
||||
for (int i=old_size; i<new_size; i++) {
|
||||
AddOutput(Track::Reference(type, i).ToString());
|
||||
}
|
||||
} else if (new_size < old_size) {
|
||||
for (int i=new_size; i<old_size; i++) {
|
||||
RemoveOutput(Track::Reference(type, i).ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVector<VideoParams> ViewerOutput::GetEnabledVideoStreams() const
|
||||
{
|
||||
QVector<VideoParams> streams;
|
||||
|
||||
int vp_sz = GetVideoStreamCount();
|
||||
|
||||
for (int i=0; i<vp_sz; i++) {
|
||||
VideoParams vp = GetVideoParams(i);
|
||||
|
||||
if (vp.enabled()) {
|
||||
streams.append(vp);
|
||||
}
|
||||
}
|
||||
|
||||
return streams;
|
||||
}
|
||||
|
||||
QVector<AudioParams> ViewerOutput::GetEnabledAudioStreams() const
|
||||
{
|
||||
QVector<AudioParams> streams;
|
||||
|
||||
int ap_sz = GetAudioStreamCount();
|
||||
|
||||
for (int i=0; i<ap_sz; i++) {
|
||||
AudioParams ap = GetAudioParams(i);
|
||||
|
||||
if (ap.enabled()) {
|
||||
streams.append(ap);
|
||||
}
|
||||
}
|
||||
|
||||
return streams;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user