注:写了一系列的文章,都是关于ffdshow中的位图覆盖滤镜的源代码分析的,在此列一个列表:
ffdshow 源代码分析 2: 位图覆盖滤镜(对话框部分Dialog)
ffdshow 源代码分析 3: 位图覆盖滤镜(设置部分Settings)
ffdshow 源代码分析 4: 位图覆盖滤镜(滤镜部分Filter)
ffdshow 源代码分析 5: 位图覆盖滤镜(总结)
本文我们介绍ffdshow的滤镜功能。ffdshow支持很多种滤镜,可以支持多种视频和音频的后期效果。例如OSD滤镜支持在视频的左上角显示视频相关的信息。而可视化滤镜则支持显示视频每一帧的运动矢量以及量化参数。在这里我们介绍一种位图覆盖(Bitmap)滤镜(Filter)。
效果
编译完ffdshow之后,在“项目属性->调试->命令”里面将GraphEdit.exe所在位置设置为调试程序,例如在这里我设置了《终极解码》里面自带GraphEdit.exe,路径为“C:\Program Files\Final Codecs\Codecs\GraphEdit.exe”。这样就可以使用GraphEdit.exe调试ffdshow了。
向GraphEdit.exe里面拖入一个文件“五月天 咸鱼.mp4”,结果如下图所示:
注:有的时候默认的视频解码器可能不是ffdshow,可能是CoreAVC等,可以先删除视频解码器然后添加ffdshow。
点击绿色三角形按钮就可以开始播放视频。
右键点击ffdshow组件,打开属性对话框之后,可以看见右边栏中有很多的滤镜。
勾选“位图覆盖”滤镜,然后选择一张用于覆盖的图片(在这里我选择了一张bmp格式的专辑封面)。
注:可以调整位图所在的水平位置,垂直位置,不透明度,并且可以修改位图叠加模式(在这里用混合)。
添加了该滤镜之后,播放窗口的显示内容为:
可见在右上角显示出了叠加的位图。
源代码分析
1.对话框部分
与位图覆盖(Bitmap)滤镜的对话框有关的类位于dialog目录下的Cbitmap.cpp和Cbitmap.h文件中。
先来看看Cbitmap.h中类的声明:
需要注意的是,里面类的名字居然叫TbitmapPage,而没有和头文件名字一致。= =
#ifndef _CBITMAPPAGE_H_ #define _CBITMAPPAGE_H_ #include "TconfPageDecVideo.h" //Bitmap配置页面 class TbitmapPage : public TconfPageDecVideo { private: void pos2dlg(void), opacity2dlg(void); //设置文件路径 void onFlnm(void); protected: virtual INT_PTR msgProc(UINT uMsg, WPARAM wParam, LPARAM lParam); public: //构造函数 TbitmapPage(TffdshowPageDec *Iparent, const TfilterIDFF *idff); //初始化 virtual void init(void); //配置数据传入到对话框界面 virtual void cfg2dlg(void); virtual void translate(void); }; #endif
再看看Cbitmap.cpp文件吧。关键的代码都已经加上了注释。
/* * Copyright (c) 2004-2006 Milan Cutka * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ //Bitmap配置页面 #include "stdafx.h" #include "TsubtitlesSettings.h" #include "TbitmapSettings.h" #include "Cbitmap.h" //初始化 void TbitmapPage::init(void) { //设置滑动条范围 edLimitText(IDC_ED_BITMAP_FLNM, MAX_PATH); tbrSetRange(IDC_TBR_BITMAP_POSX, 0, 100, 10); tbrSetRange(IDC_TBR_BITMAP_POSY, 0, 100, 10); tbrSetRange(IDC_TBR_BITMAP_OPACITY, 0, 256); } //配置数据传入到对话框界面 void TbitmapPage::cfg2dlg(void) { //各种设置 //EditControl设置 setDlgItemText(m_hwnd, IDC_ED_BITMAP_FLNM, cfgGetStr(IDFF_bitmapFlnm)); pos2dlg(); cbxSetCurSel(IDC_CBX_BITMAP_ALIGN, cfgGet(IDFF_bitmapAlign)); cbxSetCurSel(IDC_CBX_BITMAP_MODE, cfgGet(IDFF_bitmapMode)); opacity2dlg(); } //Bitmap位置信息 void TbitmapPage::pos2dlg(void) { char_t s[260]; int x; //获取 x = cfgGet(IDFF_bitmapPosx); TsubtitlesSettings::getPosHoriz(x, s, this, IDC_LBL_BITMAP_POSX, countof(s)); setDlgItemText(m_hwnd, IDC_LBL_BITMAP_POSX, s); //设置 tbrSet(IDC_TBR_BITMAP_POSX, x); x = cfgGet(IDFF_bitmapPosy); TsubtitlesSettings::getPosVert(x, s, this, IDC_LBL_BITMAP_POSY, countof(s)); setDlgItemText(m_hwnd, IDC_LBL_BITMAP_POSY, s); tbrSet(IDC_TBR_BITMAP_POSY, x); } void TbitmapPage::opacity2dlg(void) { int o = cfgGet(IDFF_bitmapStrength); tbrSet(IDC_TBR_BITMAP_OPACITY, o); setText(IDC_LBL_BITMAP_OPACITY, _l("%s %i%%"), _(IDC_LBL_BITMAP_OPACITY), 100 * o / 256); } INT_PTR TbitmapPage::msgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_ED_BITMAP_FLNM: if (HIWORD(wParam) == EN_CHANGE && !isSetWindowText) { char_t flnm[MAX_PATH]; GetDlgItemText(m_hwnd, IDC_ED_BITMAP_FLNM, flnm, MAX_PATH); cfgSet(IDFF_bitmapFlnm, flnm); } return TRUE; } break; } return TconfPageDecVideo::msgProc(uMsg, wParam, lParam); } //设置文件路径 void TbitmapPage::onFlnm(void) { char_t flnm[MAX_PATH]; cfgGet(IDFF_bitmapFlnm, flnm, MAX_PATH); if (dlgGetFile(false, m_hwnd, _(-IDD_BITMAP, _l("Load image file")), _l("All supported (*.jpg,*.bmp,*.gif,*.png)\0*.bmp;*.jpg;*.jpeg;*.gif;*.png\0Windows Bitmap (*.bmp)\0*.bmp\0JPEG (*.jpg)\0*.jpg\0Compuserve Graphics Interchange (*.gif)\0*.gif\0Portable Network Graphics (*.png)\0*.png"), _l("bmp"), flnm, _l("."), 0)) { setDlgItemText(m_hwnd, IDC_ED_BITMAP_FLNM, flnm); //设置 cfgSet(IDFF_bitmapFlnm, flnm); } } void TbitmapPage::translate(void) { TconfPageBase::translate(); cbxTranslate(IDC_CBX_BITMAP_ALIGN, TsubtitlesSettings::alignments); cbxTranslate(IDC_CBX_BITMAP_MODE, TbitmapSettings::modes); } //构造函数 TbitmapPage::TbitmapPage(TffdshowPageDec *Iparent, const TfilterIDFF *idff): TconfPageDecVideo(Iparent, idff) { //各种绑定 resInter = IDC_CHB_BITMAP; static const TbindTrackbar<TbitmapPage> htbr[] = { IDC_TBR_BITMAP_POSX, IDFF_bitmapPosx, &TbitmapPage::pos2dlg, IDC_TBR_BITMAP_POSY, IDFF_bitmapPosy, &TbitmapPage::pos2dlg, IDC_TBR_BITMAP_OPACITY, IDFF_bitmapStrength, &TbitmapPage::opacity2dlg, 0, 0, NULL }; bindHtracks(htbr); static const TbindCombobox<TbitmapPage> cbx[] = { IDC_CBX_BITMAP_ALIGN, IDFF_bitmapAlign, BINDCBX_SEL, NULL, IDC_CBX_BITMAP_MODE, IDFF_bitmapMode, BINDCBX_SEL, NULL, 0 }; bindComboboxes(cbx); static const TbindButton<TbitmapPage> bt[] = { IDC_BT_BITMAP_FLNM, &TbitmapPage::onFlnm, 0, NULL }; bindButtons(bt); }
看ffdshow源代码的时候,开始会比较费劲。为什么?因为它使用了大量自己写的API函数,以及自己定义的结构体。这些API函数的种类繁多,如果一个一个都看完,估计就精疲力竭了。经过一段时间的学习之后,我发现最方便的方法还是根据函数名字推测其用法。因此我就不深入剖析ffdshow的API函数了。
以上源代码中包含以下API(大致按出现先后次序,可能没有例举全,在这里只是举例子):
edLimitText();//限制输入字符串长度 tbrSetRange();//设置滑动条范围 setDlgItemText();//设置组件名称 cbxSetCurSel();//设置下拉框当前选项 cfgGet();//从注册表中读取变量的值 tbrSet();//设置滑动条的值 bindHtracks();//绑定注册表变量和滑动条 bindComboboxes();//绑定注册表变量和下拉框 bindButtons();//绑定函数和按钮
从以上函数大致可以看出tbr***()基本上都是操作滑动条的,cbx***()基本上都是操作下拉框的,函数基本上可以从名称上理解其的意思。bind***()就是绑定注册表变量和控件的。注意ffdshow里面有注册表变量这么一个概念。这些变量的值存在系统的注册表里面,不会因为程序结束运行而消失。就目前我的观察来看,绝大部分注册表变量存的是一个整数值。这些注册表变量都以IDFF_xxx的名称预编译定义在ffdshow_constants.h头文件中。与MFC控件可以直接与CString,int等变量绑定不同,ffdshow控件只可以和注册表变量绑定。即每次运行的时候都从注册表加载变量的值到界面上。存储的时候把界面上的值存储到注册表中。
注:注册表变量如下所示(截取了一小段)
#define IDFF_filterBitmap 1650 #define IDFF_isBitmap 1651 #define IDFF_showBitmap 1652 #define IDFF_orderBitmap 1653 #define IDFF_fullBitmap 1654 #define IDFF_bitmapFlnm 1655 #define IDFF_bitmapPosx 1656 #define IDFF_bitmapPosy 1657 #define IDFF_bitmapPosmode 1658 #define IDFF_bitmapAlign 1659 #define IDFF_bitmapMode 1660 #define IDFF_bitmapStrength 1661
此外需要注意的是,ffdshow尽管包含了图形化的属性界面,却没有使用MFC类库,因而MFC的很多函数都不能使用,对此我还不甚了解为什么要这样,以后有机会要探究探究。
相关推荐
ffdshow 源代码分析 2: 位图覆盖滤镜(对话框部分 Dialog) 290 ffdshow 源代码分析 3: 位图覆盖滤镜(设置部分Settings) 297 ffdshow 源代码分析 4: 位图覆盖滤镜(滤镜部分Filter) 301 ffdshow 源代码分析 5...
ffdshow 源代码分析 2: 位图覆盖滤镜(对话框部分Dialog) 304 ffdshow 源代码分析 3: 位图覆盖滤镜(设置部分Settings) 312 ffdshow 源代码分析 4: 位图覆盖滤镜(滤镜部分Filter) 317 ffdshow 源代码分析 5:...
进入`trunk`目录,我们可以看到源代码的组织结构,通常包括以下部分: - **Source**:包含核心解码和处理的源代码。 - **Include**:头文件,定义了接口和数据结构。 - **Config**:配置文件,用于设置编译选项和...
5. **滤波器开发**:ffdshow源代码提供了一个很好的实例,展示了如何编写DirectShow滤波器,包括注册滤镜、实现滤镜接口、处理媒体样本等。 6. **编译与调试**:获取源代码后,开发者可以尝试在Visual Studio等环境...
开发者可以通过分析和修改FFDSHOW源代码,学习到以下知识点: - **视频和音频解码原理**:了解各种编码标准的内部工作方式,例如H.264的宏块解码、熵解码等。 - **DirectShow编程**:学习如何创建和使用...
通过分析ffdshow的源代码,开发者可以深入理解视频解码的底层原理,学习如何在DirectShow架构下实现自定义的滤镜和解码器。此外,源代码还提供了丰富的配置选项,允许用户自定义解码行为,例如改变视频质量、添加...
在本压缩包中,你将找到FFDShow在directshow下的源代码,这对于深入理解DirectShow架构以及H.264等现代视频编码技术具有重要的学习价值。 首先,我们来探讨一下FFDShow的主要功能。FFDShow主要负责在DirectShow播放...
2. `Doxyfile`:这是Doxygen配置文件,Doxygen是一个源代码文档生成工具,用于自动从源代码中提取注释,生成API文档。 3. `ffdshow.dsp`:这是一个Visual Studio项目文件,包含了FFDShow SDK的工程设置和编译选项。...
提到“ffdshow源代码中移植过来的”,这表明X264的某些部分或全部代码可能已经整合到了ffdshow项目中。ffdshow是一款著名的DirectShow滤镜,用于解码多种视频和音频格式,包括H.264。将X264集成到ffdshow中,可以...
描述中提到的“完整的FFDSHOW代码”意味着这个压缩包包含了FFDShow解码器的所有源代码,开发者可以通过这些源代码了解FFDShow的工作原理,甚至对其进行修改或扩展以适应特定需求。源代码通常对开发者来说是极其宝贵...
这个压缩包"ffdshow_source_2011_12_28 ffdshow源码(2011-12-28)"包含了2011年12月28日版本的ffdshow的源代码,对于开发者来说,这是一个宝贵的资源,可以深入了解其内部工作原理并进行二次开发或定制。 1. **...
总的来说,ffdshow代码是一个涵盖视频解码、画质优化和用户自定义功能的综合性工具。通过学习它的源码,开发者可以提升在视频处理领域的专业技能,同时也可以为自己的项目引入类似的功能。无论是对个人学习还是商业...
ffdshow和FFmpeg的部分模块就可能包含这样的优化代码。使用NASM,开发者可以更直接地控制处理器的行为,实现高效的编码和解码算法。 总的来说,这个压缩包提供了一个完整的ffdshow开发环境,包括了源码、SDK、开发...
在IT领域,开发一个能播放多种文件格式的播放器是一项技术性强且实用的任务。这个"多种文件播放器源代码"项目显然...通过学习和分析这个源代码,开发者不仅可以提升C++编程技能,还能了解多媒体处理领域的核心技术。
ffdshow的源码分析可以帮助开发者深入理解视频解码的过程,包括如何解析视频流、提取帧数据、进行颜色空间转换以及如何应用各种解码优化技术。对于想要自定义解码器功能或实现特定视频处理算法的开发者来说,这是一...
ffdshow的源代码采用C++编写,遵循LGPL许可协议,这意味着其他开发者可以自由地使用、修改和分发这个软件。由于其开源性质,ffdshow获得了社区的持续维护和支持,不断更新以适应新的编码标准和技术进步。此外,...
本文将详细探讨一款使用VC++编写的MP3播放器的源代码,该程序已经在VC6.0环境下通过编译,并且具有独特的界面设计和位图贴图功能。为了更好地理解这个项目,我们将从以下几个方面进行深入分析: 1. **VC++编程基础*...
ffdshow作为一款开源且免费的解码滤镜,它支持多种编码格式,如H.264、MPEG-4 ASP、DivX、Xvid等,极大地拓宽了用户可播放的视频类型。 ffdshow的工作原理是接收已编码的视频数据,然后将其转化为计算机可以理解和...
对于进阶用户来说,还可以编写自定义的滤镜和处理脚本来扩展ffdshow的功能。 在使用ffdshow时,需要注意的是,虽然它兼容多种格式,但并不意味着它可以解码所有的媒体文件。有些特殊的编码格式或者加密的媒体文件...
本项目以"视频播放源代码directshow开发"为主题,旨在分享一个基于DirectShow的简单视频播放器的实现,但需要注意的是,该播放器可能存在一些错误。 DirectShow的核心概念是过滤器(Filter),包括捕获、解码、...