various: implement sequence pixel aspect ratios and interlacing settings

Implements the following:
- Sequences have pixel aspect ratios that work in tandem with footage PARs
  to render footage correctly. Viewer and export also acknowledge PARs
- Sequences can have interlacing settings. This doesn't do anything yet,
  eventually the renderer will need to interlace/deinterlace/reinterlace
  appropriately in order to conform all the footage to the sequence. Export
  acknowledges interlacing, but this only affects metadata, not the image.
This commit is contained in:
itsmattkc
2020-08-10 01:47:26 +10:00
parent 901f1001af
commit 28dcff10c0
51 changed files with 1201 additions and 605 deletions
+1
View File
@@ -41,6 +41,7 @@ add_subdirectory(projecttoolbar)
add_subdirectory(resizablescrollbar)
add_subdirectory(scope)
add_subdirectory(slider)
add_subdirectory(standardcombos)
add_subdirectory(taskview)
add_subdirectory(timebased)
add_subdirectory(timelinewidget)
@@ -29,7 +29,8 @@ QVariant NodeTableTraverser::ProcessVideoFootage(StreamPtr stream, const rationa
return QVariant::fromValue(VideoParams(video_stream->width(),
video_stream->height(),
video_stream->timebase(),
video_stream->format()));
video_stream->format(),
video_stream->pixel_aspect_ratio()));
}
QVariant NodeTableTraverser::ProcessAudioFootage(StreamPtr stream, const TimeRange &input_time)
+28
View File
@@ -0,0 +1,28 @@
# 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}
widget/standardcombos/channellayoutcombobox.h
widget/standardcombos/frameratecombobox.h
widget/standardcombos/interlacedcombobox.h
widget/standardcombos/pixelaspectratiocombobox.h
widget/standardcombos/pixelformatcombobox.h
widget/standardcombos/sampleratecombobox.h
widget/standardcombos/standardcombos.h
widget/standardcombos/videodividercombobox.h
PARENT_SCOPE
)
@@ -0,0 +1,62 @@
/***
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 CHANNELLAYOUTCOMBOBOX_H
#define CHANNELLAYOUTCOMBOBOX_H
#include <QComboBox>
#include "render/audioparams.h"
OLIVE_NAMESPACE_ENTER
class ChannelLayoutComboBox : public QComboBox
{
Q_OBJECT
public:
ChannelLayoutComboBox(QWidget* parent = nullptr) :
QComboBox(parent)
{
foreach (const uint64_t& ch_layout, AudioParams::kSupportedChannelLayouts) {
this->addItem(AudioParams::ChannelLayoutToString(ch_layout),
QVariant::fromValue(ch_layout));
}
}
uint64_t GetChannelLayout() const
{
return this->currentData().toULongLong();
}
void SetChannelLayout(uint64_t ch)
{
for (int i=0; i<this->count(); i++) {
if (this->itemData(i).toULongLong() == ch) {
this->setCurrentIndex(i);
break;
}
}
}
};
OLIVE_NAMESPACE_EXIT
#endif // CHANNELLAYOUTCOMBOBOX_H
@@ -0,0 +1,62 @@
/***
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 FRAMERATECOMBOBOX_H
#define FRAMERATECOMBOBOX_H
#include <QComboBox>
#include "common/rational.h"
#include "render/videoparams.h"
OLIVE_NAMESPACE_ENTER
class FrameRateComboBox : public QComboBox
{
Q_OBJECT
public:
FrameRateComboBox(QWidget* parent = nullptr) :
QComboBox(parent)
{
foreach (const rational& fr, VideoParams::kSupportedFrameRates) {
this->addItem(VideoParams::FrameRateToString(fr), QVariant::fromValue(fr));
}
}
rational GetFrameRate() const
{
return this->currentData().value<rational>();
}
void SetFrameRate(const rational& r)
{
for (int i=0; i<this->count(); i++) {
if (this->itemData(i).value<rational>() == r) {
this->setCurrentIndex(i);
break;
}
}
}
};
OLIVE_NAMESPACE_EXIT
#endif // FRAMERATECOMBOBOX_H
@@ -0,0 +1,57 @@
/***
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 INTERLACEDCOMBOBOX_H
#define INTERLACEDCOMBOBOX_H
#include <QComboBox>
#include "render/videoparams.h"
OLIVE_NAMESPACE_ENTER
class InterlacedComboBox : public QComboBox
{
Q_OBJECT
public:
InterlacedComboBox(QWidget* parent = nullptr) :
QComboBox(parent)
{
// These must match the Interlacing enum in VideoParams
this->addItem(tr("None (Progressive)"));
this->addItem(tr("Top-Field First"));
this->addItem(tr("Bottom-Field First"));
}
VideoParams::Interlacing GetInterlaceMode() const
{
return static_cast<VideoParams::Interlacing>(this->currentIndex());
}
void SetInterlaceMode(VideoParams::Interlacing mode)
{
this->setCurrentIndex(mode);
}
};
OLIVE_NAMESPACE_EXIT
#endif // INTERLACEDCOMBOBOX_H
@@ -0,0 +1,127 @@
/***
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 PIXELASPECTRATIOCOMBOBOX_H
#define PIXELASPECTRATIOCOMBOBOX_H
#include <QComboBox>
#include "common/ratiodialog.h"
#include "render/videoparams.h"
OLIVE_NAMESPACE_ENTER
class PixelAspectRatioComboBox : public QComboBox
{
Q_OBJECT
public:
PixelAspectRatioComboBox(QWidget* parent = nullptr) :
QComboBox(parent),
dont_prompt_custom_par_(false)
{
QStringList par_names = VideoParams::GetStandardPixelAspectRatioNames();
for (int i=0; i<VideoParams::kStandardPixelAspects.size(); i++) {
const rational& ratio = VideoParams::kStandardPixelAspects.at(i);
this->addItem(par_names.at(i),
QVariant::fromValue(ratio));
}
// Always add custom item last, much of the logic relies on this. Set this to the current AR so
// that if none of the above are ==, it will eventually select this item
this->addItem(QString());
UpdateCustomItem(rational());
// Pick up index signal to query for custom aspect ratio if requested
connect(this, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &PixelAspectRatioComboBox::IndexChanged);
}
rational GetPixelAspectRatio() const
{
return this->currentData().value<rational>();
}
void SetPixelAspectRatio(const rational& r)
{
// Determine which index to select on startup
for (int i=0; i<this->count(); i++) {
if (this->itemData(i).value<rational>() == r) {
this->setCurrentIndex(i);
return;
}
}
// Must not have found the ratio, so it must be custom
UpdateCustomItem(r);
dont_prompt_custom_par_ = true;
this->setCurrentIndex(this->count() - 1);
dont_prompt_custom_par_ = false;
}
private slots:
void IndexChanged(int index)
{
if (dont_prompt_custom_par_) {
return;
}
// Detect if custom was selected, in which case query what the new AR should be
if (index == this->count() - 1) {
// Query for custom pixel aspect ratio
bool ok;
double custom_ratio = GetFloatRatioFromUser(this,
tr("Set Custom Pixel Aspect Ratio"),
&ok);
if (ok) {
UpdateCustomItem(rational::fromDouble(custom_ratio));
}
}
}
private:
void UpdateCustomItem(const rational &ratio)
{
const int custom_index = this->count() - 1;
if (ratio.isNull()) {
this->setItemText(custom_index,
tr("Custom..."));
// Use 1:1 to prevent any real chance of the PAR being set to 0
this->setItemData(custom_index,
QVariant::fromValue(rational(1)));
} else {
this->setItemText(custom_index,
VideoParams::FormatPixelAspectRatioString(tr("Custom (%1)"), ratio));
this->setItemData(custom_index,
QVariant::fromValue(ratio));
}
}
bool dont_prompt_custom_par_;
};
OLIVE_NAMESPACE_EXIT
#endif // PIXELASPECTRATIOCOMBOBOX_H
@@ -0,0 +1,67 @@
/***
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 PIXELFORMATCOMBOBOX_H
#define PIXELFORMATCOMBOBOX_H
#include <QComboBox>
#include "render/pixelformat.h"
OLIVE_NAMESPACE_ENTER
class PixelFormatComboBox : public QComboBox
{
Q_OBJECT
public:
PixelFormatComboBox(bool alpha_only, bool float_only, QWidget* parent = nullptr) :
QComboBox(parent)
{
// Set up preview formats
for (int i=0;i<PixelFormat::PIX_FMT_COUNT;i++) {
PixelFormat::Format pix_fmt = static_cast<PixelFormat::Format>(i);
if ((!alpha_only || PixelFormat::FormatHasAlphaChannel(pix_fmt))
&& (!float_only || PixelFormat::FormatIsFloat(pix_fmt))) {
this->addItem(PixelFormat::GetName(pix_fmt), pix_fmt);
}
}
}
PixelFormat::Format GetPixelFormat() const
{
return static_cast<PixelFormat::Format>(this->currentData().toInt());
}
void SetPixelFormat(PixelFormat::Format fmt)
{
for (int i=0; i<this->count(); i++) {
if (this->itemData(i).toInt() == fmt) {
this->setCurrentIndex(i);
break;
}
}
}
};
OLIVE_NAMESPACE_EXIT
#endif // PIXELFORMATCOMBOBOX_H
@@ -0,0 +1,61 @@
/***
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 SAMPLERATECOMBOBOX_H
#define SAMPLERATECOMBOBOX_H
#include <QComboBox>
#include "render/audioparams.h"
OLIVE_NAMESPACE_ENTER
class SampleRateComboBox : public QComboBox
{
Q_OBJECT
public:
SampleRateComboBox(QWidget* parent = nullptr) :
QComboBox(parent)
{
foreach (int sr, AudioParams::kSupportedSampleRates) {
this->addItem(AudioParams::SampleRateToString(sr), sr);
}
}
int GetSampleRate() const
{
return this->currentData().toInt();
}
void SetSampleRate(int rate)
{
for (int i=0; i<this->count(); i++) {
if (this->itemData(i).toInt() == rate) {
this->setCurrentIndex(i);
break;
}
}
}
};
OLIVE_NAMESPACE_EXIT
#endif // SAMPLERATECOMBOBOX_H
@@ -0,0 +1,32 @@
/***
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 STANDARDCOMBOS_H
#define STANDARDCOMBOS_H
#include "channellayoutcombobox.h"
#include "frameratecombobox.h"
#include "interlacedcombobox.h"
#include "pixelaspectratiocombobox.h"
#include "pixelformatcombobox.h"
#include "sampleratecombobox.h"
#include "videodividercombobox.h"
#endif // STANDARDCOMBOS_H
@@ -0,0 +1,69 @@
/***
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 VIDEODIVIDERCOMBOBOX_H
#define VIDEODIVIDERCOMBOBOX_H
#include <QComboBox>
#include "render/videoparams.h"
OLIVE_NAMESPACE_ENTER
class VideoDividerComboBox : public QComboBox
{
Q_OBJECT
public:
VideoDividerComboBox(QWidget* parent = nullptr) :
QComboBox(parent)
{
foreach (int d, VideoParams::kSupportedDividers) {
QString name;
if (d == 1) {
name = tr("Full");
} else {
name = tr("1/%1").arg(d);
}
this->addItem(name, d);
}
}
int GetDivider() const
{
return this->currentData().toInt();
}
void SetDivider(int d)
{
for (int i=0; i<this->count(); i++) {
if (this->itemData(i).toInt() == d) {
this->setCurrentIndex(i);
break;
}
}
}
};
OLIVE_NAMESPACE_EXIT
#endif // VIDEODIVIDERCOMBOBOX_H
+4
View File
@@ -88,6 +88,8 @@ void FootageViewerWidget::SetFootage(Footage *footage)
video_stream->height(),
video_stream->frame_rate().flipped(),
static_cast<PixelFormat::Format>(Config::Current()["DefaultSequencePreviewFormat"].toInt()),
video_stream->pixel_aspect_ratio(),
video_stream->interlacing(),
VideoParams::generate_auto_divider(video_stream->width(), video_stream->height())));
NodeParam::ConnectEdge(video_node_->output(), viewer_node_->texture_input());
} else {
@@ -98,6 +100,8 @@ void FootageViewerWidget::SetFootage(Footage *footage)
height,
Config::Current()["DefaultSequenceFrameRate"].value<rational>(),
static_cast<PixelFormat::Format>(Config::Current()["DefaultSequencePreviewFormat"].toInt()),
Config::Current()["DefaultSequencePixelAspect"].value<rational>(),
Config::Current()["DefaultSequenceInterlacing"].value<VideoParams::Interlacing>(),
VideoParams::generate_auto_divider(width, height)));
}
+15 -10
View File
@@ -164,7 +164,8 @@ void ViewerWidget::TimeChangedEvent(const int64_t &i)
void ViewerWidget::ConnectNodeInternal(ViewerOutput *n)
{
connect(n, &ViewerOutput::SizeChanged, this, &ViewerWidget::SizeChangedSlot);
connect(n, &ViewerOutput::SizeChanged, this, &ViewerWidget::SetViewerResolution);
connect(n, &ViewerOutput::PixelAspectChanged, this, &ViewerWidget::SetViewerPixelAspect);
connect(n, &ViewerOutput::LengthChanged, this, &ViewerWidget::LengthChangedSlot);
connect(n, &ViewerOutput::VideoParamsChanged, this, &ViewerWidget::UpdateRendererVideoParameters);
connect(n, &ViewerOutput::AudioParamsChanged, this, &ViewerWidget::UpdateRendererAudioParameters);
@@ -176,7 +177,8 @@ void ViewerWidget::ConnectNodeInternal(ViewerOutput *n)
n->audio_playback_cache()->SetParameters(n->audio_params());
SizeChangedSlot(n->video_params().width(), n->video_params().height());
SetViewerResolution(n->video_params().width(), n->video_params().height());
SetViewerPixelAspect(n->video_params().pixel_aspect_ratio());
last_length_ = rational();
LengthChangedSlot(n->GetLength());
@@ -213,7 +215,8 @@ void ViewerWidget::DisconnectNodeInternal(ViewerOutput *n)
{
PauseInternal();
disconnect(n, &ViewerOutput::SizeChanged, this, &ViewerWidget::SizeChangedSlot);
disconnect(n, &ViewerOutput::SizeChanged, this, &ViewerWidget::SetViewerResolution);
disconnect(n, &ViewerOutput::PixelAspectChanged, this, &ViewerWidget::SetViewerPixelAspect);
disconnect(n, &ViewerOutput::LengthChanged, this, &ViewerWidget::LengthChangedSlot);
disconnect(n, &ViewerOutput::VideoParamsChanged, this, &ViewerWidget::UpdateRendererVideoParameters);
disconnect(n, &ViewerOutput::AudioParamsChanged, this, &ViewerWidget::UpdateRendererAudioParameters);
@@ -224,7 +227,7 @@ void ViewerWidget::DisconnectNodeInternal(ViewerOutput *n)
ruler()->SetPlaybackCache(nullptr);
// Effectively disables the viewer and clears the state
SizeChangedSlot(0, 0);
SetViewerResolution(0, 0);
display_widget_->DisconnectColorManager();
foreach (ViewerWindow* window, windows_) {
@@ -280,11 +283,6 @@ void ViewerWidget::SetColorMenuEnabled(bool enabled)
color_menu_enabled_ = enabled;
}
void ViewerWidget::SetOverrideSize(int width, int height)
{
SizeChangedSlot(width, height);
}
void ViewerWidget::SetMatrix(const QMatrix4x4 &mat)
{
display_widget_->SetMatrix(mat);
@@ -1061,7 +1059,7 @@ void ViewerWidget::PlaybackTimerUpdate()
}
}
void ViewerWidget::SizeChangedSlot(int width, int height)
void ViewerWidget::SetViewerResolution(int width, int height)
{
sizer_->SetChildSize(width, height);
@@ -1070,6 +1068,13 @@ void ViewerWidget::SizeChangedSlot(int width, int height)
}
}
void ViewerWidget::SetViewerPixelAspect(const rational &ratio)
{
sizer_->SetPixelAspectRatio(ratio);
// FIXME: Update windows too
}
void ViewerWidget::LengthChangedSlot(const rational &length)
{
if (last_length_ != length) {
+4 -4
View File
@@ -73,8 +73,6 @@ public:
*/
void SetColorMenuEnabled(bool enabled);
void SetOverrideSize(int width, int height);
void SetMatrix(const QMatrix4x4& mat);
/**
@@ -124,6 +122,10 @@ public slots:
void CacheSequenceInOut();
void SetViewerResolution(int width, int height);
void SetViewerPixelAspect(const rational& ratio);
signals:
/**
* @brief Wrapper for ViewerGLWidget::CursorColor()
@@ -257,8 +259,6 @@ private:
private slots:
void PlaybackTimerUpdate();
void SizeChangedSlot(int width, int height);
void LengthChangedSlot(const rational& length);
void UpdateRendererVideoParameters();
+15 -10
View File
@@ -27,7 +27,9 @@ OLIVE_NAMESPACE_ENTER
ViewerSizer::ViewerSizer(QWidget *parent) :
QWidget(parent),
widget_(nullptr),
aspect_ratio_(0),
width_(0),
height_(0),
pixel_aspect_(1),
zoom_(0)
{
}
@@ -51,11 +53,12 @@ void ViewerSizer::SetChildSize(int width, int height)
width_ = width;
height_ = height;
if (!width_ || !height_) {
aspect_ratio_ = 0;
} else {
aspect_ratio_ = static_cast<double>(width_) / static_cast<double>(height_);
}
UpdateSize();
}
void ViewerSizer::SetPixelAspectRatio(const rational &pixel_aspect)
{
pixel_aspect_ = pixel_aspect;
UpdateSize();
}
@@ -81,7 +84,7 @@ void ViewerSizer::UpdateSize()
}
// If the aspect ratio is 0, the widget is always hidden
if (qIsNull(aspect_ratio_)) {
if (!width_ || !height_) {
widget_->setVisible(false);
return;
}
@@ -91,6 +94,8 @@ void ViewerSizer::UpdateSize()
QSize child_size;
QMatrix4x4 child_matrix;
double sequence_aspect_ratio = static_cast<double>(width_) / static_cast<double>(height_) * pixel_aspect_.toDouble();
if (zoom_ <= 0) {
// If zoom is 0, we auto-fit
@@ -98,12 +103,12 @@ void ViewerSizer::UpdateSize()
child_size = size();
if (our_aspect_ratio > aspect_ratio_) {
if (our_aspect_ratio > sequence_aspect_ratio) {
// This container is wider than the image, scale by height
child_size = QSize(qRound(child_size.height() * aspect_ratio_), height());
child_size = QSize(qRound(child_size.height() * sequence_aspect_ratio), height());
} else {
// This container is taller than the image, scale by width
child_size = QSize(width(), qRound(child_size.width() / aspect_ratio_));
child_size = QSize(width(), qRound(child_size.width() / sequence_aspect_ratio));
}
} else {
+7 -4
View File
@@ -24,6 +24,7 @@
#include <QWidget>
#include "common/define.h"
#include "common/rational.h"
OLIVE_NAMESPACE_ENTER
@@ -56,6 +57,11 @@ public:
*/
void SetChildSize(int width, int height);
/**
* @brief Set pixel aspect ratio
*/
void SetPixelAspectRatio(const rational& pixel_aspect);
/**
* @brief Set the zoom value of the child widget
*
@@ -91,10 +97,7 @@ private:
int width_;
int height_;
/**
* @brief Aspect ratio calculated from the size provided by SetChildSize()
*/
double aspect_ratio_;
rational pixel_aspect_;
/**
* @brief Internal zoom value