From 6586b4413f8c1132aba586740fba60a46b003695 Mon Sep 17 00:00:00 2001
From: andreasGBL <29144928+andreasGBL@users.noreply.github.com>
Date: Mon, 29 Apr 2024 23:30:04 +0200
Subject: [PATCH] Added option to rotate and flip the video

---
 include/ffmpegwrapper.h |  3 +++
 include/structs.h       | 10 +++++++++
 src/ffmpegwrapper.cpp   | 16 +++++++++++++++
 src/videolowwindow.cpp  | 15 ++++++++++----
 src/videolowwindow.ui   | 45 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 85 insertions(+), 4 deletions(-)

diff --git a/include/ffmpegwrapper.h b/include/ffmpegwrapper.h
index c95ef6a..324ffde 100644
--- a/include/ffmpegwrapper.h
+++ b/include/ffmpegwrapper.h
@@ -5,6 +5,7 @@ struct TrimSettings;
 struct CodecConfig;
 struct Resolution;
 struct Video;
+enum TRANSFORM_CONFIG;
 
 class QTime;
 class QString;
@@ -16,6 +17,7 @@ struct ExportSettings {
 	bool vertical;
 	bool audioOnly;
 	bool videoOnly;
+	TRANSFORM_CONFIG transformConfig ;
 };
 
 class FFMPEGWrapper
@@ -33,6 +35,7 @@ class FFMPEGWrapper
 	QString getMBitRateString(double MBitRate);
 	QString getFramerateFilter(double Framerate, double vidFramerate);
 	QString getScaleFilterString(Resolution const & res, Resolution const & vidRes, int HardwareAcceleration, bool vertical);
+	QString getTransformFilterString(TRANSFORM_CONFIG const& t_config, bool vertical);
 
 	QString getVideoCodecString(CodecConfig const & codec, bool trimOnly);
 	QString getAudioCodecString(const Video& video, const TrimSettings& settings, const CodecConfig& codec, const ExportSettings& exports);
diff --git a/include/structs.h b/include/structs.h
index 28ff5c4..bf812a9 100644
--- a/include/structs.h
+++ b/include/structs.h
@@ -62,6 +62,16 @@ Resolution const RESOLUTIONS[] = {
 	}
 };
 
