Commit 96026871 authored by Julius Künzel's avatar Julius Künzel
Browse files

Add field order option to project settings

This uses "avfilter.fieldorder" internally.

Fixes #1355
parent b8309bbc
......@@ -480,6 +480,7 @@ bool Core::setCurrentProfile(const QString &profilePath)
emit m_monitorManager->updatePreviewScaling();
if (m_guiConstructed && m_mainWindow->hasTimeline() && m_mainWindow->getCurrentTimeline()->controller()->getModel()) {
m_mainWindow->getCurrentTimeline()->controller()->getModel()->updateProfile(getProjectProfile());
m_mainWindow->getCurrentTimeline()->controller()->getModel()->updateFieldOrderFilter(getCurrentProfile());
checkProfileValidity();
emit m_mainWindow->getCurrentTimeline()->controller()->frameFormatChanged();
}
......
......@@ -28,9 +28,6 @@ ProfilesDialog::ProfilesDialog(const QString &profileDescription, QWidget *paren
m_view.setupUi(this);
m_view.info_message->hide();
// TODO setting the fied order is not implemented yet
m_view.label_field_order->setVisible(false);
m_view.field_order->setVisible(false);
// Fill colorspace list (see mlt_profile.h)
m_view.colorspace->addItem(ProfileRepository::getColorspaceDescription(601), 601);
......@@ -78,9 +75,6 @@ ProfilesDialog::ProfilesDialog(const QString &profilePath, bool, QWidget *parent
{
m_view.setupUi(this);
m_view.info_message->hide();
// TODO setting the fied order is not implemented yet
m_view.label_field_order->setVisible(false);
m_view.field_order->setVisible(false);
// Fill colorspace list (see mlt_profile.h)
m_view.colorspace->addItem(ProfileRepository::getColorspaceDescription(601), 601);
......@@ -285,6 +279,7 @@ void ProfilesDialog::saveProfile(const QString &path)
profile->m_width = m_view.size_w->value();
profile->m_height = m_view.size_h->value();
profile->m_progressive = m_view.scanning->currentIndex() == 1;
profile->m_bottom_field_first = m_view.field_order->currentIndex() == 1;
profile->m_sample_aspect_num = m_view.aspect_num->value();
profile->m_sample_aspect_den = m_view.aspect_den->value();
profile->m_display_aspect_num = m_view.display_num->value();
......@@ -334,6 +329,7 @@ void ProfilesDialog::slotUpdateDisplay(QString currentProfilePath)
m_view.frame_num->setValue(curProfile->frame_rate_num());
m_view.frame_den->setValue(curProfile->frame_rate_den());
m_view.scanning->setCurrentIndex(curProfile->progressive() ? 1 : 0);
m_view.field_order->setCurrentIndex(curProfile->bottom_field_first() ? 1 : 0);
slotScanningChanged(m_view.scanning->currentIndex());
if (curProfile->progressive() != 0) {
m_view.fields->setText(locale.toString(double(curProfile->frame_rate_num() / curProfile->frame_rate_den()), 'f', 2));
......
......@@ -17,7 +17,7 @@ bool ProfileInfo::operator==(const ProfileInfo &other) const
int sar = sample_aspect_num() * 100 / sample_aspect_den();
int dar = display_aspect_num() * 100 / display_aspect_den();
return other.frame_rate_num() * 100 / other.frame_rate_den() == fps && other.width() == width() && other.height() == height() &&
other.progressive() == progressive() && other.sample_aspect_num() * 100 / other.sample_aspect_den() == sar &&
other.progressive() == progressive() && (progressive() ? true : other.bottom_field_first() == bottom_field_first()) && other.sample_aspect_num() * 100 / other.sample_aspect_den() == sar &&
other.display_aspect_num() * 100 / other.display_aspect_den() == dar && other.colorspace() == colorspace();
}
......
......@@ -29,6 +29,7 @@ public:
virtual int width() const = 0;
virtual int height() const = 0;
virtual bool progressive() const = 0;
virtual bool bottom_field_first() const = 0;
virtual int sample_aspect_num() const = 0;
virtual int sample_aspect_den() const = 0;
virtual double sar() const = 0;
......
......@@ -14,9 +14,11 @@
#include <QDir>
#include <QFile>
#include <memory>
ProfileModel::ProfileModel(const QString &path)
: m_path(path)
, m_invalid(false)
, m_bottom_field_first(false)
{
if (!QFile::exists(path) && path.contains(QLatin1Char('/'))) {
qCWarning(KDENLIVE_LOG) << "WARNING, COULD NOT FIND PROFILE " << path << ". We will default to DV_PAL profile";
......@@ -29,6 +31,21 @@ ProfileModel::ProfileModel(const QString &path)
m_invalid = true;
}
}
QFile f(path);
if (f.open(QFile::ReadOnly | QFile::Text)) {
int lineCt = 0;
QTextStream in(&f);
while (!in.atEnd() && lineCt < 30)
{
QString line = in.readLine();
if (line.contains(QStringLiteral("bottom_field_first"))) {
m_bottom_field_first = line.split(QStringLiteral("=")).at(1).toInt() == 1;
qDebug() << "FOUND" << "bottom_field_first value:" << m_bottom_field_first;
f.close();
}
}
f.close();
}
m_profile = std::make_unique<Mlt::Profile>(path.toStdString().c_str());
m_description = QString(m_profile->description());
}
......@@ -73,6 +90,11 @@ bool ProfileModel::progressive() const
return m_profile->progressive();
}
bool ProfileModel::bottom_field_first() const
{
return m_bottom_field_first;
}
int ProfileModel::sample_aspect_num() const
{
return m_profile->sample_aspect_num();
......@@ -132,7 +154,8 @@ ProfileParam::ProfileParam(QDomElement element)
: m_description(element.attribute(QStringLiteral("description")))
, m_frame_rate_num(element.attribute(QStringLiteral("frame_rate_num")).toInt())
, m_frame_rate_den(element.attribute(QStringLiteral("frame_rate_den")).toInt())
, m_progressive((element.attribute(QStringLiteral("progressive")).toInt() != 0))
, m_progressive(element.attribute(QStringLiteral("progressive")).toInt() != 0)
, m_bottom_field_first(element.attribute(QStringLiteral("bottom_field_first")).toInt() != 0)
, m_sample_aspect_num(element.attribute(QStringLiteral("sample_aspect_num")).toInt())
, m_sample_aspect_den(element.attribute(QStringLiteral("sample_aspect_den")).toInt())
, m_display_aspect_num(element.attribute(QStringLiteral("display_aspect_num")).toInt())
......@@ -164,6 +187,7 @@ ProfileParam::ProfileParam(ProfileInfo *p)
, m_width(p->width())
, m_height(p->height())
, m_progressive(p->progressive())
, m_bottom_field_first(p->bottom_field_first())
, m_sample_aspect_num(p->sample_aspect_num())
, m_sample_aspect_den(p->sample_aspect_den())
, m_display_aspect_num(p->display_aspect_num())
......@@ -183,6 +207,7 @@ ProfileParam::ProfileParam(ProfileParam *p)
, m_width(p->width())
, m_height(p->height())
, m_progressive(p->progressive())
, m_bottom_field_first(p->bottom_field_first())
, m_sample_aspect_num(p->sample_aspect_num())
, m_sample_aspect_den(p->sample_aspect_den())
, m_display_aspect_num(p->display_aspect_num())
......@@ -200,6 +225,7 @@ ProfileParam::ProfileParam(Mlt::Profile *p)
, m_width(p->width())
, m_height(p->height())
, m_progressive(p->progressive())
, m_bottom_field_first(false)
, m_sample_aspect_num(p->sample_aspect_num())
, m_sample_aspect_den(p->sample_aspect_den())
, m_display_aspect_num(p->display_aspect_num())
......@@ -238,6 +264,10 @@ bool ProfileParam::progressive() const
{
return m_progressive;
}
bool ProfileParam::bottom_field_first() const
{
return m_bottom_field_first;
}
int ProfileParam::sample_aspect_num() const
{
return m_sample_aspect_num;
......
......@@ -36,6 +36,7 @@ public:
int width() const override;
int height() const override;
bool progressive() const override;
bool bottom_field_first() const override;
int sample_aspect_num() const override;
int sample_aspect_den() const override;
double sar() const override;
......@@ -57,6 +58,7 @@ protected:
QString m_path;
bool m_invalid;
QString m_description;
bool m_bottom_field_first;
std::unique_ptr<Mlt::Profile> m_profile;
};
......@@ -81,6 +83,7 @@ public:
int width() const override;
int height() const override;
bool progressive() const override;
bool bottom_field_first() const override;
int sample_aspect_num() const override;
int sample_aspect_den() const override;
int display_aspect_num() const override;
......@@ -101,6 +104,7 @@ public:
int m_width;
int m_height;
bool m_progressive;
bool m_bottom_field_first;
int m_sample_aspect_num;
int m_sample_aspect_den;
int m_display_aspect_num;
......
......@@ -178,6 +178,7 @@ const QString ProfileRepository::saveProfile(ProfileInfo *profile, QString profi
<< "width=" << profile->width() << '\n'
<< "height=" << profile->height() << '\n'
<< "progressive=" << static_cast<int>(profile->progressive()) << '\n'
<< "bottom_field_first=" << static_cast<int>(profile->bottom_field_first()) << '\n'
<< "sample_aspect_num=" << profile->sample_aspect_num() << '\n'
<< "sample_aspect_den=" << profile->sample_aspect_den() << '\n'
<< "display_aspect_num=" << profile->display_aspect_num() << '\n'
......
......@@ -194,11 +194,10 @@ void ProfileWidget::fillDescriptionPanel(const QString &profile_path)
description += i18n("Frame rate: %1 fps<br/>", profile->fps());
description += i18n("Pixel aspect ratio: %1<br/>", profile->sar());
description += i18n("Color space: %1<br/>", profile->colorspaceDescription());
QString interlaced = i18n("yes");
if (profile->progressive()) {
interlaced = i18n("no");
description += i18n("Interlaced: %1</p>", profile->progressive() ? i18n("no") : i18n("yes"));
if (!profile->progressive()) {
description += i18n("Field order: %1</p>", profile->bottom_field_first() ? i18n("Bottom field first") : i18n("Top field first"));
}
description += i18n("Interlaced: %1</p>", interlaced);
}
m_descriptionPanel->setHtml(description);
}
......
......@@ -24,6 +24,7 @@
//#include "timeline2/view/timelinewidget.h"
//#include "timeline2/view/timelinecontroller.h"
#include "timeline2/model/timelinefunctions.hpp"
#include "profiles/profilemodel.hpp"
#include "monitor/monitormanager.h"
......@@ -5677,6 +5678,40 @@ void TimelineModel::updateProfile(Mlt::Profile *profile)
buildTrackCompositing(true);
}
void TimelineModel::updateFieldOrderFilter(std::unique_ptr<ProfileModel> &ptr)
{
std::shared_ptr<Mlt::Filter> foFilter = nullptr;
for (int i = 0; i < m_tractor->filter_count(); i++) {
std::shared_ptr<Mlt::Filter> fl(m_tractor->filter(i));
if (!fl->is_valid()) {
continue;
}
const QString filterService = fl->get("mlt_service");
int foundCount = 0;
if (filterService == QLatin1String("avfilter.fieldorder")) {
foundCount++;
if ((ptr->progressive() || foundCount > 1) && fl->get_int("internal_added") == 237) {
// If the profile is progressiv, field order is redundant: remove
// Also we only need one field order filter
m_tractor->detach(*fl.get());
} else {
foFilter = fl;
foFilter->set("internal_added", 237);
foFilter->set("av.order", ptr->bottom_field_first() ? "bff" : "tff");
}
}
}
// Build default filter if not found
if (!ptr->progressive() && foFilter == nullptr) {
foFilter.reset(new Mlt::Filter(m_tractor->get_profile(), "avfilter.fieldorder"));
if (foFilter->is_valid()) {
foFilter->set("internal_added", 237);
foFilter->set("av.order", ptr->bottom_field_first() ? "bff" : "tff");
m_tractor->attach(*foFilter.get());
}
}
}
int TimelineModel::getBlankSizeNearClip(int clipId, bool after) const
{
READ_LOCK();
......
......@@ -28,6 +28,7 @@ class SnapModel;
class SubtitleModel;
class TimelineItemModel;
class TrackModel;
class ProfileModel;
/** @brief This class represents a Timeline object, as viewed by the backend.
In general, the Gui associated with it will send modification queries (such as resize or move), and this class authorize them or not depending on the
......@@ -733,6 +734,9 @@ public:
/** @brief Refresh the tractor profile in case a change was requested. */
void updateProfile(Mlt::Profile *profile);
/** @brief Add, remove or refresh the internal added avfilter.fieldorder effect based on the given profile*/
void updateFieldOrderFilter(std::unique_ptr<ProfileModel> &ptr);
/** @brief Clear the current selection
@param onDeletion is true when the selection is cleared as a result of a deletion
*/
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment