注:写了一系列的有关ffdshow对解码器的封装的代码,列表如下:
ffdshow 源代码分析 6: 对解码器的dll的封装(libavcodec)
ffdshow 源代码分析 7: libavcodec视频解码器类(TvideoCodecLibavcodec)
ffdshow 源代码分析 8: 视频解码器类(TvideoCodecDec)
ffdshow 源代码分析 9: 编解码器有关类的总结

==========

前面两篇文章介绍了ffdshow中libavcodec的封装类Tlibavcodec,以及libavcodec的解码器类TvideoCodecLibavcodec:

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

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

其中libavcodec的解码器类TvideoCodecLibavcodec通过调用Tlibavcodec中的方法实现了libavcodec的dll中方法的调用;而它继承了TvideoCodecDec,本文正是要分析它继承的这个类。

TvideoCodecDec是所有视频解码器共有的父类。可以看一下它的继承关系:

可见,除了TvideoCodecLibavcodec继承了TvideoCodecDec之外,还有好几个类继承了TvideoCodecDec,比如说:TvideoCodecLibmpeg2,TvideoCodecXviD4等等…。突然来了兴趣,我们可以看一下其他的解码器类的定义是什么样的。

TvideoCodecLibmpeg2定义如下:

/* *雷霄骅 *leixiaohua1020@126.com *中国传媒大学/数字电视技术 */
#ifndef _TVIDEOCODECLIBMPEG2_H_
#define _TVIDEOCODECLIBMPEG2_H_#include "TvideoCodec.h"
#include "libmpeg2/include/mpeg2.h"class Tdll;
struct Textradata;
class TccDecoder;
//libmpeg2解码器
class TvideoCodecLibmpeg2 : public TvideoCodecDec
{
private:Tdll *dll;uint32_t (*mpeg2_set_accel)(uint32_t accel);mpeg2dec_t* (*mpeg2_init)(void);const mpeg2_info_t* (*mpeg2_info)(mpeg2dec_t *mpeg2dec);mpeg2_state_t (*mpeg2_parse)(mpeg2dec_t *mpeg2dec);void (*mpeg2_buffer)(mpeg2dec_t *mpeg2dec, const uint8_t *start, const uint8_t *end);void (*mpeg2_close)(mpeg2dec_t *mpeg2dec);void (*mpeg2_reset)(mpeg2dec_t *mpeg2dec, int full_reset);void (*mpeg2_set_rtStart)(mpeg2dec_t *mpeg2dec, int64_t rtStart);int (*mpeg2_guess_aspect)(const mpeg2_sequence_t * sequence, unsigned int * pixel_width, unsigned int * pixel_height);mpeg2dec_t *mpeg2dec;const mpeg2_info_t *info;bool wait4Iframe;int sequenceFlag;REFERENCE_TIME avgTimePerFrame;TffPict oldpict;Textradata *extradata;TccDecoder *ccDecoder;Tbuffer *buffer;uint32_t oldflags;bool m_fFilm;int SetDeinterlaceMethod(void);void init(void);HRESULT decompressI(const unsigned char *src, size_t srcLen, IMediaSample *pIn);protected:virtual bool beginDecompress(TffPictBase &pict, FOURCC infcc, const CMediaType &mt, int sourceFlags);public:TvideoCodecLibmpeg2(IffdshowBase *Ideci, IdecVideoSink *Isink);virtual ~TvideoCodecLibmpeg2();static const char_t *dllname;virtual int getType(void) const {return IDFF_MOVIE_LIBMPEG2;}virtual int caps(void) const {return CAPS::VIS_QUANTS;}virtual void end(void);virtual HRESULT decompress(const unsigned char *src, size_t srcLen, IMediaSample *pIn);virtual bool onSeek(REFERENCE_TIME segmentStart);virtual HRESULT BeginFlush();
};#endif

TvideoCodecXviD4定义如下:

