Skip to content

Commit

Permalink
Merge audio update pull request from andreasGBL/develop
Browse files Browse the repository at this point in the history
Update 0.8 - Audio features (trimming, removing audio, displaying audio information)
  • Loading branch information
andreasGBL authored Nov 20, 2022
2 parents d59ebcc + 50db0ee commit 77d1b62
Show file tree
Hide file tree
Showing 8 changed files with 831 additions and 397 deletions.
17 changes: 13 additions & 4 deletions include/ffmpegwrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,33 @@ struct Video;
class QTime;
class QString;

struct ExportSettings {
double VideoMBitRate;
double framerate;
bool trimOnly;
bool vertical;
bool audioOnly;
bool videoOnly;
};

class FFMPEGWrapper
{
public:
FFMPEGWrapper();
bool exportFile(Video const & video, TrimSettings const & settings, double MBitRate, Resolution const & res, CodecConfig const & codec, int Framerate, bool trimOnly, bool vertical);
bool exportFile(Video const & video, TrimSettings const & settings, Resolution const & res, CodecConfig const & codec, ExportSettings const & exports);
private:
QString getFileName(QString const & filePath);
QString getExportFileName(QString const & fileName);
QString getExportFileName(QString const & fileName, bool audioOnly, const QString & audioFileType);
QString getPath(QString const & filePath);
QString getExportFilePath(QString const & filePath);
QString getExportFilePath(QString const& filePath, bool audioOnly, const QString & audioFileType);

QString getTrimString(QTime const & start, QTime const & end, Video const & video);
QString getMBitRateString(double MBitRate);
QString getFramerateFilter(double Framerate, double vidFramerate);
QString getScaleFilterString(Resolution const & res, Resolution const & vidRes, int HardwareAcceleration, bool vertical);

QString getVideoCodecString(CodecConfig const & codec, bool trimOnly);
QString getAudioCodecString(bool canCopy);
QString getAudioCodecString(const Video& video, const TrimSettings& settings, const CodecConfig& codec, const ExportSettings& exports);
QString getHardwareAccelerationString(int HardwareAcceleration, bool usesScaleFilter);
QString getInputFileString(QString const & filePath);
QString getOutputFileString(QString const & filePath);
Expand Down
3 changes: 2 additions & 1 deletion include/filedropwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ class QMimeData;

namespace acceptedFileTypes {
QString const MP4("mp4");
QString const ALL[1] = { MP4 };
QString const MP3("mp3");
QString const ALL[2] = { MP4, MP3 };
}

class FileDropWidget : public QLabel
Expand Down
64 changes: 46 additions & 18 deletions include/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,6 @@ struct Resolution {
int height;
};

//struct Codec {
// std::string defaultName;
// std::string NVIDIA;
// std::string AMD;
//};

struct TrimSettings {
QTime start;
QTime end;
Expand Down Expand Up @@ -76,55 +70,87 @@ float const FRAMERATES[] = {
240
};

enum CODEC_IDX {
int const AUDIO_BITRATES[] = {
0,
320,
256,
192,
160,
128,
64
};

enum VIDEO_CODEC {
H264,
HEVC,
UNSUPPORTED
UNSUPPORTED_VIDEO
};

enum AUDIO_CODEC {
AAC,
MP3,
UNSUPPORTED_AUDIO
};

QString const CODEC_IDX_STRINGS[] = {
QString const VIDEO_CODEC_STRINGS[] = {
"H264",
"HEVC",
"Unsupported"
};

QString const AUDIO_CODEC_STRINGS[]{
"AAC",
"MP3",
"Unsupported"
};

QString const AUDIO_ENCODER_STRINGS[]{
"aac",
"libmp3lame",
"Unsupported"
};

struct CodecConfig {
int id;
int videoCodec;
QString name;
HARDWARE_ACCELERATION hw_acceleration;
QString encoderName;
QString videoEncoderName;
std::vector<QString> profiles;
int profile; //also default profile
int mainProfile;
std::vector<QString> extraOptions;
int audioBitrateIdx;
int audioCodec;
QString audioCodecName;
QString audioEncoderName;
};

CodecConfig const DefaultCodecs[2][3] = {
{
{
CODEC_IDX::H264, CODEC_IDX_STRINGS[CODEC_IDX::H264], HARDWARE_ACCELERATION::NONE, "libx264", {"Baseline", "Main", "High", "High10", "High444"}, 2, 1, {"", "", "", "", " -pix_fmt yuv444p"}
VIDEO_CODEC::H264, VIDEO_CODEC_STRINGS[VIDEO_CODEC::H264], HARDWARE_ACCELERATION::NONE, "libx264", {"Baseline", "Main", "High", "High10", "High444"}, 2, 1, {"", "", "", "", " -pix_fmt yuv444p"}, 0, AUDIO_CODEC::AAC, AUDIO_CODEC_STRINGS[AUDIO_CODEC::AAC], AUDIO_ENCODER_STRINGS[AUDIO_CODEC::AAC]
},
{
CODEC_IDX::H264, CODEC_IDX_STRINGS[CODEC_IDX::H264], HARDWARE_ACCELERATION::NVIDIA, "h264_nvenc", {"Baseline", "Main", "High", "High444p"}, 2, 1, {"", "", "", " -pix_fmt yuv444p"}
VIDEO_CODEC::H264, VIDEO_CODEC_STRINGS[VIDEO_CODEC::H264], HARDWARE_ACCELERATION::NVIDIA, "h264_nvenc", {"Baseline", "Main", "High", "High444p"}, 2, 1, {"", "", "", " -pix_fmt yuv444p"}, 0, AUDIO_CODEC::AAC, AUDIO_CODEC_STRINGS[AUDIO_CODEC::AAC], AUDIO_ENCODER_STRINGS[AUDIO_CODEC::AAC]
},
{
CODEC_IDX::H264, CODEC_IDX_STRINGS[CODEC_IDX::H264], HARDWARE_ACCELERATION::AMD, "h264_amf", {"Constrained_Baseline", "Main", "High", "Constrained_High"}, 2, 1, {" -quality:v 2"}
VIDEO_CODEC::H264, VIDEO_CODEC_STRINGS[VIDEO_CODEC::H264], HARDWARE_ACCELERATION::AMD, "h264_amf", {"Constrained_Baseline", "Main", "High", "Constrained_High"}, 2, 1, {" -quality:v 2"}, 0, AUDIO_CODEC::AAC, AUDIO_CODEC_STRINGS[AUDIO_CODEC::AAC], AUDIO_ENCODER_STRINGS[AUDIO_CODEC::AAC]
}
},
{
{
CODEC_IDX::HEVC, CODEC_IDX_STRINGS[CODEC_IDX::HEVC], HARDWARE_ACCELERATION::NONE, "libx265", {"Main", "Main10", "Main12"}, 0, 0, {""}
VIDEO_CODEC::HEVC, VIDEO_CODEC_STRINGS[VIDEO_CODEC::HEVC], HARDWARE_ACCELERATION::NONE, "libx265", {"Main", "Main10", "Main12"}, 0, 0, {""}, 0, AUDIO_CODEC::AAC, AUDIO_CODEC_STRINGS[AUDIO_CODEC::AAC], AUDIO_ENCODER_STRINGS[AUDIO_CODEC::AAC]
},
{
CODEC_IDX::HEVC, CODEC_IDX_STRINGS[CODEC_IDX::HEVC], HARDWARE_ACCELERATION::NVIDIA, "hevc_nvenc", {"Main", "Main10", "Rext"}, 0, 0, {""}
VIDEO_CODEC::HEVC, VIDEO_CODEC_STRINGS[VIDEO_CODEC::HEVC], HARDWARE_ACCELERATION::NVIDIA, "hevc_nvenc", {"Main", "Main10", "Rext"}, 0, 0, {""}, 0, AUDIO_CODEC::AAC, AUDIO_CODEC_STRINGS[AUDIO_CODEC::AAC], AUDIO_ENCODER_STRINGS[AUDIO_CODEC::AAC]
},
{
CODEC_IDX::HEVC, CODEC_IDX_STRINGS[CODEC_IDX::HEVC], HARDWARE_ACCELERATION::AMD, "hevc_amf", {"Main"}, 0, 0, {" -quality:v 0"} //TODO: test AMD codec
VIDEO_CODEC::HEVC, VIDEO_CODEC_STRINGS[VIDEO_CODEC::HEVC], HARDWARE_ACCELERATION::AMD, "hevc_amf", {"Main"}, 0, 0, {" -quality:v 0"} /* TODO: test AMD codec */, 0, AUDIO_CODEC::AAC, AUDIO_CODEC_STRINGS[AUDIO_CODEC::AAC], AUDIO_ENCODER_STRINGS[AUDIO_CODEC::AAC]
}
}
};

//CodecConfig getDefaultCodec(CODEC_IDX codec, HARDWARE_ACCELERATION acc = HARDWARE_ACCELERATION::NONE) {
//CodecConfig getDefaultCodec(VIDEO_CODEC codec, HARDWARE_ACCELERATION acc = HARDWARE_ACCELERATION::NONE) {
// return DefaultCodecs[codec][acc];
//}

Expand All @@ -135,4 +161,6 @@ struct Video {
double framerate;
CodecConfig codec;
double bitrate;
double audioBitrate;
QTime audioLength;
};
3 changes: 3 additions & 0 deletions include/videolowwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ private slots:
void gotCutInformation(QTime start, QTime end, bool cancelled);
void startTimeEdited();
void endTimeEdited();
void uncheckRemoveAudio(bool isAudioOnlyChecked);
void uncheckAudioOnly(bool isRemoveAudioChecked);

public slots:
void newVideoFile(Video const & vid);
Expand All @@ -52,6 +54,7 @@ public slots:
void quickH264(double MBitRate);
void quickHEVC(double MBitRate);
void handleExportExitCode(bool success, bool hardwareAcc);
void setQuickExportsEnabled(bool enabled);

TrimSettings getTrimSettings();
FFMPEGWrapper *ffmpeg = nullptr;
Expand Down
52 changes: 33 additions & 19 deletions src/ffmpegwrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ FFMPEGWrapper::FFMPEGWrapper()
}
}

bool FFMPEGWrapper::exportFile(const Video& video, const TrimSettings& settings, double MBitRate, const Resolution& res, const CodecConfig& codec, int Framerate, bool trimOnly, bool vertical)
bool FFMPEGWrapper::exportFile(const Video& video, const TrimSettings& settings, const Resolution& res, const CodecConfig& codec, const ExportSettings & exports)
{
const QString& filePath = video.filePath;
QString expFilePath = getExportFilePath(filePath);
QString expFilePath = getExportFilePath(filePath, exports.audioOnly, codec.audioCodecName);
std::cout << "Export File Path: " << expFilePath.toStdString().c_str() << std::endl;
QString cmd = "ffmpeg -y ";
//options part 1
Expand All @@ -31,18 +31,25 @@ bool FFMPEGWrapper::exportFile(const Video& video, const TrimSettings& settings,

//filters
std::vector<QString> filters;
QString framerateFilter = getFramerateFilter(Framerate, video.framerate);
QString scaleFilter = getScaleFilterString(res, video.resolution, codec.hw_acceleration, vertical);
QString framerateFilter = getFramerateFilter(exports.framerate, video.framerate);
QString scaleFilter = getScaleFilterString(res, video.resolution, codec.hw_acceleration, exports.vertical);

//options part2
QString audioCodec = getAudioCodecString(settings.start == QTime(0, 0) || !settings.trim || trimOnly);
QString videoCodec = getVideoCodecString(codec, trimOnly);
QString bitrate = getMBitRateString(MBitRate);
QString audioCodec = getAudioCodecString(video, settings, codec, exports);
QString videoCodec = getVideoCodecString(codec, exports.trimOnly);
QString bitrate = getMBitRateString(exports.VideoMBitRate);
QString outputFile = getOutputFileString(expFilePath);

//options part1 hwac
QString hwacc = getHardwareAccelerationString(codec.hw_acceleration, scaleFilter.length() > 0);

if (exports.audioOnly) {
videoCodec = "-vn";
bitrate = "";
hwacc = "";
framerateFilter = "";
scaleFilter = "";
}
//add options part 1
if (trimming.length() > 0 && settings.trim)
cmd += trimming + " ";
Expand Down Expand Up @@ -79,11 +86,11 @@ QString FFMPEGWrapper::getFileName(QString const& filePath)
return filePath.mid(lastIdx);
}

QString FFMPEGWrapper::getExportFileName(QString const& fileName)
QString FFMPEGWrapper::getExportFileName(QString const& fileName, bool audioOnly, const QString & audioFileType)
{
auto endIdx = fileName.lastIndexOf(".");
auto file = fileName.mid(0, endIdx);
auto ending = fileName.mid(endIdx + 1);
auto ending = audioOnly ? audioFileType : fileName.mid(endIdx + 1);
return file + "Export." + ending;
}

Expand All @@ -93,10 +100,10 @@ QString FFMPEGWrapper::getPath(QString const& filePath)
return filePath.mid(0, lastIdx);
}

QString FFMPEGWrapper::getExportFilePath(QString const& filePath)
QString FFMPEGWrapper::getExportFilePath(QString const& filePath, bool audioOnly, const QString & audioFileType)
{
QString fileName = getFileName(filePath);
return getPath(filePath) + getExportFileName(fileName);
return getPath(filePath) + getExportFileName(fileName, audioOnly, audioFileType);
}

QString FFMPEGWrapper::getTrimString(QTime const& start, QTime const& end, Video const& video)
Expand Down Expand Up @@ -126,13 +133,15 @@ QString FFMPEGWrapper::getFramerateFilter(double Framerate, double vidFramerate)

QString FFMPEGWrapper::getScaleFilterString(Resolution const& res, Resolution const& vidRes, int HardwareAcceleration, bool vertical)
{
if (res.height <= 0 && res.width <= 0 || (res.height == vidRes.height && res.width == vidRes.width)) {
int w = res.width, h = res.height;
if (vertical)
std::swap(w, h);
if (h <= 0 && w <= 0 || (h == vidRes.height && w == vidRes.width)) {
return QString("");
}
QString d1 = QString::number(res.width);
QString d2 = QString::number(res.height);
if (vertical)
std::swap(d1, d2);
QString d1 = QString::number(w);
QString d2 = QString::number(h);

QString resolutionString = d1 + ":" + d2;
switch (HardwareAcceleration)
{
Expand All @@ -150,16 +159,21 @@ QString FFMPEGWrapper::getVideoCodecString(CodecConfig const& codec, bool trimOn
return prefix + "copy";
}
else {
return prefix + codec.encoderName + " -vprofile " + codec.profiles[codec.profile].toLower() + codec.extraOptions[codec.profile % codec.extraOptions.size()]; // use modulo to never go out of bounds on shorter vectors
return prefix + codec.videoEncoderName + " -vprofile " + codec.profiles[codec.profile].toLower() + codec.extraOptions[codec.profile % codec.extraOptions.size()]; // use modulo to never go out of bounds on shorter vectors
}
}

QString FFMPEGWrapper::getAudioCodecString(bool canCopy)
QString FFMPEGWrapper::getAudioCodecString(const Video& video, const TrimSettings& settings, const CodecConfig& codec, const ExportSettings& exports)
{
bool canCopy = ((settings.start == QTime(0, 0) || !settings.trim) && codec.audioCodec == video.codec.audioCodec && codec.audioBitrateIdx == 0) || exports.trimOnly;
int audioBitrate = AUDIO_BITRATES[codec.audioBitrateIdx];
QString audioBitrateString = codec.audioBitrateIdx == 0 ? "" : " -b:a " + QString::number(audioBitrate) + "K";
if (canCopy)
return QString("-c:a copy");
else if (exports.videoOnly)
return QString("-an");
else
return QString("");
return QString("-c:a " + codec.audioEncoderName + audioBitrateString);
}

QString FFMPEGWrapper::getHardwareAccelerationString(int HardwareAcceleration, bool usesScaleFilter)
Expand Down
Loading

0 comments on commit 77d1b62

Please sign in to comment.