ffdshow 源代码分析 4: 位图覆盖滤镜(滤镜部分Filter)
=====================================================
ffdshow源代码分析系列文章列表:
ffdshow 源代码分析 2: 位图覆盖滤镜(对话框部分Dialog)
ffdshow 源代码分析 3: 位图覆盖滤镜(设置部分Settings)
ffdshow 源代码分析 4: 位图覆盖滤镜(滤镜部分Filter)
ffdshow 源代码分析 6: 对解码器的dll的封装(libavcodec)
ffdshow 源代码分析 7: libavcodec视频解码器类(TvideoCodecLibavcodec)
ffdshow 源代码分析 8: 视频解码器类(TvideoCodecDec)
=====================================================
第一篇文章介绍了ffdshow的位图覆盖滤镜的对话框(Dialog)部分:ffdshow 源代码分析2 : 位图覆盖滤镜(对话框部分Dialog)
第二篇文章介绍了ffdshow的位图覆盖滤镜的设置(Settings)部分:ffdshow 源代码分析 3: 位图覆盖滤镜(设置部分Settings)
此外还有一个滤镜部分(Filter)。这三个部分就可以组成一个ffdshow的滤镜功能了。本文就来简介一下ffdshow的滤镜部分。
滤镜部分(Filter)
ffdshow的滤镜的滤镜部分(怎么感觉名字有点重复 = =,算了先这么叫吧)的功能主要用于完成具体的图像处理功能。具体到位图覆盖滤镜的话,就是用于把图片覆盖到视频上面,他是ffdshow滤镜的核心。
与位图覆盖(Bitmap)滤镜的滤镜处理有关的类位于imgFilters目录下的TimgFilterBitmap.h和TimgFilterBitmap.cpp文件中。
先来看看TimgFilterBitmap.h
这里要注意一下,该类的名字叫TimgFilterBitmap。它的声明方式确实比较奇怪:DECLARE_FILTER(TimgFilterBitmap, public, TimgFilter)
可以看出DECLARE_FILTER是一个宏,具体这个宏的内部代码就先不查看了,否则会感觉很混乱,暂且留下一个小小的谜团。在这里只要知道这是声明了一个滤镜类就可以了。
其实TimgFilterBitmap的核心函数不多,就一个,那就是process(),具体的处理功能都是在这个函数里面实现的。
/*
*雷霄骅
*leixiaohua1020@126.com
*中国传媒大学/数字电视技术
*/
#ifndef _TIMGFILTERBITMAP_H_
#define _TIMGFILTERBITMAP_H_
//叠加一张位图
#include "TimgFilter.h"
#include "Tfont.h"
struct TffPict;
struct TbitmapSettings;
//特别的声明方式 = =
DECLARE_FILTER(TimgFilterBitmap, public, TimgFilter)
private:
//图像
TffPict *bitmap;
//内存
Tbuffer bitmapbuf;
char_t oldflnm[MAX_PATH];
typedef void (*Tblendplane)(const TcspInfo &cspInfo, const unsigned int dx[3], const unsigned int dy[3], unsigned char *dst[3], const stride_t dststride[3], const unsigned char *src[3], const stride_t srcstride[3], int strength, int invstrength);
//注意 这个类有一个实例,名字叫w
class TrenderedSubtitleLineBitmap : public TrenderedSubtitleWordBase
{
public:
TrenderedSubtitleLineBitmap(void): TrenderedSubtitleWordBase(false) {}
TffPict *pict;
const TbitmapSettings *cfg;
//叠加
Tblendplane blend;
//打印
virtual void print(int startx, int starty /* not used */, unsigned int dx[3], int dy1[3], unsigned char *dstLn[3], const stride_t stride[3], const unsigned char *bmp[3], const unsigned char *msk[3], REFERENCE_TIME rtStart = REFTIME_INVALID) const;
} w;
TrenderedSubtitleLine l;
//是TrenderedSubtitleLine的一个vector
TrenderedSubtitleLines ls;
int oldmode;
//几种叠加方式
template<class _mm> static void blend(const TcspInfo &cspInfo, const unsigned int dx[3], const unsigned int dy[3], unsigned char *dst[3], const stride_t dststride[3], const unsigned char *src[3], const stride_t srcstride[3], int strength, int invstrength);
template<class _mm> static void add(const TcspInfo &cspInfo, const unsigned int dx[3], const unsigned int dy[3], unsigned char *dst[3], const stride_t dststride[3], const unsigned char *src[3], const stride_t srcstride[3], int strength, int invstrength);
template<class _mm> static void darken(const TcspInfo &cspInfo, const unsigned int dx[3], const unsigned int dy[3], unsigned char *dst[3], const stride_t dststride[3], const unsigned char *src[3], const stride_t srcstride[3], int strength, int invstrength);
template<class _mm> static void lighten(const TcspInfo &cspInfo, const unsigned int dx[3], const unsigned int dy[3], unsigned char *dst[3], const stride_t dststride[3], const unsigned char *src[3], const stride_t srcstride[3], int strength, int invstrength);
template<class _mm> static void softlight(const TcspInfo &cspInfo, const unsigned int dx[3], const unsigned int dy[3], unsigned char *dst[3], const stride_t dststride[3], const unsigned char *src[3], const stride_t srcstride[3], int strength, int invstrength);
template<class _mm> static void exclusion(const TcspInfo &cspInfo, const unsigned int dx[3], const unsigned int dy[3], unsigned char *dst[3], const stride_t dststride[3], const unsigned char *src[3], const stride_t srcstride[3], int strength, int invstrength);
//获取叠加方式
template<class _mm> static Tblendplane getBlend(int mode);
protected:
virtual bool is(const TffPictBase &pict, const TfilterSettingsVideo *cfg);
virtual uint64_t getSupportedInputColorspaces(const TfilterSettingsVideo *cfg) const
{
return FF_CSPS_MASK_YUV_PLANAR;
}
public:
TimgFilterBitmap(IffdshowBase *Ideci, Tfilters *Iparent);
virtual ~TimgFilterBitmap();
//核心函数(Filter配置信息队列,图像,配置信息)
virtual HRESULT process(TfilterQueue::iterator it, TffPict &pict, const TfilterSettingsVideo *cfg0);
};
#endif
再来看看TimgFilterBitmap.cpp
这个文件本身代码量是比较大的,只是其他部分我都还没有仔细分析,确实没那没多时间。。。在这里仅简要分析一下最核心的函数process()。正是这个函数真正实现了滤镜的功能。在这个位图叠加滤镜中,process()实现了位图在视频上面的叠加功能。
//核心函数(Filter配置信息队列,图像,配置信息)
HRESULT TimgFilterBitmap::process(TfilterQueue::iterator it, TffPict &pict, const TfilterSettingsVideo *cfg0)
{
//都有这一句= =
if (is(pict, cfg0)) {
//Bitmap的配置信息
const TbitmapSettings *cfg = (const TbitmapSettings*)cfg0;
init(pict, cfg->full, cfg->half);
unsigned char *dst[4];
bool cspChanged = getCurNext(FF_CSPS_MASK_YUV_PLANAR, pict, cfg->full, COPYMODE_DEF, dst);
//处理
if (!bitmap || cspChanged || stricmp(oldflnm, cfg->flnm) != 0) {
ff_strncpy(oldflnm, cfg->flnm, countof(oldflnm));
if (bitmap) {
delete bitmap;
}
//新建一张图
//通过cfg->flnm路径
//载入bitmapbuf
bitmap = new TffPict(csp2, cfg->flnm, bitmapbuf, deci);
//3个颜色分量?
for (int i = 0; i < 3; i++) {
w.dx[i] = bitmap->rectFull.dx >> bitmap->cspInfo.shiftX[i];
w.dy[i] = bitmap->rectFull.dy >> bitmap->cspInfo.shiftY[i];
w.bmp[i] = bitmap->data[i];
w.bmpmskstride[i] = bitmap->stride[i];
}
w.dxChar = w.dx[0];
w.dyChar = w.dy[0];
}
if (bitmap->rectFull.dx != 0) {
if (oldmode != cfg->mode)
if (Tconfig::cpu_flags & FF_CPU_SSE2) {
//获取叠加方式(SSE2)
//在cfg的mode里
w.blend = getBlend<Tsse2>(oldmode = cfg->mode);
} else {
//获取叠加方式(MMX)
w.blend = getBlend<Tmmx>(oldmode = cfg->mode);
}
//输出到屏幕上的设置
TprintPrefs prefs(deci, NULL);
//各种参数
prefs.dx = dx2[0];
prefs.dy = dy2[0];
prefs.xpos = cfg->posx;
prefs.ypos = cfg->posy;
//模式不同的话
if (cfg->posmode == 1) {
prefs.xpos *= -1;
prefs.ypos *= -1;
}
prefs.align = cfg->align;
prefs.linespacing = 100;
prefs.csp = pict.csp;
w.pict = &pict;
w.cfg = cfg;
//打印,需要用到TprintPrefs
ls.print(prefs, dst, stride2);
}
}
//最后都是这一句?
return parent->processSample(++it, pict);
}
ffdshow 源代码分析 4: 位图覆盖滤镜(滤镜部分Filter)的更多相关文章
- ffdshow 源代码分析 5: 位图覆盖滤镜(总结)
===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...
- ffdshow 源代码分析 3: 位图覆盖滤镜(设置部分Settings)
===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...
- ffdshow 源代码分析 2: 位图覆盖滤镜(对话框部分Dialog)
===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...
- 转:ffdshow 源代码分析
ffdshow神奇的功能:视频播放时显示运动矢量和QP FFDShow可以称得上是全能的解码.编码器.最初FFDShow只是mpeg视频解码器,不过现在他能做到的远不止于此.它能够解码的视频格式已经远 ...
- ffdshow 源代码分析 9: 编解码器有关类的总结
===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...
- ffdshow 源代码分析 8: 视频解码器类(TvideoCodecDec)
===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...
- ffdshow 源代码分析 7: libavcodec视频解码器类(TvideoCodecLibavcodec)
===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...
- ffdshow 源代码分析 6: 对解码器的dll的封装(libavcodec)
===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...
- ffdshow 源代码分析1 : 整体结构
ffdshow是一个非常强大的DirectShow解码器,封装了ffmpeg,libmpeg2等解码库.它也提供了丰富的加工处理选项,可以锐化画面,调节画面的亮度等等.不止是视频,FFDShow现在同 ...
随机推荐
- Linux telnet远程登录操作
telnet (如果不行 可以却换root帐户试试 su - root) 1.安装telnet-server sudo dpkg -i xinetd_1%3a2.3.14-7ubuntu3_ ...
- 仿qq最新侧滑菜单
为了后续对这个项目进行优化,比如透明度动画.背景图的位移动画,以及性能上的优化. 我把这个项目上传到github上面,请大家随时关注. github地址https://github.com/sungu ...
- Java基础---基础加强---增强for循环、自动拆装箱及享元、枚举的作用、实现带有构造方法、透彻分析反射的基础_Class类、成员变量的反射、数组参数的成员方法进行反射、数组的反射应用
在perference 加content Assist 可以设置快捷键 透视图与视图 透视图:Debug和java主窗口 视图:每一个小窗口就是视图 高版本的java可运行低版本的java版本 常见的 ...
- Unity插件 - MeshEditor(四) 模型融化特效
现在的电影里有很多妖魔在死亡后身体逐渐融化并下滑最后化为一滩黑水的情景,本次出于兴趣大致研究了这个效果,原理是控制模型的顶点向一个方向坍塌,坍塌到最低点时再根据法线方向扩散形成黑水状. 第一步: 添加 ...
- hashmap简单实例(个人使用经验)
一.HashMap<int,String>是错误的:因为int是基本类型,而key和value要求是对象,所以要用Integer而不是int.HashMap<String,Objec ...
- Android初级教程之内容提供者获取联系人信息
内容提供折详细理论知识请参考之前的博文:http://blog.csdn.net/qq_32059827/article/details/51646513 这里新建了三个联系人信息,通过查看系统联系人 ...
- volatile适用场合
volatile适用场合 要在多线程中安全的适用volatitle变量,必须同时满足: 1.对变量的写入操作不依赖其当前值 不满足:number++.count = count * 5等 ...
- 使用C++的string实现高精度加法运算
对于超大数字的运算,用long long int仍然不能解决,这时候就需要考虑通过模拟运算和数组存储来实现高精度运算. 本文讨论借助C++的string来实现高精度的运算. 首先输入的量直接存储为st ...
- Linux中的端口占用问题
本文将会阐述两种解决端口占用的方法. 本文会用到的服务器端的程序如下: #include "unp.h" #include <time.h> int main(int ...
- C#神器 委托 + Unity神器 协程
作为源生的C#程序员,可能已经非常了解委托(delegate).行动(Action)以及C#的事件了,不过作为一个半道转C#的程序员而言,这些东西可能还是有些陌生的,虽然委托并非是C#独创,亦非是首创 ...