/* *雷霄骅 *leixiaohua1020@126.com *中国传媒大学/数字电视技术 */
#ifndef _TVIDEOCODECXVID4_H_
#define _TVIDEOCODECXVID4_H_#include "TvideoCodec.h"class Tdll;
struct Textradata;
//xvid解码器
class TvideoCodecXviD4 : public TvideoCodecDec
{
private:void create(void);Tdll *dll;
public:TvideoCodecXviD4(IffdshowBase *Ideci, IdecVideoSink *IsinkD);virtual ~TvideoCodecXviD4();int (*xvid_global)(void *handle, int opt, void *param1, void *param2);int (*xvid_decore)(void *handle, int opt, void *param1, void *param2);int (*xvid_plugin_single)(void *handle, int opt, void *param1, void *param2);int (*xvid_plugin_lumimasking)(void *handle, int opt, void *param1, void *param2);static const char_t *dllname;
private:void *enchandle, *dechandle;int psnr;TffPict pict;Tbuffer pictbuf;static int me_hq(int rd3), me_(int me3);Textradata *extradata;REFERENCE_TIME rtStart, rtStop;
protected:virtual bool beginDecompress(TffPictBase &pict, FOURCC infcc, const CMediaType &mt, int sourceFlags);virtual HRESULT flushDec(void);
public:virtual int getType(void) const {return IDFF_MOVIE_XVID4;}virtual int caps(void) const {return CAPS::VIS_QUANTS;}virtual HRESULT decompress(const unsigned char *src, size_t srcLen, IMediaSample *pIn);
};#endif

从以上这2种解码器类的定义,我们可以看出一些规律,比如说:

1.  都有Tdll *dll这个变量,用于加载视频解码器的dll
2.  都有beginDecompress()函数,用于初始化解码器
3.  都有decompress()函数,用于解码

好了,闲话不说,回归正题,来看一下这些解码器共有的父类:TvideoCodecDec

