Skip to content

Commit

Permalink
transcode:新增 指定转码stream,排出其余stream;
Browse files Browse the repository at this point in the history
  • Loading branch information
RealChuan committed Mar 14, 2024
1 parent c9eea5b commit ea15fb6
Show file tree
Hide file tree
Showing 18 changed files with 204 additions and 127 deletions.
2 changes: 2 additions & 0 deletions examples/transcoder/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ set(PROJECT_SOURCES
audioencodertableview.hpp
audioencoderwidget.cc
audioencoderwidget.hpp
commonwidgets.cc
commonwidgets.hpp
main.cc
mainwindow.cc
mainwindow.hpp
Expand Down
17 changes: 17 additions & 0 deletions examples/transcoder/commonwidgets.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "commonwidgets.hpp"

#include <QtWidgets>

namespace CommonWidgets {

auto createComboBox(QWidget *parent) -> QComboBox *
{
const auto *comboBoxStyleSheet = "QComboBox {combobox-popup:0;}";
auto *comboBox = new QComboBox(parent);
comboBox->setView(new QListView(comboBox));
comboBox->setMaxVisibleItems(10);
comboBox->setStyleSheet(comboBoxStyleSheet);
return comboBox;
}

} // namespace CommonWidgets
13 changes: 13 additions & 0 deletions examples/transcoder/commonwidgets.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef COMMONWIDGETS_HPP
#define COMMONWIDGETS_HPP

class QComboBox;
class QWidget;

namespace CommonWidgets {

auto createComboBox(QWidget *parent) -> QComboBox *;

} // namespace CommonWidgets

#endif // COMMONWIDGETS_HPP
20 changes: 15 additions & 5 deletions examples/transcoder/mainwindow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class MainWindow::MainWindowPrivate
transcoder->parseInputFile();
}

