finalized very, very basic OTIO support

Ironed out various project and footage loading issues, and a single
cache invalidation issue.
This commit is contained in:
itsmattkc
2020-10-23 01:26:17 +11:00
parent 9613730ee8
commit bc60c74562
32 changed files with 473 additions and 301 deletions
-3
View File
@@ -16,9 +16,6 @@
add_subdirectory(ffmpeg)
add_subdirectory(oiio)
if(OpenTimelineIO_FOUND)
add_subdirectory(otio)
endif()
set(OLIVE_SOURCES
${OLIVE_SOURCES}
+14 -16
View File
@@ -27,13 +27,13 @@
#include "codec/ffmpeg/ffmpegcommon.h"
#include "codec/ffmpeg/ffmpegdecoder.h"
#include "codec/oiio/oiiodecoder.h"
#ifdef USE_OTIO
#include "codec/otio/otiodecoder.h"
#endif
#include "codec/waveinput.h"
#include "codec/waveoutput.h"
#include "common/filefunctions.h"
#include "common/timecodefunctions.h"
#ifdef USE_OTIO
#include "task/project/loadotio/loadotio.h"
#endif
#include "task/taskmanager.h"
#include "project/project.h"
@@ -92,16 +92,13 @@ QVector<DecoderPtr> ReceiveListOfAllDecoders() {
// The order in which these decoders are added is their priority when probing. Hence FFmpeg should usually be last,
// since it supports so many formats and we presumably want to override those formats with a more specific decoder.
#ifdef USE_OTIO
decoders.append(std::make_shared<OTIODecoder>());
#endif
decoders.append(std::make_shared<OIIODecoder>());
decoders.append(std::make_shared<FFmpegDecoder>());
return decoders;
}
ItemPtr Decoder::ProbeMedia(const QString &filename, const QAtomicInt* cancelled)
FootagePtr Decoder::ProbeMedia(Project* project, const QString &filename, const QAtomicInt* cancelled)
{
// Check for a valid filename
if (filename.isEmpty()) {
@@ -127,21 +124,22 @@ ItemPtr Decoder::ProbeMedia(const QString &filename, const QAtomicInt* cancelled
DecoderPtr decoder = decoder_list.at(i);
ItemPtr item = decoder->Probe(filename, cancelled);
FootagePtr footage = decoder->Probe(filename, cancelled);
if (item) {
if (footage) {
QFileInfo file_info(filename);
footage->set_name(file_info.fileName());
footage->set_filename(filename);
if (item->type() == Item::kFootage) {
// Attach the successful Decoder to this Footage object
FootagePtr footage = std::static_pointer_cast<Footage>(item);
footage->set_decoder(decoder->id());
footage->SetValid();
}
footage->set_decoder(decoder->id());
footage->set_project(project);
footage->set_timestamp(file_info.lastModified().toMSecsSinceEpoch());
footage->SetValid();
// FIXME: Cache the results so we don't have to probe if this media is added a second time
return item;
return footage;
}
}
+2 -2
View File
@@ -102,7 +102,7 @@ public:
* TRUE if the Decoder was able to decode this file. FALSE if not. This function should have filled the Footage
* object with metadata if it returns TRUE. Otherwise, the Footage object should be untouched.
*/
virtual ItemPtr Probe(const QString& filename, const QAtomicInt* cancelled) const = 0;
virtual FootagePtr Probe(const QString& filename, const QAtomicInt* cancelled) const = 0;
/**
* @brief Open media/allocate memory
@@ -199,7 +199,7 @@ public:
*
* TRUE if a Decoder was successfully able to parse and probe this file. FALSE if not.
*/
static ItemPtr ProbeMedia(const QString& filename, const QAtomicInt *cancelled);
static FootagePtr ProbeMedia(Project *project, const QString& filename, const QAtomicInt *cancelled);
/**
* @brief Create a Decoder instance using a Decoder ID
+2 -2
View File
@@ -450,7 +450,7 @@ bool FFmpegDecoder::SupportsAudio()
return true;
}
ItemPtr FFmpegDecoder::Probe(const QString& filename, const QAtomicInt* cancelled) const
FootagePtr FFmpegDecoder::Probe(const QString& filename, const QAtomicInt* cancelled) const
{
// Variable for receiving errors from FFmpeg
int error_code;
@@ -578,7 +578,7 @@ ItemPtr FFmpegDecoder::Probe(const QString& filename, const QAtomicInt* cancelle
if (avstream->duration == AV_NOPTS_VALUE) {
// Loop through stream until we get the whole duration
FFmpegDecoderInstance instance(filename, i);
FFmpegDecoderInstance instance(filename_c, i);
AVPacket* pkt = av_packet_alloc();
AVFrame* frame = av_frame_alloc();
+1 -1
View File
@@ -147,7 +147,7 @@ public:
// Destructor
virtual ~FFmpegDecoder() override;
virtual ItemPtr Probe(const QString& filename, const QAtomicInt* cancelled) const override;
virtual FootagePtr Probe(const QString& filename, const QAtomicInt* cancelled) const override;
virtual bool Open() override;
virtual FramePtr RetrieveVideo(const rational &timecode, const int& divider) override;
+1 -1
View File
@@ -45,7 +45,7 @@ QString OIIODecoder::id()
return QStringLiteral("oiio");
}
ItemPtr OIIODecoder::Probe(const QString& filename, const QAtomicInt* cancelled) const
FootagePtr OIIODecoder::Probe(const QString& filename, const QAtomicInt* cancelled) const
{
if (!FileTypeIsSupported(filename)) {
return nullptr;
+1 -1
View File
@@ -37,7 +37,7 @@ public:
virtual QString id() override;
virtual ItemPtr Probe(const QString& filename, const QAtomicInt* cancelled) const override;
virtual FootagePtr Probe(const QString& filename, const QAtomicInt* cancelled) const override;
virtual bool Open() override;
virtual FramePtr RetrieveVideo(const rational &timecode, const int& divider) override;
-22
View File
@@ -1,22 +0,0 @@
# Olive - Non-Linear Video Editor
# Copyright (C) 2019 Olive Team
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
set(OLIVE_SOURCES
${OLIVE_SOURCES}
codec/otio/otiodecoder.h
codec/otio/otiodecoder.cpp
PARENT_SCOPE
)
-123
View File
@@ -1,123 +0,0 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
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 3 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, see <http://www.gnu.org/licenses/>.
***/
#include "otiodecoder.h"
#include <opentimelineio/clip.h>
#include <opentimelineio/externalReference.h>
#include <opentimelineio/timeline.h>
#include "node/block/clip/clip.h"
#include "node/block/gap/gap.h"
#include "project/item/sequence/sequence.h"
OLIVE_NAMESPACE_ENTER
OTIODecoder::OTIODecoder()
{
}
QString OTIODecoder::id()
{
return QStringLiteral("otio");
}
ItemPtr OTIODecoder::Probe(const QString& filename, const QAtomicInt* cancelled) const
{
if (filename.endsWith(QStringLiteral(".otio"), Qt::CaseInsensitive)) {
opentimelineio::v1_0::ErrorStatus es;
auto timeline = static_cast<opentimelineio::v1_0::Timeline*>(opentimelineio::v1_0::SerializableObjectWithMetadata::from_json_file(filename.toStdString(), &es));
if (es != opentimelineio::v1_0::ErrorStatus::OK) {
return nullptr;
}
SequencePtr sequence = std::make_shared<Sequence>();
// FIXME: As far as I know, OTIO doesn't store video/audio parameters?
sequence->set_default_parameters();
sequence->set_name(QString::fromStdString(timeline->name()));
for (auto c : timeline->tracks()->children()) {
auto otio_track = static_cast<opentimelineio::v1_0::Track*>(c.value);
// Create a new track
TrackOutput* track = nullptr;
// Determine what kind of track it is
if (otio_track->kind() == "Video") {
track = sequence->viewer_output()->track_list(Timeline::kTrackTypeVideo)->AddTrack();
} else if (otio_track->kind() == "Audio") {
track = sequence->viewer_output()->track_list(Timeline::kTrackTypeAudio)->AddTrack();
} else {
qWarning() << "Found unknown track type:" << otio_track->kind().c_str();
continue;
}
// Get clips from track
std::map<opentimelineio::v1_0::Composable*, opentimelineio::v1_0::TimeRange> clip_map = otio_track->range_of_all_children(&es);
if (es != opentimelineio::v1_0::ErrorStatus::OK) {
return nullptr;
}
for (auto it=clip_map.cbegin(); it!=clip_map.cend(); it++) {
Block* block = nullptr;
if (it->first->schema_name() == "Clip") {
block = new ClipBlock();
auto otio_clip = static_cast<opentimelineio::v1_0::Clip*>(it->first);
/*
if (otio_clip->media_reference()->schema_name() == "ExternalReference") {
QString footage_url = QString::fromStdString(static_cast<opentimelineio::v1_0::ExternalReference*>(otio_clip->media_reference())->target_url());
ItemPtr footage = Decoder::ProbeMedia(footage_url, cancelled);
}
*/
} else if (it->first->schema_name() == "Gap") {
block = new GapBlock();
} else {
qWarning() << "Found unknown block type:" << it->first->schema_name().c_str();
}
block->SetLabel(QString::fromStdString(it->first->name()));
block->set_length_and_media_out(rational::fromDouble(it->second.duration().to_seconds()));
sequence->AddNode(block);
track->AppendBlock(block);
}
}
return sequence;
}
return nullptr;
}
OLIVE_NAMESPACE_EXIT
-45
View File
@@ -1,45 +0,0 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
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 3 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, see <http://www.gnu.org/licenses/>.
***/
#ifndef OTIODECODER_H
#define OTIODECODER_H
#include "codec/decoder.h"
OLIVE_NAMESPACE_ENTER
class OTIODecoder : public Decoder
{
Q_OBJECT
public:
OTIODecoder();
virtual QString id() override;
virtual bool Open() override {return false;}
virtual void Close() override {}
virtual ItemPtr Probe(const QString& filename, const QAtomicInt* cancelled) const override;
};
OLIVE_NAMESPACE_EXIT
#endif // OTIODECODER_H