//具体 视频 解码器的父类,存一些公共信息
class TvideoCodecDec : virtual public TvideoCodec, virtual public TcodecDec
{
protected:bool isdvdproc;comptrQ<IffdshowDecVideo> deciV;IdecVideoSink *sinkD;TvideoCodecDec(IffdshowBase *Ideci, IdecVideoSink *Isink);Rational guessMPEG2sar(const Trect &r, const Rational &sar2, const Rational &containerSar);class TtelecineManager{private:TvideoCodecDec* parent;int segment_count;int pos_in_group;struct {int fieldtype;int repeat_pict;REFERENCE_TIME rtStart;} group[2]; // store information about 2 recent frames.REFERENCE_TIME group_rtStart;bool film;int cfg_softTelecine;public:TtelecineManager(TvideoCodecDec* Iparent);void get_timestamps(TffPict &pict);void get_fieldtype(TffPict &pict);void new_frame(int top_field_first, int repeat_pict, const REFERENCE_TIME &rtStart, const REFERENCE_TIME &rtStop);void onSeek(void);} telecineManager;public:static TvideoCodecDec* initDec(IffdshowBase *deci, IdecVideoSink *Isink, AVCodecID codecId, FOURCC fcc, const CMediaType &mt);virtual ~TvideoCodecDec();virtual int caps(void) const {return CAPS::NONE;}virtual bool testMediaType(FOURCC fcc, const CMediaType &mt) {return true;}virtual void forceOutputColorspace(const BITMAPINFOHEADER *hdr, int *ilace, TcspInfos &forcedCsps) {*ilace = 0; //cspInfos of forced output colorspace, empty when entering function}enum {SOURCE_REORDER = 1};virtual bool beginDecompress(TffPictBase &pict, FOURCC infcc, const CMediaType &mt, int sourceFlags) = 0;virtual HRESULT decompress(const unsigned char *src, size_t srcLen, IMediaSample *pIn) = 0;virtual bool onDiscontinuity(void) {return false;}virtual HRESULT onEndOfStream(void) {return S_OK;}unsigned int quantsDx, quantsStride, quantsDy, quantBytes, quantType;//QP表void *quants;uint16_t *intra_matrix, *inter_matrix;//计算平均QPfloat calcMeanQuant(void);//画运动矢量virtual bool drawMV(unsigned char *dst, unsigned int dx, stride_t stride, unsigned int dy) const {return false;}virtual const char* get_current_idct(void) {return NULL;}virtual int useDXVA(void) {return 0;};virtual void setOutputPin(IPin * /*pPin*/) {}
};

TvideoCodecDec这个类中,还定义了一个类TtelecineManager。这种在类里面再定义一个类的方式还是不太多见的。TtelecineManager这个类的作用还没有研究,先不管它。

可以看出,TvideoCodecDec类的定义并不复杂,最主要的变量有如下几个,这几个变量都是子类中会用到的:

comptrQ<IffdshowDecVideo>deciV:重要性不言而喻,回头介绍
IdecVideoSink *sinkD:重要性不言而喻,回头介绍
void *quants:QP表(为什么要存在这里还没搞清)

TvideoCodecDec类定义了几个函数:

initDec():初始化解码器(重要)
calcMeanQuant():计算平均QP(为什么要在这里计算还没搞清)

TvideoCodecDec类还定义了一些纯虚函数,作为接口,这些函数的实现都在TvideoCodecDec的子类中完成【这几个函数是最重要的】:

beginDecompress();
decompress();

TvideoCodecDec类中最重要的函数只有一个,就是initDec(),作用主要是初始化解码器。其他的很多函数大多只是定义了一个名称,并没有实现,因为都是打算在具体各种解码器类中再进行实现的。

看一下initDec()的代码:

TvideoCodecDec* TvideoCodecDec::initDec(IffdshowBase *deci, IdecVideoSink *sink, AVCodecID codecId, FOURCC fcc, const CMediaType &mt)
{// DXVA mode is a preset settingswitch (codecId) {case AV_CODEC_ID_H264:if (deci->getParam2(IDFF_filterMode) & IDFF_FILTERMODE_VIDEODXVA) {if (deci->getParam2(IDFF_dec_DXVA_H264)) {codecId = CODEC_ID_H264_DXVA;} else {return NULL;}}break;case AV_CODEC_ID_VC1:case CODEC_ID_WMV9_LIB:if (deci->getParam2(IDFF_filterMode) & IDFF_FILTERMODE_VIDEODXVA) {if (deci->getParam2(IDFF_dec_DXVA_VC1)) {codecId = CODEC_ID_VC1_DXVA;} else {return NULL;}}break;default:break;}TvideoCodecDec *movie = NULL;if (is_quicksync_codec(codecId)) {movie = new TvideoCodecQuickSync(deci, sink, codecId);} else if (lavc_codec(codecId)) {movie = new TvideoCodecLibavcodec(deci, sink);} else if (raw_codec(codecId)) {movie = new TvideoCodecUncompressed(deci, sink);} else if (wmv9_codec(codecId)) {movie = new TvideoCodecWmv9(deci, sink);} else if (codecId == CODEC_ID_XVID4) {movie = new TvideoCodecXviD4(deci, sink);} else if (codecId == CODEC_ID_LIBMPEG2) {movie = new TvideoCodecLibmpeg2(deci, sink);} else if (codecId == CODEC_ID_AVISYNTH) {movie = new TvideoCodecAvisynth(deci, sink);} else if (codecId == CODEC_ID_H264_DXVA || codecId == CODEC_ID_VC1_DXVA) {movie = new TvideoCodecLibavcodecDxva(deci, sink, codecId);} else {return NULL;}if (!movie) {return NULL;}if (movie->ok && movie->testMediaType(fcc, mt)) {movie->codecId = codecId;return movie;} else if (is_quicksync_codec(codecId)) {// QuickSync decoder init failed, revert to internal decoder.switch (codecId) {case CODEC_ID_H264_QUICK_SYNC:codecId = AV_CODEC_ID_H264;break;case CODEC_ID_MPEG2_QUICK_SYNC:codecId = CODEC_ID_LIBMPEG2;break;case CODEC_ID_VC1_QUICK_SYNC:codecId = CODEC_ID_WMV9_LIB;break;default:ASSERT(FALSE); // this shouldn't happen!}delete movie;// Call this function again with the new codecId.return initDec(deci, sink, codecId, fcc, mt);} else {delete movie;return NULL;}
}

这个函数的功能还是比较好理解的,根据CodecID的不同,创建不同的解码器(从TvideoCodecLibavcodec,TvideoCodecXviD4,TvideoCodecLibmpeg2这些里面选择)。

虽然不知道用途是什么,但是我们可以顺便看一下计算平均QP的函数,就是把quants1指向的QP表里面的数据求了一个平均值:

//计算平均QP
float TvideoCodecDec::calcMeanQuant(void)
{if (!quants || !quantsDx || !quantsDy) {return 0;}unsigned int sum = 0, num = quantsDx * quantsDy;unsigned char *quants1 = (unsigned char*)quants;for (unsigned int y = 0; y < quantsDy; y++)for (unsigned int x = 0; x < quantsDx; x++) {sum += quants1[(y * quantsStride + x) * quantBytes];}return float(sum) / num;
}

转载于:https://www.cnblogs.com/leixiaohua1020/p/3901965.html

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. Media Player Classic - HC 源代码分析 4:核心类 (CMainFrame)(3)

