MFC实现FFmpeg音视频转码器


***【在线视频教程】***

好文章,来自【福优学苑@音视频+流媒体】

整体界面设计

MVC架构

文件列表

转码参数

图片水印(文字水印?)

转码进度

开始转码




整体界面设计

image.png

image.png



MVC架构

MVC(Model-View-Controller)框架

其实从字面意思来说,只能了解各大概,view应该是视图的意思,那Model和Controller究竟是什么?




Model: 处理数据逻辑和程序运行状态

View:  则只负责显示

Controller: 通常负责处理用户交互的部分,从视图读取数据与用户输入,并向模型发送数据;这里顺便提一下,在Qt里面我们并没有Controller的概念,而是Delegate(委托),意义很明显:控制器委托模型来处理数据,模型委托控制器来做数据的交互。


这样的框架好处是很明显的:

- 高重用性:一个模型可以有多个视图,同样一个视图也可以对应多个模型

- 低耦合:因为模型与视图分离,所以可以独立的拓展和修改而不产生相互的影响

- 快速开发和便捷部署




各个控件的布局与美化

Image:显示图片


选择“Add Resource...”,弹出“Add Resource”对话框:

然后在左侧的“Resource Type”中选择“Bitmap”,点按钮“Import”,显示一个文件对话框,我们选择res文件夹中的test.bmp图片文件,

 Frame:显示一个无填充的矩形框,边框颜色可以通过Color属性的下拉列表设定

       Etched Horz:显示一条横分割线

       Etched Vert:显示一条竖分割线

       Rectangle:显示一个填充的矩形框,矩形颜色可通过Color属性的下拉列表设定

       Icon:显示一个图标(Icon),图标通过Image 下拉列表来设置图标资源ID

       Bitmap:显示一个位图(Bitmap),位图通过Image 下拉列表来设置位图资源ID

       Enhanced Metafile:显示一个加强的元数据文件(Metafile)

       Owner Draw:自绘



Label:标签字体和颜色

实际的应用中,可以用WM_CTLCOLOR 消息改变mfc中控件的颜色,比如现在就来改变一个static text控件的


字体、字体大小、字体颜色和背景色。

例如对话框的类为CTestDlg.

1. 在对话框的类中添加两个变量.

方法:在classview选项卡中,选择CTestDlg,右键,add member variable.


CBrush m_brush;

CFont m_font; 


在OnInitDialog()函数中添加:


// TODO: ……

m_font.CreatePointFont(150,"华文行楷");//代表15号字体,华文行楷

m_brush.CreateSolidBrush(RGB(0,255,0));//画刷为绿色


 


2 添加WM_CTLCOLOR 消息响应,添加的方法为:

add windows message handler->WM_CTLCOLOR->add and edit


 


3 在HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 函数中的todo后添加代码,即:

HBRUSH CYourDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)

{

HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);


 // TODO: Change any attributes of the DC here

 if (pWnd->GetDlgCtrlID() == IDC_STATICText)

 {


  pDC->SetBkColor(RGB(0,255,0));//背景色为绿色

  pDC->SetTextColor(RGB(255, 0, 0));//文字为红色

  pDC->SelectObject(&m_font);//文字为15号字体,华文行楷

  return m_brush;

 }


 // TODO: Return a different brush if the default is not desired

 return hbr;


}


CFileDialog:选择文件


CString strFile = _T("");

CFileDialog    dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("Describe Files (*.mp4)|*.mp4|All Files (*.*)|*.*||"), NULL);


if (dlgFile.DoModal())

{

strFile = dlgFile.GetPathName();

AfxMessageBox(strFile);

}



ComboBox :组合框控件

打开 Class Wizard,添加控件对应变量,如:CComboBoxm_cbExamble;


 InsertString() 将 Item 插入指定位置 nIndex,如:

m_cbExample.InsertString( nIndex, “StringData” );


int nIndex = m_cbExample.GetCurSel();

CString strCBText;

m_cbExample.GetLBText( nIndex, strCBText);


CString转char*

注意:ASCII编码, 如果是unicode编码,请不要这么使用

char* buf;

CString str="hello";

buf=(LPSTR)(LPCTSTR)str;




文件列表

1、为控件添加变量:m_ctrFileList

2、将ListControl控件的View属性修改为Report


3、在OnInitDialog()函数中添加如下代码:

m_ctrFileList.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

//设置ListControl样式,带网格


//添加列标题

m_ctrFileList.InsertColumn(0, "标题0", LVCFMT_LEFT, 130);