void initUI()
void initUI() const
{
QSize size;
double frameRate = 0;
Expand Down Expand Up @@ -198,9 +198,20 @@ void MainWindow::onStart()

d_ptr->transcoder->setInFilePath(inPath);
d_ptr->transcoder->setOutFilePath(outPath);
d_ptr->transcoder->setVideoEncodeContext(d_ptr->videoEncoderWidget->encodeContext());
d_ptr->transcoder->setAudioEncodeContext(
d_ptr->audioEncoderWidget->encodeContexts().first());
d_ptr->transcoder->setGpuDecode(d_ptr->videoEncoderWidget->isGpuDecode());

Ffmpeg::EncodeContexts encodeContexts(d_ptr->transcoder->decodeContexts().size());
auto videoEncodeContexts = d_ptr->videoEncoderWidget->encodeContext();
auto audioEncodeContexts = d_ptr->audioEncoderWidget->encodeContexts();
auto subtitleEncodeContexts = d_ptr->subtitleEncoderWidget->encodeContexts();
encodeContexts.replace(videoEncodeContexts.streamIndex, videoEncodeContexts);
for (const auto &context : std::as_const(audioEncodeContexts)) {
encodeContexts.replace(context.streamIndex, context);
}
for (const auto &context : std::as_const(subtitleEncodeContexts)) {
encodeContexts.replace(context.streamIndex, context);
}
d_ptr->transcoder->setEncodeContexts(encodeContexts);

if (QFile::exists(subtitlePath)) {
d_ptr->transcoder->setSubtitleFilename(subtitlePath);
Expand All @@ -213,7 +224,6 @@ void MainWindow::onStart()
setWindowTitle(filename);

d_ptr->fpsTimer->start(1000);

} else if (d_ptr->statusWidget->status() == tr("Stop")) {
d_ptr->transcoder->stopTranscode();
d_ptr->statusWidget->setProgress(0);
Expand Down
27 changes: 9 additions & 18 deletions examples/transcoder/styleditemdelegate.cc
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
#include "styleditemdelegate.hpp"
#include "commonwidgets.hpp"

#include <ffmpeg/encodecontext.hpp>
#include <ffmpeg/ffmpegutils.hpp>

#include <QtWidgets>

auto createComboBox(QWidget *parent) -> QComboBox *
{
const auto *comboBoxStyleSheet = "QComboBox {combobox-popup:0;}";
auto *comboBox = new QComboBox(parent);
comboBox->setView(new QListView(comboBox));
comboBox->setMaxVisibleItems(10);
comboBox->setStyleSheet(comboBoxStyleSheet);
return comboBox;
}

AudioEncoderDelegate::AudioEncoderDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{}
Expand All @@ -25,7 +16,7 @@ auto AudioEncoderDelegate::createEditor(QWidget *parent,
{
static auto audioEncodercs = Ffmpeg::getCodecsInfo(AVMEDIA_TYPE_AUDIO, true);

auto *comboBox = createComboBox(parent);
auto *comboBox = CommonWidgets::createComboBox(parent);
for (const auto &codec : std::as_const(audioEncodercs)) {
comboBox->addItem(codec.displayName, QVariant::fromValue(codec));
}
Expand Down Expand Up @@ -54,7 +45,7 @@ auto ChannelLayoutDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &,
const QModelIndex &index) const -> QWidget *
{
auto *comboBox = createComboBox(parent);
auto *comboBox = CommonWidgets::createComboBox(parent);
auto data = index.data(Qt::UserRole).value<Ffmpeg::EncodeContext>();
for (const auto &chLayout : std::as_const(data.chLayouts)) {
comboBox->addItem(chLayout.channelName, chLayout.channel);
Expand Down Expand Up @@ -84,7 +75,7 @@ auto ProfileDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &,
const QModelIndex &index) const -> QWidget *
{
auto *comboBox = createComboBox(parent);
auto *comboBox = CommonWidgets::createComboBox(parent);
auto data = index.data(Qt::UserRole).value<Ffmpeg::EncodeContext>();
for (const auto &profile : std::as_const(data.profiles)) {
comboBox->addItem(profile.name, profile.profile);
Expand Down Expand Up @@ -114,7 +105,7 @@ auto SampleRateDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &,
const QModelIndex &index) const -> QWidget *
{
auto *comboBox = createComboBox(parent);
auto *comboBox = CommonWidgets::createComboBox(parent);
auto data = index.data(Qt::UserRole).value<Ffmpeg::EncodeContext>();
for (const auto &sampleRate : std::as_const(data.sampleRates)) {
comboBox->addItem(QString::number(sampleRate), sampleRate);
Expand All @@ -140,14 +131,14 @@ RemovedDelegate::RemovedDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{}

bool RemovedDelegate::editorEvent(QEvent *event,
auto RemovedDelegate::editorEvent(QEvent *event,
QAbstractItemModel *model,
const QStyleOptionViewItem &option,
const QModelIndex &index)
const QModelIndex &index) -> bool
{
if (event->type() == QEvent::MouseButtonRelease) {
auto e = static_cast<QMouseEvent *>(event);
if (e) {
auto *e = static_cast<QMouseEvent *>(event);
if (e != nullptr) {
emit removed(index);
qDebug() << "remove";
}
Expand Down
2 changes: 2 additions & 0 deletions examples/transcoder/transcoder.pro
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ SOURCES += \
audioencodermodel.cc \
audioencodertableview.cc \
audioencoderwidget.cc \
commonwidgets.cc \
main.cc \
mainwindow.cc \
outputwidget.cc \
Expand All @@ -34,6 +35,7 @@ HEADERS += \
audioencodermodel.hpp \
audioencodertableview.hpp \
audioencoderwidget.hpp \
commonwidgets.hpp \
mainwindow.hpp \
outputwidget.hpp \
previewwidget.hpp \
Expand Down
58 changes: 30 additions & 28 deletions examples/transcoder/videoencoderwidget.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "videoencoderwidget.hpp"
#include "commonwidgets.hpp"

#include <ffmpeg/avcontextinfo.h>
#include <ffmpeg/codeccontext.h>
Expand All @@ -12,11 +13,7 @@ class VideoEncoderWidget::VideoEncoderWidgetPrivate
explicit VideoEncoderWidgetPrivate(VideoEncoderWidget *q)
: q_ptr(q)
{
const auto *const comboBoxStyleSheet{"QComboBox {combobox-popup:0;}"};
videoEncoderCbx = new QComboBox(q_ptr);
videoEncoderCbx->setView(new QListView(videoEncoderCbx));
videoEncoderCbx->setMaxVisibleItems(10);
videoEncoderCbx->setStyleSheet(comboBoxStyleSheet);
videoEncoderCbx = CommonWidgets::createComboBox(q_ptr);
auto videoCodecs = Ffmpeg::getCodecsInfo(AVMEDIA_TYPE_VIDEO, true);
for (const auto &codec : std::as_const(videoCodecs)) {
videoEncoderCbx->addItem(codec.displayName, QVariant::fromValue(codec));
Expand Down Expand Up @@ -111,7 +108,7 @@ class VideoEncoderWidget::VideoEncoderWidgetPrivate
QSpinBox *maxBitrateSbx;
QSpinBox *bitrateSbx;

QSize originalSize;
Ffmpeg::EncodeContext decodeContext;
};

VideoEncoderWidget::VideoEncoderWidget(QWidget *parent)
Expand All @@ -127,20 +124,25 @@ VideoEncoderWidget::~VideoEncoderWidget() = default;

auto VideoEncoderWidget::encodeContext() const -> Ffmpeg::EncodeContext
{
Ffmpeg::EncodeContext encodeParam;
encodeParam.mediaType = AVMEDIA_TYPE_VIDEO;
encodeParam.setEncoderName(d_ptr->currentCodecName());
encodeParam.size = {d_ptr->widthSbx->value(), d_ptr->heightSbx->value()};
encodeParam.gpuDecode = d_ptr->gpuDecodeCbx->isChecked();
encodeParam.minBitrate = d_ptr->minBitrateSbx->value();
encodeParam.maxBitrate = d_ptr->maxBitrateSbx->value();
encodeParam.bitrate = d_ptr->bitrateSbx->value();
encodeParam.crf = d_ptr->crfSbx->value();
encodeParam.preset = d_ptr->presetCbx->currentText();
encodeParam.tune = d_ptr->tuneCbx->currentText();
// encodeParam.profile = d_ptr->profileCbx->currentText();

return encodeParam;
Ffmpeg::EncodeContext encodeContext;
encodeContext.streamIndex = d_ptr->decodeContext.streamIndex;
encodeContext.mediaType = AVMEDIA_TYPE_VIDEO;
encodeContext.setEncoderName(d_ptr->currentCodecName());
encodeContext.size = {d_ptr->widthSbx->value(), d_ptr->heightSbx->value()};
encodeContext.minBitrate = d_ptr->minBitrateSbx->value();
encodeContext.maxBitrate = d_ptr->maxBitrateSbx->value();
encodeContext.bitrate = d_ptr->bitrateSbx->value();
encodeContext.crf = d_ptr->crfSbx->value();
encodeContext.preset = d_ptr->presetCbx->currentText();
encodeContext.tune = d_ptr->tuneCbx->currentText();
// encodeContext.profile = d_ptr->profileCbx->currentText();

return encodeContext;
}

bool VideoEncoderWidget::isGpuDecode() const
{
return d_ptr->gpuDecodeCbx->isChecked();
}

void VideoEncoderWidget::setDecodeContext(const Ffmpeg::EncodeContext &decodeContext)
Expand All @@ -158,15 +160,15 @@ void VideoEncoderWidget::setDecodeContext(const Ffmpeg::EncodeContext &decodeCon
d_ptr->widthSbx->blockSignals(false);
d_ptr->heightSbx->blockSignals(false);

d_ptr->originalSize = decodeContext.size;

if (decodeContext.maxBitrate <= 0) {
d_ptr->calBitrate();
} else {
d_ptr->minBitrateSbx->setValue(decodeContext.minBitrate);
d_ptr->maxBitrateSbx->setValue(decodeContext.maxBitrate);
d_ptr->bitrateSbx->setValue(decodeContext.bitrate);
}

d_ptr->decodeContext = decodeContext;
}

void VideoEncoderWidget::onEncoderChanged()
Expand All @@ -185,11 +187,11 @@ void VideoEncoderWidget::onEncoderChanged()

void VideoEncoderWidget::onVideoWidthChanged()
{
if (!d_ptr->aspectCheckBox->isChecked() || !d_ptr->originalSize.isValid()) {
if (!d_ptr->aspectCheckBox->isChecked() || !d_ptr->decodeContext.size.isValid()) {
return;
}
auto multiple = d_ptr->originalSize.width() * 1.0 / d_ptr->widthSbx->value();
int height = d_ptr->originalSize.height() / multiple;
auto multiple = d_ptr->decodeContext.size.width() * 1.0 / d_ptr->widthSbx->value();
int height = d_ptr->decodeContext.size.height() / multiple;
d_ptr->heightSbx->blockSignals(true);
d_ptr->heightSbx->setValue(height);
d_ptr->heightSbx->blockSignals(false);
Expand All @@ -198,11 +200,11 @@ void VideoEncoderWidget::onVideoWidthChanged()

void VideoEncoderWidget::onVideoHeightChanged()
{
if (!d_ptr->aspectCheckBox->isChecked() || !d_ptr->originalSize.isValid()) {
if (!d_ptr->aspectCheckBox->isChecked() || !d_ptr->decodeContext.size.isValid()) {
return;
}
auto multiple = d_ptr->originalSize.height() * 1.0 / d_ptr->heightSbx->value();
int width = d_ptr->originalSize.width() / multiple;
auto multiple = d_ptr->decodeContext.size.height() * 1.0 / d_ptr->heightSbx->value();
int width = d_ptr->decodeContext.size.width() / multiple;
d_ptr->widthSbx->blockSignals(true);
d_ptr->widthSbx->setValue(width);
d_ptr->widthSbx->blockSignals(false);
Expand Down
2 changes: 2 additions & 0 deletions examples/transcoder/videoencoderwidget.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class VideoEncoderWidget : public QWidget
void setDecodeContext(const Ffmpeg::EncodeContext &decodeContext);
[[nodiscard]] auto encodeContext() const -> Ffmpeg::EncodeContext;

bool isGpuDecode() const;

private slots:
void onEncoderChanged();
void onVideoWidthChanged();
Expand Down
9 changes: 4 additions & 5 deletions ffmpeg/codeccontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class CodecContext::CodecContextPrivate
codecCtx->global_quality = FF_QP2LAMBDA * crf + 0.5;
auto quality = QString::number(crf, 'f', 2);
av_dict_set(&encodeOptions, "crf", quality.toUtf8().data(), 0);
} else if (codecName.contains("nvenc")) { // nvidia编码器
} else if (codecName.contains("_nvenc")) { // nvidia编码器
double adjustedQualityI = crf - 2;
double adjustedQualityB = crf + 2;
if (adjustedQualityB > EncodeLimit::crf_max) {
Expand All @@ -105,7 +105,7 @@ class CodecContext::CodecContextPrivate
av_dict_set(&encodeOptions, "init_qpP", quality.toUtf8().data(), 0);
av_dict_set(&encodeOptions, "init_qpB", qualityB.toUtf8().data(), 0);
av_dict_set(&encodeOptions, "init_qpI", qualityI.toUtf8().data(), 0);
} else if (codecName.contains("vce")) { // amd vce编码器
} else if (codecName.contains("_vce")) { // amd vce编码器
int maxQuality = EncodeLimit::crf_max;
double qualityOffsetThreshold = 8;
double qualityOffsetP = 2;
Expand Down Expand Up @@ -145,12 +145,11 @@ class CodecContext::CodecContextPrivate
if (codecCtx->codec_id != AV_CODEC_ID_H265) {
av_dict_set(&encodeOptions, "qp_b", qualityB.toUtf8().data(), 0);
}
} else if (codecName.contains("mf")) { // ffmpeg mf编码器

} else if (codecName.contains("_mf")) { // ffmpeg mf编码器
auto quality = QString::number(crf, 'f', 2);
av_dict_set(&encodeOptions, "rate_control", "quality", 0);
av_dict_set(&encodeOptions, "quality", quality.toUtf8().data(), 0);
av_dict_set(&encodeOptions, "hw_encoding", "1", 0);
// av_dict_set(&encodeOptions, "hw_encoding", "1", 0);
} else {
codecCtx->flags |= AV_CODEC_FLAG_QSCALE;
codecCtx->global_quality = FF_QP2LAMBDA * crf + 0.5;
Expand Down
2 changes: 1 addition & 1 deletion ffmpeg/encodecontext.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ EncodeContext::EncodeContext(AVStream *stream, AVContextInfo *info)
{
auto *avCodecContext = info->codecCtx()->avCodecCtx();
const auto *codec = avCodecContext->codec;
this->streamIndex = stream->index;
streamIndex = stream->index;
mediaType = avCodecContext->codec_type;
minBitrate = avCodecContext->rc_min_rate;
maxBitrate = avCodecContext->rc_max_rate;
Expand Down
3 changes: 1 addition & 2 deletions ffmpeg/encodecontext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ struct FFMPEG_EXPORT EncodeContext
QString sourceInfo;

int streamIndex = -1;
AVMediaType mediaType;
AVMediaType mediaType = AVMEDIA_TYPE_UNKNOWN;

qint64 minBitrate = -1;
qint64 maxBitrate = -1;
Expand All @@ -67,7 +67,6 @@ struct FFMPEG_EXPORT EncodeContext
int crf = 18;

// video
bool gpuDecode = true;
QSize size = {-1, -1};
QString preset = "slow";
QString tune = "film";
Expand Down
7 changes: 7 additions & 0 deletions ffmpeg/ffmpegutils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -233,4 +233,11 @@ auto getChLayouts(const QVector<AVChannelLayout> &channelLayout) -> ChLayouts
return chLayouts.isEmpty() ? s_chLayouts : chLayouts;
}

QByteArray convertUrlToFfmpegInput(const QString &url)
{
QByteArray inpuUrl = QUrl::fromUserInput(url).isLocalFile() ? url.toUtf8()
: QUrl(url).toEncoded();
return inpuUrl;
}

} // namespace Ffmpeg
2 changes: 2 additions & 0 deletions ffmpeg/ffmpegutils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ using ChLayouts = QVector<ChLayout>;

auto FFMPEG_EXPORT getChLayouts(const QVector<AVChannelLayout> &channelLayout) -> ChLayouts;

auto convertUrlToFfmpegInput(const QString &url) -> QByteArray;

} // namespace Ffmpeg

Q_DECLARE_METATYPE(Ffmpeg::CodecInfo);
Expand Down
4 changes: 2 additions & 2 deletions ffmpeg/filter/filter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Filter::FilterPrivate
timeBase.den,
sampleAspectRatio.num,
sampleAspectRatio.den);
qDebug() << "Video filter in args:" << args;
qInfo() << "Video filter in args:" << args;

create(args);
}
Expand All @@ -60,7 +60,7 @@ class Filter::FilterPrivate
avFrame->sample_rate,
av_get_sample_fmt_name(static_cast<AVSampleFormat>(avFrame->format)),
getAVChannelLayoutDescribe(avFrame->ch_layout).toUtf8().data());
qDebug() << "Audio filter in args:" << args;
qInfo() << "Audio filter in args:" << args;

create(args);
}
Expand Down
Loading

0 comments on commit ea15fb6

Please sign in to comment.