added probe on import functionality
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "decoder/probeserver.h"
|
||||
#include "panel/panelfocusmanager.h"
|
||||
#include "panel/project/project.h"
|
||||
#include "project/item/footage/footage.h"
|
||||
@@ -152,6 +153,8 @@ void Core::ImportFiles(const QStringList &urls)
|
||||
f->set_name(file_info.fileName());
|
||||
//file_info.lastModified();
|
||||
|
||||
olive::ProbeMedia(f);
|
||||
|
||||
active_project->root()->add_child(f);
|
||||
|
||||
}
|
||||
|
||||
@@ -37,6 +37,33 @@ public:
|
||||
Stream* stream();
|
||||
void set_stream(Stream* fs);
|
||||
|
||||
/**
|
||||
* @brief Probe a footage file and dump metadata about it
|
||||
*
|
||||
* When a Footage file is imported, we'll need to know whether Olive is equipped with a decoder for utilizing it
|
||||
* and metadata should be retrieved about it if so. For this purpose, the Footage object is passed through all
|
||||
* Probe() functions of available deocders until one returns TRUE. A FALSE return means the Decoder was unable to
|
||||
* parse this file and the next should be tried.
|
||||
*
|
||||
* Probe() differs from Open() since it focuses on a file as a whole rather than one particular stream. Probe()
|
||||
* should be able to be run directly without calling Open() or Close() and should free its memory before returning.
|
||||
*
|
||||
* Probe() will never be called on an object that is also used for decoding. In other words, it will never be called
|
||||
* alongside Open() or Close() externally, so Probe() can use variables that would otherwise be used for decoding
|
||||
* without conflict.
|
||||
*
|
||||
* @param f
|
||||
*
|
||||
* A Footage object to probe. The Footage object will have a valid filename and will be empty prior to being sent
|
||||
* to this function (i.e. Footage::Clear() will not have to be called).
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* 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 bool Probe(Footage* f) = 0;
|
||||
|
||||
/**
|
||||
* @brief Open media/allocate memory
|
||||
*
|
||||
|
||||
@@ -100,6 +100,14 @@ bool FFmpegDecoder::Open()
|
||||
return true;
|
||||
}
|
||||
|
||||
FramePtr FFmpegDecoder::Retrieve(const rational &timecode, const rational &length)
|
||||
{
|
||||
Q_UNUSED(timecode)
|
||||
Q_UNUSED(length)
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void FFmpegDecoder::Close()
|
||||
{
|
||||
if (opts_ != nullptr) {
|
||||
@@ -120,6 +128,95 @@ void FFmpegDecoder::Close()
|
||||
open_ = false;
|
||||
}
|
||||
|
||||
bool FFmpegDecoder::Probe(Footage *f)
|
||||
{
|
||||
int error_code;
|
||||
|
||||
// Convert QString to a C strng
|
||||
QByteArray ba = f->filename().toUtf8();
|
||||
const char* filename = ba.constData();
|
||||
|
||||
// Open file in a format context
|
||||
error_code = avformat_open_input(&fmt_ctx_, filename, nullptr, nullptr);
|
||||
|
||||
// Handle format context error
|
||||
if (error_code == 0) {
|
||||
|
||||
// Retrieve metadata about the media
|
||||
av_dump_format(fmt_ctx_, stream()->index(), filename, 0);
|
||||
|
||||
// Dump it into the Footage object
|
||||
for (unsigned int i=0;i<fmt_ctx_->nb_streams;i++) {
|
||||
|
||||
avstream_ = fmt_ctx_->streams[i];
|
||||
|
||||
Stream* str;
|
||||
|
||||
if (avstream_->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
|
||||
// Create a video stream object
|
||||
VideoStream* video_stream = new VideoStream();
|
||||
|
||||
video_stream->set_width(avstream_->codecpar->width);
|
||||
video_stream->set_height(avstream_->codecpar->height);
|
||||
|
||||
str = video_stream;
|
||||
|
||||
} else if (avstream_->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
|
||||
// Create an audio stream object
|
||||
AudioStream* audio_stream = new AudioStream();
|
||||
|
||||
audio_stream->set_layout(avstream_->codecpar->channel_layout);
|
||||
audio_stream->set_channels(avstream_->codecpar->channels);
|
||||
audio_stream->set_sample_rate(avstream_->codecpar->sample_rate);
|
||||
|
||||
str = audio_stream;
|
||||
|
||||
} else {
|
||||
|
||||
// This is data we can't utilize at the moment, but we make a Stream object anyway to keep parity with the file
|
||||
str = new Stream();
|
||||
|
||||
// Set the correct codec type based on FFmpeg's result
|
||||
switch (avstream_->codecpar->codec_type) {
|
||||
case AVMEDIA_TYPE_UNKNOWN:
|
||||
str->set_type(Stream::kUnknown);
|
||||
break;
|
||||
case AVMEDIA_TYPE_DATA:
|
||||
str->set_type(Stream::kData);
|
||||
break;
|
||||
case AVMEDIA_TYPE_SUBTITLE:
|
||||
str->set_type(Stream::kSubtitle);
|
||||
break;
|
||||
case AVMEDIA_TYPE_ATTACHMENT:
|
||||
str->set_type(Stream::kAttachment);
|
||||
break;
|
||||
|
||||
// We should never realistically get here, but we make an "invalid" stream just in case
|
||||
// We don't use a "default:" in case more AVMEDIA_TYPEs get introduced in later APIs that need handling
|
||||
case AVMEDIA_TYPE_NB:
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
str->set_type(Stream::kUnknown);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
str->set_index(avstream_->index);
|
||||
str->set_timebase(avstream_->time_base);
|
||||
|
||||
f->add_stream(str);
|
||||
}
|
||||
}
|
||||
|
||||
// Free all memory
|
||||
Close();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FFmpegDecoder::FFmpegErr(int error_code)
|
||||
{
|
||||
char err[1024];
|
||||
|
||||
@@ -10,7 +10,10 @@ class FFmpegDecoder : public Decoder
|
||||
public:
|
||||
FFmpegDecoder();
|
||||
|
||||
virtual bool Probe(Footage *f) override;
|
||||
|
||||
virtual bool Open() override;
|
||||
virtual FramePtr Retrieve(const rational &timecode, const rational &length = 0) override;
|
||||
virtual void Close() override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1,8 +1,24 @@
|
||||
#include "probeserver.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
|
||||
#include "decoder/ffmpeg/ffmpegdecoder.h"
|
||||
|
||||
bool olive::Probe(Footage *f)
|
||||
bool olive::ProbeMedia(Footage *f)
|
||||
{
|
||||
// Check for a valid filename
|
||||
if (f->filename().isEmpty()) {
|
||||
qWarning() << QCoreApplication::translate("ProbeMedia", "Tried to probe media with an empty filename");
|
||||
return false;
|
||||
}
|
||||
|
||||
FFmpegDecoder ff_dec;
|
||||
|
||||
// Pass footage through FFmpeg's probe function
|
||||
if (ff_dec.Probe(f)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
bool Probe(Footage* f);
|
||||
bool ProbeMedia(Footage* f);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -22,11 +22,7 @@
|
||||
|
||||
AudioStream::AudioStream()
|
||||
{
|
||||
}
|
||||
|
||||
Stream::Type AudioStream::type()
|
||||
{
|
||||
return kAudio;
|
||||
set_type(kAudio);
|
||||
}
|
||||
|
||||
const int &AudioStream::channels()
|
||||
@@ -39,12 +35,12 @@ void AudioStream::set_channels(const int &channels)
|
||||
channels_ = channels;
|
||||
}
|
||||
|
||||
const int &AudioStream::layout()
|
||||
const uint64_t &AudioStream::layout()
|
||||
{
|
||||
return layout_;
|
||||
}
|
||||
|
||||
void AudioStream::set_layout(const int &layout)
|
||||
void AudioStream::set_layout(const uint64_t &layout)
|
||||
{
|
||||
layout_ = layout;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
#ifndef AUDIOSTREAM_H
|
||||
#define AUDIOSTREAM_H
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
#include "rational.h"
|
||||
#include "stream.h"
|
||||
|
||||
@@ -29,20 +33,18 @@ class AudioStream : public Stream
|
||||
public:
|
||||
AudioStream();
|
||||
|
||||
virtual Type type() override;
|
||||
|
||||
const int& channels();
|
||||
void set_channels(const int& channels);
|
||||
|
||||
const int& layout();
|
||||
void set_layout(const int& layout);
|
||||
const uint64_t& layout();
|
||||
void set_layout(const uint64_t& layout);
|
||||
|
||||
const int& sample_rate();
|
||||
void set_sample_rate(const int& sample_rate);
|
||||
|
||||
private:
|
||||
int channels_;
|
||||
int layout_;
|
||||
uint64_t layout_;
|
||||
int sample_rate_;
|
||||
};
|
||||
|
||||
|
||||
@@ -25,6 +25,20 @@ Footage::Footage()
|
||||
|
||||
}
|
||||
|
||||
Footage::~Footage()
|
||||
{
|
||||
ClearStreams();
|
||||
}
|
||||
|
||||
void Footage::Clear()
|
||||
{
|
||||
// Clear filename string
|
||||
filename_.clear();
|
||||
|
||||
// Clear all streams
|
||||
ClearStreams();
|
||||
}
|
||||
|
||||
const QString &Footage::filename()
|
||||
{
|
||||
return filename_;
|
||||
@@ -45,21 +59,32 @@ void Footage::set_timestamp(const QDateTime &t)
|
||||
timestamp_ = t;
|
||||
}
|
||||
|
||||
void Footage::add_stream(const Stream &s)
|
||||
void Footage::add_stream(Stream *s)
|
||||
{
|
||||
// Add a copy of this stream to the list
|
||||
streams_.append(s);
|
||||
|
||||
// Set its footage parent to this
|
||||
streams_.last().set_footage(this);
|
||||
streams_.last()->set_footage(this);
|
||||
}
|
||||
|
||||
const Stream *Footage::stream(int index)
|
||||
{
|
||||
return &streams_.at(index);
|
||||
return streams_.at(index);
|
||||
}
|
||||
|
||||
Item::Type Footage::type() const
|
||||
{
|
||||
return kFootage;
|
||||
}
|
||||
|
||||
void Footage::ClearStreams()
|
||||
{
|
||||
// Delete all streams
|
||||
for (int i=0;i<streams_.size();i++) {
|
||||
delete streams_.at(i);
|
||||
}
|
||||
|
||||
// Empty array
|
||||
streams_.clear();
|
||||
}
|
||||
|
||||
@@ -34,23 +34,49 @@ class Footage : public Item
|
||||
public:
|
||||
Footage();
|
||||
|
||||
virtual ~Footage() override;
|
||||
|
||||
/**
|
||||
* @brief Deleted copy constructor
|
||||
*/
|
||||
Footage(const Footage& other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Deleted move constructor
|
||||
*/
|
||||
Footage(Footage&& other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Deleted copy assignment
|
||||
*/
|
||||
Footage& operator=(const Footage& other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Deleted move assignment
|
||||
*/
|
||||
Footage& operator=(Footage&& other) = delete;
|
||||
|
||||
void Clear();
|
||||
|
||||
const QString& filename();
|
||||
void set_filename(const QString& s);
|
||||
|
||||
const QDateTime& timestamp();
|
||||
void set_timestamp(const QDateTime& t);
|
||||
|
||||
void add_stream(const Stream& s);
|
||||
void add_stream(Stream* s);
|
||||
const Stream* stream(int index);
|
||||
|
||||
virtual Type type() const override;
|
||||
|
||||
private:
|
||||
void ClearStreams();
|
||||
|
||||
QString filename_;
|
||||
|
||||
QDateTime timestamp_;
|
||||
|
||||
QList<Stream> streams_;
|
||||
QList<Stream*> streams_;
|
||||
};
|
||||
|
||||
#endif // FOOTAGE_H
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "stream.h"
|
||||
|
||||
Stream::Stream() :
|
||||
footage_(nullptr)
|
||||
footage_(nullptr),
|
||||
type_(kUnknown)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -10,6 +11,16 @@ Stream::~Stream()
|
||||
{
|
||||
}
|
||||
|
||||
const Stream::Type &Stream::type()
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
void Stream::set_type(const Stream::Type &type)
|
||||
{
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
Footage *Stream::footage()
|
||||
{
|
||||
return footage_;
|
||||
@@ -20,11 +31,6 @@ void Stream::set_footage(Footage *f)
|
||||
footage_ = f;
|
||||
}
|
||||
|
||||
Stream::Type Stream::type()
|
||||
{
|
||||
return kUnknown;
|
||||
}
|
||||
|
||||
const rational &Stream::timebase()
|
||||
{
|
||||
return timebase_;
|
||||
|
||||
@@ -27,7 +27,8 @@ public:
|
||||
*/
|
||||
virtual ~Stream();
|
||||
|
||||
virtual Type type();
|
||||
const Type& type();
|
||||
void set_type(const Type& type);
|
||||
|
||||
Footage* footage();
|
||||
void set_footage(Footage* f);
|
||||
@@ -45,6 +46,8 @@ private:
|
||||
|
||||
int index_;
|
||||
|
||||
Type type_;
|
||||
|
||||
};
|
||||
|
||||
#endif // STREAM_H
|
||||
|
||||
@@ -22,11 +22,7 @@
|
||||
|
||||
VideoStream::VideoStream()
|
||||
{
|
||||
}
|
||||
|
||||
Stream::Type VideoStream::type()
|
||||
{
|
||||
return kVideo;
|
||||
set_type(kVideo);
|
||||
}
|
||||
|
||||
const int &VideoStream::width()
|
||||
|
||||
@@ -29,8 +29,6 @@ class VideoStream : public Stream
|
||||
public:
|
||||
VideoStream();
|
||||
|
||||
virtual Type type() override;
|
||||
|
||||
const int& width();
|
||||
void set_width(const int& width);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user