4、添加一行内容:


m_ctrFileList.InsertItem(0, _T("Java"));

m_ctrFileList.SetItemText(0, 1, _T("3"));

m_ctrFileList.SetItemText(0, 2, _T("1"));


//设改行文字背景颜色

m_ctrList.SetTextBkColor(RGB(255, 0, 0)); 



5、改变表项:

OnLvnItemchangedListFilelist:

LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

// TODO: 在此添加控件通知处理程序代码

*pResult = 0;


CString strLangName;    // 选择语言的名称字符串   

NMLISTVIEW *pNMListView = (NMLISTVIEW*)pNMHDR;


if (-1 != pNMListView->iItem)        // 如果iItem不是-1,就说明有列表项被选择   

{

// 获取被选择列表项第一个子项的文本   

strLangName = m_ctrFileList.GetItemText(pNMListView->iItem, 2);

// 将选择的语言显示与编辑框中   

AfxMessageBox(strLangName);

}





转码参数

private:

CComboBox m_EncodeVideoTypes;

CComboBox m_EncodeAudioTypes;

CComboBox m_MuxerTypes;



图片水印



开始转码


有一个坑:命令行解析

int split_commandline(OptionParseContext *octx, int argc, char *argv[],

                      const OptionDef *options,

                      const OptionGroupDef *groups, int nb_groups)

{

// 强制读取命令行参数:

///// by fyxy, 坑:强制读取命令行

    argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc);

///// by fyxy, prepare_app_arguments(&argc, &argv);

}


本地测试:直接转码

char *arrParams[10] = { 0 };

for (int k = 0; k < 10; k++) {

arrParams[k] = new char[64]();

}

strcpy(arrParams[0], "xxx_mainx_ffmpeg431");

strcpy(arrParams[1], "-i");

strcpy(arrParams[2], "D:\\_movies\\__test\\ande_302.mp4");

strcpy(arrParams[3], "-vcodec");

strcpy(arrParams[4], "libx264");

strcpy(arrParams[5], "-acodec");

strcpy(arrParams[6], "copy");

strcpy(arrParams[7], "-y");

strcpy(arrParams[8], "ande_302--test121.flv");


m_TCProgress.SetRange(0, 100);

//AfxMessageBox(m_ctrFileList.GetItemText(i, 5));

m_TCProgress.SetPos(100);

/// 准备参数

main_ffmpeg431(9, arrParams);


for (int k = 0; k < 10; k++) {

delete[] arrParams[k];

arrParams[k] = NULL;

}


开启一个独立的工作线程


//创建第一个线程ThreadProc,相对优先级THREAD_PRIORITY_IDLE面对任何等级调整为1    

    AfxBeginThread((AFX_THREADPROC)ThreadProc,&lparam,THREAD_PRIORITY_IDLE);


工作者线程的函数必须是全局函数或静态成员函数,不能是普通的成员函数

 

//坑:static DWORD __cdecl TCThreadProc(LPVOID pParam)

DWORD WINAPI ThreadProc(LPVOID pParam)

{

    

    return 0;

}



又一个坑:exit_program(...)

///// by fyxy, 退出进程

void exit_program(int ret)

{

    if (program_exit)

        program_exit(ret);


    exit(ret);

}






转码进度

进度条

CProgressCtrl


MFC定时器

在MFC中和定时器相关的有三个函数:

UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)( HWND, UINT, UINT, DWORD) );

afx_msg void OnTimer( UINT nIDEvent );

BOOL KillTimer( int nIDEvent );


(1)在resource.h中定义两个定时器的ID

#define IDTIMER1  1

#define IDTIMER2  2


(2)在CMainFrame的OnCreate函数中定义两个定时器的属性。

SetTimer(TIMEID1,5000,0);

SetTimer(TIMEID2,7000,0);


(3) CMainFrame中对WM_TIMER进行响应。

oid CMainFrame::OnTimer(UINT nIDEvent)

{

    // TODO: Add your message handler code here and/or call default

    switch(nIDEvent) {

    case TIMEID1:

        {   

            AfxMessageBox("定时器1!");

            break;

        }

case TIMEID2:

        {   

            AfxMessageBox("定时器2!");

            break;

        }

    default:

        ;

    }

   

    CFrameWnd::OnTimer(nIDEvent);

}


 


(4)在CMainFrame的析构函数中添加

KillTimer(IDTIMER1);

KillTimer(IDTIMER2);


好文章,来自【福优学苑@音视频+流媒体】
***【在线视频教程】***