+enum TRANSFORM_CONFIG {
+	IDENTITY,
+	PLUS90,
+	PLUS180,
+	PLUS270,
+	HFLIP,
+	VFLIP,
+	SIZE //last element, denoted as size
+};
+
 float const FRAMERATES[] = {
 	0,
 	30,
diff --git a/src/ffmpegwrapper.cpp b/src/ffmpegwrapper.cpp
index ce71db2..bdb57f0 100644
--- a/src/ffmpegwrapper.cpp
+++ b/src/ffmpegwrapper.cpp
@@ -33,6 +33,7 @@ bool FFMPEGWrapper::exportFile(const Video& video, const TrimSettings& settings,
 	std::vector<QString> filters;
 	QString framerateFilter = getFramerateFilter(exports.framerate, video.framerate);
 	QString scaleFilter = getScaleFilterString(res, video.resolution, codec.hw_acceleration, exports.vertical);
+	QString transformFilter = getTransformFilterString(exports.transformConfig, exports.vertical);
 
 	//options part2
 	QString audioCodec = getAudioCodecString(video, settings, codec, exports);
@@ -60,6 +61,8 @@ bool FFMPEGWrapper::exportFile(const Video& video, const TrimSettings& settings,
 		filters.push_back(framerateFilter);
 	if (scaleFilter.length() > 0)
 		filters.push_back(scaleFilter);
+	if (transformFilter.length() > 0)
+		filters.push_back(transformFilter);
 
 	//Add filters:
 	QString videoFilterString("-vf \"");
@@ -152,6 +155,19 @@ QString FFMPEGWrapper::getScaleFilterString(Resolution const& res, Resolution co
 	}
 }
 
+QString FFMPEGWrapper::getTransformFilterString(TRANSFORM_CONFIG const& t_config, bool vertical)
+{
+	QString options[6] = {
+		"",
+		"transpose=1",
+		"transpose=1,transpose=1",
+		"transpose=2",
+		"hflip",
+		"vflip"
+	};
+	return options[t_config];
+}
+
 QString FFMPEGWrapper::getVideoCodecString(CodecConfig const& codec, bool trimOnly)
 {
 	QString prefix = "-c:v ";
diff --git a/src/videolowwindow.cpp b/src/videolowwindow.cpp
index ffb3496..9b16f39 100644
--- a/src/videolowwindow.cpp
+++ b/src/videolowwindow.cpp
@@ -102,7 +102,8 @@ void VideoLowWindow::quickH264(double MBitRate)
 			false,
 			false,
 			false,
-			false
+			false,
+			TRANSFORM_CONFIG::IDENTITY
 		};
 		handleExportExitCode(
 			ffmpeg->exportFile(
@@ -128,7 +129,8 @@ void VideoLowWindow::quickHEVC(double MBitRate)
 			false,
 			false,
 			false,
-			false
+			false,
+			TRANSFORM_CONFIG::IDENTITY
 		};
 		handleExportExitCode(
 			ffmpeg->exportFile(
@@ -229,13 +231,17 @@ void VideoLowWindow::exportVideo()
 	std::cout << "export" << std::endl;
 	if (currentVideo) {
 		auto codec = getCodecConfig();
+		int transformIndex = ui->transformCombobox->currentIndex();
+		TRANSFORM_CONFIG transform = static_cast<TRANSFORM_CONFIG>((transformIndex < TRANSFORM_CONFIG::IDENTITY || transformIndex >= TRANSFORM_CONFIG::SIZE) ? 0 : transformIndex);
+
 		ExportSettings exp = {
 			ui->BitrateDoubleSpinBox->value(),
 			FRAMERATES[ui->FramerateComboBox->currentIndex()],
 			false,
 			ui->verticalVideoCheckbox->isChecked(),
 			ui->AudioOnlyCheckBox->isChecked(),
-			ui->RemoveAudioCheckBox->isChecked()
+			ui->RemoveAudioCheckBox->isChecked(),
+			transform
 		};
 
 		handleExportExitCode(
@@ -269,7 +275,8 @@ void VideoLowWindow::quickTrimOnly()
 			true,
 			false,
 			false,
-			false
+			false,
+			TRANSFORM_CONFIG::IDENTITY
 		};
 		handleExportExitCode(
 			ffmpeg->exportFile(
diff --git a/src/videolowwindow.ui b/src/videolowwindow.ui
index 7771a18..bfdb296 100644
--- a/src/videolowwindow.ui
+++ b/src/videolowwindow.ui
@@ -370,6 +370,51 @@
                  </item>
                 </layout>
                </item>
+               <item>
+                <layout class="QHBoxLayout" name="horizontalLayout_10">
+                 <item>
+                  <widget class="QLabel" name="rotationLabel">
+                   <property name="text">
+                    <string>Rotation (clockwise) / Mirror:</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <widget class="QComboBox" name="transformCombobox">
+                   <item>
+                    <property name="text">
+                     <string>None</string>
+                    </property>
+                   </item>
+                   <item>
+                    <property name="text">
+                     <string>+90°</string>
+                    </property>
+                   </item>
+                   <item>
+                    <property name="text">
+                     <string>+180°</string>
+                    </property>
+                   </item>
+                   <item>
+                    <property name="text">
+                     <string>+270°</string>
+                    </property>
+                   </item>
+                   <item>
+                    <property name="text">
+                     <string>Horizontal Flip</string>
+                    </property>
+                   </item>
+                   <item>
+                    <property name="text">
+                     <string>Vertical Flip</string>
+                    </property>
+                   </item>
+                  </widget>
+                 </item>
+                </layout>
+               </item>
               </layout>
              </item>
             </layout>