• Qt 集成 FFmpeg 实现颜色格式转换


    目录

    1. Qt 集成 FFmpeg

    1.1 下载 FFmpeg

    1.2 Qt 集成 FFmpeg

    1.2.1 修改 .pro 文件

    1.2.2 放入 dll 文件

    1.2.3 代码中使用 FFmpeg

    2. 图像格式转换

    3. 预览

    4. 项目地址


    项目需要,写个小工具来实现图像颜色格式的转换,主要的 Feature 如下:

    1. 支持输入输出图像格式选择:
    2. 支持对输入图像进行缩放;
    3. 支持对输入输出图像预览;

    支持的图像格式转换如下:

    •  YUV420P
    •  NV12
    •  NV21
    •  YUV422P
    •  NV16
    •  YUYV422
    •  UYVY422
    •  YVYU422
    •  RGB24
    •  BGR24
    •  ARGB
    •  RGBA
    •  RGB565BE
    •  RGB565LE
    •  RGB444BE
    •  RGB444LE

    由于输入输出为纯图片文件,所以需要指定图像的宽高信息;

     

    1. Qt 集成 FFmpeg

    Qt 中集成 FFmpeg 的文章非常多,大家可以自行搜索,这里简单的提一下集成的过程;

    Windows 上,集成 FFmpeg 的方式有 2 种:

    1. 下载 FFmpeg 的库,代码中引用头文件来使用 FFmpeg;

    2. 下载 FFmpeg 源码,自行构建;

    这里选择第一种,下载 FFmpeg 的 DLL 来集成;

    1.1 下载 FFmpeg

    下载地址:Download FFmpeg

     选择 Windows,下面有 2 个 build,随便选一个,我选择的是第一个;

    进入后,最先看到的是 master 的 build,咱们选个 Release 的稳定版的,shared 代表是动态链接库,我们选他:

     解压后如下:

     我们要 3 部分,头文件、动态库、和导入库:

    动态库在:ffmpeg-5.1.2-full_build-shared\bin

    头文件在:ffmpeg-5.1.2-full_build-shared\include

    导入库在:ffmpeg-5.1.2-full_build-shared\include\lib

    1.2 Qt 集成 FFmpeg

    1.2.1 修改 .pro 文件

    在 Qt 的工程文件中,指定 FFmpeg 导入的头文件以及库的地方

    1. #-------------------------------------------------
    2. #
    3. # Project created by QtCreator 2022-10-16T17:35:35
    4. #
    5. #-------------------------------------------------
    6. QT += core gui
    7. RC_ICONS = logo.ico
    8. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    9. TARGET = YUVEyes
    10. TEMPLATE = app
    11. # The following define makes your compiler emit warnings if you use
    12. # any feature of Qt which has been marked as deprecated (the exact warnings
    13. # depend on your compiler). Please consult the documentation of the
    14. # deprecated API in order to know how to port your code away from it.
    15. DEFINES += QT_DEPRECATED_WARNINGS
    16. # You can also make your code fail to compile if you use deprecated APIs.
    17. # In order to do so, uncomment the following line.
    18. # You can also select to disable deprecated APIs only up to a certain version of Qt.
    19. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
    20. CONFIG += c++11
    21. SOURCES += \
    22. main.cpp \
    23. mainwindow.cpp \
    24. qtffmpegutils.cpp
    25. HEADERS += \
    26. mainwindow.h \
    27. qtffmpegutils.h \
    28. error_code.h
    29. FORMS += \
    30. mainwindow.ui
    31. # Default rules for deployment.
    32. qnx: target.path = /tmp/$${TARGET}/bin
    33. else: unix:!android: target.path = /opt/$${TARGET}/bin
    34. !isEmpty(target.path): INSTALLS += target
    35. win32: {
    36. FFMPEG_HOME=G:\MediaCodeC\ffmpeg-5.1.2-full_build-shared
    37. #设置 ffmpeg 的头文件
    38. INCLUDEPATH += $$FFMPEG_HOME/include
    39. #设置导入库的目录一边程序可以找到导入库
    40. # -L :指定导入库的目录
    41. # -l :指定要导入的 库名称
    42. LIBS += -L$$FFMPEG_HOME/lib \
    43. -lavcodec \
    44. -lavdevice \
    45. -lavfilter \
    46. -lavformat \
    47. -lavutil \
    48. -lpostproc \
    49. -lswresample \
    50. -lswscale
    51. }
    52. RESOURCES += \
    53. src.qrc

    1.2.2 放入 dll 文件

    Qt 编译的时候,会生成一个编译的文件夹,将我们用到的 dll 扔进去:

     好了,基本环境准备完毕;

    1.2.3 代码中使用 FFmpeg

    在代码中,包含 FFmpeg 的头文件即可使用 FFmpeg 的库了:

     打印 FFmpeg 的 AVCodec 版本号:

     

     

    2. 图像格式转换

    图像格式转换可以使用 FFmpeg 的 sws_scale 函数进行,该函数的原型为:

    能够支持不同 AVPixelFormat 的像素格式转换,并且能够进行缩放功能;

    这里定义一个专门使用的类 qtffmpegutils.h,来进行转换工作:

    1. #ifndef QTFFMPEGUTILS_H
    2. #define QTFFMPEGUTILS_H
    3. extern "C"{
    4. #include "libswscale/swscale.h"
    5. #include "libavutil/opt.h"
    6. #include "libavutil/imgutils.h"
    7. }
    8. #include "error_code.h"
    9. typedef struct {
    10. const char *filename;
    11. int width;
    12. int height;
    13. AVPixelFormat format;
    14. } RawVideoFile;
    15. typedef struct {
    16. char *pixels;
    17. int width;
    18. int height;
    19. AVPixelFormat format;
    20. } RawVideoFrame;
    21. class QtFFmpegUtils
    22. {
    23. public:
    24. QtFFmpegUtils();
    25. static int convertRawVideo(RawVideoFile &in, RawVideoFile &out);
    26. static int convertToRGB888(RawVideoFile &in, uint8_t *rgb888_data);
    27. static int getBufferSize(AVPixelFormat pix_fmt, int width, int height);
    28. //static void convertRawFrame(RawVideoFrame &in, RawVideoFrame &out);
    29. };
    30. #endif // QTFFMPEGUTILS_H

    在 qtffmpegutils.cpp 中调用了 FFmpeg 的 sws_scale 逻辑:

    1. #include "qtffmpegutils.h"
    2. #include
    3. #include
    4. QtFFmpegUtils::QtFFmpegUtils()
    5. {
    6. }
    7. int QtFFmpegUtils::convertRawVideo(RawVideoFile &in, RawVideoFile &out)
    8. {
    9. int ret = APP_SUCCESS;
    10. SwsContext *ctx = nullptr;
    11. uint8_t *inData[4], *outData[4];
    12. int inStrides[4], outStrides[4];
    13. int inFrameSize, outFrameSize;
    14. QFile inFile(in.filename);
    15. QFile outFile(out.filename);
    16. ret = av_image_alloc(inData, inStrides, in.width, in.height, in.format, 1);
    17. if(ret < 0){
    18. char errbuf[1024];
    19. av_strerror(ret,errbuf,sizeof (errbuf));
    20. qDebug() << "av_image_alloc inData error:" << errbuf;
    21. ret = APP_FFMPEG_ALLOC_FAILED;
    22. goto alloc_failed_1;
    23. }
    24. ret = av_image_alloc(outData, outStrides, out.width, out.height, out.format, 1);
    25. if (ret < 0) {
    26. char errbuf[1024];
    27. av_strerror(ret, errbuf, sizeof (errbuf));
    28. qDebug() << "av_image_alloc outData error:" << errbuf;
    29. ret = APP_FFMPEG_ALLOC_FAILED;
    30. goto alloc_failed_2;
    31. }
    32. ret = APP_SUCCESS;
    33. ctx = sws_getContext(in.width, in.height, in.format,
    34. out.width, out.height, out.format,
    35. SWS_BILINEAR, nullptr, nullptr, nullptr);
    36. if (!ctx) {
    37. qDebug() << "sws_getContext error";
    38. ret = APP_FFMPEG_SWS_GETCTX_FAILED;
    39. goto get_ctx_failed;
    40. }
    41. if (!inFile.open(QFile::ReadOnly)) {
    42. qDebug() << "open in file failure";
    43. ret = APP_OPENFILE_FAILED;
    44. goto in_file_open_falied;
    45. }
    46. if (!outFile.open(QFile::WriteOnly)) {
    47. qDebug() << "open out file failure";
    48. ret = APP_OPENFILE_FAILED;
    49. goto out_file_open_failed;
    50. }
    51. inFrameSize = av_image_get_buffer_size(in.format, in.width, in.height, 1);
    52. outFrameSize = av_image_get_buffer_size(out.format, out.width, out.height, 1);
    53. while (inFile.read((char *)inData[0], inFrameSize) == inFrameSize) {
    54. sws_scale(ctx, inData, inStrides, 0, in.height, outData, outStrides);
    55. outFile.write((char *)outData[0], outFrameSize);
    56. }
    57. outFile.close();
    58. out_file_open_failed:
    59. inFile.close();
    60. in_file_open_falied:
    61. sws_freeContext(ctx);
    62. get_ctx_failed:
    63. av_freep(&outData[0]);
    64. alloc_failed_2:
    65. av_freep(&inData[0]);
    66. alloc_failed_1:
    67. return ret;
    68. }
    69. int QtFFmpegUtils::convertToRGB888(RawVideoFile &in, uint8_t *rgb888_data)
    70. {
    71. int ret = APP_SUCCESS;
    72. SwsContext *ctx = nullptr;
    73. uint8_t *inData[4], *outData[4];
    74. int inStrides[4], outStrides[4];
    75. int inFrameSize, outFrameSize;
    76. QFile inFile(in.filename);
    77. ret = av_image_alloc(inData, inStrides, in.width, in.height, in.format, 1);
    78. if(ret < 0){
    79. char errbuf[1024];
    80. av_strerror(ret,errbuf,sizeof (errbuf));
    81. qDebug() << "av_image_alloc inData error:" << errbuf;
    82. ret = APP_FFMPEG_ALLOC_FAILED;
    83. goto alloc_failed_1;
    84. }
    85. ret = av_image_alloc(outData, outStrides, in.width, in.height, AV_PIX_FMT_RGB24, 1);
    86. if (ret < 0) {
    87. char errbuf[1024];
    88. av_strerror(ret, errbuf, sizeof (errbuf));
    89. qDebug() << "av_image_alloc outData error:" << errbuf;
    90. ret = APP_FFMPEG_ALLOC_FAILED;
    91. goto alloc_failed_2;
    92. }
    93. ret = APP_SUCCESS;
    94. ctx = sws_getContext(in.width, in.height, in.format,
    95. in.width, in.height, AV_PIX_FMT_RGB24,
    96. SWS_BILINEAR, nullptr, nullptr, nullptr);
    97. if (!ctx) {
    98. qDebug() << "sws_getContext error";
    99. ret = APP_FFMPEG_SWS_GETCTX_FAILED;
    100. goto get_ctx_failed;
    101. }
    102. if (!inFile.open(QFile::ReadOnly)) {
    103. qDebug() << "open in file failure";
    104. ret = APP_OPENFILE_FAILED;
    105. goto in_file_open_falied;
    106. }
    107. inFrameSize = av_image_get_buffer_size(in.format, in.width, in.height, 1);
    108. outFrameSize = av_image_get_buffer_size(AV_PIX_FMT_RGB24, in.width, in.height, 1);
    109. if (inFile.read((char *)inData[0], inFrameSize) == inFrameSize) {
    110. sws_scale(ctx, inData, inStrides, 0, in.height, outData, outStrides);
    111. memcpy(rgb888_data, outData[0], outFrameSize);
    112. }
    113. else {
    114. qDebug("Read not finished");
    115. ret = APP_READ_FILE_NOT_FINISHED;
    116. }
    117. inFile.close();
    118. in_file_open_falied:
    119. sws_freeContext(ctx);
    120. get_ctx_failed:
    121. av_freep(&outData[0]);
    122. alloc_failed_2:
    123. av_freep(&inData[0]);
    124. alloc_failed_1:
    125. return ret;
    126. }
    127. int QtFFmpegUtils::getBufferSize(AVPixelFormat pix_fmt, int width, int height)
    128. {
    129. return av_image_get_buffer_size(pix_fmt, width, height, 1);
    130. }

    3. 预览

    代码中,使用一个 QLabel 作为预览输入输出的图片,mainwindow.h 定义如下:

    1. #ifndef MAINWINDOW_H
    2. #define MAINWINDOW_H
    3. #include
    4. #include
    5. // ffmpeg header
    6. extern "C" {
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. }
    13. #include "error_code.h"
    14. #include "qtffmpegutils.h"
    15. namespace Ui {
    16. class MainWindow;
    17. }
    18. class MainWindow : public QMainWindow
    19. {
    20. Q_OBJECT
    21. public:
    22. explicit MainWindow(QWidget *parent = nullptr);
    23. ~MainWindow();
    24. private:
    25. Ui::MainWindow *ui;
    26. AVPixelFormat mInputFormat;
    27. AVPixelFormat mOutputFormat;
    28. QLabel *mLabel;
    29. // Format debug function
    30. QString GetAVPixelFormatString(AVPixelFormat format);
    31. void ShowImageInRGB888(RawVideoFile in);
    32. private slots:
    33. void on_OpenInputFileBtn_Clicked();
    34. void on_SelectOutputFileBtn_Clicked();
    35. void on_StartConvertBtn_Clicked();
    36. void on_ShowInputImageBtn_Clicked();
    37. void on_ShowOutputImageBtn_Clicked();
    38. void on_InputFormatComboBox_Activated(int item_idx);
    39. void on_OutputFormatComboBox_Activated(int item_idx);
    40. void on_AboutActicon_Clicked(bool trigger);
    41. };
    42. #endif // MAINWINDOW_H

    mainwindow.cpp 逻辑如下,主要处理一些按键之类的逻辑和显示 QLabel:

    1. #include "mainwindow.h"
    2. #include "ui_mainwindow.h"
    3. #include "qtffmpegutils.h"
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #define WIDTH_IN_4K 3840
    11. #define HEIGHT_IN_4K 2160
    12. #define MAX_SUPPORT_WIDTH (WIDTH_IN_4K)
    13. #define MAX_SUPPORT_HEIGHT (HEIGHT_IN_4K)
    14. #define RGB888_IN_BYTE (8)
    15. typedef struct _DebugFormatInfo {
    16. AVPixelFormat format;
    17. QString string;
    18. } _DebugFormatInfo_t;
    19. static AVPixelFormat ComboxSupportFormatList[] = {
    20. AV_PIX_FMT_YUV420P,
    21. AV_PIX_FMT_NV12,
    22. AV_PIX_FMT_NV21,
    23. AV_PIX_FMT_YUV422P,
    24. AV_PIX_FMT_NV16,
    25. AV_PIX_FMT_YUYV422,
    26. AV_PIX_FMT_UYVY422,
    27. AV_PIX_FMT_YVYU422,
    28. AV_PIX_FMT_RGB24,
    29. AV_PIX_FMT_BGR24,
    30. AV_PIX_FMT_ARGB,
    31. AV_PIX_FMT_RGBA,
    32. AV_PIX_FMT_RGB565BE,
    33. AV_PIX_FMT_RGB565LE,
    34. AV_PIX_FMT_RGB444BE,
    35. AV_PIX_FMT_RGB444LE
    36. };
    37. static _DebugFormatInfo_t DebugFormatInfo[] = {
    38. {AV_PIX_FMT_YUV420P, "AV_PIX_FMT_YUV420P "},
    39. {AV_PIX_FMT_NV12, "AV_PIX_FMT_NV12 "},
    40. {AV_PIX_FMT_NV21, "AV_PIX_FMT_NV21 "},
    41. {AV_PIX_FMT_YUV422P, "AV_PIX_FMT_YUV422P "},
    42. {AV_PIX_FMT_NV16, "AV_PIX_FMT_NV16 "},
    43. {AV_PIX_FMT_YUYV422, "AV_PIX_FMT_YUYV422 "},
    44. {AV_PIX_FMT_UYVY422, "AV_PIX_FMT_UYVY422 "},
    45. {AV_PIX_FMT_YVYU422, "AV_PIX_FMT_YVYU422 "},
    46. {AV_PIX_FMT_RGB24, "AV_PIX_FMT_RGB24 "},
    47. {AV_PIX_FMT_BGR24, "AV_PIX_FMT_BGR24 "},
    48. {AV_PIX_FMT_ARGB, "AV_PIX_FMT_ARGB "},
    49. {AV_PIX_FMT_RGBA, "AV_PIX_FMT_RGBA "},
    50. {AV_PIX_FMT_RGB565BE, "AV_PIX_FMT_RGB565BE"},
    51. {AV_PIX_FMT_RGB565LE, "AV_PIX_FMT_RGB565LE"},
    52. {AV_PIX_FMT_RGB444BE, "AV_PIX_FMT_RGB444BE"},
    53. {AV_PIX_FMT_RGB444LE, "AV_PIX_FMT_RGB444LE"}
    54. };
    55. MainWindow::MainWindow(QWidget *parent) :
    56. QMainWindow(parent),
    57. ui(new Ui::MainWindow)
    58. {
    59. ui->setupUi(this);
    60. qDebug("AVCodeC Version = %s", av_version_info());
    61. mInputFormat = ComboxSupportFormatList[0];
    62. mOutputFormat = ComboxSupportFormatList[0];
    63. mLabel = new QLabel();
    64. ui->lineEdit_Input_W->setValidator(new QIntValidator(0, MAX_SUPPORT_WIDTH, this));
    65. ui->lineEdit_Input_H->setValidator(new QIntValidator(0, MAX_SUPPORT_HEIGHT, this));
    66. ui->lineEdit_Output_W->setValidator(new QIntValidator(0, MAX_SUPPORT_WIDTH, this));
    67. ui->lineEdit_Output_H->setValidator(new QIntValidator(0, MAX_SUPPORT_HEIGHT, this));
    68. connect(ui->Btn_OpenInputFile, SIGNAL(clicked()), this, SLOT(on_OpenInputFileBtn_Clicked()));
    69. connect(ui->Btn_SelectOutputFile, SIGNAL(clicked()), this, SLOT(on_SelectOutputFileBtn_Clicked()));
    70. connect(ui->Btn_ShowInputImage, SIGNAL(clicked()), this, SLOT(on_ShowInputImageBtn_Clicked()));
    71. connect(ui->Btn_ShowOutputImage, SIGNAL(clicked()), this, SLOT(on_ShowOutputImageBtn_Clicked()));
    72. connect(ui->Btn_StartConvert, SIGNAL(clicked()), this, SLOT(on_StartConvertBtn_Clicked()));
    73. connect(ui->comboBoxIn, SIGNAL(activated(int)), this, SLOT(on_InputFormatComboBox_Activated(int)));
    74. connect(ui->comboBoxOut,SIGNAL(activated(int)), this, SLOT(on_OutputFormatComboBox_Activated(int)));
    75. connect(ui->actionVersion, SIGNAL(triggered(bool)), this, SLOT(on_AboutActicon_Clicked(bool)));
    76. }
    77. MainWindow::~MainWindow()
    78. {
    79. delete ui;
    80. }
    81. void MainWindow::on_OpenInputFileBtn_Clicked()
    82. {
    83. QFileDialog *fileDialog = new QFileDialog(this);
    84. fileDialog->setWindowTitle(tr("Open File"));
    85. fileDialog->setDirectory(".");
    86. fileDialog->setViewMode(QFileDialog::Detail);
    87. if(fileDialog->exec() == QDialog::Accepted) {
    88. QString path = fileDialog->selectedFiles()[0];
    89. QFileInfo fileInfo(path);
    90. if (fileInfo.isFile()) {
    91. ui->Label_InputFilePath->setText(path);
    92. } else {
    93. QMessageBox::information(nullptr, tr("Warning"), tr("Not exist :") + path);
    94. }
    95. }
    96. }
    97. void MainWindow::on_SelectOutputFileBtn_Clicked()
    98. {
    99. QFileDialog *fileDialog = new QFileDialog(this);
    100. fileDialog->setWindowTitle(tr("Select Location"));
    101. fileDialog->setDirectory(".");
    102. fileDialog->setViewMode(QFileDialog::Detail);
    103. if(fileDialog->exec() == QDialog::Accepted) {
    104. QString path = fileDialog->selectedFiles()[0];
    105. QFileInfo fileInfo(path);
    106. if (fileInfo.isFile()) {
    107. QMessageBox::StandardButton rb = QMessageBox::question(nullptr,
    108. tr("Question"),
    109. tr("Output File exist, Do you want cover it?"),
    110. QMessageBox::Yes | QMessageBox::No,
    111. QMessageBox::Yes);
    112. if(rb == QMessageBox::Yes) {
    113. ui->Label_OutputFilePath->setText(path);
    114. }
    115. } else {
    116. ui->Label_OutputFilePath->setText(path);
    117. }
    118. }
    119. }
    120. void MainWindow::on_ShowInputImageBtn_Clicked()
    121. {
    122. bool ok = false;
    123. int input_w, input_h;
    124. QString input_file_path;
    125. RawVideoFile video_info;
    126. input_w = ui->lineEdit_Input_W->text().toInt(&ok, 10);
    127. input_h = ui->lineEdit_Input_H->text().toInt(&ok, 10);
    128. // Check if the input file not be set
    129. input_file_path = ui->Label_InputFilePath->text();
    130. if (input_file_path.isEmpty())
    131. {
    132. QMessageBox::information(nullptr, tr("Warning"), tr("Select a input file first"));
    133. return;
    134. }
    135. std::string in_str = input_file_path.toStdString();
    136. video_info.width = input_w;
    137. video_info.height = input_h;
    138. video_info.format = mInputFormat;
    139. video_info.filename = in_str.c_str();
    140. ShowImageInRGB888(video_info);
    141. }
    142. void MainWindow::on_ShowOutputImageBtn_Clicked()
    143. {
    144. bool ok = false;
    145. int output_w, output_h;
    146. QString output_file_path;
    147. RawVideoFile video_info;
    148. output_w = ui->lineEdit_Output_W->text().toInt(&ok, 10);
    149. output_h = ui->lineEdit_Output_H->text().toInt(&ok, 10);
    150. // Check if the output file not be set
    151. output_file_path = ui->Label_OutputFilePath->text();
    152. if (output_file_path.isEmpty())
    153. {
    154. QMessageBox::information(nullptr, tr("Warning"), tr("Select a input file first"));
    155. return;
    156. }
    157. std::string in_str = output_file_path.toStdString();
    158. video_info.width = output_w;
    159. video_info.height = output_h;
    160. video_info.format = mOutputFormat;
    161. video_info.filename = in_str.c_str();
    162. ShowImageInRGB888(video_info);
    163. }
    164. void MainWindow::on_InputFormatComboBox_Activated(int item_idx)
    165. {
    166. mInputFormat = ComboxSupportFormatList[item_idx];
    167. qDebug("InputFormatComboBox Item=%d", item_idx);
    168. }
    169. void MainWindow::on_OutputFormatComboBox_Activated(int item_idx)
    170. {
    171. mOutputFormat = ComboxSupportFormatList[item_idx];
    172. qDebug("OutputFormatComboBox Item=%d", item_idx);
    173. }
    174. void MainWindow::on_StartConvertBtn_Clicked()
    175. {
    176. bool ok = false;
    177. int input_w, input_h, output_w, output_h;
    178. QString input_file_path, output_file_path;
    179. RawVideoFile in;
    180. RawVideoFile out;
    181. int ret;
    182. // Check if the input file is null
    183. if (ui->lineEdit_Input_W->text().isEmpty() ||
    184. ui->lineEdit_Input_H->text().isEmpty() ||
    185. ui->lineEdit_Output_H->text().isEmpty() ||
    186. ui->lineEdit_Output_W->text().isEmpty())
    187. {
    188. QMessageBox::information(nullptr, tr("Warning"), tr("Please add input/output width/height info!"));
    189. return;
    190. }
    191. input_w = ui->lineEdit_Input_W->text().toInt(&ok, 10);
    192. if (ok != true)
    193. {
    194. QMessageBox::information(nullptr, tr("Warning"), tr("input_w String to Int failed"));
    195. return;
    196. }
    197. input_h = ui->lineEdit_Input_H->text().toInt(&ok, 10);
    198. if (ok != true)
    199. {
    200. QMessageBox::information(nullptr, tr("Warning"), tr("input_h String to Int failed"));
    201. return;
    202. }
    203. output_w = ui->lineEdit_Output_W->text().toInt(&ok, 10);
    204. if (ok != true)
    205. {
    206. QMessageBox::information(nullptr, tr("Warning"), tr("output_w String to Int failed"));
    207. return;
    208. }
    209. output_h = ui->lineEdit_Output_H->text().toInt(&ok, 10);
    210. if (ok != true)
    211. {
    212. QMessageBox::information(nullptr, tr("Warning"), tr("output_h String to Int failed"));
    213. return;
    214. }
    215. // Check if the input file not be set
    216. input_file_path = ui->Label_InputFilePath->text();
    217. if (input_file_path.isEmpty())
    218. {
    219. QMessageBox::information(nullptr, tr("Warning"), tr("Select a input file first"));
    220. return;
    221. }
    222. // Check if the output file not be set
    223. output_file_path = ui->Label_OutputFilePath->text();
    224. if (output_file_path.isEmpty())
    225. {
    226. QMessageBox::information(nullptr, tr("Warning"), tr("Select a output file"));
    227. return;
    228. }
    229. std::string in_str = input_file_path.toStdString();
    230. std::string out_str = output_file_path.toStdString();
    231. in.width = input_w;
    232. in.height = input_h;
    233. in.format = mInputFormat;
    234. in.filename = in_str.c_str();
    235. out.width = output_w;
    236. out.height = output_h;
    237. out.format = mOutputFormat;
    238. out.filename = out_str.c_str();
    239. qDebug("StartConvert input w=%d, h=%d", input_w, input_h);
    240. qDebug(" input format=%s", GetAVPixelFormatString(mInputFormat).toStdString().data());
    241. qDebug(" output w=%d, h=%d", output_w, output_h);
    242. qDebug(" output format=%s", GetAVPixelFormatString(mOutputFormat).toStdString().data());
    243. ret = QtFFmpegUtils::convertRawVideo(in, out);
    244. if (ret == APP_SUCCESS) {
    245. QMessageBox::information(nullptr, tr("Congratulation!"), tr("Convert Successfully"),
    246. QMessageBox::Yes, QMessageBox::Yes);
    247. } else {
    248. QMessageBox::information(nullptr, tr("Oops"), tr("Convert Failed : ") + QString::number(ret, 10),
    249. QMessageBox::Yes, QMessageBox::Yes);
    250. }
    251. }
    252. void MainWindow::ShowImageInRGB888(RawVideoFile in)
    253. {
    254. uint8_t *rgb888_data = nullptr;
    255. int ret = APP_SUCCESS;
    256. int buffer_size = 0;
    257. buffer_size = QtFFmpegUtils::getBufferSize(AV_PIX_FMT_RGB24, in.width, in.height);
    258. //rgb888_data = (uint8_t *)malloc(in.width * in.height * RGB888_IN_BYTE);
    259. rgb888_data = (uint8_t *)malloc(buffer_size);
    260. if (rgb888_data == nullptr) {
    261. QMessageBox::information(nullptr, tr("Warning"), tr("Malloc failed"));
    262. return;
    263. }
    264. ret = QtFFmpegUtils::convertToRGB888(in, rgb888_data);
    265. if (ret == APP_SUCCESS) {
    266. qDebug("Convert to RGB888 Successful");
    267. } else {
    268. QMessageBox::information(nullptr, tr("Oops"), tr("Show Image Failed : ") + QString::number(ret, 10),
    269. QMessageBox::Yes, QMessageBox::Yes);
    270. }
    271. QImage *qimage = new QImage(rgb888_data, in.width, in.height, QImage::Format_RGB888);
    272. QPixmap pixmap = QPixmap::fromImage(*qimage);
    273. //mLabel->setGeometry(100, 100, in.width, in.height);
    274. mLabel->setMaximumSize(in.width, in.height);
    275. mLabel->resize(in.width, in.height);
    276. mLabel->setPixmap(pixmap);
    277. mLabel->show();
    278. free(rgb888_data);
    279. }
    280. void MainWindow::on_AboutActicon_Clicked(bool trigger)
    281. {
    282. QMessageBox MBox;
    283. MBox.setWindowTitle("CSC Tools");
    284. MBox.setText("Powered by StephenZhou\n\nSoftware Version : V1.0 Beta \n\nGenerate at 2022.10.29");
    285. MBox.setIconPixmap(QPixmap(":/logo.ico"));
    286. MBox.exec();
    287. }
    288. QString MainWindow::GetAVPixelFormatString(AVPixelFormat format)
    289. {
    290. QString str = "N/A";
    291. for (unsigned int i = 0; i < sizeof(DebugFormatInfo) / sizeof(_DebugFormatInfo_t); i++) {
    292. if (format == DebugFormatInfo[i].format)
    293. {
    294. str = DebugFormatInfo[i].string;
    295. break;
    296. }
    297. }
    298. return str;
    299. }

     

    4. 项目地址

    https://gitee.com/stephenzhou-tech/csc_tools

  • 相关阅读:
    处理普通用户安装启动mysql报Can‘t find error-message file‘usrsharemysqlerrmsg.sys‘ 问题
    06-MySQL-进阶-视图&存储函数&存储过程&触发器
    CGAL 计算点云的最值
    自学Python笔记总结(2——了解)
    ERP系统选型需谨慎
    基于人工神经网络的车牌识别系统的研究(Matlab代码实现)
    Top 10 Best Golang Project For Beginners
    [postgresql]postgresqlg使用enerate_series() 函数补全统计
    Linux设备树详解
    【JS 构造|原型|原型链|继承(圣杯模式)|ES6类语法】上篇
  • 原文地址:https://blog.csdn.net/zhoutaopower/article/details/127603400