backend for frame rate conform done
This commit is contained in:
+19
-19
@@ -181,13 +181,13 @@ Sequence* create_sequence_from_media(QVector<Media*>& media_list) {
|
||||
if (m->ready) {
|
||||
if (!got_video_values) {
|
||||
for (int j=0;j<m->video_tracks.size();j++) {
|
||||
const FootageStream& ms = m->video_tracks.at(j);
|
||||
s->width = ms.video_width;
|
||||
s->height = ms.video_height;
|
||||
if (ms.video_frame_rate != 0) {
|
||||
s->frame_rate = ms.video_frame_rate;
|
||||
const FootageStream& ms = m->video_tracks.at(j);
|
||||
s->width = ms.video_width;
|
||||
s->height = ms.video_height;
|
||||
if (ms.video_frame_rate != 0) {
|
||||
s->frame_rate = ms.video_frame_rate * m->speed;
|
||||
|
||||
if (ms.video_interlacing != VIDEO_PROGRESSIVE) s->frame_rate *= 2;
|
||||
if (ms.video_interlacing != VIDEO_PROGRESSIVE) s->frame_rate *= 2;
|
||||
|
||||
// only break with a decent frame rate, otherwise there may be a better candidate
|
||||
got_video_values = true;
|
||||
@@ -197,8 +197,8 @@ Sequence* create_sequence_from_media(QVector<Media*>& media_list) {
|
||||
}
|
||||
if (!got_audio_values) {
|
||||
for (int j=0;j<m->audio_tracks.size();j++) {
|
||||
const FootageStream& ms = m->audio_tracks.at(j);
|
||||
s->audio_frequency = ms.audio_frequency;
|
||||
const FootageStream& ms = m->audio_tracks.at(j);
|
||||
s->audio_frequency = ms.audio_frequency;
|
||||
got_audio_values = true;
|
||||
break;
|
||||
}
|
||||
@@ -853,22 +853,22 @@ void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only,
|
||||
stream.writeAttribute("in", QString::number(f->in));
|
||||
stream.writeAttribute("out", QString::number(f->out));
|
||||
for (int j=0;j<f->video_tracks.size();j++) {
|
||||
const FootageStream& ms = f->video_tracks.at(j);
|
||||
const FootageStream& ms = f->video_tracks.at(j);
|
||||
stream.writeStartElement("video");
|
||||
stream.writeAttribute("id", QString::number(ms.file_index));
|
||||
stream.writeAttribute("width", QString::number(ms.video_width));
|
||||
stream.writeAttribute("height", QString::number(ms.video_height));
|
||||
stream.writeAttribute("framerate", QString::number(ms.video_frame_rate, 'f', 10));
|
||||
stream.writeAttribute("infinite", QString::number(ms.infinite_length));
|
||||
stream.writeAttribute("id", QString::number(ms.file_index));
|
||||
stream.writeAttribute("width", QString::number(ms.video_width));
|
||||
stream.writeAttribute("height", QString::number(ms.video_height));
|
||||
stream.writeAttribute("framerate", QString::number(ms.video_frame_rate, 'f', 10));
|
||||
stream.writeAttribute("infinite", QString::number(ms.infinite_length));
|
||||
stream.writeEndElement();
|
||||
}
|
||||
for (int j=0;j<f->audio_tracks.size();j++) {
|
||||
const FootageStream& ms = f->audio_tracks.at(j);
|
||||
const FootageStream& ms = f->audio_tracks.at(j);
|
||||
stream.writeStartElement("audio");
|
||||
stream.writeAttribute("id", QString::number(ms.file_index));
|
||||
stream.writeAttribute("channels", QString::number(ms.audio_channels));
|
||||
stream.writeAttribute("layout", QString::number(ms.audio_layout));
|
||||
stream.writeAttribute("frequency", QString::number(ms.audio_frequency));
|
||||
stream.writeAttribute("id", QString::number(ms.file_index));
|
||||
stream.writeAttribute("channels", QString::number(ms.audio_channels));
|
||||
stream.writeAttribute("layout", QString::number(ms.audio_layout));
|
||||
stream.writeAttribute("frequency", QString::number(ms.audio_frequency));
|
||||
stream.writeEndElement();
|
||||
}
|
||||
stream.writeEndElement();
|
||||
|
||||
+1
-1
@@ -178,7 +178,7 @@ void Timeline::create_ghosts_from_media(Sequence* seq, long entry_point, QVector
|
||||
can_import = m->ready;
|
||||
if (m->using_inout) {
|
||||
double source_fr = 30;
|
||||
if (m->video_tracks.size() > 0 && !qIsNull(m->video_tracks.at(0).video_frame_rate)) source_fr = m->video_tracks.at(0).video_frame_rate;
|
||||
if (m->video_tracks.size() > 0 && !qIsNull(m->video_tracks.at(0).video_frame_rate)) source_fr = m->video_tracks.at(0).video_frame_rate * m->speed;
|
||||
default_clip_in = refactor_frame_number(m->in, source_fr, seq->frame_rate);
|
||||
default_clip_out = refactor_frame_number(m->out, source_fr, seq->frame_rate);
|
||||
}
|
||||
|
||||
+1
-1
@@ -576,7 +576,7 @@ void Viewer::set_media(Media* m) {
|
||||
const FootageStream& video_stream = footage->video_tracks.at(0);
|
||||
seq->width = video_stream.video_width;
|
||||
seq->height = video_stream.video_height;
|
||||
if (video_stream.video_frame_rate > 0 && !video_stream.infinite_length) seq->frame_rate = video_stream.video_frame_rate;
|
||||
if (video_stream.video_frame_rate > 0 && !video_stream.infinite_length) seq->frame_rate = video_stream.video_frame_rate * footage->speed;
|
||||
|
||||
Clip* c = new Clip(seq);
|
||||
c->media = media;
|
||||
|
||||
+14
-11
@@ -247,7 +247,8 @@ void cache_audio_worker(Clip* c, bool scrubbing, QVector<Clip*>& nests) {
|
||||
#ifdef AUDIOWARNINGS
|
||||
dout << "pre cutoff deets::: rev_frame.pts:" << rev_frame->pts << "rev_frame.nb_samples" << rev_frame->nb_samples << "rev_target:" << c->reverse_target;
|
||||
#endif
|
||||
rev_frame->nb_samples = qRound64(static_cast<double>(c->reverse_target - rev_frame->pts) / c->stream->codecpar->sample_rate * (current_audio_freq() / c->speed));
|
||||
double playback_speed = c->speed * c->media->to_footage()->speed;
|
||||
rev_frame->nb_samples = qRound64(static_cast<double>(c->reverse_target - rev_frame->pts) / c->stream->codecpar->sample_rate * (current_audio_freq() / playback_speed));
|
||||
#ifdef AUDIOWARNINGS
|
||||
dout << "post cutoff deets::" << rev_frame->nb_samples;
|
||||
#endif
|
||||
@@ -451,7 +452,7 @@ void cache_video_worker(Clip* c, long playhead) {
|
||||
AVFrame* frame = av_frame_alloc();
|
||||
|
||||
Footage* media = c->media->to_footage();
|
||||
const FootageStream* ms = media->get_stream_from_file_index(true, c->media_stream);
|
||||
const FootageStream* ms = media->get_stream_from_file_index(true, c->media_stream);
|
||||
|
||||
while ((retr_ret = av_buffersink_get_frame(c->buffersink_ctx, frame)) == AVERROR(EAGAIN)) {
|
||||
if (c->multithreaded && c->cacher->interrupt) return; // abort
|
||||
@@ -546,7 +547,7 @@ void reset_cache(Clip* c, long target_frame) {
|
||||
c->frame->pts = 0;
|
||||
}
|
||||
} else {
|
||||
const FootageStream* ms = c->media->to_footage()->get_stream_from_file_index(c->track < 0, c->media_stream);
|
||||
const FootageStream* ms = c->media->to_footage()->get_stream_from_file_index(c->track < 0, c->media_stream);
|
||||
if (ms->infinite_length) {
|
||||
/*avcodec_flush_buffers(c->codecCtx);
|
||||
av_seek_frame(c->formatCtx, ms->file_index, 0, AVSEEK_FLAG_BACKWARD);*/
|
||||
@@ -640,7 +641,7 @@ void open_clip_worker(Clip* clip) {
|
||||
Footage* m = clip->media->to_footage();
|
||||
QByteArray ba = m->url.toUtf8();
|
||||
const char* filename = ba.constData();
|
||||
const FootageStream* ms = m->get_stream_from_file_index(clip->track < 0, clip->media_stream);
|
||||
const FootageStream* ms = m->get_stream_from_file_index(clip->track < 0, clip->media_stream);
|
||||
|
||||
int errCode = avformat_open_input(
|
||||
&clip->formatCtx,
|
||||
@@ -670,7 +671,7 @@ void open_clip_worker(Clip* clip) {
|
||||
clip->codecCtx = avcodec_alloc_context3(clip->codec);
|
||||
avcodec_parameters_to_context(clip->codecCtx, clip->stream->codecpar);
|
||||
|
||||
clip->max_queue_size = (ms->infinite_length) ? 1 : qCeil(ms->video_frame_rate*0.5);
|
||||
clip->max_queue_size = (ms->infinite_length) ? 1 : qCeil(ms->video_frame_rate * m->speed * 0.5);
|
||||
if (ms->video_interlacing != VIDEO_PROGRESSIVE) clip->max_queue_size *= 2;
|
||||
|
||||
clip->opts = NULL;
|
||||
@@ -797,7 +798,9 @@ void open_clip_worker(Clip* clip) {
|
||||
|
||||
int target_sample_rate = current_audio_freq();
|
||||
|
||||
if (qFuzzyCompare(clip->speed, 1.0)) {
|
||||
double playback_speed = clip->speed * m->speed;
|
||||
|
||||
if (qFuzzyCompare(playback_speed, 1.0)) {
|
||||
avfilter_link(clip->buffersrc_ctx, 0, clip->buffersink_ctx, 0);
|
||||
} else if (clip->maintain_audio_pitch) {
|
||||
AVFilterContext* previous_filter = clip->buffersrc_ctx;
|
||||
@@ -805,10 +808,10 @@ void open_clip_worker(Clip* clip) {
|
||||
|
||||
char speed_param[10];
|
||||
|
||||
if (clip->speed != 1.0) {
|
||||
double base = (clip->speed > 1.0) ? 2.0 : 0.5;
|
||||
// if (playback_speed != 1.0) {
|
||||
double base = (playback_speed > 1.0) ? 2.0 : 0.5;
|
||||
|
||||
double speedlog = log(clip->speed) / log(base);
|
||||
double speedlog = log(playback_speed) / log(base);
|
||||
int whole2 = qFloor(speedlog);
|
||||
speedlog -= whole2;
|
||||
|
||||
@@ -826,11 +829,11 @@ void open_clip_worker(Clip* clip) {
|
||||
last_filter = NULL;
|
||||
avfilter_graph_create_filter(&last_filter, avfilter_get_by_name("atempo"), "atempo", speed_param, NULL, clip->filter_graph);
|
||||
avfilter_link(previous_filter, 0, last_filter, 0);
|
||||
}
|
||||
// }
|
||||
|
||||
avfilter_link(last_filter, 0, clip->buffersink_ctx, 0);
|
||||
} else {
|
||||
target_sample_rate = qRound64(target_sample_rate / clip->speed);
|
||||
target_sample_rate = qRound64(target_sample_rate / playback_speed);
|
||||
avfilter_link(clip->buffersrc_ctx, 0, clip->buffersink_ctx, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -266,7 +266,9 @@ double playhead_to_clip_seconds(Clip* c, long playhead) {
|
||||
// returns time in seconds
|
||||
long clip_frame = playhead_to_clip_frame(c, playhead);
|
||||
if (c->reverse) clip_frame = c->getMaximumLength() - clip_frame - 1;
|
||||
return ((double) clip_frame/c->sequence->frame_rate)*c->speed;
|
||||
double secs = ((double) clip_frame/c->sequence->frame_rate)*c->speed;
|
||||
if (c->media != NULL && c->media->get_type() == MEDIA_TYPE_FOOTAGE) secs *= c->media->to_footage()->speed;
|
||||
return secs;
|
||||
}
|
||||
|
||||
int64_t seconds_to_timestamp(Clip* c, double seconds) {
|
||||
|
||||
+33
-33
@@ -11,55 +11,55 @@ extern "C" {
|
||||
|
||||
#include "project/clip.h"
|
||||
|
||||
Footage::Footage() : ready(false), preview_gen(NULL), invalid(false), in(0), out(0) {
|
||||
ready_lock.lock();
|
||||
Footage::Footage() : ready(false), preview_gen(NULL), invalid(false), in(0), out(0), speed(1.0) {
|
||||
ready_lock.lock();
|
||||
}
|
||||
|
||||
Footage::~Footage() {
|
||||
reset();
|
||||
reset();
|
||||
}
|
||||
|
||||
void Footage::reset() {
|
||||
if (preview_gen != NULL) {
|
||||
preview_gen->cancel();
|
||||
preview_gen->wait();
|
||||
}
|
||||
video_tracks.clear();
|
||||
audio_tracks.clear();
|
||||
ready = false;
|
||||
}
|
||||
video_tracks.clear();
|
||||
audio_tracks.clear();
|
||||
ready = false;
|
||||
}
|
||||
|
||||
long Footage::get_length_in_frames(double frame_rate) {
|
||||
if (length >= 0) return qFloor(((double) length / (double) AV_TIME_BASE) * frame_rate);
|
||||
return 0;
|
||||
if (length >= 0) return qFloor(((double) length / (double) AV_TIME_BASE) * frame_rate / speed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
FootageStream* Footage::get_stream_from_file_index(bool video, int index) {
|
||||
if (video) {
|
||||
for (int i=0;i<video_tracks.size();i++) {
|
||||
if (video_tracks.at(i).file_index == index) {
|
||||
return &video_tracks[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i=0;i<audio_tracks.size();i++) {
|
||||
if (audio_tracks.at(i).file_index == index) {
|
||||
return &audio_tracks[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
if (video) {
|
||||
for (int i=0;i<video_tracks.size();i++) {
|
||||
if (video_tracks.at(i).file_index == index) {
|
||||
return &video_tracks[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i=0;i<audio_tracks.size();i++) {
|
||||
if (audio_tracks.at(i).file_index == index) {
|
||||
return &audio_tracks[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FootageStream::make_square_thumb() {
|
||||
// generate square version for QListView?
|
||||
int square_size = qMax(video_preview.width(), video_preview.height());
|
||||
QPixmap pixmap(square_size, square_size);
|
||||
pixmap.fill(Qt::transparent);
|
||||
QPainter p(&pixmap);
|
||||
int diff = (video_preview.width() - video_preview.height())>>1;
|
||||
int sqx = (diff < 0) ? -diff : 0;
|
||||
int sqy = (diff > 0) ? diff : 0;
|
||||
p.drawImage(sqx, sqy, video_preview);
|
||||
video_preview_square = QIcon(pixmap);
|
||||
// generate square version for QListView?
|
||||
int square_size = qMax(video_preview.width(), video_preview.height());
|
||||
QPixmap pixmap(square_size, square_size);
|
||||
pixmap.fill(Qt::transparent);
|
||||
QPainter p(&pixmap);
|
||||
int diff = (video_preview.width() - video_preview.height())>>1;
|
||||
int sqx = (diff < 0) ? -diff : 0;
|
||||
int sqy = (diff > 0) ? diff : 0;
|
||||
p.drawImage(sqx, sqy, video_preview);
|
||||
video_preview_square = QIcon(pixmap);
|
||||
}
|
||||
|
||||
+29
-28
@@ -23,45 +23,46 @@ struct FootageStream {
|
||||
int video_width;
|
||||
int video_height;
|
||||
bool infinite_length;
|
||||
double video_frame_rate;
|
||||
int video_interlacing;
|
||||
double video_frame_rate;
|
||||
int video_interlacing;
|
||||
int video_auto_interlacing;
|
||||
int audio_channels;
|
||||
int audio_layout;
|
||||
int audio_frequency;
|
||||
bool enabled;
|
||||
int audio_channels;
|
||||
int audio_layout;
|
||||
int audio_frequency;
|
||||
bool enabled;
|
||||
|
||||
// preview thumbnail/waveform
|
||||
bool preview_done;
|
||||
QImage video_preview;
|
||||
QIcon video_preview_square;
|
||||
// preview thumbnail/waveform
|
||||
bool preview_done;
|
||||
QImage video_preview;
|
||||
QIcon video_preview_square;
|
||||
QVector<char> audio_preview;
|
||||
void make_square_thumb();
|
||||
void make_square_thumb();
|
||||
};
|
||||
|
||||
struct Footage {
|
||||
Footage();
|
||||
~Footage();
|
||||
Footage();
|
||||
~Footage();
|
||||
|
||||
QString url;
|
||||
QString name;
|
||||
QString url;
|
||||
QString name;
|
||||
int64_t length;
|
||||
QVector<FootageStream> video_tracks;
|
||||
QVector<FootageStream> audio_tracks;
|
||||
int save_id;
|
||||
bool ready;
|
||||
bool invalid;
|
||||
QVector<FootageStream> video_tracks;
|
||||
QVector<FootageStream> audio_tracks;
|
||||
int save_id;
|
||||
bool ready;
|
||||
bool invalid;
|
||||
double speed;
|
||||
|
||||
PreviewGenerator* preview_gen;
|
||||
QMutex ready_lock;
|
||||
PreviewGenerator* preview_gen;
|
||||
QMutex ready_lock;
|
||||
|
||||
bool using_inout;
|
||||
long in;
|
||||
long out;
|
||||
bool using_inout;
|
||||
long in;
|
||||
long out;
|
||||
|
||||
long get_length_in_frames(double frame_rate);
|
||||
FootageStream *get_stream_from_file_index(bool video, int index);
|
||||
void reset();
|
||||
long get_length_in_frames(double frame_rate);
|
||||
FootageStream *get_stream_from_file_index(bool video, int index);
|
||||
void reset();
|
||||
};
|
||||
|
||||
#endif // FOOTAGE_H
|
||||
|
||||
+200
-200
@@ -13,311 +13,311 @@
|
||||
#include "debug.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
}
|
||||
|
||||
QString get_interlacing_name(int interlacing) {
|
||||
switch (interlacing) {
|
||||
case VIDEO_PROGRESSIVE: return "None (Progressive)";
|
||||
case VIDEO_TOP_FIELD_FIRST: return "Top Field First";
|
||||
case VIDEO_BOTTOM_FIELD_FIRST: return "Bottom Field First";
|
||||
default: return "Invalid";
|
||||
}
|
||||
switch (interlacing) {
|
||||
case VIDEO_PROGRESSIVE: return "None (Progressive)";
|
||||
case VIDEO_TOP_FIELD_FIRST: return "Top Field First";
|
||||
case VIDEO_BOTTOM_FIELD_FIRST: return "Bottom Field First";
|
||||
default: return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
QString get_channel_layout_name(int channels, uint64_t layout) {
|
||||
switch (channels) {
|
||||
case 0: return "Invalid"; break;
|
||||
case 1: return "Mono"; break;
|
||||
case 2: return "Stereo"; break;
|
||||
default: {
|
||||
char buf[50];
|
||||
av_get_channel_layout_string(buf, sizeof(buf), channels, layout);
|
||||
return QString(buf);
|
||||
}
|
||||
}
|
||||
switch (channels) {
|
||||
case 0: return "Invalid"; break;
|
||||
case 1: return "Mono"; break;
|
||||
case 2: return "Stereo"; break;
|
||||
default: {
|
||||
char buf[50];
|
||||
av_get_channel_layout_string(buf, sizeof(buf), channels, layout);
|
||||
return QString(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Media::Media(Media* iparent) :
|
||||
parent(iparent),
|
||||
throbber(NULL),
|
||||
root(false),
|
||||
type(-1)
|
||||
parent(iparent),
|
||||
throbber(NULL),
|
||||
root(false),
|
||||
type(-1)
|
||||
{}
|
||||
|
||||
Media::~Media() {
|
||||
switch (get_type()) {
|
||||
case MEDIA_TYPE_FOOTAGE: delete to_footage(); break;
|
||||
case MEDIA_TYPE_SEQUENCE: if (object != NULL) delete to_sequence(); break;
|
||||
}
|
||||
if (throbber != NULL) delete throbber;
|
||||
qDeleteAll(children);
|
||||
switch (get_type()) {
|
||||
case MEDIA_TYPE_FOOTAGE: delete to_footage(); break;
|
||||
case MEDIA_TYPE_SEQUENCE: if (object != NULL) delete to_sequence(); break;
|
||||
}
|
||||
if (throbber != NULL) delete throbber;
|
||||
qDeleteAll(children);
|
||||
}
|
||||
|
||||
Footage *Media::to_footage() {
|
||||
return static_cast<Footage*>(object);
|
||||
return static_cast<Footage*>(object);
|
||||
}
|
||||
|
||||
Sequence *Media::to_sequence() {
|
||||
return static_cast<Sequence*>(object);
|
||||
return static_cast<Sequence*>(object);
|
||||
}
|
||||
|
||||
void Media::set_footage(Footage *f) {
|
||||
type = MEDIA_TYPE_FOOTAGE;
|
||||
object = f;
|
||||
type = MEDIA_TYPE_FOOTAGE;
|
||||
object = f;
|
||||
}
|
||||
|
||||
void Media::set_sequence(Sequence *s) {
|
||||
set_icon(QIcon(":/icons/sequence.png"));
|
||||
type = MEDIA_TYPE_SEQUENCE;
|
||||
object = s;
|
||||
if (s != NULL) update_tooltip();
|
||||
set_icon(QIcon(":/icons/sequence.png"));
|
||||
type = MEDIA_TYPE_SEQUENCE;
|
||||
object = s;
|
||||
if (s != NULL) update_tooltip();
|
||||
}
|
||||
|
||||
void Media::set_folder() {
|
||||
if (folder_name.isEmpty()) folder_name = "New Folder";
|
||||
set_icon(QIcon(":/icons/folder.png"));
|
||||
type = MEDIA_TYPE_FOLDER;
|
||||
object = NULL;
|
||||
if (folder_name.isEmpty()) folder_name = "New Folder";
|
||||
set_icon(QIcon(":/icons/folder.png"));
|
||||
type = MEDIA_TYPE_FOLDER;
|
||||
object = NULL;
|
||||
}
|
||||
|
||||
void Media::set_icon(const QIcon &ico) {
|
||||
icon = ico;
|
||||
icon = ico;
|
||||
}
|
||||
|
||||
void Media::set_parent(Media *p) {
|
||||
parent = p;
|
||||
parent = p;
|
||||
}
|
||||
|
||||
void Media::update_tooltip(const QString& error) {
|
||||
switch (type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
Footage* f = to_footage();
|
||||
tooltip = "Name: " + f->name + "\nFilename: " + f->url + "\n";
|
||||
switch (type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
Footage* f = to_footage();
|
||||
tooltip = "Name: " + f->name + "\nFilename: " + f->url + "\n";
|
||||
|
||||
if (error.isEmpty()) {
|
||||
if (f->video_tracks.size() > 0) {
|
||||
tooltip += "Video Dimensions: ";
|
||||
for (int i=0;i<f->video_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += QString::number(f->video_tracks.at(i).video_width) + "x" + QString::number(f->video_tracks.at(i).video_height);
|
||||
}
|
||||
tooltip += "\n";
|
||||
if (error.isEmpty()) {
|
||||
if (f->video_tracks.size() > 0) {
|
||||
tooltip += "Video Dimensions: ";
|
||||
for (int i=0;i<f->video_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += QString::number(f->video_tracks.at(i).video_width) + "x" + QString::number(f->video_tracks.at(i).video_height);
|
||||
}
|
||||
tooltip += "\n";
|
||||
|
||||
if (!f->video_tracks.at(0).infinite_length) {
|
||||
tooltip += "Frame Rate: ";
|
||||
for (int i=0;i<f->video_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
if (f->video_tracks.at(i).video_interlacing == VIDEO_PROGRESSIVE) {
|
||||
tooltip += QString::number(f->video_tracks.at(i).video_frame_rate);
|
||||
} else {
|
||||
tooltip += QString::number(f->video_tracks.at(i).video_frame_rate * 2);
|
||||
tooltip += " fields (" + QString::number(f->video_tracks.at(i).video_frame_rate) + " frames)";
|
||||
}
|
||||
}
|
||||
tooltip += "\n";
|
||||
}
|
||||
if (!f->video_tracks.at(0).infinite_length) {
|
||||
tooltip += "Frame Rate: ";
|
||||
for (int i=0;i<f->video_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
if (f->video_tracks.at(i).video_interlacing == VIDEO_PROGRESSIVE) {
|
||||
tooltip += QString::number(f->video_tracks.at(i).video_frame_rate * f->speed);
|
||||
} else {
|
||||
tooltip += QString::number(f->video_tracks.at(i).video_frame_rate * f->speed * 2);
|
||||
tooltip += " fields (" + QString::number(f->video_tracks.at(i).video_frame_rate * f->speed) + " frames)";
|
||||
}
|
||||
}
|
||||
tooltip += "\n";
|
||||
}
|
||||
|
||||
tooltip += "Interlacing: ";
|
||||
for (int i=0;i<f->video_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += get_interlacing_name(f->video_tracks.at(i).video_interlacing);
|
||||
}
|
||||
}
|
||||
tooltip += "Interlacing: ";
|
||||
for (int i=0;i<f->video_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += get_interlacing_name(f->video_tracks.at(i).video_interlacing);
|
||||
}
|
||||
}
|
||||
|
||||
if (f->audio_tracks.size() > 0) {
|
||||
tooltip += "\n";
|
||||
if (f->audio_tracks.size() > 0) {
|
||||
tooltip += "\n";
|
||||
|
||||
tooltip += "Audio Frequency: ";
|
||||
for (int i=0;i<f->audio_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += QString::number(f->audio_tracks.at(i).audio_frequency);
|
||||
}
|
||||
tooltip += "\n";
|
||||
tooltip += "Audio Frequency: ";
|
||||
for (int i=0;i<f->audio_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += QString::number(f->audio_tracks.at(i).audio_frequency * f->speed);
|
||||
}
|
||||
tooltip += "\n";
|
||||
|
||||
tooltip += "Audio Channels: ";
|
||||
for (int i=0;i<f->audio_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += get_channel_layout_name(f->audio_tracks.at(i).audio_channels, f->audio_tracks.at(i).audio_layout);
|
||||
}
|
||||
// tooltip += "\n";
|
||||
}
|
||||
} else {
|
||||
tooltip += error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
{
|
||||
Sequence* s = to_sequence();
|
||||
tooltip = "Name: " + s->name
|
||||
+ "\nVideo Dimensions: " + QString::number(s->width) + "x" + QString::number(s->height)
|
||||
+ "\nFrame Rate: " + QString::number(s->frame_rate)
|
||||
+ "\nAudio Frequency: " + QString::number(s->audio_frequency)
|
||||
+ "\nAudio Layout: " + get_channel_layout_name(av_get_channel_layout_nb_channels(s->audio_layout), s->audio_layout);
|
||||
}
|
||||
break;
|
||||
}
|
||||
tooltip += "Audio Channels: ";
|
||||
for (int i=0;i<f->audio_tracks.size();i++) {
|
||||
if (i > 0) {
|
||||
tooltip += ", ";
|
||||
}
|
||||
tooltip += get_channel_layout_name(f->audio_tracks.at(i).audio_channels, f->audio_tracks.at(i).audio_layout);
|
||||
}
|
||||
// tooltip += "\n";
|
||||
}
|
||||
} else {
|
||||
tooltip += error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
{
|
||||
Sequence* s = to_sequence();
|
||||
tooltip = "Name: " + s->name
|
||||
+ "\nVideo Dimensions: " + QString::number(s->width) + "x" + QString::number(s->height)
|
||||
+ "\nFrame Rate: " + QString::number(s->frame_rate)
|
||||
+ "\nAudio Frequency: " + QString::number(s->audio_frequency)
|
||||
+ "\nAudio Layout: " + get_channel_layout_name(av_get_channel_layout_nb_channels(s->audio_layout), s->audio_layout);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *Media::to_object() {
|
||||
return object;
|
||||
return object;
|
||||
}
|
||||
|
||||
int Media::get_type() {
|
||||
return type;
|
||||
return type;
|
||||
}
|
||||
|
||||
const QString &Media::get_name() {
|
||||
switch (type) {
|
||||
case MEDIA_TYPE_FOOTAGE: return to_footage()->name;
|
||||
case MEDIA_TYPE_SEQUENCE: return to_sequence()->name;
|
||||
switch (type) {
|
||||
case MEDIA_TYPE_FOOTAGE: return to_footage()->name;
|
||||
case MEDIA_TYPE_SEQUENCE: return to_sequence()->name;
|
||||
default: return folder_name;
|
||||
}
|
||||
}
|
||||
|
||||
void Media::set_name(const QString &n) {
|
||||
switch (type) {
|
||||
case MEDIA_TYPE_FOOTAGE: to_footage()->name = n; break;
|
||||
case MEDIA_TYPE_SEQUENCE: to_sequence()->name = n; break;
|
||||
case MEDIA_TYPE_FOLDER: folder_name = n; break;
|
||||
}
|
||||
switch (type) {
|
||||
case MEDIA_TYPE_FOOTAGE: to_footage()->name = n; break;
|
||||
case MEDIA_TYPE_SEQUENCE: to_sequence()->name = n; break;
|
||||
case MEDIA_TYPE_FOLDER: folder_name = n; break;
|
||||
}
|
||||
}
|
||||
|
||||
double Media::get_frame_rate(int stream) {
|
||||
switch (get_type()) {
|
||||
switch (get_type()) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
Footage* f = to_footage();
|
||||
if (stream < 0) return f->video_tracks.at(0).video_frame_rate;
|
||||
return f->get_stream_from_file_index(true, stream)->video_frame_rate;
|
||||
if (stream < 0) return f->video_tracks.at(0).video_frame_rate * f->speed;
|
||||
return f->get_stream_from_file_index(true, stream)->video_frame_rate * f->speed;
|
||||
}
|
||||
case MEDIA_TYPE_SEQUENCE: return to_sequence()->frame_rate;
|
||||
}
|
||||
case MEDIA_TYPE_SEQUENCE: return to_sequence()->frame_rate;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int Media::get_sampling_rate(int stream) {
|
||||
switch (get_type()) {
|
||||
switch (get_type()) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
Footage* f = to_footage();
|
||||
if (stream < 0) return f->audio_tracks.at(0).audio_frequency;
|
||||
return to_footage()->get_stream_from_file_index(false, stream)->audio_frequency;
|
||||
if (stream < 0) return f->audio_tracks.at(0).audio_frequency * f->speed;
|
||||
return to_footage()->get_stream_from_file_index(false, stream)->audio_frequency * f->speed;
|
||||
}
|
||||
case MEDIA_TYPE_SEQUENCE: return to_sequence()->audio_frequency;
|
||||
}
|
||||
return 0;
|
||||
case MEDIA_TYPE_SEQUENCE: return to_sequence()->audio_frequency;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Media::appendChild(Media *child) {
|
||||
child->set_parent(this);
|
||||
children.append(child);
|
||||
child->set_parent(this);
|
||||
children.append(child);
|
||||
}
|
||||
|
||||
bool Media::setData(int col, const QVariant &value) {
|
||||
if (col == 0) {
|
||||
QString n = value.toString();
|
||||
if (!n.isEmpty() && get_name() != n) {
|
||||
undo_stack.push(new MediaRename(this, value.toString()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (col == 0) {
|
||||
QString n = value.toString();
|
||||
if (!n.isEmpty() && get_name() != n) {
|
||||
undo_stack.push(new MediaRename(this, value.toString()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Media *Media::child(int row) {
|
||||
return children.value(row);
|
||||
return children.value(row);
|
||||
}
|
||||
|
||||
int Media::childCount() const {
|
||||
return children.count();
|
||||
return children.count();
|
||||
}
|
||||
|
||||
int Media::columnCount() const {
|
||||
return 3;
|
||||
return 3;
|
||||
}
|
||||
|
||||
QVariant Media::data(int column, int role) {
|
||||
switch (role) {
|
||||
case Qt::DecorationRole:
|
||||
if (column == 0) {
|
||||
if (get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
Footage* f = to_footage();
|
||||
if (f->video_tracks.size() > 0
|
||||
&& f->video_tracks.at(0).preview_done) {
|
||||
return f->video_tracks.at(0).video_preview_square;
|
||||
}
|
||||
}
|
||||
switch (role) {
|
||||
case Qt::DecorationRole:
|
||||
if (column == 0) {
|
||||
if (get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
Footage* f = to_footage();
|
||||
if (f->video_tracks.size() > 0
|
||||
&& f->video_tracks.at(0).preview_done) {
|
||||
return f->video_tracks.at(0).video_preview_square;
|
||||
}
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
break;
|
||||
case Qt::DisplayRole:
|
||||
switch (column) {
|
||||
case 0: return (root) ? "Name" : get_name();
|
||||
case 1:
|
||||
if (root) return "Duration";
|
||||
if (get_type() == MEDIA_TYPE_SEQUENCE) {
|
||||
Sequence* s = to_sequence();
|
||||
return frame_to_timecode(s->getEndFrame(), config.timecode_view, s->frame_rate);
|
||||
}
|
||||
if (get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
Footage* f = to_footage();
|
||||
double r = 30;
|
||||
return icon;
|
||||
}
|
||||
break;
|
||||
case Qt::DisplayRole:
|
||||
switch (column) {
|
||||
case 0: return (root) ? "Name" : get_name();
|
||||
case 1:
|
||||
if (root) return "Duration";
|
||||
if (get_type() == MEDIA_TYPE_SEQUENCE) {
|
||||
Sequence* s = to_sequence();
|
||||
return frame_to_timecode(s->getEndFrame(), config.timecode_view, s->frame_rate);
|
||||
}
|
||||
if (get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
Footage* f = to_footage();
|
||||
double r = 30;
|
||||
|
||||
if (f->video_tracks.size() > 0 && !qIsNull(f->video_tracks.at(0).video_frame_rate))
|
||||
r = f->video_tracks.at(0).video_frame_rate;
|
||||
if (f->video_tracks.size() > 0 && !qIsNull(f->video_tracks.at(0).video_frame_rate))
|
||||
r = f->video_tracks.at(0).video_frame_rate * f->speed;
|
||||
|
||||
long len = f->get_length_in_frames(r);
|
||||
if (len > 0) return frame_to_timecode(len, config.timecode_view, r);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (root) return "Rate";
|
||||
if (get_type() == MEDIA_TYPE_SEQUENCE) return QString::number(get_frame_rate()) + " FPS";
|
||||
if (get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
Footage* f = to_footage();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (root) return "Rate";
|
||||
if (get_type() == MEDIA_TYPE_SEQUENCE) return QString::number(get_frame_rate()) + " FPS";
|
||||
if (get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
Footage* f = to_footage();
|
||||
double r;
|
||||
if (f->video_tracks.size() > 0 && !qIsNull(r = get_frame_rate())) {
|
||||
return QString::number(get_frame_rate()) + " FPS";
|
||||
} else if (f->audio_tracks.size() > 0) {
|
||||
return QString::number(get_sampling_rate()) + " Hz";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Qt::ToolTipRole:
|
||||
return tooltip;
|
||||
}
|
||||
return QVariant();
|
||||
} else if (f->audio_tracks.size() > 0) {
|
||||
return QString::number(get_sampling_rate()) + " Hz";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Qt::ToolTipRole:
|
||||
return tooltip;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int Media::row() const {
|
||||
if (parent) {
|
||||
return parent->children.indexOf(const_cast<Media*>(this));
|
||||
}
|
||||
return 0;
|
||||
if (parent) {
|
||||
return parent->children.indexOf(const_cast<Media*>(this));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Media *Media::parentItem() {
|
||||
return parent;
|
||||
return parent;
|
||||
}
|
||||
|
||||
void Media::removeChild(int i) {
|
||||
children.removeAt(i);
|
||||
children.removeAt(i);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user