=====================================================

ffdshow源代码分析系列文章列表:

ffdshow 源代码分析 1: 整体结构

ffdshow 源代码分析 2: 位图覆盖滤镜(对话框部分Dialog)

ffdshow 源代码分析 3: 位图覆盖滤镜(设置部分Settings)

ffdshow 源代码分析 4: 位图覆盖滤镜(滤镜部分Filter)

ffdshow 源代码分析 5: 位图覆盖滤镜(总结)

ffdshow 源代码分析 6: 对解码器的dll的封装(libavcodec)

ffdshow 源代码分析 7: libavcodec视频解码器类(TvideoCodecLibavcodec)

ffdshow 源代码分析 8: 视频解码器类(TvideoCodecDec)

ffdshow 源代码分析 9: 编解码器有关类的总结

=====================================================

第一篇文章介绍了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)的更多相关文章

  1. ffdshow 源代码分析 5: 位图覆盖滤镜(总结)

    ===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...

  2. ffdshow 源代码分析 3: 位图覆盖滤镜(设置部分Settings)

    ===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...

  3. ffdshow 源代码分析 2: 位图覆盖滤镜(对话框部分Dialog)

    ===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...

  4. 转:ffdshow 源代码分析

    ffdshow神奇的功能:视频播放时显示运动矢量和QP FFDShow可以称得上是全能的解码.编码器.最初FFDShow只是mpeg视频解码器,不过现在他能做到的远不止于此.它能够解码的视频格式已经远 ...

  5. ffdshow 源代码分析 9: 编解码器有关类的总结

    ===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...

  6. ffdshow 源代码分析 8: 视频解码器类(TvideoCodecDec)

    ===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...

  7. ffdshow 源代码分析 7: libavcodec视频解码器类(TvideoCodecLibavcodec)

    ===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...

  8. ffdshow 源代码分析 6: 对解码器的dll的封装(libavcodec)

    ===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...

  9. ffdshow 源代码分析1 : 整体结构

    ffdshow是一个非常强大的DirectShow解码器,封装了ffmpeg,libmpeg2等解码库.它也提供了丰富的加工处理选项,可以锐化画面,调节画面的亮度等等.不止是视频,FFDShow现在同 ...

随机推荐

  1. Spark调度模式-FIFO和FAIR

    Spark中的调度模式主要有两种:FIFO和FAIR.默认情况下Spark的调度模式是FIFO(先进先出),谁先提交谁先执行,后面的任务需要等待前面的任务执行.而FAIR(公平调度)模式支持在调度池中 ...

  2. 二维码扫描&集合排序

    一.二维码扫描机制 二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的:在代码编制上巧妙地利用构 ...

  3. maven隐式依赖引起的包冲突

    包冲突 使用maven管理项目时可能会遇到包冲突的情况比如:log4j-over-slf4j.jar 和 slf4j-log4j12.jar这两个包同时一起运行时就会有问题. 这种冲突可能是显式依赖导 ...

  4. Windows平台下的多线程编程

    线程是进程的一条执行路径,它包含独立的堆栈和CPU寄存器状态,每个线程共享所有的进程资源,包括打开的文件.信号标识及动态分配的内存等.一个进程内的所有线程使用同一个地址空间,而这些线程的执行由系统调度 ...

  5. Android初级教程反射+AIDL+内容观察者监控黑名单号码代码模板

    对于想要拦截一些莫名的陌生号码,就需要电话拦截功能与删除其电话记录功能.拦截的主要业务逻辑,分别是在一个服务里面进行:1.注册电话监听:2.取消注册电话监听(当然注册于取消是在服务里面建立一个广播接收 ...

  6. Objc中为何某些类的属性要设置为copy而不是strong?

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 不知道大家是否注意,我们再使用一些第三方类的时候大多数情况下对 ...

  7. 05_MyBatis基于注解的开发

     要想开发基于注解的MyBatis应用.需要先写一个带有注解的接口. PersonDao.java的写法如下: package com.rl.dao; import java.util.List; ...

  8. Activity和Window的View的移动的一些思考与体会,腾讯悬浮小火箭的实现策略

    Activity和Window的View的移动的一些思考与体会,腾讯悬浮小火箭的实现策略 事实上写这个也是因为自己实际在项目中用到了才会去研究已经写文章,对于View的移动,其实说实话,已经有很多文章 ...

  9. Android开发学习之路--Content Provider之初体验

    天气说变就变,马上又变冷了,还好空气不错,阳光也不错,早起上班的车上的人也不多,公司来的同事和昨天一样一样的,可能明天会多一些吧,那就再来学习android吧.学了两个android的组件,这里学习下 ...

  10. Java-IO之BufferedInputStream(缓冲输入流)

    BufferedInputStream是缓冲输入流,继承于FilterInputStream,作用是为另一个输入流添加一些功能,本质上是通过一个内部缓冲数组实现的.例如,在新建某输入流对应的Buffe ...