Skip to content

Commit

Permalink
transcoder;
Browse files Browse the repository at this point in the history
  • Loading branch information
RealChuan committed Mar 12, 2024
1 parent 92b5a8c commit 888d764
Show file tree
Hide file tree
Showing 23 changed files with 676 additions and 121 deletions.
6 changes: 6 additions & 0 deletions examples/transcoder/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
set(PROJECT_SOURCES
audioencodermodel.cc
audioencodermodel.hpp
audioencodertableview.cc
audioencodertableview.hpp
audioencoderwidget.cc
audioencoderwidget.hpp
main.cc
Expand All @@ -12,6 +16,8 @@ set(PROJECT_SOURCES
sourcewidget.hpp
stautuswidget.cc
stautuswidget.hpp
styleditemdelegate.cc
styleditemdelegate.hpp
videoencoderwidget.cc
videoencoderwidget.hpp)

Expand Down
164 changes: 164 additions & 0 deletions examples/transcoder/audioencodermodel.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
#include "audioencodermodel.hpp"

class AudioEncoderModel::AudioEncoderModelPrivate
{
public:
explicit AudioEncoderModelPrivate(AudioEncoderModel *q)
: q_ptr(q)
{
auto metaEnums = QMetaEnum::fromType<Property>();
for (int i = 0; i < metaEnums.keyCount(); i++) {
headers.append(metaEnums.key(i));
}
}

AudioEncoderModel *q_ptr;

Ffmpeg::EncodeContexts encodeContexts;
QStringList headers;
};

AudioEncoderModel::AudioEncoderModel(QObject *parent)
: QAbstractTableModel{parent}
, d_ptr(new AudioEncoderModelPrivate(this))
{}

AudioEncoderModel::~AudioEncoderModel() = default;

auto AudioEncoderModel::rowCount(const QModelIndex &parent) const -> int
{
Q_UNUSED(parent);
return d_ptr->encodeContexts.size();
}

auto AudioEncoderModel::columnCount(const QModelIndex &parent) const -> int
{
Q_UNUSED(parent);
return d_ptr->headers.size();
}

auto AudioEncoderModel::data(const QModelIndex &index, int role) const -> QVariant
{
if (!index.isValid()) {
return {};
}

auto row = index.row();
auto col = index.column();

const auto &data = d_ptr->encodeContexts.at(row);
switch (role) {
case Qt::TextAlignmentRole: return Qt::AlignCenter;
case Qt::WhatsThisRole:
case Qt::ToolTipRole:
case Qt::DisplayRole:
case Qt::EditRole: { //双击为空需添加
switch (col) {
case Property::ID: return row;
case Property::Encoder: return data.codecInfo().displayName;
case Property::ChannelLayout: return data.chLayout().channelName;
case Property::Bitrate: return data.bitrate;
case Property::Crf: return data.crf;
case Property::Profile: {
auto profile = data.profile();
if (profile.profile >= 0) {
return profile.name;
}
return {};
}
default: break;
}
break;
case Qt::UserRole: return QVariant::fromValue(data);
}
default: break;
}
return {};
}

auto AudioEncoderModel::setData(const QModelIndex &index, const QVariant &value, int role) -> bool
{
if (!index.isValid()) {
return false;
}

auto row = index.row();
auto col = index.column();

auto &data = d_ptr->encodeContexts[row];
switch (role) {
case Qt::EditRole: {
switch (col) {
case Property::Encoder: {
auto codec = value.value<Ffmpeg::CodecInfo>();
if (data.codecInfo() != codec) {
data.setEncoderName(codec.name);
emit dataChanged(index, index);
}
} break;
case Property::ChannelLayout: {
auto channel = static_cast<AVChannel>(value.toLongLong());
if (data.chLayout().channel != channel) {
data.setChannel(channel);
emit dataChanged(index, index);
}
} break;
case Property::Bitrate:
data.maxBitrate = data.minBitrate = data.bitrate = value.toInt();
break;
case Property::Crf: data.crf = value.toInt();
case Property::Profile: {
auto profile = value.toInt();
if (data.profile().profile != profile) {
data.setProfile(profile);
emit dataChanged(index, index);
}
} break;
default: break;
}
} break;
default: break;
}

return false;
}

auto AudioEncoderModel::flags(const QModelIndex &index) const -> Qt::ItemFlags
{
if (!index.isValid()) {
return {};
}
auto flags = QAbstractTableModel::flags(index);
if (index.column() != Property::ID) {
flags |= Qt::ItemIsEditable;
}
return flags;
}

auto AudioEncoderModel::headerData(int section, Qt::Orientation orientation, int role) const
-> QVariant
{
if (section < 0 || section >= d_ptr->headers.size() || orientation != Qt::Horizontal) {
return {};
}
switch (role) {
case Qt::TextAlignmentRole: return Qt::AlignCenter;
case Qt::WhatsThisRole:
case Qt::ToolTipRole:
case Qt::DisplayRole: return d_ptr->headers.at(section);
default: break;
}
return {};
}

void AudioEncoderModel::setDatas(const Ffmpeg::EncodeContexts &encodeContexts)
{
beginResetModel();
d_ptr->encodeContexts = encodeContexts;
endResetModel();
}

Ffmpeg::EncodeContexts AudioEncoderModel::datas() const
{
return d_ptr->encodeContexts;
}
39 changes: 39 additions & 0 deletions examples/transcoder/audioencodermodel.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef AUDIOENCODERMODEL_HPP
#define AUDIOENCODERMODEL_HPP

#include <ffmpeg/encodecontext.hpp>

#include <QAbstractTableModel>

class AudioEncoderModel : public QAbstractTableModel
{
Q_OBJECT
public:
enum Property { ID, Encoder, ChannelLayout, Bitrate, Crf, Profile };
Q_ENUM(Property);

explicit AudioEncoderModel(QObject *parent = nullptr);
~AudioEncoderModel() override;

[[nodiscard]] auto rowCount(const QModelIndex &parent = QModelIndex()) const -> int override;
[[nodiscard]] auto columnCount(const QModelIndex &parent = QModelIndex()) const -> int override;

[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
auto setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)
-> bool override;

[[nodiscard]] Qt::ItemFlags flags(const QModelIndex &index) const override;

[[nodiscard]] QVariant headerData(int section,
Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;

void setDatas(const Ffmpeg::EncodeContexts &encodeContexts);
Ffmpeg::EncodeContexts datas() const;

private:
class AudioEncoderModelPrivate;
QScopedPointer<AudioEncoderModelPrivate> d_ptr;
};

#endif // AUDIOENCODERMODEL_HPP
67 changes: 67 additions & 0 deletions examples/transcoder/audioencodertableview.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include "audioencodertableview.hpp"
#include "audioencodermodel.hpp"
#include "styleditemdelegate.hpp"

#include <QHeaderView>

class AudioEncoderTableView::AudioEncoderTableViewPrivate
{
public:
explicit AudioEncoderTableViewPrivate(AudioEncoderTableView *q)
: q_ptr(q)
{
model = new AudioEncoderModel(q_ptr);
}

AudioEncoderTableView *q_ptr;

AudioEncoderModel *model;
};

AudioEncoderTableView::AudioEncoderTableView(QWidget *parent)
: QTableView{parent}
, d_ptr(new AudioEncoderTableViewPrivate(this))
{
setupUI();
}

AudioEncoderTableView::~AudioEncoderTableView() {}

void AudioEncoderTableView::setDatas(const Ffmpeg::EncodeContexts &encodeContexts)
{
d_ptr->model->setDatas(encodeContexts);
}

Ffmpeg::EncodeContexts AudioEncoderTableView::datas() const
{
return d_ptr->model->datas();
}

void AudioEncoderTableView::setupUI()
{
setModel(d_ptr->model);

setShowGrid(true);
setWordWrap(false);
setAlternatingRowColors(true);
verticalHeader()->setVisible(false);
verticalHeader()->setDefaultSectionSize(35);
horizontalHeader()->setStretchLastSection(true);
horizontalHeader()->setDefaultSectionSize(120);
horizontalHeader()->setMinimumSectionSize(60);
horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
horizontalHeader()->setSectionResizeMode(AudioEncoderModel::Property::Encoder,
QHeaderView::Stretch);
setIconSize(QSize(20, 20));

setItemDelegateForColumn(AudioEncoderModel::Property::Encoder, new AudioEncoderDelegate(this));
setItemDelegateForColumn(AudioEncoderModel::Property::ChannelLayout,
new ChannelLayoutDelegate(this));
setItemDelegateForColumn(AudioEncoderModel::Property::Profile, new ProfileDelegate(this));

setColumnWidth(AudioEncoderModel::Property::ID, 50);
setColumnWidth(AudioEncoderModel::Property::ChannelLayout, 100);
setColumnWidth(AudioEncoderModel::Property::Bitrate, 100);
setColumnWidth(AudioEncoderModel::Property::Crf, 50);
setColumnWidth(AudioEncoderModel::Property::Profile, 100);
}
24 changes: 24 additions & 0 deletions examples/transcoder/audioencodertableview.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef AUDIOENCODERTABLEVIEW_HPP
#define AUDIOENCODERTABLEVIEW_HPP

#include <ffmpeg/encodecontext.hpp>

#include <QTableView>

class AudioEncoderTableView : public QTableView
{
public:
explicit AudioEncoderTableView(QWidget *parent = nullptr);
~AudioEncoderTableView() override;

void setDatas(const Ffmpeg::EncodeContexts &encodeContexts);
Ffmpeg::EncodeContexts datas() const;

private:
void setupUI();

class AudioEncoderTableViewPrivate;
QScopedPointer<AudioEncoderTableViewPrivate> d_ptr;
};

#endif // AUDIOENCODERTABLEVIEW_HPP
36 changes: 13 additions & 23 deletions examples/transcoder/audioencoderwidget.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "audioencoderwidget.hpp"
#include "audioencodertableview.hpp"

#include <ffmpeg/avcontextinfo.h>
#include <ffmpeg/ffmpegutils.hpp>
Expand All @@ -19,10 +20,9 @@ class AudioEncoderWidget::AudioEncoderWidgetPrivate
audioEncoderCbx->setStyleSheet(comboBoxStyleSheet);
auto audioEncodercs = Ffmpeg::getCodecsInfo(AVMEDIA_TYPE_AUDIO, true);
for (const auto &codec : std::as_const(audioEncodercs)) {
auto text = QString("%1 (%2)").arg(codec.longName).arg(codec.name);
audioEncoderCbx->addItem(text, QVariant::fromValue(codec));
audioEncoderCbx->addItem(codec.displayName, QVariant::fromValue(codec));
if (codec.codecId == AV_CODEC_ID_AAC) {
audioEncoderCbx->setCurrentText(text);
audioEncoderCbx->setCurrentText(codec.displayName);
}
}
audioEncoderCbx->model()->sort(0);
Expand All @@ -49,10 +49,12 @@ class AudioEncoderWidget::AudioEncoderWidgetPrivate
maxBitrateSbx->setRange(0, INT_MAX);
maxBitrateSbx->setValue(defaultBitrate);

audioEncoderTable = new AudioEncoderTableView(q_ptr);

init();
}

void init()
void init() const
{
Ffmpeg::EncodeContext encodeParam;

Expand All @@ -76,6 +78,8 @@ class AudioEncoderWidget::AudioEncoderWidgetPrivate

QSpinBox *minBitrateSbx;
QSpinBox *maxBitrateSbx;

AudioEncoderTableView *audioEncoderTable;
};

AudioEncoderWidget::AudioEncoderWidget(QWidget *parent)
Expand All @@ -89,29 +93,14 @@ AudioEncoderWidget::AudioEncoderWidget(QWidget *parent)

AudioEncoderWidget::~AudioEncoderWidget() = default;

auto AudioEncoderWidget::setEncoder(AVCodecID codecId) -> bool
void AudioEncoderWidget::setDecodeContext(const Ffmpeg::EncodeContexts &decodeContexts)
{
Ffmpeg::CodecInfo codec{"", "", codecId};
auto index = d_ptr->audioEncoderCbx->findData(QVariant::fromValue(codec));
auto finded = (index >= 0);
if (finded) {
d_ptr->audioEncoderCbx->setCurrentIndex(index);
}
return finded;
d_ptr->audioEncoderTable->setDatas(decodeContexts);
}

auto AudioEncoderWidget::encodeParam() const -> Ffmpeg::EncodeContext
auto AudioEncoderWidget::encodeContexts() const -> Ffmpeg::EncodeContexts
{
Ffmpeg::EncodeContext encodeParam;
encodeParam.mediaType = AVMEDIA_TYPE_AUDIO;
encodeParam.encoderName = d_ptr->currentCodecName();
encodeParam.channel = static_cast<AVChannel>(d_ptr->chLayoutCbx->currentData().toLongLong());
encodeParam.crf = d_ptr->crfSbx->value();
encodeParam.minBitrate = d_ptr->minBitrateSbx->value();
encodeParam.maxBitrate = d_ptr->maxBitrateSbx->value();
encodeParam.bitrate = d_ptr->maxBitrateSbx->value();

return encodeParam;
return d_ptr->audioEncoderTable->datas();
}

void AudioEncoderWidget::onEncoderChanged()
Expand Down Expand Up @@ -155,6 +144,7 @@ void AudioEncoderWidget::setupUI()
layout->addRow(tr("Encoder:"), d_ptr->audioEncoderCbx);
layout->addRow(tr("Channel Layout:"), d_ptr->chLayoutCbx);
layout->addRow(hLayout);
layout->addRow(d_ptr->audioEncoderTable);
}

void AudioEncoderWidget::buildConnect()
Expand Down
Loading

0 comments on commit 888d764

Please sign in to comment.