    ===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...

  10. Media Player Classic - HC 源代码分析 3:核心类 (CMainFrame)(2)

    ===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...

最新文章

  1. php 上传乱码_如何解决php文件上传中文乱码问题
  2. SAP云平台上的ABAP编程环境里如何消费第三方服务
  3. 饼图的引导线怎么加_4步学会EXCEL复合条饼图制作方法,让统计结果更直观!
  4. mysql 写磁盘_图解MySQL | [原理解析] MySQL insert 语句的磁盘写入之旅
  5. jQuery - (JQuery datatables api 使用解读)
  6. 深度学习4线性回归,逻辑回归
  7. 工作75::一直报404
  8. 三星Galaxy A70s现身GeekBench数据库:搭载6400万像素传感器
  9. 修改服务器Apache-Coyote/1.1标识为自定义内容
  10. [转载]C#深拷贝的方法
  11. 位深度8位什么水平_佳能1DX3视频12位RAW拍摄和8位mp4拍摄的色彩有多大差别
  12. 文学类的论文真的不需要数据么?
  13. 嵌入式系统通信库设计
  14. 【计算机网络】实验报告一:验证性实验
  15. HSSFWorkbook EXCEL导出
  16. bitset和bitget
  17. 【GitHub学生包】2022年12月GitHub学生包最新申请教程 18次认证失败的经验之谈
  18. JQuery中$是什么?
  19. compiler java_使用JavaCompiler编译java源文件
  20. 广义相加模型(GAM)及R实现

热门文章

  1. Android Bluetooth HCI log 详解
  2. 远控开发记录02_手机定位
  3. “我爱淘”冲刺阶段Scrum站立会议9
  4. Word怎么转PDF?分享三种非常简单的方法
  5. 喜欢是可以培养的,学习也是
  6. 剑指offer整理(附python代码)——递归
  7. 第十七届全国大学智能汽车竞赛竞速比赛规则
  8. linux更新后不能进入系统,Ubuntu内核升级后无法进入系统的解决办法
  9. 【Unity3D】使用 FBX 格式的外部模型 ③ ( FBX 模型中的材质重映射 | FBX 模型使用外部材质 | FBX 模型的分解重组 )
  10. 大中型企业建立IT服务台的意义及实践