当前位置:   article > 正文

开源项目之Splayer 射手影音播放器_dsm muxer

dsm muxer


Splayer
射手影音播放器)是一款高画面、低消耗、智能化、精致美观的影音播放器。

具有如下八个独创:

独创ShaderEngineTM图像增强引擎,4倍速驱动,降低画面噪点,锐利画质呈现,低画质视频照样全屏放
独创LiveColorTM彩色增强算法,画面色彩更艳丽
独创SmartAmplifyTM智能音场平衡技术,声效更显震撼

独创FastMotionTM解码优化技术,大幅降低CPU和内存占用。多核 SSE2 SSE3 MMX GPU优化
独创PowerTravelTM旅行节电模式,降低能耗,增加笔记本的巡航时间
独创EyeCareTM护眼模式,久看不疲劳,健康最重要

独创Anti-SillyTM智能免配置,数百逻辑分支自动根据硬件配置选择最佳模式。
独创CloudMatchingTM智能显示字幕技术,外语片从此不再需要找寻匹配字幕

Splayer 是一款开源项目,项目总共有87个工程(含测试工程),如图:


效果如图:




这是我目前接触最大的项目,刚接触时不知道如何下手,于是把所有的库都大致的分析了一遍,由于缺少资料所以很多分析都带有主观,难免有瑕疵,

但我然仍贴出来,以鼓励我继续研究,我计划把Splayer集成为一个视频播放的控件,现在计划已经进行了38%,但由于工作原因,这项计划被搁置了,

但我相信我会慢慢把它完成,因为我是一个码农,o(∩_∩)o 哈哈!~~~

2012tvod项目如图:



效果如图:




 进入主题了,由于Splayer项目过多,所以把它分成二个部分(主程序、类库),现在从类库开始分析了。

  1. libpng libpng是OSI认证开源软件,主要负责读写png文件。该库是用来创立和操作png格式的图像文件.png格式是设计来替代gif,他对于更小范围的tiff(标记图
  2. 象文件格式)。Splayer中类CPngIMage是对该库的应用,该类在libpng.h中。

  1. decss DVD解密源码,专门针对DVD安全机制设计的破解其内容混合系统的,利用decss的功能从网上下载DVD格式的数字电影,还可以用DivX软件将下载的数字电影
  2. 压缩存储到硬盘或光盘上。该类库需要用到BaseClasses库。 该库有五个类,分别是CDeCSSInputPin、CVobDec、CDVDSession、CLBAFile、CVobFile。
dsutil   directshow工具类库,主要负责视频处理、捕获应用…等操作。该类库需要用到BaseClasses库和foundation库。该库还有类:IDSMPropertyBagImpl 编码器选项设置接口、CDSMResource、IDSMResourceBagImpl、CDSMChapter、IDSMChapterBagImpl、CDSMChapterBag、CFontInstaller 字体的初始化、CGolombBuffer、CH264Nalu、CHdmvClipInfo、CMediaTypeEx、CNullRenderer、CNullVideoRenderer、CNullUVideoRenderer、CNullAudioRenderer、CNullUAudioRenderer、CNullTextRenderer、CCpuID。其中DSUtil.h 包含很多视频操作函数。

foundation  该库是一个辅助库,内含:base64编解码、同步类CriticalSection/AutoCSLock、文件路径操作类FilePath、信息输出类LogController、加载资源类ResLoader、定义字符串Strings、多线程辅助模块ThreadHelperImpl、实例生成模块LazyInstanceImpl。
id3lib 该库是用于读、写和操纵ID3v1和ID3v2标签的对于媒体类型的文件,它能够调用id3lib库来获取诸如作者,唱片年代,风格等tag信息,如果是视频媒体文件,它还会抓图。

libssf 该库为一个操作 影视字幕以及特效的类库。
lyriclib 该库为歌词匹配类库。
subpic 该库为操作位图类库(例如 字幕图片显示)。
sqlitepp 该库是一个C++封装的 SQLite组件,开源、免费。目的是使用面向对象的方式来简化SQLite的使用,具有面向对象的访问方式。程序将通过它生成数据库,该数据库是settings.db 负责记录设置信息。
subtitles 该库是操作视频字幕的库。
svplib  该库是一个 字幕获取功能库,内含:CSVPEqualizer、CSVPRarLib 压缩包rar文件操作、CSVPSubfilterLib、CSVPToolBox 文件路径操作类。
yaml-cpp 是一个 开源的YAML 解析器。
CmdUI 是一个界面设置属性的对话框
ResizableLib 为一个界面库,可以根据父窗口的位置和大小动态调整控件窗口的大小。
sizecbar 为实现浮动工具条!
TreePropSheet 为树控件目录即文件目录
Updater 程序的升级程序
libmad 该库是一个MPEG音频解码库,是一个高-品质的??的的的MPEG音频解码器。目前,它支持MPEG-1和MPEG-2扩展到较低的采样频率,以及所谓的MPEG 2.5格式,是一个独立库。

filters 该库是滤波函数库等,该库主要有程序类CFilterApp、CInternalPropertyPageWnd属性窗体、CInternalPropertyPage属性页、CInternalPropertyPageTempl模块、CPinInfoWnd。
liba52  该库是一个解码ATSC A/52流的库,还包括一个MPEG-1和MPEG-2节目流复用器(音频和视频)。编码的环绕立体声缩混  大多数用户明显增加任意缩混扬声器配置,并实施动态范围压缩。
libdts  该库是一个DTS相干声学解码器库 负责解码DTS相干声学流,用于一个跨平台的视频播放和流VLC媒体播放器。
zlib 该库是一个压缩算法的库,提供数据压缩用的函式库。
libfaad 该库是软高级音频(AAC)解码器,含丁苯橡胶解码。其中in_mp4 - Winamp的MPEG-4 AAC文件输入插件,QCD的 - 典型的球员的AAC插件,QCDMp4 - 典型的播放器MP4插件,XMMS - XMMS的AAC插件,MPEG4IP - 为MPEG4IP播放器插件。
libdirac 该库是一个开源的视频编解码器。它采用了传统的混合视频编解码器架构,是与小波转换而不是通常的块转换。运动补偿使用重叠的块,以减少区块会扰乱变换编码阶段的文物。
baseclasses 该库是DirectX 自带的一个库,是微软推出的一套基于Windows系统的多媒体应用程式接口APIs函式。
libflac   该库是FLAC文件解码器的一个库,是无损音频编解码器库。
libavcodec  该库是非常先进的音频/视频编解码库,用于各种类型声音/图像编解码,无法使用VS2008编译。
libvorbisidec 该库是Ogg文件编解码器。
libmpeg2 该库是一个解码MPEG-2和MPEG-1视频的库。
SyncClock   该库是同步卡与服务器的时间设置库,该库主要有:CSyncClock、CSyncClockFilter。
BaseMuxer 该库为输入/输出流混合器基库,合成器可将特定的音视频流合成为特定的媒体容器格式,并交给文件写滤镜写入到磁盘中,从而最终实现媒体格式的转换。特定的合成器需要与特定的音视频编码器配合才能起作用,只不过有些合成器比较挑食,只能容纳一种类型的音视频编码,而有些合成器胃口很好,可容纳的多种音视频编码,如WMV和ASF的合成器只能容纳下WMA音频和WMV视频,而AVI的合成器则可以容纳从非压缩的RGB视频及PCM音频到高压缩率的DivX视频及MP3音频,至于MKV和DSM的合成器,几乎算是万能合成器了,该库主要有CBaseMuxerFilter、CBaseMuxerInputPin、CBaseMuxerOutputPin、CBaseMuxerRawOutputPin。
DSMMuxer 介绍同上,该库主要有CDSMMuxerFilter类
MatroskaMuxer 介绍同上,是负责将音频流和视频流合成为MKV格式,但要输出,还需要一个文件写出滤镜(File writer),它负责把“Matroska Muxer”合成的结果写入到磁盘当中,该类库主要有CMatroskaMuxerInputPinCMatroskaMuxerOutputPinCMatroskaMuxerFilter等类
wavdest 主要用于将采集到的视频流写入到指定的文件,文件格式是.WAV。该库主要有CWavDestOutputPin、CWavDestFilter等类
streamdrivethru  该库是驱动流通过输入/输出引脚过滤器,该库主要有CStreamDriveThruInputPin、CStreamDriveThruOutputPin、CStreamDriveThruFilter等类。
AviSplitter  该库是AVI的滤镜分离器,默认用System的,因稳定性和兼容性最好;Gabest的可以读下载不完整的AVI文件;而Haali的支持多音轨的切换。该库涉及:BaseSplitter库、BaseClasses库,该库主要有:CAviFileCAviPlotterWndCAviReportWndCAviSplitterOutputPinCAviSplitterFilterCAviSourceFilter
basesplitter 该库是分词基类,该库涉及dsutil、unrar、AudioSwitcher类库,该库主要有:CAsyncFileReaderCAsyncUrlReader、Packet、CPacketQueue、CBaseSplitterInputPin、CBaseSplitterOutputPin、CBaseSplitterFilter、CBaseSplitterFile、CBaseSplitterFileEx、CMultiFiles
diracSplitter  该库是dirac滤镜分离器库,该库涉及:BaseSplitter库、BaseClasses库,该库主要有CDiracSplitterFilter、CDiracSourceFilter、CDiracVideoDecoder、CDiracSplitterFile。
DSMSplitter  该库是dsm滤镜分离器库,该库涉及:BaseSplitter库、BaseClasses库,该库主要有CDSMSplitterFilter、CDSMSourceFilter、CDSMSplitterFile等类。
EASplitter  该库是ea滤镜分离器库,该库涉及:BaseSplitter库、BaseClasses库、DSUtil库、ffmpeg库等,该库主要有CEAFile、CEASpliterFilter、CEASourceFilter。
flvsplitter  该库是flv滤镜分离器库,该库涉及:BaseSplitter库、BaseClasses库、DSUtil库、libVP62(flash vp6解码器)库,该库主要有CFLVSplitterFilter、CFLVSourceFilter、VP62
MatroskaSplitter 该库是MKV滤镜分离器库(MKV视频的分离器),该库主要涉及:BaseSplitter库、BaseClasses库、DSUtil库。该库类较多。
mp4splitter  该库是MP4滤镜分离器库,该库主要涉及:BaseSplitter库、BaseClasses库、DSUtil库、Zlib库。该库主要有:CMP4SplitterFilter、CMP4SourceFilter、CMPEG4VideoSplitterFilter、CMPEG4VideoSourceFilter、CMP4SplitterFile……等等。
MpaSplitter  该库是Mpa滤镜分离器库,该库主要涉及:BaseSplitter库BaseClasses库DSUtil库该库主要有:CMpaSplitterFilterCMpaSplitterFile等类
MpegSplitter  该库是MPEG滤镜分离器库,一个MPEG的分割工具,可将大尺寸MPEG文件分割成数个小尺寸的MPEG文件。该库主要涉及:BaseSplitter库、BaseClasses库、DSUtil库。该库主要有:CMpegSplitterFilterCMpegSourceFilterCMpegSplitterFileCMpegSplitterSettingsWnd等类。
WMVSpliter 该库为WMV滤镜分离器库,WMA是一种视频编码格式,该库主要有StreamOnAsyncReader、ptr_shared_count(线程安全的共享数)、StreamInput、WMFOutputPin(输出引脚,提供的解码器的压缩数据)、IEncapsulatedAccess(分配缓冲区WMF时,我们需要返回一个IMediaSample对象周围的包装/INSSBuffer的接口)、EncapsulateSample、WMFDemuxFilter(分析器过滤器本身)、
NutSplitter  该库主要涉及:BaseSplitter库BaseClasses库DSUtil库该库主要有:CNutFileCNutSplitterFilterCNutSourceFilter等类
OggSplitter  该库是Ogg滤镜分离器库,Ogg是一种新的音频压缩格式,类似于MP3等的音乐格式。该库主要涉及:BaseSplitter库、BaseClasses库、DSUtil库。该库主要有:OggPage类、COggFile类、OggPacket类、COggSplitterOutputPin类、COggVorbisOutputPin类、COggDirectShowOutputPin类、COggS treamOutputPin类、COggSplitterFilter类、COggSourceFilter类…等等。
RealMediaSplitter 该库是real滤镜分离器库,是real播放器为除realplay外播放器播放real格式,比如RM,RMVB等等格式的播放插件.有了这个插件,其他播放器才能够播放REAL格式的视频,音频等文件.
RoQSplitter 该库是分离式联轴器的旋转编码器,该库主要有CRoQSplitterFilter、CRoQSourceFilter、CRoQVideoDecoder、CRoQAudioDecoder等类。
ssfsplitter 该库是特效字幕d的滤镜分离器,该库主要有CSSFSplitterFilter、CSSFSourceFilter等类。
asyncreader 该库是读取网络上的编码后的视频数据库,读取后交给解码filter该库主要有:CAsyncStreamCAsyncIoCAsyncOutputPinCAsyncReader
cddareader 该库是开源滤镜MPC,DTS技术编码的音频具有细节丰富定位精确的特点,是传统CD和Dolby环绕声效的后继者该库主要有:CCDDAStreamCCDDAReader类
cdxareader  该库为系统滤镜,该库主要有CCDXAStream、CCDXAReader类。
udpreader   该库为系统滤镜,该库主要有CUDPStream、CUDPReader类。
vtsreader   该库为系统滤镜,该库主要有CVTSStream、CVTSReader类。
MpcAudioRenderer 该库为使用WASAPI音频输出MPC音频渲染器,该库主要有CMpcAudioRenderer类。
basesource  该库是解码文件的基础库,该库主要有:CBaseSource、CBaseStream等类。
dtsac3source该库是DTS/AC3输出滤镜的库,DTS(Digital Theater Systems)是一种高质量的多声道音频编码方式,目前主要用作DVD的伴音。DTS 5.1的最大码率(Bitrate)与LPCM(LPCM是数位非经压缩的声音规格,音质佳,所占容量空间较大)相同,可达1536Kbps,远高于目前另一种流行的多声道编码系统──Dolby Digital AC3448Kbps,虽然同样是有损压缩,但它可提供更为逼真,细节更为丰富的音响效果。用DVD中DTS音轨来制作音乐CD无疑是非常理想的。该库主要有:CDTSAC3Source、CDTSAC3Stream等类。
flicsource  该库是处理fli文件的库,主要有CFLICSourceCFLICStream等类
flacsource  该库是音频压缩编解码库,其特点是无损压缩不同于其他有损压缩编码如MP3AAC,它不会破坏任何原有的音频资讯,所以可以还原音乐光盘音质该库主要有:CFlacSourceCFlacStream类该库主要牵涉
shoutcastsource  该库是采用了MPEG Layer 3(MP3)技术,实现了因特网上的音频流的实时广播或者点播该库主要有:CShoutcastSourceCShoutcastStream等类
d2vsource 该库为d2v输出滤镜的库,d2v即数字化视频,该库主要有CMPEG2Dec、CD2VSource、CMPEG2Dec等类。
subtitlesource 该库为字幕输出滤镜的库,该库主要有CSubtitleSource、CSubtitleStream等类。
audioswitcher  该库是一个自动切换扬声器的库,涉及主程序的eqPerset负责设置音频,该库主要有:AudioStreamResamplerCAudioSwitcherFilterCStreamSwitcherPassThruCStreamSwitcherAllocatorCStreamSwitcherInputPinCStreamSwitcherOutputPinCStreamSwitcherFilter
Mpeg2DecFilter 该库是为测试程序是libmpeg2。它解码MPEG-1和MPEG-2视频流,还包括一个MPEG-1和MPEG-2解复用器节目流。该库牵涉:BaseVideoFilter.lib libmpeg2.lib dsutil.lib 等库,该库主要有:IMpeg2DecFilter接口、CMpeg2Info、CMpeg2Dec、CMpeg2DecFilter、CMpeg2DecInputPin、CMpeg2DecOutputPin、CSubpicInputPin、CMpe g2DecSettingsWnd等类。
avi2ac3filter 该库为AC3音效辅助插件库,目前DVDrip在制作音频部分时普遍采用两种方式:MP3格式压缩音轨和保留DVD中原有的AC3音频文件。一般来说,Windows操作系统已经自带了MP3的解码器——Fhg Radium MP3 codec,因此采用MP3格式做的DVDrip音频我们都可以听到。但对于以AC3音频文件制作的DVDrip,我们就只能看到图像而听不到声音了,该库主要有CAVI2AC3Filter类。
bufferfilter 该库为滤镜输出缓冲区库,该库主要有CBufferFilter、CBufferFilterOutputPin等类。
decssfilter 该库为CSS滤镜,对常规的CSS的一个扩展子集,可以使应用对象(文字,图片...)产生类似于PHOTOSHOP中的模糊,通透,边缘发光等效果。该库主要有CDeCSSFilter类。
Mpeg2DecFilter 该库为mpeg1、mpeg2解码过滤器,该库主要有CMpeg2Info、CMpeg2Dec、CMpeg2DecFilter、CMpeg2DecInputPin、CMpeg2DecOutputPin、CSubpicInputPin、CClosedCaptionOutputPin、CMpeg2DecSettingsWnd等类。
MpaDecFilter  该库为MPC H264/VC1硬解码器(主音频解码器),该库主要有CMpaDecFilterCMpaDecInputPinCMpaDecSettingsWnd等类
basevideofilter 该库为解码视频播放过滤器基库,该库主要有CBaseVideoFilter、CBaseVideoInputAllocator、CBaseVideoInputPin、CBaseVideoInputPin、CBaseVideoOutputPin等类。
MPCVideoDec 该库为主视频解码类库,该库主要有CMPCAudioDecFilterCMPCVideoDecFilterCMPCVideoDecSettingsWnd等类
svpfilter 该库为字幕滤镜类库,该库主要有CSVPSubFilter类。


mplayerc为主程序,主程序自绘控件,以及应用视频音频编解码播放,此处就简单的看看涉及视频播放主要有哪些类!

  1. //渲染操作图像基类 定义如下
  2. class CBaseGraph
  3. : public CUnknown
  4. , public IGraphBuilder2 //IGraphBuilder接口允许应用程序调用时的过滤器图表管理器试图建立一个完整的过滤器图表
  5. , public IMediaControl  //IMediaControl接口提供控制的数据流通过过滤器图的方法。它包括运行,暂停和停止图形的方法
  6. , public IMediaEventEx  //其中包含了用于检索事件通知和用于重写筛选器图形的默认事件处理的方法
  7. , public IMediaSeeking  //IMediaSeeking接口包含寻求内流的位置,并设置播放速度的方法
  8. , public IVideoWindow  //IVideoWindow接口设置视频窗口的属性。应用程序可以使用它来 ​​设置窗口的所有者窗口的位置和尺寸,和其他属性。
  9. , public IBasicVideo  //IBasicVideo接口设置视频属性,如目标和源矩形。
  10. , public IBasicAudio   //IBasicAudio接口控制音频流的音量和平衡。
  11. , public IAMOpenProgress    //IAMOpenProgress接口报告的文件打开操作的进度,使应用程序能够取消操作。
  12. , public IGraphEngine //渲染引擎接口
  1. //播放flash类
  2. class CShockwaveGraph : public CBaseGraph
  1. class CMacrovisionKicker
  2. : public CUnknown
  3. , public IKsPropertySet //IKsPropertySet接口的最初目的是作为一种有效的方式来设置和检索WDM驱动程序的设备属性,使用KSProxy翻译用户模式COM方法调用进入内核模式属性的WDM流类驱动程序所使用的设置
interface __declspec(uuid("165BE9D6-0929-4363-9BA3-580D735AA0F6")) IGraphBuilder2 : public IFilterGraph2
  1. //IFilterGraph2接口扩展IFilterGraph的的IGraphBuilder接口,其中包含建立过滤器图表的方法。
  2. //筛选器图形管理器实现了这个接口。应用程序可以使用它建立图表时,利用它提供的其他方法的优势。
class __declspec(uuid("96F3E0BE-1BA4-4E79-973D-191FE425C86B")) CDeinterlacerFilter : public CTransformFilter
  1. //CTransformFilter类是为实施变换过滤器的基类。这个类是专为实施变换过滤器与一个输入引脚和一个输出引脚。
  2. //它使用的输入引脚和输出引脚独立的分配器。要创建一个过滤器,数据处理,使用CTransInPlaceFilter类。
  1. //DX7分配器演示
  2. class CDX7AllocatorPresenter
  3. : public ISubPicAllocatorPresenterImpl //图像分配操作接口
  1. //DX9分配器演示
  2. class CDX9AllocatorPresenter
  3. : public ISubPicAllocatorPresenterImpl //图像分配操作接口
  1. //DXR分配器演示
  2. class CDXRAllocatorPresenter:
  3. public ISubPicAllocatorPresenterImpl //图像分配操作接口
  1. //EVR方式输出
  2. class COuterEVR:
  3. public CUnknown,
  4. public IVMRffdshow9,
  5. public IVMRMixerBitmap9, //使应用程序从位图或Direct3D表面上的视频流,混合静态图像,当使用视频混合渲染过滤器(VMR-9)。
  6. public IBaseFilter //IBaseFilter接口是DirectShow过滤器的主界面
  1. //EVR分配器演示
  2. class CEVRAllocatorPresenter:
  3. public CDX9AllocatorPresenter,
  4. public IMFGetService, //查询指定的服务接口的对象。
  5. public IMFTopologyServiceLookupClient, //初始化视频混合器或演示。此接口由混频器和演示,使他们能够增强视频渲染器(EVR)查询接口指针。
  6. public IMFVideoDeviceID, //返回视频渲染组件支持的设备标识符。实现此接口由混频器和增强视频渲染器(EVR)的主持人。
  7. public IMFVideoPresenter, //增强视频渲染器(EVR)提供了一个默认的视频演示,应用程序可以实现自定义的主持人。
  8. public IDirect3DDeviceManager9, //使两个线程共享相同的Direct3D 9设备,并提供访问的DirectX视频加速(DXVA)功能的设备。
  9. public IMFAsyncCallback, //回调接口的异步方法完成时通知应用程序。
  10. public IQualProp, //IQualProp接口提供视频渲染性能信息检索的方法。
  11. public IMFRateSupport, //查询范围的支持,包括反向播放的播放率。
  12. public IMFVideoDisplayControl, //控制如何增强型视频渲染器(EVR)显示视频。
  13. public IEVRTrustedVideoPlugin //1启用插件在增强视频渲染器(EVR)与保护媒体工作的组成部分。
  1. //映射过滤器
  2. class CFilterMapper2 :
  3. protected CUnknown,
  4. public IFilterMapper2 //注册和取消注册的过滤器,并在注册表中找到过滤器。
  1. //过滤器重叠 (找最近的过滤器)
  2. class FilterOverride
  1. //FG过滤器
  2. class CFGFilter
  1. //FG过滤器注册
  2. class CFGFilterRegistry :
  3. public CFGFilter
  1. //FG过滤器文件
  2. class CFGFilterFile :
  3. public CFGFilter
  1. //FG过滤器视频渲染
  2. class CFGFilterVideoRenderer :
  3. public CFGFilter
  1. //FG过滤器管理
  2. class CFGManager
  3. : public CUnknown
  4. , public IGraphBuilder2
  5. , public IGraphBuilderDeadEnd
  6. , public CCritSec //CCritSec类提供了一个线程锁。
  1. //添加过滤器
  2. class CFGManagerCustom : public CFGManager
  1. //视频播放时触发 寻找和链接过滤器
  2. class CFGManagerPlayer
  3. : public CFGManagerCustom
  1. //DVD播放时触发 添加对应的过滤器以及渲染图像
  2. class CFGManagerDVD
  3. : public CFGManagerPlayer
  1. //视频捕捉触发
  2. class CFGManagerCapture
  3. : public CFGManagerPlayer
  1. //合成器
  2. class CFGManagerMuxer
  3. : public CFGManagerCustom
  1. //FG聚合 可以根据riid查询对应的接口
  2. class CFGAggregator
  3. : public CUnknown
  1. //同步锁
  2. class CGenlock
  1. //QT视图操作接口
  2. interface __declspec(uuid("A6AE36F7-A6F2-4157-AF54-6599857E4E20")) IQTVideoSurface : public IUnknown
  1. //视频解码设置类 读取显卡信息
  2. class MPCVideoDecSetting
  1. //VMR9方式输出
  2. class COuterVMR9:
  3. public CUnknown,
  4. public IVideoWindow, //视频窗口接口
  5. public IBasicVideo2, //视频渲染过滤器和视频混合渲染过滤器实现这个接口,但通过过滤器图表管理器的应用程序接口暴露。
  6. public IVMRWindowlessControl, //IVMRWindowlessControl界面控制视频混合渲染过滤器(VMR-7)如何呈现在一个容器内窗口的视频流
  7. public IVMRffdshow9,
  8. public IVMRMixerBitmap9 //IVMRMixerBitmap9接口,使应用程序从位图或Direct3D表面上的视频流,混合静态图像,当使用视频混合渲染过滤器(VMR-9)
  1. //像素着色器编译器
  2. class CPixelShaderCompiler
  1. //QT7分配器演示
  2. class CQT7AllocatorPresenter
  3. : public CDX7AllocatorPresenter //
  4. , public IQTVideoSurface //qt视图操作接口
  1. //QT9分配器演示
  2. class CQT9AllocatorPresenter:
  3. public CDX9AllocatorPresenter,
  4. public IQTVideoSurface //QT视图操作接口
  1. //实现QuickTime多媒体文件播放
  2. class CQuicktimeWindow : public CPlayerWindow
  1. //QuickTime多媒体文件渲染
  2. class CQuicktimeGraph :
  3. public CBaseGraph,  //基类渲染
  4. public IVideoFrameStep //实现单帧前进后退
  1. //实现RealMedia多媒体文件播放
  2. class CRealMediaPlayer
  3. : public CUnknown
  4. , public IRMAErrorSink //错误处理接口
  5. , public IRMAClientAdviseSink //能够使 RealPlayer的上层感知内核中播放 状态的改变以及其他相关信息
  6. , public IRMAAuthenticationManager //可以控制网络上多个数码复合机的认证数据,并能对每个用户的认证数据进行简单有效的设置。
  7. , public IRMASiteSupplier //rma站点提供接口
  8. , public IRMAPassiveSiteWatcher //通过站点观察接口
  9. , public IRMAAudioHook //音频钩子接口
  1. //RealMedia媒体视频视图操作
  2. class CRealMediaVideoSurface
  3. : public CUnknown
  4. , public IRMAVideoSurface //视图操作接口
  1. //RM7分配器演示
  2. class CRM7AllocatorPresenter
  3. : public CDX7AllocatorPresenter
  4. , public IRMAVideoSurface //视图操作接口
  1. //RM9分配器演示
  2. class CRM9AllocatorPresenter:
  3. public CDX9AllocatorPresenter,
  4. public IRMAVideoSurface //RMA视图操作接口
  1. //VMR7分配器演示
  2. class CVMR7AllocatorPresenter
  3. : public CDX7AllocatorPresenter
  4. , public IVMRSurfaceAllocator //分配器演示使用这个接口进行通信的VMR
  5. , public IVMRImagePresenter //IVMRImagePresenter9接口来实现的默认分配器演示视频混合呈现过滤器(VMR-9),VMR-9使用此接口通知分配器演示的,它应该呈现的视频帧中所提供的Direct3D表面。
  6. , public IVMRWindowlessControl //显示窗口控制接口
  1. //VMR9分配器演示
  2. class CVMR9AllocatorPresenter
  3. : public CDX9AllocatorPresenter,
  4. public IVMRSurfaceAllocator9, //分配器演示使用这个接口进行通信的VMR
  5. public IVMRImagePresenter9, //IVMRImagePresenter9接口来实现的默认分配器演示视频混合呈现过滤器(VMR-9),VMR-9使用此接口通知分配器演示的,它应该呈现的视频帧中所提供的Direct3D表面。
  6. public IVMRWindowlessControl9 //显示窗口控制接口
  1. class __declspec(uuid("96F3E0BE-1BA4-4E79-973D-191FE425C86B")) CDeinterlacerFilter
  2. : public CTransformFilter // 用来浏览视频 时候旋转
  1. class __declspec(uuid("E2BA9B7B-B65D-4804-ACB2-89C3E55511DB")) CTextPassThruFilter :
  2. public CBaseFilter,
  3. public CCritSec


视频播放大致跟这些类/接口有关!

主程序是如何播放的?先来看看主程序的几个成员函数:

  1. // Operations 准备视频播放操作
  2. bool OpenMediaPrivate(CAutoPtr<OpenMediaData> pOMD);
  3. // 准备关闭当前视频操作
  4. void CloseMediaPrivate();
  5. //创建渲染对象
  6. void OpenCreateGraphObject(OpenMediaData* pOMD);
  7. //路径操作
  8. HRESULT OpenMMSUrlStream(CString szFn);
  9. //打开目标文件
  10. void OpenFile(OpenFileData* pOFD);
  11. //打开DVD
  12. void OpenDVD(OpenDVDData* pODD);
  13. //打开视频捕捉
  14. void OpenCapture(OpenDeviceData* pODD);
  15. //通用渲染
  16. void OpenCustomizeGraph();
  17. //初始化视频操作
  18. void OpenSetupVideo();
  19. //初始化音频操作
  20. void OpenSetupAudio();
这些函数进行了视频相关操作!~

当打开文件时触发

  1. m_pGraphThread = (CGraphThread*)AfxBeginThread(RUNTIME_CLASS(CGraphThread));
  2. if(m_pGraphThread)
  3. m_pGraphThread->SetMainFrame(this);
销毁时触发

  1. if(m_pGraphThread)
  2. {
  3. CAMEvent e;
  4. m_pGraphThread->PostThreadMessage(CGraphThread::TM_EXIT, 0, (LPARAM)&e);
  5. if(!e.Wait(5000))
  6. {
  7. TRACE(_T("ERROR: Must call TerminateThread() on CMainFrame::m_pGraphThread->m_hThread\n"));
  8. TerminateThread(m_pGraphThread->m_hThread, -1);
  9. }
  10. }

  1. 打开文件流程分析:
  2. void CMainFrame::OnFileOpenQuick()
  3. {
  4. 正在加载或列表未生成 则直接返回
  5. if(m_iMediaLoadState == MLS_LOADING || !IsWindow(m_wndPlaylistBar)) return;
  6. 近期文件列表
  7. CRecentFileList& MRU = AfxGetAppSettings().MRU;
  8. CString szLastFile; 最后一次看的视频文件
  9. MRU.ReadList(); 读取列表的文件路径
  10. if(MRU.GetSize() > 0){
  11. szLastFile = MRU[0]; 把读取的文件信息取出
  12. }
  13. CString filter;
  14. CAtlArray<CString> mask;
  15. 从设置里面读取过滤的设置
  16. AfxGetAppSettings().Formats.GetFilter(filter, mask);
  17. COpenFileDlg fd(mask, true, NULL, szLastFile,
  18. OFN_EXPLORER|OFN_ENABLESIZING|OFN_HIDEREADONLY|OFN_ALLOWMULTISELECT|OFN_ENABLEINCLUDENOTIFY,
  19. filter, this);
  20. if(fd.DoModal() != IDOK) return; 显示出打开文件对话框
  21. CAtlList<CString> fns;
  22. POSITION pos = fd.GetStartPosition();
  23. while(pos) fns.AddTail(fd.GetNextPathName(pos)); 把选中的文件加入进来
  24. bool fMultipleFiles = false;
  25. 判断是否多选 或选中的是目录
  26. if(fns.GetCount() > 1
  27. || fns.GetCount() == 1
  28. && (fns.GetHead()[fns.GetHead().GetLength()-1] == '\\'
  29. || fns.GetHead()[fns.GetHead().GetLength()-1] == '*'))
  30. {
  31. fMultipleFiles = true;
  32. }
  33. 猜测 关闭Media
  34. SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
  35. ShowWindow(SW_SHOW);
  36. SetForegroundWindow();
  37. 列表打开文件
  38. m_wndPlaylistBar.Open(fns, fMultipleFiles);
  39. 播放列表个数为一 且可见 并且不是自由的 则显示或隐藏
  40. if(m_wndPlaylistBar.GetCount() == 1 && m_wndPlaylistBar.IsWindowVisible() && !m_wndPlaylistBar.IsFloating())
  41. {
  42. ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
  43. }
  44. OpenCurPlaylistItem(); 打开当前列表选中项
  45. }
  46. 进入 OpenCurPlaylistItem 函数分析 参数为树节点 默认为零
  47. void CMainFrame::OpenCurPlaylistItem(REFERENCE_TIME rtStart)
  48. {
  49. 如果列表中没有 则直接退出
  50. if(m_wndPlaylistBar.GetCount() == 0) return;
  51. CPlaylistItem pli;
  52. 得到当前选中项 如果没有则选中第一项
  53. if(!m_wndPlaylistBar.GetCur(pli)) m_wndPlaylistBar.SetFirst();
  54. if(!m_wndPlaylistBar.GetCur(pli)) return;
  55. AppSettings& s = AfxGetAppSettings();
  56. if(rtStart == 0){
  57. CString fn;
  58. fn = pli.m_fns.GetHead(); 获得文件路径
  59. // SVP_LogMsg5(L"GetFav Start1 %s", fn);
  60. favtype ft ;
  61. ft = FAV_FILE;
  62. if (!fn.IsEmpty() && s.autoResumePlay){
  63. 文件存在 且 自动恢复播放
  64. std::string str = Strings::WStringToString(fn.GetBuffer());
  65. CString szMatchmd5 = HashController::GetInstance()->GetMD5Hash(str.c_str(), str.length()).c_str();
  66. SVP_LogMsg5(L"GetFav Start %s", szMatchmd5);
  67. CAtlList<CString> sl;
  68. s.GetFav(ft, sl, TRUE); 得到以前保存的数据
  69. CString PosStr ;
  70. POSITION pos = sl.GetHeadPosition(); 获得
  71. while(pos){ //判断以前是否播放过
  72. PosStr = sl.GetNext(pos) ;
  73. if( PosStr.Find(szMatchmd5 + _T(";")) == 0 ){
  74. break;
  75. }else{
  76. PosStr.Empty();
  77. }
  78. }
  79. if(!PosStr.IsEmpty()){ 如果未播放 则记录
  80. int iPos = PosStr.ReverseFind( _T(';') );
  81. if(iPos >= 0){
  82. CString s2 = PosStr.Right( PosStr.GetLength() - iPos - 1 );
  83. _stscanf(s2, _T("%I64d"), &rtStart); // pos
  84. }
  85. SVP_LogMsg5(L"Got %f", double(rtStart) );
  86. }
  87. 是否恢复退出时的状态
  88. m_is_resume_from_last_exit_point = TRUE;
  89. //SVP_LogMsg5(L"GetFav Done");
  90. }
  91. }else if(rtStart == -1){
  92. rtStart = 0;
  93. }
  94. 打开媒体文件 根据OpenMediaData*初始化 OpenMediaData里面保存了路径和rtStart
  95. CAutoPtr<OpenMediaData> p(m_wndPlaylistBar.GetCurOMD(rtStart));
  96. if(p) OpenMedia(p); 根据CAutoPtr<OpenMediaData> 进行打开播放
  97. }
  98. 进入OpenMedia进行 打开播放
  99. void CMainFrame::OpenMedia(CAutoPtr<OpenMediaData> pOMD)
  100. {
  101. // shortcut
  102. if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
  103. {
  104. 如果是DeviceData数据
  105. if(m_iMediaLoadState == MLS_LOADED && pAMTuner
  106. && m_VidDispName == p->DisplayName[0] && m_AudDispName == p->DisplayName[1])
  107. {
  108. m_wndCaptureBar.m_capdlg.SetVideoInput(p->vinput);
  109. m_wndCaptureBar.m_capdlg.SetVideoChannel(p->vchannel);
  110. m_wndCaptureBar.m_capdlg.SetAudioInput(p->ainput);
  111. return;
  112. }
  113. }
  114. 如果当前正在播放则关闭
  115. if(m_iMediaLoadState != MLS_CLOSED)
  116. CloseMedia();
  117. 更改状态
  118. m_iMediaLoadState = MLS_LOADING; // HACK: hides the logo
  119. m_wndView.Invalidate();
  120. AppSettings& s = AfxGetAppSettings();
  121. bool fUseThread = true;
  122. if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p))
  123. {
  124. 如果是打开的文件
  125. if(p->fns.GetCount() > 0)
  126. {
  127. 解码类型
  128. engine_t e = s.Formats.GetEngine(p->fns.GetHead());
  129. 如果是DirectShow 类型 只有.ram .rm .ra .qt .mov .ram 不需要
  130. fUseThread = e == DirectShow /*|| e == RealMedia || e == QuickTime*/;
  131. }
  132. }
  133. else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
  134. {
  135. fUseThread = false;
  136. }
  137. 如果渲染线程存在 且 需要使用线程 且 需要打开工作线程
  138. if(m_pGraphThread && fUseThread&&AfxGetAppSettings().fEnableWorkerThreadForOpening)
  139. m_pGraphThread->PostThreadMessage(CGraphThread::TM_OPEN, 0, (LPARAM)pOMD.Detach());
  140. else
  141. OpenMediaPrivate(pOMD);
  142. }
  143. 进入 CGraphThread::TM_OPEN 事件 用一个新的线程打开播放文件
  144. void CGraphThread::OnOpen(WPARAM wParam, LPARAM lParam)
  145. {
  146. if(m_pMainFrame)
  147. {
  148. CAutoPtr<OpenMediaData> pOMD((OpenMediaData*)lParam);
  149. m_pMainFrame->OpenMediaPrivate(pOMD);
  150. }
  151. }
  152. 进入OpenMediaPrivate 分析
  153. bool CMainFrame::OpenMediaPrivate(CAutoPtr<OpenMediaData> pOMD)
  154. {
  155. CString err, aborted(_T("Aborted"));
  156. AppSettings& s = AfxGetAppSettings(); 获得设置信息
  157. {
  158. 打开关闭锁
  159. CAutoLock mOpenCloseLock(&m_csOpenClose);
  160. s.bIsIVM = false;
  161. s.szCurrentExtension.Empty();
  162. 如果状态不是关闭 且 不是正在加载 则出错
  163. 一定要是加载状态 或是关闭状态
  164. if(m_iMediaLoadState != MLS_CLOSED && m_iMediaLoadState != MLS_LOADING)
  165. {
  166. ASSERT(0);
  167. return(false);
  168. }
  169. s.bExternalSubtitleTime = false;
  170. 设置Slider
  171. m_wndSeekBar.SetRange(0, 100);
  172. 记录
  173. s.szFGMLog.Empty();
  174. 设置声道
  175. s.SetNumberOfSpeakers(s.iDecSpeakers , -1);
  176. 正在加载状态
  177. m_iMediaLoadState = MLS_LOADING;
  178. 2.5秒加载
  179. SetTimer(TIMER_LOADING, 2500, NULL);
  180. 不显示关闭
  181. // FIXME: Don't show "Closed" initially
  182. PostMessage(WM_KICKIDLE); 调用主线程更新的东西
  183. m_fUpdateInfoBar = false;
  184. try
  185. {
  186. 打开终止 异常
  187. if(m_fOpeningAborted) throw aborted;
  188. if(OpenFileData* pOFD = dynamic_cast<OpenFileData*>(pOMD.m_p))
  189. {
  190. 文件不存在异常
  191. if(pOFD->fns.IsEmpty()) throw ResStr(IDS_MSG_THROW_FILE_NOT_FOUND);
  192. CString fn = pOFD->fns.GetHead();
  193. 取出格式
  194. s.szCurrentExtension = fn.Right(4).MakeLower();
  195. 格式比较
  196. .ivm格式
  197. if(s.szCurrentExtension == _T(".ivm"))
  198. s.bIsIVM = true;
  199. s.bDisableSoftCAVCForce = false;
  200. .mkv格式
  201. if(!(s.useGPUAcel && s.bHasCUDAforCoreAVC) && !s.bDisableSoftCAVC
  202. && s.szCurrentExtension == _T(".mkv"))
  203. {
  204. FILE* fp;
  205. if ( _wfopen_s( &fp, fn, _T("rb")) == 0)
  206. {
  207. char matchbuf[0x4000];
  208. size_t iRead = fread(matchbuf, sizeof( char ), 0x4000 ,fp);
  209. if( iRead > 200 && find_string_in_buf(matchbuf, iRead-100, "wpredp=2") > 0 )
  210. s.bDisableSoftCAVCForce = true;
  211. fclose(fp);
  212. }
  213. }
  214. int i = fn.Find(_T(":\\"));
  215. if(i > 0)
  216. {
  217. 判断文件所在盘
  218. CString drive = fn.Left(i+2);
  219. UINT type = GetDriveType(drive);
  220. CAtlList<CString> sl;
  221. 可移动的 驱动
  222. if(type == DRIVE_REMOVABLE || type == DRIVE_CDROM && GetCDROMType(drive[0], sl) != CDROM_Audio)
  223. {
  224. int ret = IDRETRY;
  225. while(ret == IDRETRY)
  226. {
  227. WIN32_FIND_DATA findFileData;
  228. HANDLE h = FindFirstFile(fn, &findFileData);
  229. if(h != INVALID_HANDLE_VALUE)
  230. {
  231. FindClose(h);
  232. ret = IDOK;
  233. }
  234. else
  235. {
  236. CString msg;
  237. msg.Format(ResStr(IDS_MSG_WARN_NOT_FOUND_AND_PLS_INSERT_DISK), fn);
  238. ret = AfxMessageBox(msg, MB_RETRYCANCEL);
  239. }
  240. }
  241. if(ret != IDOK) throw aborted;
  242. }else{
  243. 否则是本地盘 判断文件是否存在
  244. CSVPToolBox svpTool;
  245. if(!svpTool.ifFileExist(fn, true)){
  246. //SVP_LogMsg5(L"SVP 文件不存在" );
  247. throw ResStr(IDS_MSG_THROW_FILE_NOT_EXIST);
  248. }
  249. }
  250. }
  251. }
  252. 打开终止异常
  253. if(m_fOpeningAborted) throw aborted;
  254. 创建渲染对象 关键一
  255. OpenCreateGraphObject(pOMD); 待分析
  256. 打开终止异常
  257. if(m_fOpeningAborted) throw aborted;
  258. m_pCAP2 = NULL;
  259. m_pCAP = NULL;
  260. m_pSVPSub = NULL;
  261. 判断打开的文件的类型 待分析
  262. if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p)) OpenFile(p);
  263. else if(OpenDVDData* p = dynamic_cast<OpenDVDData*>(pOMD.m_p)) OpenDVD(p);
  264. else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p)) OpenCapture(p);
  265. else throw _T("Can't open, invalid input parameters");
  266. 查找相关接口
  267. pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP, FALSE);
  268. pGB->FindInterface(__uuidof(ISubPicAllocatorPresenterRender), (void**)&m_pCAPR, TRUE);
  269. pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter2), (void**)&m_pCAP2, TRUE);
  270. pGB->FindInterface(__uuidof(IVMRMixerControl9),(void**)&m_pMC, TRUE);
  271. 如果未找到 则用另外一种方法查找
  272. if(!m_pCAP){
  273. CComQIPtr<ISubPicAllocatorPresenter> pCAP = FindFilter(__uuidof(CSVPSubFilter), pGB);
  274. if(pCAP){
  275. m_pCAP = pCAP;
  276. CComQIPtr<ISVPSubFilter> pSVPSub= pCAP;
  277. if(pSVPSub)
  278. m_pSVPSub = pSVPSub;
  279. }
  280. }
  281. 如果找到 则进行相关操作
  282. if (m_pMC)
  283. {
  284. if (SetVMR9ColorControl(s.dBrightness, s.dContrast, s.dHue, s.dSaturation) == FALSE)
  285. OsdMsg_SetShader();
  286. else
  287. {
  288. CString szMsg;
  289. szMsg.Format(ResStr(IDS_OSD_MSG_BRIGHT_CONTRAST_CHANGED), s.dBrightness, s.dContrast);
  290. SendStatusMessage(szMsg, 3000);
  291. }
  292. SetShaders(true);
  293. }
  294. // === EVR !
  295. pGB->FindInterface(__uuidof(IMFVideoDisplayControl), (void**)&m_pMFVDC, TRUE);
  296. if (m_pMFVDC)
  297. {
  298. RECT Rect;
  299. ::GetClientRect (m_wndView.m_hWnd, &Rect);
  300. m_pMFVDC->SetVideoWindow (m_wndView.m_hWnd);
  301. m_pMFVDC->SetVideoPosition(NULL, &Rect);
  302. }
  303. 打开终止异常
  304. if(m_fOpeningAborted) throw aborted;
  305. 打开自定义大小的图像
  306. OpenCustomizeGraph(); 待分析
  307. 打开终止异常
  308. if(m_fOpeningAborted) throw aborted;
  309. 打开初始化视频
  310. OpenSetupVideo(); 待分析
  311. 打开终止异常
  312. if(m_fOpeningAborted) throw aborted;
  313. 打开初始化音频
  314. OpenSetupAudio(); 待分析
  315. 打开终止异常
  316. if(m_fOpeningAborted) throw aborted;
  317. 打开终止异常
  318. if(m_fOpeningAborted) throw aborted;
  319. 改变声道
  320. if(m_iAudioChannelMaping)
  321. OnAudioChannalMapMenu(IDS_AUDIOCHANNALMAPNORMAL+m_iAudioChannelMaping); 待分析
  322. 加载完毕
  323. m_iMediaLoadState = MLS_LOADED;
  324. 记录开始播放时间
  325. time(&m_tPlayStartTime);
  326. 发送暂停消息
  327. PostMessage(WM_COMMAND, ID_PLAY_PAUSE); 待分析
  328. 如果是打开 则发送播放消息
  329. if(!(AfxGetAppSettings().nCLSwitches&CLSW_OPEN))
  330. PostMessage(WM_COMMAND, ID_PLAY_PLAY); 待分析
  331. AfxGetAppSettings().nCLSwitches &= ~CLSW_OPEN;
  332. if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p))
  333. {
  334. 如果有记录 则跳到记录位置
  335. if(p->rtStart > 0)
  336. PostMessage(WM_RESUMEFROMSTATE, (WPARAM)PM_FILE, (LPARAM)(p->rtStart/10000)); // REFERENCE_TIME doesn't fit in LPARAM under a 32bit env.
  337. }
  338. else if(OpenDVDData* p = dynamic_cast<OpenDVDData*>(pOMD.m_p))
  339. {
  340. if(p->pDvdState)
  341. PostMessage(WM_RESUMEFROMSTATE, (WPARAM)PM_DVD, (LPARAM)(CComPtr<IDvdState>(p->pDvdState).Detach())); // must be released by the called message handler
  342. }
  343. else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD.m_p))
  344. {
  345. m_wndCaptureBar.m_capdlg.SetVideoInput(p->vinput);
  346. m_wndCaptureBar.m_capdlg.SetVideoChannel(p->vchannel);
  347. m_wndCaptureBar.m_capdlg.SetAudioInput(p->ainput);
  348. }
  349. 进行加载字幕
  350. if(m_pCAP && (!m_fAudioOnly || m_fRealMediaGraph))
  351. {
  352. POSITION pos = pOMD->subs.GetHeadPosition();
  353. while(pos){ LoadSubtitle(pOMD->subs.GetNext(pos));}
  354. }
  355. 当前进程是不是主线程
  356. if(::GetCurrentThreadId() == AfxGetApp()->m_nThreadID)
  357. {
  358. OnFilePostOpenmedia();
  359. }
  360. else
  361. {
  362. PostMessage(WM_COMMAND, ID_FILE_POST_OPENMEDIA); 待分析
  363. }
  364. 初始化标题
  365. OpenSetupWindowTitle(pOMD->title); 待分析
  366. 初始化打开时间
  367. time_t tOpening = time(NULL);
  368. 当状态不是加载完成或正在加载 则循环 还在加载前则循环
  369. while(m_iMediaLoadState != MLS_LOADED
  370. && m_iMediaLoadState != MLS_CLOSING // FIXME
  371. )
  372. {
  373. if( (time(NULL) - tOpening) > 10)
  374. throw aborted;
  375. Sleep(50);
  376. }
  377. }
  378. catch(LPCTSTR msg)
  379. {
  380. err = msg;
  381. }
  382. catch(CString msg)
  383. {
  384. err = msg;
  385. }
  386. }
  387. if(!err.IsEmpty())
  388. {
  389. 存在错误
  390. SendStatusMessage(err, 3000);
  391. CloseMediaPrivate();
  392. m_closingmsg = err;
  393. OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD.m_p);
  394. if(p && err != aborted)
  395. {
  396. m_wndPlaylistBar.SetCurValid(false);
  397. if(m_wndPlaylistBar.GetCount() > 1)
  398. {
  399. CPlaylistItem pli[2];
  400. m_wndPlaylistBar.GetCur(pli[0]);
  401. m_wndPlaylistBar.SetNext();
  402. m_wndPlaylistBar.GetCur(pli[1]);
  403. if(pli[0].m_id != pli[1].m_id)
  404. {
  405. //CAutoPtr<OpenMediaData> p(m_wndPlaylistBar.GetCurOMD());
  406. //if(p) OpenMediaPrivate(p);
  407. }
  408. }
  409. }
  410. }
  411. else
  412. {
  413. m_wndPlaylistBar.SetCurValid(true); 列表设置
  414. }
  415. 调用主线程更新的东西
  416. PostMessage(WM_KICKIDLE); // calls main thread to update things
  417. return(err.IsEmpty());
  418. }
  419. ————————————————————————————————————————————
  420. 2.5秒 循环载入
  421. case TIMER_LOADING:
  422. {
  423. KillTimer(TIMER_LOADING);
  424. if (IsSomethingLoading())
  425. {
  426. SetTimer( TIMER_LOADING , 1000, NULL);
  427. CString msg;
  428. if (m_fBuffering)
  429. {
  430. BeginEnumFilters(pGB, pEF, pBF)
  431. {
  432. if (CComQIPtr<IAMNetworkStatus, &IID_IAMNetworkStatus> pAMNS = pBF)
  433. {
  434. long BufferingProgress = 0;
  435. if (SUCCEEDED(pAMNS->get_BufferingProgress(&BufferingProgress)) && BufferingProgress > 0 && BufferingProgress < 99)
  436. {
  437. msg.Format(ResStr(IDS_CONTROLS_BUFFERING), BufferingProgress);
  438. SendStatusMessage(msg,1000);
  439. SVP_LogMsg5(msg);
  440. }
  441. break;
  442. }
  443. }
  444. EndEnumFilters
  445. }
  446. else if (pAMOP)
  447. {
  448. __int64 t = 0, c = 0;
  449. if (SUCCEEDED(pAMOP->QueryProgress(&t, &c)) && t > 0 && c < t)
  450. {
  451. msg.Format(ResStr(IDS_CONTROLS_BUFFERING), c*100/t);
  452. SendStatusMessage(msg,1000);
  453. SVP_LogMsg5(msg);
  454. }
  455. }
  456. else
  457. SendStatusMessage(ResStr(IDS_CONTROLS_OPENING), 1000);
  458. }
  459. }
  460. break;
  461. 进入CMainFrame::OpenCreateGraphObject 分析
  462. void CMainFrame::OpenCreateGraphObject(OpenMediaData* pOMD)
  463. {
  464. 解码接口不为空
  465. ASSERT(pGB == NULL);
  466. m_fCustomGraph = false;
  467. m_fRealMediaGraph = m_fShockwaveGraph = m_fQuicktimeGraph = false;
  468. AppSettings& s = AfxGetAppSettings();
  469. if(OpenFileData* p = dynamic_cast<OpenFileData*>(pOMD))
  470. {
  471. 获得解码类型
  472. engine_t engine = s.Formats.GetEngine(p->fns.GetHead());
  473. std::wstring ct = ContentType::Get(p->fns.GetHead());
  474. if(ct == L"video/x-ms-asf")
  475. {
  476. // TODO: put something here to make the windows media source filter load later
  477. }
  478. else if (ct == L"audio/x-pn-realaudio"
  479. || ct == L"audio/x-pn-realaudio-plugin"
  480. || ct == L"audio/x-realaudio-secure"
  481. || ct == L"video/vnd.rn-realvideo-secure"
  482. || ct == L"application/vnd.rn-realmedia"
  483. || ct.find(L"vnd.rn-") != ct.npos
  484. || ct.find(L"realaudio") != ct.npos
  485. || ct.find(L"realvideo") != ct.npos)
  486. {
  487. // TODO: go fuck this!!!
  488. engine = RealMedia;
  489. }
  490. else if (ct == L"application/x-shockwave-flash")
  491. {
  492. engine = ShockWave;
  493. }
  494. else if (ct == L"video/quicktime"
  495. || ct == L"application/x-quicktimeplayer")
  496. {
  497. engine = QuickTime;
  498. }
  499. if (engine == RealMedia)
  500. engine = DirectShow;
  501. SVP_LogMsg5(L"got content type %s %d", ct.c_str(), engine );
  502. HRESULT hr;
  503. CComPtr<IUnknown> pUnk;
  504. if(engine == RealMedia)
  505. {
  506. if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CRealMediaGraph(m_wndView.m_hWnd, hr)))
  507. throw _T("Out of memory");
  508. if(SUCCEEDED(hr) && !!(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
  509. m_fRealMediaGraph = true;
  510. }
  511. else if(engine == ShockWave)
  512. {
  513. if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CShockwaveGraph(m_wndView.m_hWnd, hr)))
  514. throw _T("Out of memory");
  515. if(FAILED(hr) || !(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
  516. throw _T("Can't create shockwave control");
  517. m_fShockwaveGraph = true;
  518. }
  519. else if(engine == QuickTime)
  520. {
  521. if(!(pUnk = (IUnknown*)(INonDelegatingUnknown*)new CQuicktimeGraph(m_wndView.m_hWnd, hr)))
  522. throw _T("Out of memory");
  523. if(SUCCEEDED(hr) && !!(pGB = CComQIPtr<IGraphBuilder>(pUnk)))
  524. m_fQuicktimeGraph = true;
  525. }
  526. m_fCustomGraph = m_fRealMediaGraph || m_fShockwaveGraph || m_fQuicktimeGraph;
  527. if(!m_fCustomGraph)
  528. {
  529. 视频播放解码 生成接口
  530. pGB = new CFGManagerPlayer(_T("CFGManagerPlayer"), NULL, s.SrcFilters, s.TraFilters, m_wndView.m_hWnd);
  531. }
  532. }
  533. else if(OpenDVDData* p = dynamic_cast<OpenDVDData*>(pOMD))
  534. {
  535. pGB = new CFGManagerDVD(_T("CFGManagerDVD"), NULL, s.SrcFilters, s.TraFilters, m_wndView.m_hWnd);
  536. }
  537. else if(OpenDeviceData* p = dynamic_cast<OpenDeviceData*>(pOMD))
  538. {
  539. pGB = new CFGManagerCapture(_T("CFGManagerCapture"), NULL, s.SrcFilters, s.TraFilters, m_wndView.m_hWnd);
  540. }
  541. if(!pGB)
  542. {
  543. throw _T("Failed to create the filter graph object");
  544. }
  545. pGB->AddToROT();
  546. 把视频解码接口赋值给其它
  547. pMC = pGB; pME = pGB; pMS = pGB; // general
  548. pVW = pGB; pBV = pGB; // video
  549. pBA = pGB; // audio
  550. pFS = pGB;
  551. if(!(pMC && pME && pMS)
  552. || !(pVW && pBV)
  553. || !(pBA))
  554. {
  555. throw ResStr(IDS_MSG_THROW_BROKEN_DIRECTX_SUPPORT);
  556. }
  557. 发送WM_GRAPHNOTIFY 消息
  558. if(FAILED(pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0)))
  559. {
  560. throw _T("Could not set target window for graph notification");
  561. }
  562. m_pProv = (IUnknown*)new CKeyProvider(); 键盘提供者接口
  563. if(CComQIPtr<IObjectWithSite> pObjectWithSite = pGB)
  564. pObjectWithSite->SetSite(m_pProv); 键盘站点 捕获键盘消息
  565. m_pCB = new CDSMChapterBag(NULL, NULL); dstuil库中类
  566. }
  567. 进入OpenFile分析
  568. void CMainFrame::OpenFile(OpenFileData* pOFD)
  569. {
  570. if(pOFD->fns.IsEmpty()) 文件为空 则抛出异常
  571. throw _T("Invalid argument");
  572. AppSettings& s = AfxGetAppSettings(); 获得设置信息
  573. bool fFirst = true;
  574. POSITION pos = pOFD->fns.GetHeadPosition();
  575. while(pos)
  576. {
  577. CString fn = pOFD->fns.GetNext(pos);
  578. fn.Trim();
  579. if(fn.IsEmpty() && !fFirst)
  580. break;
  581. CString fnLower = fn;
  582. fnLower.MakeLower();
  583. HRESULT hr = -1;
  584. 如果不是mms://路径或mmsh://路径
  585. if(FAILED(hr) && ( fnLower.Find(_T("mms://")) == 0 || fnLower.Find(_T("mmsh://")) == 0 )){ //
  586. //render mms our own way
  587. hr = OpenMMSUrlStream(fn);
  588. }
  589. if(FAILED(hr)) 渲染文件 持续了很长时间
  590. hr = pGB->RenderFile(CStringW(fn), NULL);
  591. 如果是网络文件 则大概网络流
  592. if(FAILED(hr) && ( fnLower.Find(_T("http") == 0 || fnLower.Find(_T("https://")) == 0
  593. || fnLower.Find(_T("udp://")) == 0 || fnLower.Find(_T("tcp://")) == 0)) ){ //
  594. //render mms our own way
  595. hr = OpenMMSUrlStream(fn);
  596. }
  597. /* not sure why this is not work for http youku etc 不知道这是为什么不适用于HTTP优酷等
  598. HRESULT hr = -1;
  599. if( ( fn.MakeLower().Find(_T("mms://")) == 0 || fn.MakeLower().Find(_T("mmsh://")) == 0 || (fn.MakeLower().Find(_T("http:")) == 0 && fn.MakeLower().Find(_T(":8902")) > 0 ))){
  600. //render mms our own way
  601. hr = OpenMMSUrlStream(fn);
  602. }
  603. if(FAILED(hr))
  604. hr = pGB->RenderFile(CStringW(fn), NULL);
  605. */
  606. 依然失败 则寻找错误 记录错误
  607. if(FAILED(hr))
  608. {
  609. if(fFirst)
  610. {
  611. //if(s.fReportFailedPins)
  612. {
  613. CComQIPtr<IGraphBuilderDeadEnd> pGBDE = pGB;
  614. if(pGBDE && pGBDE->GetCount()) CMediaTypesDlg(pGBDE, this).DoModal();
  615. }
  616. CString err;
  617. switch(hr)
  618. {
  619. case E_ABORT: err = ResStr(IDS_MSG_THROW_OPRATION_CANCELED); break;
  620. case E_FAIL: case E_POINTER: default:
  621. err.Format(ResStr(IDS_MSG_THROW_UNABLE_OPEN_FILE) , hr);
  622. break;
  623. case E_INVALIDARG: err = ResStr(IDS_MSG_THROW_ILLEGE_FILENAME); break;
  624. case E_OUTOFMEMORY: err = ResStr(IDS_MSG_THROW_OUTOF_MEMORY); break;
  625. case VFW_E_CANNOT_CONNECT: err = ResStr(IDS_MSG_THROW_UNABLE_DECODE); break;
  626. case VFW_E_CANNOT_LOAD_SOURCE_FILTER: err = ResStr(IDS_MSG_THROW_UNSUPPORT_SOURCE); break;
  627. case VFW_E_CANNOT_RENDER: err = ResStr(IDS_MSG_THROW_FAIL_CREATE_RENDER); break;
  628. case VFW_E_INVALID_FILE_FORMAT: err = _T("Invalid file format"); break;
  629. case VFW_E_NOT_FOUND: err = ResStr(IDS_MSG_THROW_FILE_NOT_FOUND); break;
  630. case VFW_E_UNKNOWN_FILE_TYPE: err = ResStr(IDS_MSG_THROW_UNKNOWN_FILE_TYPE); break;
  631. case VFW_E_UNSUPPORTED_STREAM: err = ResStr(IDS_MSG_THROW_UNSUPPORT_STREAM_TYPE); break;
  632. }
  633. throw err;
  634. }
  635. }
  636. 是否保存记录
  637. if(s.fKeepHistory)
  638. {
  639. if(this->m_lastUrl == fn){ 本次与上次是否相同
  640. CRecentFileList* pMRU = &s.MRUUrl;
  641. pMRU->ReadList();
  642. pMRU->Add(fn);
  643. pMRU->WriteList();
  644. this->m_lastUrl.Empty();
  645. }else{
  646. 不同则写入
  647. CRecentFileList* pMRU = fFirst ? &s.MRU : &s.MRUDub;
  648. pMRU->ReadList();
  649. pMRU->Add(fn);
  650. pMRU->WriteList();
  651. }
  652. }
  653. if(fFirst) 第一次运行? 搜索字幕
  654. {
  655. AppSettings& s = AfxGetAppSettings();
  656. pOFD->title = fn;
  657. m_fnCurPlayingFile = fn;
  658. //是否有字幕? 沒有则下载字幕
  659. CSVPToolBox svpTool;
  660. //搜索目录下同名字幕
  661. CAtlArray<CString> subSearchPaths;
  662. subSearchPaths.Add(_T("."));
  663. subSearchPaths.Add(s.GetSVPSubStorePath());
  664. subSearchPaths.Add(svpTool.GetPlayerPath(L"SVPSub"));
  665. subSearchPaths.Add(_T(".\\subtitles"));
  666. subSearchPaths.Add(_T(".\\Subs"));
  667. subSearchPaths.Add(_T("c:\\subtitles"));
  668. CAtlArray<SubFile> ret;
  669. POSITION pos = pOFD->subs.GetHeadPosition();
  670. while(pos){
  671. POSITION cur = pos;
  672. CString szSubFn = pOFD->subs.GetNext(pos);
  673. if(!svpTool.ifFileExist(szSubFn))
  674. pOFD->subs.RemoveAt(cur);
  675. }
  676. CSVPRarLib svpRar;
  677. if( svpRar.SplitPath(fn) ){
  678. GetSubFileNames(svpRar.m_fnRAR, subSearchPaths, ret);
  679. CAtlArray<SubFile> ret2;
  680. GetSubFileNames(svpRar.m_fnInsideRar, subSearchPaths, ret2);
  681. ret.Append(ret2);
  682. }else{
  683. GetSubFileNames(fn, subSearchPaths, ret);
  684. //AfxMessageBox(fn);
  685. }
  686. for(int i = 0; i < ret.GetCount(); i++){
  687. SubFile szBuf = ret.GetAt(i);
  688. //AfxMessageBox(szBuf.fn);
  689. if ( pOFD->subs.Find( szBuf.fn ) == NULL && svpTool.ifFileExist(szBuf.fn)){
  690. pOFD->subs.AddTail(szBuf.fn);
  691. //AfxMessageBox(szBuf.fn);
  692. }
  693. }
  694. //AfxMessageBox(_T("1"));
  695. if ( pOFD->subs.GetCount() <= 0){
  696. // AfxMessageBox(_T("2"));
  697. if(s.autoDownloadSVPSub){
  698. CPath fPath(fn);
  699. CString szExt;
  700. szExt.Format(_T(" %s;"),fPath.GetExtension());
  701. if(s.CheckSVPSubExts.Find(szExt) >= 0 ){
  702. SVPSubDownloadByVPath(fn);
  703. }else{
  704. //SendStatusMessage( _T("正在播放的文件类型看来不需要字幕,终止自动智能匹配"), 1000);
  705. }
  706. }
  707. }
  708. }
  709. fFirst = false;
  710. if(m_fCustomGraph) break;
  711. } 智能匹配字幕结束
  712. //if(s.fReportFailedPins)
  713. { 如果绘图挂了 类型对话框弹出
  714. CComQIPtr<IGraphBuilderDeadEnd> pGBDE = pGB;
  715. if(pGBDE && pGBDE->GetCount()) CMediaTypesDlg(pGBDE, this).DoModal();
  716. }
  717. if(!(pAMOP = pGB))
  718. {
  719. BeginEnumFilters(pGB, pEF, pBF)
  720. if(pAMOP = pBF) break;
  721. EndEnumFilters
  722. }
  723. if(FindFilter(__uuidof(CShoutcastSource), pGB))
  724. m_fUpdateInfoBar = true;
  725. SetupChapters(); 初始化章节
  726. 枚举 寻找IKeyFrameInfo 接口
  727. CComQIPtr<IKeyFrameInfo> pKFI;
  728. BeginEnumFilters(pGB, pEF, pBF)
  729. if(pKFI = pBF) break;
  730. EndEnumFilters
  731. UINT nKFs = 0, nKFsTmp = 0;
  732. if(pKFI && S_OK == pKFI->GetKeyFrameCount(nKFs) && nKFs > 0)
  733. {
  734. m_kfs.SetCount(nKFsTmp = nKFs);
  735. if(S_OK != pKFI->GetKeyFrames(&TIME_FORMAT_MEDIA_TIME, m_kfs.GetData(), nKFsTmp) || nKFsTmp != nKFs)
  736. m_kfs.RemoveAll();
  737. }
  738. m_iPlaybackMode = PM_FILE;
  739. }
  740. 进入SetupChapters() 初始化章节
  741. void CMainFrame::SetupChapters()
  742. {
  743. ASSERT(m_pCB); 解码不为空
  744. m_pCB->ChapRemoveAll();
  745. 查找过滤接口 并添加到pBFs
  746. CInterfaceList<IBaseFilter> pBFs;
  747. BeginEnumFilters(pGB, pEF, pBF)
  748. pBFs.AddTail(pBF);
  749. EndEnumFilters
  750. POSITION pos;
  751. 循环遍历过滤接口 进行追加操作 具体什么 待分析
  752. pos = pBFs.GetHeadPosition();
  753. while(pos && !m_pCB->ChapGetCount())
  754. {
  755. IBaseFilter* pBF = pBFs.GetNext(pos);
  756. CComQIPtr<IDSMChapterBag> pCB = pBF;
  757. if(!pCB) continue;
  758. for(DWORD i = 0, cnt = pCB->ChapGetCount(); i < cnt; i++)
  759. {
  760. REFERENCE_TIME rt;
  761. CComBSTR name;
  762. if(SUCCEEDED(pCB->ChapGet(i, &rt, &name)))
  763. m_pCB->ChapAppend(rt, name);
  764. }
  765. }
  766. 循环遍历过滤接口 进行追加操作 具体什么 待分析
  767. pos = pBFs.GetHeadPosition();
  768. while(pos && !m_pCB->ChapGetCount())
  769. {
  770. IBaseFilter* pBF = pBFs.GetNext(pos);
  771. CComQIPtr<IChapterInfo> pCI = pBF;
  772. if(!pCI) continue;
  773. CHAR iso6391[3];
  774. ::GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, iso6391, 3);
  775. CStringA iso6392 = ISO6391To6392(iso6391);
  776. if(iso6392.GetLength() < 3) iso6392 = "eng";
  777. UINT cnt = pCI->GetChapterCount(CHAPTER_ROOT_ID);
  778. for(UINT i = 1; i <= cnt; i++)
  779. {
  780. UINT cid = pCI->GetChapterId(CHAPTER_ROOT_ID, i);
  781. ChapterElement ce;
  782. if(pCI->GetChapterInfo(cid, &ce))
  783. {
  784. char pl[3] = {iso6392[0], iso6392[1], iso6392[2]};
  785. char cc[] = " ";
  786. CComBSTR name;
  787. name.Attach(pCI->GetChapterStringInfo(cid, pl, cc));
  788. m_pCB->ChapAppend(ce.rtStart, name);
  789. }
  790. }
  791. }
  792. 循环遍历过滤接口 进行追加操作 具体什么 待分析
  793. pos = pBFs.GetHeadPosition();
  794. while(pos && !m_pCB->ChapGetCount())
  795. {
  796. IBaseFilter* pBF = pBFs.GetNext(pos);
  797. CComQIPtr<IAMExtendedSeeking, &IID_IAMExtendedSeeking> pES = pBF;
  798. if(!pES) continue;
  799. long MarkerCount = 0;
  800. if(SUCCEEDED(pES->get_MarkerCount(&MarkerCount)))
  801. {
  802. for(long i = 1; i <= MarkerCount; i++)
  803. {
  804. double MarkerTime = 0;
  805. if(SUCCEEDED(pES->GetMarkerTime(i, &MarkerTime)))
  806. {
  807. CStringW name;
  808. name.Format(L"Chapter %d", i);
  809. CComBSTR bstr;
  810. if(S_OK == pES->GetMarkerName(i, &bstr))
  811. name = bstr;
  812. m_pCB->ChapAppend(REFERENCE_TIME(MarkerTime*10000000), name);
  813. }
  814. }
  815. }
  816. }
  817. 循环遍历过滤接口 进行追加操作 具体什么 待分析
  818. pos = pBFs.GetHeadPosition();
  819. while(pos && !m_pCB->ChapGetCount())
  820. {
  821. IBaseFilter* pBF = pBFs.GetNext(pos);
  822. if(GetCLSID(pBF) != CLSID_OggSplitter)
  823. continue;
  824. BeginEnumPins(pBF, pEP, pPin)
  825. {
  826. if(m_pCB->ChapGetCount()) break;
  827. if(CComQIPtr<IPropertyBag> pPB = pPin)
  828. {
  829. for(int i = 1; ; i++)
  830. {
  831. CStringW str;
  832. CComVariant var;
  833. var.Clear();
  834. str.Format(L"CHAPTER%02d", i);
  835. if(S_OK != pPB->Read(str, &var, NULL))
  836. break;
  837. int h, m, s, ms;
  838. WCHAR wc;
  839. if(7 != swscanf(CStringW(var), L"%d%c%d%c%d%c%d", &h, &wc, &m, &wc, &s, &wc, &ms))
  840. break;
  841. CStringW name;
  842. name.Format(L"Chapter %d", i);
  843. var.Clear();
  844. str += L"NAME";
  845. if(S_OK == pPB->Read(str, &var, NULL))
  846. name = var;
  847. m_pCB->ChapAppend(10000i64*(((h*60 + m)*60 + s)*1000 + ms), name);
  848. }
  849. }
  850. }
  851. EndEnumPins
  852. }
  853. m_pCB->ChapSort();
  854. }
  855. 进入OpenCustomizeGraph 自定义图像大小
  856. void CMainFrame::OpenCustomizeGraph()
  857. {
  858. 总共有enum {PM_NONE, PM_FILE, PM_DVD, PM_CAPTURE}种模式
  859. PM_CAPTURE 模式 不支持自定义图像大小
  860. if(m_iPlaybackMode == PM_CAPTURE) return;
  861. CleanGraph(); 清楚画像
  862. if(m_iPlaybackMode == PM_FILE) 文件模式
  863. {
  864. if(m_pCAP) {
  865. if(AfxGetAppSettings().fAutoloadSubtitles) {
  866. AddTextPassThruFilter(); 进行了很多连接 需要分析
  867. }
  868. }
  869. }
  870. 同步视频
  871. AppSettings& s = AfxGetAppSettings();
  872. if (s.m_RenderSettings.bSynchronizeVideo)
  873. {
  874. HRESULT hr;
  875. m_pRefClock = DNew CSyncClockFilter(NULL, &hr);
  876. CStringW name;
  877. name.Format(L"SyncClock Filter");
  878. pGB->AddFilter(m_pRefClock, name);
  879. CComPtr<IReferenceClock> refClock;
  880. m_pRefClock->QueryInterface(IID_IReferenceClock, reinterpret_cast<void**>(&refClock));
  881. CComPtr<IMediaFilter> mediaFilter;
  882. pGB->QueryInterface(IID_IMediaFilter, reinterpret_cast<void**>(&mediaFilter));
  883. mediaFilter->SetSyncSource(refClock);
  884. mediaFilter = NULL;
  885. refClock = NULL;
  886. m_pRefClock->QueryInterface(IID_ISyncClock, reinterpret_cast<void**>(&m_pSyncClock));
  887. }
  888. BeginEnumFilters(pGB, pEF, pBF)
  889. {
  890. 查找CLSID_OggSplitter 控件
  891. if(GetCLSID(pBF) == CLSID_OggSplitter)
  892. {
  893. 查找IAMStreamSelect接口
  894. if(CComQIPtr<IAMStreamSelect> pSS = pBF)
  895. {
  896. LCID idAudio = AfxGetAppSettings().idAudioLang;
  897. if(!idAudio) idAudio = GetUserDefaultLCID();
  898. LCID idSub = AfxGetAppSettings().idSubtitlesLang;
  899. if(!idSub) idSub = GetUserDefaultLCID();
  900. DWORD cnt = 0;
  901. pSS->Count(&cnt);
  902. for(DWORD i = 0; i < cnt; i++)
  903. {
  904. AM_MEDIA_TYPE* pmt = NULL;
  905. DWORD dwFlags = 0;
  906. LCID lcid = 0;
  907. DWORD dwGroup = 0;
  908. WCHAR* pszName = NULL;
  909. if(SUCCEEDED(pSS->Info((long)i, &pmt, &dwFlags, &lcid, &dwGroup, &pszName, NULL, NULL)))
  910. {
  911. CStringW name(pszName), sound(L"Sound"), subtitle(L"Subtitle");
  912. if(idAudio != -1 && (idAudio&0x3ff) == (lcid&0x3ff) // sublang seems to be zeroed out in ogm...
  913. && name.GetLength() > sound.GetLength()
  914. && !name.Left(sound.GetLength()).CompareNoCase(sound))
  915. {
  916. if(SUCCEEDED(pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE)))
  917. idAudio = -1;
  918. }
  919. if(idSub != -1 && (idSub&0x3ff) == (lcid&0x3ff) // sublang seems to be zeroed out in ogm...
  920. && name.GetLength() > subtitle.GetLength()
  921. && !name.Left(subtitle.GetLength()).CompareNoCase(subtitle)
  922. && name.Mid(subtitle.GetLength()).Trim().CompareNoCase(L"off"))
  923. {
  924. if(SUCCEEDED(pSS->Enable(i, AMSTREAMSELECTENABLE_ENABLE)))
  925. idSub = -1;
  926. }
  927. if(pmt) DeleteMediaType(pmt);
  928. if(pszName) CoTaskMemFree(pszName);
  929. }
  930. }
  931. }
  932. }
  933. }
  934. EndEnumFilters
  935. CleanGraph();
  936. }
  937. 进入OpenSetupVideo() 初始化视频
  938. void CMainFrame::OpenSetupVideo()
  939. {
  940. 只自动?
  941. m_fAudioOnly = true;
  942. if (m_pMFVDC) // EVR
  943. {
  944. EVR 不支持
  945. m_fAudioOnly = false;
  946. }
  947. else if(m_pCAPR)
  948. {
  949. 获得视频大小
  950. CSize vs = m_pCAPR->GetVideoSize();
  951. m_fAudioOnly = (vs.cx <= 0 || vs.cy <= 0);
  952. }
  953. else
  954. {
  955. 否则其它
  956. {
  957. long w = 0, h = 0;
  958. if(CComQIPtr<IBasicVideo> pBV = pGB)
  959. {
  960. pBV->GetVideoSize(&w, &h);
  961. }
  962. if(w > 0 && h > 0)
  963. {
  964. m_fAudioOnly = false;
  965. }
  966. }
  967. if(m_fAudioOnly)
  968. {
  969. BeginEnumFilters(pGB, pEF, pBF)
  970. {
  971. long w = 0, h = 0;
  972. if(CComQIPtr<IVideoWindow> pVW = pBF)
  973. {
  974. long lVisible;
  975. if(FAILED(pVW->get_Visible(&lVisible)))
  976. continue;
  977. pVW->get_Width(&w);
  978. pVW->get_Height(&h);
  979. }
  980. if(w > 0 && h > 0)
  981. {
  982. m_fAudioOnly = false;
  983. break;
  984. }
  985. }
  986. EndEnumFilters
  987. }
  988. }
  989. if(m_fShockwaveGraph) flash控件
  990. {
  991. m_fAudioOnly = false;
  992. }
  993. if(m_pCAP)
  994. {
  995. SetShaders();
  996. }
  997. // else
  998. {
  999. // TESTME
  1000. pVW->put_Owner((OAHWND)m_wndView.m_hWnd);
  1001. pVW->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
  1002. pVW->put_MessageDrain((OAHWND)m_hWnd);
  1003. for(CWnd* pWnd = m_wndView.GetWindow(GW_CHILD); pWnd; pWnd = pWnd->GetNextWindow())
  1004. pWnd->EnableWindow(FALSE); // little trick to let WM_SETCURSOR thru
  1005. }
  1006. }
  1007. 进入SetShaders( BOOL silent ) 设置着色
  1008. void CMainFrame::SetShaders( BOOL silent )
  1009. {
  1010. if(!m_pCAPR) return; 不存在则直接返回
  1011. AppSettings& s = AfxGetAppSettings();
  1012. CAtlStringMap<const AppSettings::Shader*> s2s;
  1013. POSITION pos = s.m_shaders.GetHeadPosition();
  1014. while(pos)
  1015. {
  1016. const AppSettings::Shader* pShader = &s.m_shaders.GetNext(pos); 关键取值
  1017. s2s[pShader->label] = pShader;
  1018. }
  1019. if(!silent){
  1020. m_pCAPR->SetPixelShader(NULL, NULL);
  1021. if (m_pCAP2)
  1022. m_pCAP2->SetPixelShader2(NULL, NULL, true);
  1023. }
  1024. CAtlList<CString> labels;
  1025. pos = m_shaderlabels.GetHeadPosition();
  1026. while(pos)
  1027. {
  1028. const AppSettings::Shader* pShader = NULL;
  1029. if(s2s.Lookup(m_shaderlabels.GetNext(pos), pShader))
  1030. {
  1031. CStringA target = pShader->target;
  1032. CStringA srcdata = pShader->srcdata;
  1033. HRESULT hr = m_pCAPR->SetPixelShader(srcdata, target );
  1034. if(FAILED(hr))
  1035. {
  1036. //m_pCAP->SetPixelShader(NULL, NULL);
  1037. if (m_pCAP2)
  1038. hr = m_pCAP2->SetPixelShader2(srcdata, target, true);
  1039. if(FAILED(hr)){
  1040. // if (m_pCAP2)
  1041. // m_pCAP2->SetPixelShader2(NULL, NULL, true, !silent);
  1042. if(!silent)
  1043. {
  1044. CString label = pShader->label;
  1045. OsdMsg_SetShader(&label);
  1046. }
  1047. }
  1048. return;
  1049. }
  1050. labels.AddTail(pShader->label);
  1051. }
  1052. }
  1053. if(m_iMediaLoadState == MLS_LOADED)
  1054. {
  1055. CString str = Implode(labels, '|');
  1056. str.Replace(_T("|"), _T(", "));
  1057. if(!silent) SendStatusMessage(_T("Shader: ") + str, 3000);
  1058. }
  1059. if(!silent){
  1060. if (SetVMR9ColorControl(s.dBrightness , s.dContrast, 0, 0, true) == FALSE)
  1061. OsdMsg_SetShader();
  1062. }
  1063. }
  1064. 进入OpenSetupAudio() 初始化音频
  1065. void CMainFrame::OpenSetupAudio()
  1066. {
  1067. 赋值
  1068. pBA->put_Volume(m_wndToolBar.Volume);
  1069. // FIXME
  1070. // 又是从设置中取得数据
  1071. int balance = AfxGetAppSettings().nBalance;
  1072. int sign = balance>0?-1:1;
  1073. balance = max(100-abs(balance), 1);
  1074. balance = (int)((log10(1.0*balance)-2)*5000*sign);
  1075. balance = max(min(balance, 10000), -10000);
  1076. pBA->put_Balance(balance);
  1077. }
  1078. 进入CMainFrame::OpenSetupWindowTitle 初始化标题
  1079. void CMainFrame::OpenSetupWindowTitle(CString fn)
  1080. {
  1081. CString title(MAKEINTRESOURCE(IDR_MAINFRAME));
  1082. AppSettings& s = AfxGetAppSettings();
  1083. int i = s.iTitleBarTextStyle;
  1084. if(!fn.IsEmpty() && (i == 0 || i == 1))
  1085. {
  1086. if(i == 1)
  1087. {
  1088. if(m_iPlaybackMode == PM_FILE)
  1089. {
  1090. fn.Replace('\\', '/');
  1091. CString fn2 = fn.Mid(fn.ReverseFind('/')+1);
  1092. if(!fn2.IsEmpty()) fn = fn2;
  1093. if(s.fTitleBarTextTitle)
  1094. {
  1095. BeginEnumFilters(pGB, pEF, pBF)
  1096. {
  1097. if(CComQIPtr<IAMMediaContent, &IID_IAMMediaContent> pAMMC = pBF)
  1098. {
  1099. CComBSTR bstr;
  1100. if(SUCCEEDED(pAMMC->get_Title(&bstr)) && bstr.Length())
  1101. {
  1102. fn = CString(bstr.m_str);
  1103. break;
  1104. }
  1105. }
  1106. }
  1107. EndEnumFilters
  1108. }
  1109. }
  1110. else if(m_iPlaybackMode == PM_DVD)
  1111. {
  1112. fn = _T("DVD");
  1113. }
  1114. else if(m_iPlaybackMode == PM_CAPTURE)
  1115. {
  1116. fn = _T("Live");
  1117. }
  1118. }
  1119. title = fn + _T(" - ") + title;
  1120. }
  1121. //CString szBuild;
  1122. //szBuild.Format(_T(" (Build %s)"),SVP_REV_STR);
  1123. //title += szBuild;
  1124. //SetWindowText(title);
  1125. m_szTitle = title;
  1126. RedrawNonClientArea();
  1127. }
  1128. 在OpenMediaPrivate()中
  1129. PostMessage(WM_COMMAND, ID_PLAY_PAUSE);
  1130. if(!(AfxGetAppSettings().nCLSwitches&CLSW_OPEN))
  1131. PostMessage(WM_COMMAND, ID_PLAY_PLAY);
  1132. 紧紧只是更新UI?
  1133. ON_UPDATE_COMMAND_UI(ID_PLAY_PLAY, OnUpdatePlayPauseStop)
  1134. 进入OnUpdatePlayPauseStop 分析
  1135. void CMainFrame::OnUpdatePlayPauseStop(CCmdUI* pCmdUI)
  1136. {
  1137. OAFilterState fs = m_fFrameSteppingActive ? State_Paused : GetMediaState();
  1138. UI消息
  1139. pCmdUI->SetCheck(fs == State_Running && pCmdUI->m_nID == ID_PLAY_PLAY
  1140. || fs == State_Paused && pCmdUI->m_nID == ID_PLAY_PAUSE
  1141. || fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_STOP
  1142. || (fs == State_Paused || fs == State_Running) && pCmdUI->m_nID == ID_PLAY_PLAYPAUSE);
  1143. bool fEnable = false;
  1144. if(fs >= 0)
  1145. {
  1146. if(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)
  1147. {
  1148. fEnable = true;
  1149. 不能进入暂停状态,从停止使用rm
  1150. if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE && m_fRealMediaGraph) fEnable = false; // can't go into paused state from stopped with rm
  1151. else if(m_fCapturing) fEnable = false;
  1152. else if(m_fLiveWM && pCmdUI->m_nID == ID_PLAY_PAUSE) fEnable = false;
  1153. }
  1154. else if(m_iPlaybackMode == PM_DVD)
  1155. {
  1156. fEnable = m_iDVDDomain != DVD_DOMAIN_VideoManagerMenu
  1157. && m_iDVDDomain != DVD_DOMAIN_VideoTitleSetMenu;
  1158. if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE) fEnable = false;
  1159. }
  1160. }
  1161. if(pCmdUI->m_nID == ID_PLAY_PLAY || pCmdUI->m_nID == ID_PLAY_PLAYPAUSE) fEnable = true;
  1162. pCmdUI->Enable(fEnable);
  1163. }
  1164. ON_COMMAND(ID_PLAY_PAUSE, OnPlayPause)
  1165. void CMainFrame::OnPlayPause()
  1166. //支持ffdshow的排队。
  1167. //为了避免暂停黑掉,我们以锁定g_ffdshowReceive同步与ReceiveMine的。
  1168. void CMainFrame::OnPlayPause()
  1169. {
  1170. // Support ffdshow queueing.
  1171. // To avoid black out on pause, we have to lock g_ffdshowReceive to synchronize with ReceiveMine.
  1172. time(&m_tPlayPauseTime);
  1173. if(queueu_ffdshow_support)
  1174. {
  1175. CAutoLock lck(&g_ffdshowReceive);
  1176. return OnPlayPauseI();
  1177. }
  1178. OnPlayPauseI();
  1179. }
  1180. 进入OnPlayPauseI()分析
  1181. void CMainFrame::OnPlayPauseI()
  1182. {
  1183. if(m_iMediaLoadState == MLS_LOADED) 已经加载
  1184. {
  1185. if(m_iPlaybackMode == PM_FILE)
  1186. {
  1187. pMC->Pause(); 停止
  1188. }
  1189. else if(m_iPlaybackMode == PM_DVD)
  1190. {
  1191. pMC->Pause();
  1192. }
  1193. else if(m_iPlaybackMode == PM_CAPTURE)
  1194. {
  1195. pMC->Pause();
  1196. }
  1197. SetTimer(TIMER_STREAMPOSPOLLER, 40, NULL);
  1198. SetTimer(TIMER_STREAMPOSPOLLER2, 500, NULL);
  1199. SetTimer(TIMER_STATS, 1000, NULL);
  1200. KillTimer(TIMER_IDLE_TASK);
  1201. SetTimer(TIMER_IDLE_TASK, 30000, NULL);
  1202. SetAlwaysOnTop(AfxGetAppSettings().iOnTop); 设置置顶
  1203. }
  1204. MoveVideoWindow();
  1205. }
  1206. 移动视频窗体
  1207. void CMainFrame::MoveVideoWindow(bool fShowStats)
  1208. {
  1209. 视频已经加载 不是自动 窗体可见
  1210. if(m_iMediaLoadState == MLS_LOADED && !m_fAudioOnly && IsWindowVisible())
  1211. {
  1212. AppSettings &s = AfxGetAppSettings();
  1213. CRect wr;
  1214. if(!m_fFullScreen && (s.bUserAeroUI() || (!s.bUserAeroUI() && ( s.nCS & CS_TOOLBAR ))) )
  1215. {
  1216. m_wndView.GetClientRect(wr);
  1217. }
  1218. else
  1219. {
  1220. GetWindowRect(&wr);
  1221. // HACK
  1222. CRect r;
  1223. m_wndView.GetWindowRect(&r);
  1224. wr -= r.TopLeft();
  1225. }
  1226. CRect vr = CRect(0,0,0,0);
  1227. OAFilterState fs = GetMediaState();
  1228. if(fs == State_Paused || fs == State_Running || fs == State_Stopped && (m_fShockwaveGraph || m_fQuicktimeGraph))
  1229. {
  1230. CSize arxy = GetVideoSize();
  1231. int iDefaultVideoSize = AfxGetAppSettings().iDefaultVideoSize;
  1232. CSize ws =
  1233. iDefaultVideoSize == DVS_HALF ? CSize(arxy.cx/2, arxy.cy/2) :
  1234. iDefaultVideoSize == DVS_NORMAL ? arxy :
  1235. iDefaultVideoSize == DVS_DOUBLE ? CSize(arxy.cx*2, arxy.cy*2) :
  1236. wr.Size();
  1237. int w = ws.cx;
  1238. int h = ws.cy;
  1239. if(!m_fShockwaveGraph) //&& !m_fQuicktimeGraph)
  1240. {
  1241. if(iDefaultVideoSize == DVS_FROMINSIDE || iDefaultVideoSize == DVS_FROMOUTSIDE)
  1242. {
  1243. h = ws.cy;
  1244. w = MulDiv(h, arxy.cx, arxy.cy);
  1245. if(iDefaultVideoSize == DVS_FROMINSIDE && w > ws.cx
  1246. || iDefaultVideoSize == DVS_FROMOUTSIDE && w < ws.cx)
  1247. {
  1248. w = ws.cx;
  1249. h = MulDiv(w, arxy.cy, arxy.cx);
  1250. }
  1251. }
  1252. }
  1253. CSize size(
  1254. (int)(m_ZoomX*w),
  1255. (int)(m_ZoomY*h));
  1256. CPoint pos(
  1257. (int)(m_PosX*(wr.Width()*3 - m_ZoomX*w) - wr.Width()),
  1258. (int)(m_PosY*(wr.Height()*3 - m_ZoomY*h) - wr.Height()));
  1259. /* CPoint pos(
  1260. (int)(m_PosX*(wr.Width() - size.cx)),
  1261. (int)(m_PosY*(wr.Height() - size.cy)));
  1262. */
  1263. vr = CRect(pos, size);
  1264. }
  1265. wr |= CRect(0,0,0,0);
  1266. vr |= CRect(0,0,0,0);
  1267. //CString szLog;
  1268. //szLog.Format(_T("WVSize3 %d %d %d %d %d %d %d "), wr.Width(), wr.Height(), vr.Width(), vr.Height(), m_AngleX , m_AngleY , m_AngleZ);
  1269. //SVP_LogMsg(szLog);
  1270. if(m_pCAPR)
  1271. {
  1272. m_pCAPR->SetPosition(wr, vr);
  1273. m_pCAPR->SetVideoAngle(Vector(DegToRad(m_AngleX), DegToRad(m_AngleY), DegToRad(m_AngleZ)));
  1274. }
  1275. else
  1276. {
  1277. HRESULT hr;
  1278. hr = pBV->SetDefaultSourcePosition();
  1279. hr = pBV->SetDestinationPosition(vr.left, vr.top, vr.Width(), vr.Height());
  1280. hr = pVW->SetWindowPosition(wr.left, wr.top, wr.Width(), wr.Height());
  1281. if (m_pMFVDC) m_pMFVDC->SetVideoPosition (NULL, wr);
  1282. }
  1283. //SVP_LogMsg5(_T("MoveVideoWindow %d ") , wr.Height());
  1284. m_wndView.SetVideoRect(wr);
  1285. if(fShowStats && vr.Height() > 0)
  1286. {
  1287. CString info(L"正在使用智能拖拽功能。可在画面右上角进行拖拽");
  1288. // info.Format(_T("Pos %.2f %.2f, Zoom %.2f %.2f, AR %.2f"), m_PosX, m_PosY, m_ZoomX, m_ZoomY, (float)vr.Width()/vr.Height());
  1289. SendStatusMessage(info, 3000);
  1290. }
  1291. }
  1292. else
  1293. {
  1294. m_wndView.SetVideoRect();
  1295. }
  1296. CRect r;
  1297. m_wndView.GetClientRect(r);
  1298. if(m_iMediaLoadState == MLS_LOADED){
  1299. float fViewRatio = (float)r.Width() / r.Height();
  1300. CSize vsize = GetVideoSize();
  1301. float fVideoRatio = (float)vsize.cx / vsize.cy;
  1302. m_fScreenHigherThanVideo = (fViewRatio < fVideoRatio );
  1303. }
  1304. }
  1305. 仅仅只是更新UI
  1306. void CMainFrame::OnUpdatePlayPauseStop(CCmdUI* pCmdUI)
  1307. {
  1308. OAFilterState fs = m_fFrameSteppingActive ? State_Paused : GetMediaState();
  1309. pCmdUI->SetCheck(fs == State_Running && pCmdUI->m_nID == ID_PLAY_PLAY
  1310. || fs == State_Paused && pCmdUI->m_nID == ID_PLAY_PAUSE
  1311. || fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_STOP
  1312. || (fs == State_Paused || fs == State_Running) && pCmdUI->m_nID == ID_PLAY_PLAYPAUSE);
  1313. bool fEnable = false;
  1314. if(fs >= 0)
  1315. {
  1316. if(m_iPlaybackMode == PM_FILE || m_iPlaybackMode == PM_CAPTURE)
  1317. {
  1318. fEnable = true;
  1319. if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE && m_fRealMediaGraph) fEnable = false; // can't go into paused state from stopped with rm
  1320. else if(m_fCapturing) fEnable = false;
  1321. else if(m_fLiveWM && pCmdUI->m_nID == ID_PLAY_PAUSE) fEnable = false;
  1322. }
  1323. else if(m_iPlaybackMode == PM_DVD)
  1324. {
  1325. fEnable = m_iDVDDomain != DVD_DOMAIN_VideoManagerMenu
  1326. && m_iDVDDomain != DVD_DOMAIN_VideoTitleSetMenu;
  1327. if(fs == State_Stopped && pCmdUI->m_nID == ID_PLAY_PAUSE) fEnable = false;
  1328. }
  1329. }
  1330. if(pCmdUI->m_nID == ID_PLAY_PLAY || pCmdUI->m_nID == ID_PLAY_PLAYPAUSE) fEnable = true;
  1331. pCmdUI->Enable(fEnable);
  1332. }
  1333. // play 播放事件
  1334. void CMainFrame::OnPlayPlay()
  1335. {
  1336. if(m_iMediaLoadState == MLS_LOADED) 必须载入
  1337. {
  1338. if(GetMediaState() == State_Stopped) { m_iSpeedLevel = 0; time(&m_tPlayStartTime);} 记录
  1339. try
  1340. {
  1341. if(m_iPlaybackMode == PM_FILE) 文件格式
  1342. {
  1343. time_t ttNow;
  1344. time(&ttNow);
  1345. if( m_tPlayPauseTime > m_tPlayStartTime){
  1346. m_tPlayStartTime += (ttNow - m_tPlayPauseTime);
  1347. }
  1348. if(m_fEndOfStream){ 如果文件流没有 则停止
  1349. SendMessage(WM_COMMAND, ID_PLAY_STOP);
  1350. Sleep(1500);
  1351. }
  1352. pMC->Run(); 运行
  1353. }
  1354. else if(m_iPlaybackMode == PM_DVD) DVD格式
  1355. {
  1356. double dRate = 1.0;
  1357. //if(m_iSpeedLevel != -4 && m_iSpeedLevel != 0)
  1358. // dRate = pow(2.0, m_iSpeedLevel >= -3 ? m_iSpeedLevel : (-m_iSpeedLevel - 8));
  1359. dRate = 1.0 + m_iSpeedLevel * 0.1;
  1360. pDVDC->PlayForwards(dRate, DVD_CMD_FLAG_Block, NULL);
  1361. pDVDC->Pause(FALSE);
  1362. pMC->Run();
  1363. }
  1364. else if(m_iPlaybackMode == PM_CAPTURE) CAPTURE 格式
  1365. {
  1366. pMC->Stop(); // audio preview won't be in sync if we run it from paused state
  1367. pMC->Run();
  1368. }
  1369. }
  1370. catch (...)
  1371. {
  1372. SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA); 异常 就关闭视频
  1373. return;
  1374. }
  1375. SetTimer(TIMER_STREAMPOSPOLLER, 40, NULL); 位置信息
  1376. SetTimer(TIMER_STREAMPOSPOLLER2, 500, NULL); 位置2信息
  1377. SetTimer(TIMER_STATS, 1000, NULL); 状态信息
  1378. if(m_fFrameSteppingActive) // FIXME 第一次 设置声音
  1379. {
  1380. m_fFrameSteppingActive = false;
  1381. pBA->put_Volume(m_VolumeBeforeFrameStepping);
  1382. }
  1383. SetAlwaysOnTop(AfxGetAppSettings().iOnTop); 置顶
  1384. m_wndColorControlBar.CheckAbility(); 控件状态位置等信息
  1385. MoveVideoWindow(); 移动视频
  1386. }else if(m_iMediaLoadState == MLS_CLOSED){ 如果是关闭状态 则重新播放
  1387. if(m_WndSizeInited >= 2){
  1388. if(m_wndPlaylistBar.GetCount()){
  1389. OpenCurPlaylistItem();
  1390. //}else
  1391. // SendMessage(WM_COMMAND, ID_FILE_OPENMEDIA);
  1392. }
  1393. }
  1394. }
  1395. //KillTimer(TIMER_SNAP);
  1396. //SetTimer(TIMER_SNAP, 10000, NULL);
  1397. }
  1398. 进入OnFilePostOpenmedia() 分析
  1399. void CMainFrame::OnFilePostOpenmedia()
  1400. {
  1401. OpenSetupClipInfo(); 初始化剪切板信息
  1402. //A-B Control
  1403. m_aRefTime = 0;
  1404. m_bRefTime = 0;
  1405. ABControlOn = FALSE;
  1406. OpenSetupCaptureBar(); 初始化控件
  1407. AppSettings& s = AfxGetAppSettings();
  1408. m_wndColorControlBar.CheckAbility(); 检查能力
  1409. if(m_wndToolBar.IsVisible())
  1410. ShowControls(AfxGetAppSettings().nCS | CS_SEEKBAR, false); 显示控件
  1411. __int64 rtDur = 0;
  1412. pMS->GetDuration(&rtDur); 从视频接口获得当前位置
  1413. m_wndPlaylistBar.SetCurTime(rtDur); 设置控件位置
  1414. if(m_iPlaybackMode == PM_CAPTURE)
  1415. {
  1416. ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
  1417. ShowControlBar(&m_wndCaptureBar, TRUE, TRUE);
  1418. }
  1419. / /重要:不能调用任何窗口封邮件之前
  1420. / /这一点上,它会僵局时OpenMediaPrivate
  1421. / /仍在运行,并创建渲染窗口
  1422. / /相同的工作者线程
  1423. std::wstring szFileHash = HashController::GetInstance()->GetSPHash(m_fnCurPlayingFile);
  1424. CString FPath = szFileHash.c_str();
  1425. 加载第二字幕
  1426. if(m_pCAP && (!m_fAudioOnly || m_fRealMediaGraph))
  1427. {
  1428. if(m_pSubStreams.GetCount() == 0){
  1429. if ( !m_wndPlaylistBar.m_pl.szPlayListSub.IsEmpty() ){
  1430. int delayms = 0 - m_wndPlaylistBar.GetTotalTimeBeforeCur();
  1431. LoadSubtitle(m_wndPlaylistBar.m_pl.szPlayListSub, delayms , true);
  1432. }
  1433. }
  1434. if(s.fEnableSubtitles && m_pSubStreams.GetCount() > 0){
  1435. BOOL HavSubs1 = FALSE;
  1436. Sql 操作 搜索历史记录
  1437. if(AfxGetMyApp()->sqlite_local_record ){
  1438. CString szSQL;
  1439. szSQL.Format(L"SELECT subid FROM histories WHERE fpath = \"%s\" ", FPath);
  1440. int subid = AfxGetMyApp()->sqlite_local_record->get_single_int_from_sql(szSQL.GetBuffer(), -1);
  1441. if(subid >= 0){
  1442. //SVP_LogMsg5(L"subid %d %d", subid, m_pSubStreams.GetCount());
  1443. int i = subid;
  1444. 字幕流?
  1445. POSITION pos = m_pSubStreams.GetHeadPosition();
  1446. while(pos && i >= 0)
  1447. {
  1448. 循环查找
  1449. CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
  1450. if(i < pSubStream->GetStreamCount())
  1451. {
  1452. SendStatusMessage(ResStr(IDS_OSD_MSG_RESTORE_TO_LAST_REMEMBER_SUBTITLE_TRACK),3000);
  1453. CAutoLock cAutoLock(&m_csSubLock);
  1454. pSubStream->SetStream(i);
  1455. SetSubtitle(pSubStream);
  1456. HavSubs1 = true;
  1457. break;
  1458. }
  1459. i -= pSubStream->GetStreamCount();
  1460. }
  1461. }
  1462. }
  1463. 字幕流?
  1464. if(!HavSubs1 && !s.sSubStreamName1.IsEmpty()){
  1465. POSITION pos = m_pSubStreams.GetHeadPosition();
  1466. while(pos){
  1467. CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
  1468. if(!pSubStream) continue;
  1469. for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++)
  1470. {
  1471. WCHAR* pName = NULL;
  1472. if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, NULL)))
  1473. {
  1474. CString name(pName);
  1475. //SVP_LogMsg5(L"sub2 %s", name);
  1476. if( name == s.sSubStreamName1){
  1477. SetSubtitle( pSubStream);
  1478. HavSubs1 = true;
  1479. }
  1480. CoTaskMemFree(pName);
  1481. if(HavSubs1)
  1482. break;
  1483. }
  1484. }
  1485. if(HavSubs1)
  1486. break;
  1487. }
  1488. }
  1489. 设置字幕流
  1490. if(!HavSubs1){
  1491. POSITION pos = m_pSubStreams.GetHeadPosition();
  1492. while(pos){
  1493. CComPtr<ISubStream> pSubStream = m_pSubStreams.GetNext(pos);
  1494. if(!pSubStream) continue;
  1495. for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++)
  1496. {
  1497. WCHAR* pName = NULL;
  1498. if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, NULL)))
  1499. {
  1500. CString name(pName);
  1501. //SVP_LogMsg5(L"sub2 %s", name);
  1502. if( name.Find(L"plain text") > 0){ //Apple Text Media Handler (plain text)
  1503. SetSubtitle( pSubStream);
  1504. HavSubs1 = true;
  1505. }
  1506. CoTaskMemFree(pName);
  1507. if(HavSubs1)
  1508. break;
  1509. }
  1510. }
  1511. if(HavSubs1)
  1512. break;
  1513. }
  1514. }
  1515. 字幕流
  1516. if(!HavSubs1)
  1517. SetSubtitle(m_pSubStreams.GetHead());
  1518. if(s.fAutoloadSubtitles2 && m_pSubStreams2.GetCount() > 1 ){
  1519. BOOL HavSubs = false;
  1520. if(AfxGetMyApp()->sqlite_local_record ){
  1521. CString szSQL;
  1522. szSQL.Format(L"SELECT subid2 FROM histories WHERE fpath = \"%s\" ", FPath);
  1523. int subid = AfxGetMyApp()->sqlite_local_record->get_single_int_from_sql(szSQL.GetBuffer(), -1);
  1524. if(subid >= 0){
  1525. //SVP_LogMsg5(L"subid %d %d", subid, m_pSubStreams.GetCount());
  1526. int i = subid;
  1527. POSITION pos = m_pSubStreams2.GetHeadPosition();
  1528. while(pos && i >= 0)
  1529. {
  1530. CComPtr<ISubStream> pSubStream = m_pSubStreams2.GetNext(pos);
  1531. if(i < pSubStream->GetStreamCount())
  1532. {
  1533. CAutoLock cAutoLock(&m_csSubLock);
  1534. pSubStream->SetStream(i);
  1535. SetSubtitle2(pSubStream);
  1536. //SendStatusMessage(ResStr(IDS_OSD_MSG_RESTORE_TO_LAST_REMEMBER_SUBTITLE2_TRACK),3000);
  1537. HavSubs = true;
  1538. break;
  1539. }
  1540. i -= pSubStream->GetStreamCount();
  1541. }
  1542. }
  1543. }
  1544. 字幕流
  1545. if(!HavSubs && !s.sSubStreamName2.IsEmpty()){
  1546. POSITION pos = m_pSubStreams2.GetHeadPosition();
  1547. while(pos){
  1548. CComPtr<ISubStream> pSubStream = m_pSubStreams2.GetNext(pos);
  1549. if(!pSubStream) continue;
  1550. for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++)
  1551. {
  1552. WCHAR* pName = NULL;
  1553. if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, NULL)))
  1554. {
  1555. CString name(pName);
  1556. //SVP_LogMsg5(L"sub2 %s", name);
  1557. if((!s.sSubStreamName2.IsEmpty() && name == s.sSubStreamName2) ){
  1558. SetSubtitle2( pSubStream);
  1559. HavSubs = true;
  1560. }
  1561. CoTaskMemFree(pName);
  1562. if(HavSubs)
  1563. break;
  1564. }
  1565. }
  1566. if(HavSubs)
  1567. break;
  1568. }
  1569. }
  1570. 字幕流
  1571. if(!HavSubs){
  1572. POSITION pos = m_pSubStreams2.GetHeadPosition();
  1573. while(pos){
  1574. CComPtr<ISubStream> pSubStream = m_pSubStreams2.GetNext(pos);
  1575. if(!pSubStream) continue;
  1576. for(int i = 0, j = pSubStream->GetStreamCount(); i < j; i++)
  1577. {
  1578. WCHAR* pName = NULL;
  1579. if(SUCCEEDED(pSubStream->GetStreamInfo(i, &pName, NULL)))
  1580. {
  1581. CString name(pName);
  1582. //SVP_LogMsg5(L"sub2 %s", name);
  1583. if( ( name.Find(_T("en")) >= 0 || name.Find(_T("eng")) >= 0 || name.Find(_T("英文")) >= 0) ){
  1584. SetSubtitle2( pSubStream);
  1585. HavSubs = true;
  1586. }
  1587. CoTaskMemFree(pName);
  1588. if(HavSubs)
  1589. break;
  1590. }
  1591. }
  1592. if(HavSubs)
  1593. break;
  1594. }
  1595. }
  1596. if(!HavSubs){
  1597. POSITION pos = m_pSubStreams2.GetHeadPosition();
  1598. m_pSubStreams2.GetNext(pos);
  1599. if(pos)
  1600. SetSubtitle2( m_pSubStreams2.GetNext(pos));
  1601. }
  1602. }
  1603. }
  1604. //make sure the subtitle displayed
  1605. UpdateSubtitle(true); 设置字幕流
  1606. UpdateSubtitle2(true); 设置字幕流
  1607. }
  1608. 根据Sql查找历史 发送状态
  1609. if(AfxGetMyApp()->sqlite_local_record ){
  1610. CString szSQL;
  1611. szSQL.Format(L"SELECT audioid FROM histories WHERE fpath = \"%s\" ", FPath);
  1612. //SVP_LogMsg5(szSQL);
  1613. int audid = AfxGetMyApp()->sqlite_local_record->get_single_int_from_sql(szSQL.GetBuffer(), -1);
  1614. if(audid > 0){
  1615. SVP_LogMsg5(L"audid %d subs %d", audid, m_pSubStreams.GetCount());
  1616. CComQIPtr<IAMStreamSelect> pSS = FindFilter(__uuidof(CAudioSwitcherFilter), pGB);
  1617. if(!pSS) pSS = FindFilter(L"{D3CD7858-971A-4838-ACEC-40CA5D529DC8}", pGB);
  1618. if( pSS)
  1619. {
  1620. pSS->Enable(audid, AMSTREAMSELECTENABLE_ENABLE);
  1621. SendStatusMessage(ResStr(IDS_OSD_MSG_RESTORE_TO_LAST_REMEMBER_AUDIO_TRACK),3000);
  1622. }
  1623. }
  1624. }
  1625. 根据SQL 设置字幕
  1626. if (AfxGetMyApp()->sqlite_local_record)
  1627. {
  1628. CString szSQL;
  1629. if (s.fEnableSubtitles ){
  1630. szSQL.Format(L"SELECT subid FROM histories_stream WHERE fpath = \"%s\" ", FPath);
  1631. int subid = AfxGetMyApp()->sqlite_local_record->get_single_int_from_sql(szSQL.GetBuffer(), -1);
  1632. if(subid > 0){
  1633. OnPlayLanguage(subid);
  1634. }
  1635. }
  1636. szSQL.Format(L"SELECT audioid FROM histories_stream WHERE fpath = \"%s\" ", FPath);
  1637. int audid = AfxGetMyApp()->sqlite_local_record->get_single_int_from_sql(szSQL.GetBuffer(), -1);
  1638. if(audid > 0){
  1639. OnPlayLanguage(audid);
  1640. }
  1641. }
  1642. if(!m_pCAP && m_fAudioOnly){ / /这是我们第一次检测,这是仅音频文件
  1643. m_wndView.m_strAudioInfo.Empty();
  1644. //This is silly
  1645. if(!m_fLastIsAudioOnly)
  1646. ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
  1647. KillTimer(TIMER_TRANSPARENTTOOLBARSTAT);
  1648. SetTimer(TIMER_TRANSPARENTTOOLBARSTAT, 20,NULL);
  1649. rePosOSD(); 重新计算位置
  1650. }
  1651. {
  1652. WINDOWPLACEMENT wp;
  1653. wp.length = sizeof(wp);
  1654. GetWindowPlacement(&wp); 记录窗体位置
  1655. // restore magnification 只有音频的情况下
  1656. if(IsWindowVisible() && AfxGetAppSettings().fRememberZoomLevel
  1657. && !(m_fFullScreen || wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED))
  1658. {
  1659. if(m_fAudioOnly && m_fLastIsAudioOnly){
  1660. }else{
  1661. ZoomVideoWindow(); 全屏播放
  1662. // m_fFullScreen意思现在是指当前播放模式是全屏还是非全屏,如果是全屏就会在Toogle中变为非全屏,反之亦然
  1663. if (!m_fFullScreen)
  1664. {
  1665. PlayerPreference* pref = PlayerPreference::GetInstance();
  1666. bool bToBeFullScreen = pref->GetIntVar(INTVAR_TOGGLEFULLSCRENWHENPLAYBACKSTARTED);
  1667. if (bToBeFullScreen) 是否全屏
  1668. {
  1669. ToggleFullscreen(true, true);
  1670. SetCursor(NULL);
  1671. }
  1672. }
  1673. }
  1674. m_fLastIsAudioOnly = m_fAudioOnly;
  1675. }
  1676. }
  1677. if(!m_fAudioOnly && (s.nCLSwitches&CLSW_FULLSCREEN)) 全屏时
  1678. {
  1679. SendMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
  1680. s.nCLSwitches &= ~CLSW_FULLSCREEN;
  1681. }
  1682. m_bDxvaInUse = false;
  1683. m_bMustUseExternalTimer = false;
  1684. m_haveSubVoted = false;
  1685. m_DXVAMode = _T("");
  1686. 视频解码接口
  1687. CComQIPtr<IMPCVideoDecFilter> pMDF = FindFilter(__uuidof(CMPCVideoDecFilter), pGB);
  1688. if(pMDF){
  1689. GUID* DxvaGui = NULL;
  1690. DxvaGui = pMDF->GetDXVADecoderGuid();
  1691. if (DxvaGui != NULL)
  1692. {
  1693. m_DXVAMode = GetDXVAMode (DxvaGui);
  1694. m_bDxvaInUse = (m_DXVAMode != _T("Not using DXVA"));
  1695. }
  1696. }else if(FindFilter(L"{09571A4B-F1FE-4C60-9760-DE6D310C7C31}", pGB)) {
  1697. if(s.bHasCUDAforCoreAVC){
  1698. m_bDxvaInUse = true;
  1699. m_DXVAMode = _T("CoreAVC");
  1700. }
  1701. }
  1702. /*
  1703. CComQIPtr<IWMReaderAdvanced2> pWMR = FindFilter(__uuidof(IWMReaderAdvanced2), pGB);
  1704. if(pWMR){
  1705. pWMR->SetPlayMode(WMT_PLAY_MODE_STREAMING);
  1706. AfxMessageBox(L"1");
  1707. }*/
  1708. if(FindFilter(L"{FA10746C-9B63-4B6C-BC49-FC300EA5F256}", pGB)){
  1709. m_bEVRInUse = true;
  1710. }
  1711. if( FindFilter(L"{6F513D27-97C3-453C-87FE-B24AE50B1601}", pGB)){//m_bEVRInUse
  1712. SVP_LogMsg5(L"Has Divx H264 Dec and EVR so use External Timer");
  1713. m_bMustUseExternalTimer = true;
  1714. }
  1715. RedrawNonClientArea(); 重新绘画客户区
  1716. if(m_iPlaybackMode == PM_FILE){ 回放模式
  1717. if(!s.bDontNeedSVPSubFilter && !m_pCAP && s.iSVPRenderType && !m_fAudioOnly ){
  1718. s.iSVPRenderType = 0;
  1719. SendStatusMessage( ResStr(IDS_OSD_MSG_DEVICE_NOT_SUPPORT_VIDEO_QMODE), 2000);
  1720. }
  1721. if(m_fAudioOnly && m_fnCurPlayingFile.Find(L"://") < 0){
  1722. 只有音频时 查找歌词
  1723. //find lyric file
  1724. m_LyricFilePaths.RemoveAll();
  1725. CAtlArray<CString> lrcSearchPaths;
  1726. lrcSearchPaths.Add(_T("."));
  1727. lrcSearchPaths.Add(s.GetSVPSubStorePath());
  1728. CAtlArray<LrcFile> ret;
  1729. int bGotLrc = 0 ;
  1730. m_Lyric.GetLrcFileNames( m_fnCurPlayingFile , lrcSearchPaths, ret);
  1731. if( ret.GetCount() ){
  1732. LrcFile oLrcFile = ret.GetAt(0);
  1733. if( m_Lyric.LoadLyricFile( oLrcFile.fn) >= 0) 装载歌词
  1734. {
  1735. //maybe we should do something here?
  1736. if(m_Lyric.m_has_lyric)
  1737. bGotLrc = 1;
  1738. }
  1739. }
  1740. if( !bGotLrc && s.autoDownloadSVPSub ) { 没有歌词 但自动下载
  1741. //debug
  1742. //m_Lyric.LoadLyricFile(L"D:\\-=SVN=-\\test.lrc");
  1743. m_Lyric.Empty();
  1744. //download it by thead
  1745. m_Lyric.title = GetClipInfo(IDS_INFOBAR_TITLE).c_str();
  1746. m_Lyric.artist = GetClipInfo(IDS_INFOBAR_AUTHOR).c_str();
  1747. m_Lyric.album = GetClipInfo(IDS_INFOBAR_DESCRIPTION).c_str();
  1748. m_Lyric.m_sz_current_music_file = m_fnCurPlayingFile;
  1749. //m_Lyric.m_stop_downloading = 1;
  1750. //TerminateThread(m_lyricDownloadThread , 0);
  1751. 启动线程下载
  1752. m_lyricDownloadThread = AfxBeginThread(lyric_fetch_Proc, &m_Lyric, THREAD_PRIORITY_LOWEST, 0, CREATE_SUSPENDED);
  1753. m_lyricDownloadThread->m_pMainWnd = AfxGetMainWnd();
  1754. m_lyricDownloadThread->ResumeThread();
  1755. }
  1756. }
  1757. }
  1758. // send sphash to remote 发送sphash到远程
  1759. m_wndToolBar.HideMovieShareBtn(TRUE);
  1760. UserShareController::GetInstance()->HideCommentPlane();
  1761. UserShareController::GetInstance()->CloseShooterMedia();
  1762. if(IsSomethingLoaded() && !m_fAudioOnly && (UINT)((INT64)rtDur/10000000) > 90)
  1763. {
  1764. m_movieShared = false;
  1765. m_wndToolBar.HideMovieShareBtn(FALSE);
  1766. SetTimer(TIMER_MOVIESHARE, 300000, NULL);
  1767. }
  1768. KillTimer(TIMER_IDLE_TASK);
  1769. }
  1770. 进入CMainFrame::OpenSetupCaptureBar 分析
  1771. void CMainFrame::OpenSetupCaptureBar() 初始化头导航
  1772. {
  1773. 初始化控件
  1774. if(m_iPlaybackMode == PM_CAPTURE)
  1775. {
  1776. if(pVidCap && pAMVSCCap)
  1777. {
  1778. CComQIPtr<IAMVfwCaptureDialogs> pVfwCD = pVidCap;
  1779. if(!pAMXBar && pVfwCD)
  1780. {
  1781. m_wndCaptureBar.m_capdlg.SetupVideoControls(m_VidDispName, pAMVSCCap, pVfwCD);
  1782. }
  1783. else
  1784. {
  1785. m_wndCaptureBar.m_capdlg.SetupVideoControls(m_VidDispName, pAMVSCCap, pAMXBar, pAMTuner);
  1786. }
  1787. }
  1788. if(pAudCap && pAMASC)
  1789. {
  1790. CInterfaceArray<IAMAudioInputMixer> pAMAIM;
  1791. BeginEnumPins(pAudCap, pEP, pPin)
  1792. {
  1793. if(CComQIPtr<IAMAudioInputMixer> pAIM = pPin)
  1794. pAMAIM.Add(pAIM);
  1795. }
  1796. EndEnumPins
  1797. m_wndCaptureBar.m_capdlg.SetupAudioControls(m_AudDispName, pAMASC, pAMAIM);
  1798. }
  1799. }
  1800. BuildGraphVideoAudio(
  1801. m_wndCaptureBar.m_capdlg.m_fVidPreview, false,
  1802. m_wndCaptureBar.m_capdlg.m_fAudPreview, false);
  1803. }
  1804. 进入CMainFrame::BuildGraphVideoAudio 分析
  1805. bool CMainFrame::BuildGraphVideoAudio(int fVPreview, bool fVCapture, int fAPreview, bool fACapture)
  1806. {
  1807. if(!pCGB) return(false); 不存在直接返回 关键是pCGB另一个
  1808. SaveMediaState;
  1809. HRESULT hr;
  1810. pGB->NukeDownstream(pVidCap);
  1811. pGB->NukeDownstream(pAudCap);
  1812. CleanGraph();
  1813. if(pAMVSCCap) hr = pAMVSCCap->SetFormat(&m_wndCaptureBar.m_capdlg.m_mtv);
  1814. if(pAMVSCPrev) hr = pAMVSCPrev->SetFormat(&m_wndCaptureBar.m_capdlg.m_mtv);
  1815. if(pAMASC) hr = pAMASC->SetFormat(&m_wndCaptureBar.m_capdlg.m_mta);
  1816. CComPtr<IBaseFilter> pVidBuffer = m_wndCaptureBar.m_capdlg.m_pVidBuffer;
  1817. CComPtr<IBaseFilter> pAudBuffer = m_wndCaptureBar.m_capdlg.m_pAudBuffer;
  1818. CComPtr<IBaseFilter> pVidEnc = m_wndCaptureBar.m_capdlg.m_pVidEnc;
  1819. CComPtr<IBaseFilter> pAudEnc = m_wndCaptureBar.m_capdlg.m_pAudEnc;
  1820. CComPtr<IBaseFilter> pMux = m_wndCaptureBar.m_capdlg.m_pMux;
  1821. CComPtr<IBaseFilter> pDst = m_wndCaptureBar.m_capdlg.m_pDst;
  1822. CComPtr<IBaseFilter> pAudMux = m_wndCaptureBar.m_capdlg.m_pAudMux;
  1823. CComPtr<IBaseFilter> pAudDst = m_wndCaptureBar.m_capdlg.m_pAudDst;
  1824. bool fFileOutput = (pMux && pDst) || (pAudMux && pAudDst);
  1825. bool fCapture = (fVCapture || fACapture);
  1826. if(pAudCap)
  1827. {
  1828. AM_MEDIA_TYPE* pmt = &m_wndCaptureBar.m_capdlg.m_mta;
  1829. int ms = (fACapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fAudOutput) ? AUDIOBUFFERLEN : 60;
  1830. if(pMux != pAudMux && fACapture) SetLatency(pAudCap, -1);
  1831. else if(pmt->pbFormat) SetLatency(pAudCap, ((WAVEFORMATEX*)pmt->pbFormat)->nAvgBytesPerSec * ms / 1000);
  1832. }
  1833. CComPtr<IPin> pVidCapPin, pVidPrevPin, pAudCapPin, pAudPrevPin;
  1834. BuildToCapturePreviewPin(pVidCap, &pVidCapPin, &pVidPrevPin, pAudCap, &pAudCapPin, &pAudPrevPin);
  1835. // if(pVidCap)
  1836. {
  1837. bool fVidPrev = pVidPrevPin && fVPreview;
  1838. bool fVidCap = pVidCapPin && fVCapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fVidOutput;
  1839. if(fVPreview == 2 && !fVidCap && pVidCapPin)
  1840. {
  1841. pVidPrevPin = pVidCapPin;
  1842. pVidCapPin = NULL;
  1843. }
  1844. if(fVidPrev)
  1845. {
  1846. m_pCAP = NULL;
  1847. m_pCAP2 = NULL;
  1848. m_pCAPR = NULL;
  1849. pGB->Render(pVidPrevPin);
  1850. pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter), (void**)&m_pCAP, FALSE);
  1851. pGB->FindInterface(__uuidof(ISubPicAllocatorPresenterRender), (void**)&m_pCAPR, TRUE);
  1852. pGB->FindInterface(__uuidof(ISubPicAllocatorPresenter2), (void**)&m_pCAP2, TRUE);
  1853. }
  1854. if(fVidCap)
  1855. {
  1856. IBaseFilter* pBF[3] = {pVidBuffer, pVidEnc, pMux};
  1857. HRESULT hr = BuildCapture(pVidCapPin, pBF, MEDIATYPE_Video, &m_wndCaptureBar.m_capdlg.m_mtcv);
  1858. }
  1859. pAMDF = NULL;
  1860. pCGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVidCap, IID_IAMDroppedFrames, (void**)&pAMDF);
  1861. }
  1862. // if(pAudCap)
  1863. {
  1864. bool fAudPrev = pAudPrevPin && fAPreview;
  1865. bool fAudCap = pAudCapPin && fACapture && fFileOutput && m_wndCaptureBar.m_capdlg.m_fAudOutput;
  1866. if(fAPreview == 2 && !fAudCap && pAudCapPin)
  1867. {
  1868. pAudPrevPin = pAudCapPin;
  1869. pAudCapPin = NULL;
  1870. }
  1871. if(fAudPrev)
  1872. {
  1873. pGB->Render(pAudPrevPin);
  1874. }
  1875. if(fAudCap)
  1876. {
  1877. IBaseFilter* pBF[3] = {pAudBuffer, pAudEnc, pAudMux ? pAudMux : pMux};
  1878. HRESULT hr = BuildCapture(pAudCapPin, pBF, MEDIATYPE_Audio, &m_wndCaptureBar.m_capdlg.m_mtca);
  1879. }
  1880. }
  1881. if((pVidCap || pAudCap) && fCapture && fFileOutput)
  1882. {
  1883. if(pMux != pDst)
  1884. {
  1885. hr = pGB->AddFilter(pDst, L"File Writer V/A");
  1886. hr = pGB->ConnectFilter(GetFirstPin(pMux, PINDIR_OUTPUT), pDst);
  1887. }
  1888. if(CComQIPtr<IConfigAviMux> pCAM = pMux)
  1889. {
  1890. int nIn, nOut, nInC, nOutC;
  1891. CountPins(pMux, nIn, nOut, nInC, nOutC);
  1892. pCAM->SetMasterStream(nInC-1);
  1893. // pCAM->SetMasterStream(-1);
  1894. pCAM->SetOutputCompatibilityIndex(FALSE);
  1895. }
  1896. if(CComQIPtr<IConfigInterleaving> pCI = pMux)
  1897. {
  1898. // if(FAILED(pCI->put_Mode(INTERLEAVE_CAPTURE)))
  1899. if(FAILED(pCI->put_Mode(INTERLEAVE_NONE_BUFFERED)))
  1900. pCI->put_Mode(INTERLEAVE_NONE);
  1901. REFERENCE_TIME rtInterleave = 10000i64*AUDIOBUFFERLEN, rtPreroll = 0;//10000i64*500
  1902. pCI->put_Interleaving(&rtInterleave, &rtPreroll);
  1903. }
  1904. if(pMux != pAudMux && pAudMux != pAudDst)
  1905. {
  1906. hr = pGB->AddFilter(pAudDst, L"File Writer A");
  1907. hr = pGB->ConnectFilter(GetFirstPin(pAudMux, PINDIR_OUTPUT), pAudDst);
  1908. }
  1909. }
  1910. REFERENCE_TIME stop = MAX_TIME;
  1911. hr = pCGB->ControlStream(&PIN_CATEGORY_CAPTURE, NULL, NULL, NULL, &stop, 0, 0); // stop in the infinite
  1912. CleanGraph();
  1913. OpenSetupVideo();
  1914. OpenSetupAudio();
  1915. RestoreMediaState;
  1916. return(true);
  1917. }
  1918. OnFilePostOpenmedia() 中 SetTimer(TIMER_MOVIESHARE, 300000, NULL);
  1919. case TIMER_MOVIESHARE:
  1920. {
  1921. KillTimer(TIMER_MOVIESHARE);
  1922. if (IsSomethingLoaded() && !m_fAudioOnly && !m_movieShared) 已经加载 不是音频 文件不共享
  1923. {
  1924. m_movieShared = true;
  1925. std::wstring uuid, moviehash;
  1926. SPlayerGUID::GenerateGUID(uuid);
  1927. UserShareController* usc = UserShareController::GetInstance();
  1928. usc->CreateCommentPlane();
  1929. moviehash = HashController::GetInstance()->GetSPHash(m_fnCurPlayingFile);
  1930. usc->ShareMovie(uuid, moviehash, m_fnCurPlayingFile.GetString());
  1931. }
  1932. }
  1933. break;
  1934. 进入CMainFrame::ZoomVideoWindow 分析
  1935. void CMainFrame::ZoomVideoWindow(double scale)
  1936. {
  1937. if(m_iMediaLoadState != MLS_LOADED) return; 没有装载 直接退出 ?
  1938. AppSettings& s = AfxGetAppSettings();
  1939. if(s.bUserAeroUI()){ 用户区域UI
  1940. m_lTransparentToolbarStat = 0;
  1941. m_wndFloatToolBar->ShowWindow(SW_HIDE);
  1942. }
  1943. BOOL bThisIsAutoZoom = false; 自动大小
  1944. if(scale <= 0)
  1945. {
  1946. bThisIsAutoZoom = true;
  1947. scale =
  1948. s.iZoomLevel == 0 ? 0.5 :
  1949. s.iZoomLevel == 1 ? 1.0 :
  1950. s.iZoomLevel == 2 ? 2.0 :
  1951. s.iZoomLevel == 3 ? GetZoomAutoFitScale() :
  1952. 1.0;
  1953. m_last_size_of_current_kind_of_video.cx = -1;
  1954. m_last_size_of_current_kind_of_video.cy = -1;
  1955. }
  1956. if(m_fFullScreen) 如果全屏 则全屏
  1957. {
  1958. OnViewFullscreen();
  1959. }
  1960. MINMAXINFO mmi;
  1961. OnGetMinMaxInfo(&mmi);
  1962. CRect r;
  1963. int w = 0, h = 0;
  1964. if(!m_fAudioOnly) 不是音频
  1965. {
  1966. CSize arxy = m_original_size_of_current_video = GetVideoSize();
  1967. long lWidth = int(arxy.cx * scale + 0.5);
  1968. long lHeight = int(arxy.cy * scale + 0.5);
  1969. CString string_remember_windows_size_for_this_video_size_parm;
  1970. string_remember_windows_size_for_this_video_size_parm.Format(L"ORGSIZE%dx%d", m_original_size_of_current_video.cx, m_original_size_of_current_video.cy );
  1971. AppSettings& s = AfxGetAppSettings();
  1972. long lPerfWidth = m_last_size_of_current_kind_of_video.cx = AfxGetMyApp()->GetProfileInt(ResStr(IDS_R_SETTINGS)+L"REMENBERWNDSIZE", string_remember_windows_size_for_this_video_size_parm+L"W", -1);
  1973. long lPerfHeight = m_last_size_of_current_kind_of_video.cy = AfxGetMyApp()->GetProfileInt(ResStr(IDS_R_SETTINGS)+L"REMENBERWNDSIZE", string_remember_windows_size_for_this_video_size_parm+L"H", -1);
  1974. DWORD style = GetStyle();
  1975. CRect r3 ,r4;
  1976. GetWindowRect(r3);
  1977. m_wndView.GetWindowRect(r4);
  1978. //GetClientRect(&r1);
  1979. //m_wndView.GetClientRect(&r2);
  1980. int wDelta = 0;
  1981. int hDelta = 0;
  1982. wDelta = r3.Width() - r4.Width();
  1983. hDelta = r3.Height() - r4.Height();
  1984. if(style&WS_CAPTION)
  1985. {
  1986. //h += GetSystemMetrics(SM_CYCAPTION);
  1987. //w += 2; h += 2; // for the 1 pixel wide sunken frame
  1988. //w += 2; h += 3; // for the inner black border
  1989. }
  1990. GetWindowRect(r);
  1991. if (lHeight + hDelta < 280 || lWidth + wDelta < 480) {
  1992. int w1 = 480 - wDelta;
  1993. int h1 = 280 - hDelta;
  1994. SVP_ASSERT(w1 > 0);
  1995. SVP_ASSERT(h1 > 0);
  1996. // Re-evaluate current 'w' and 'h' to keep aspect ratio
  1997. int h2 = arxy.cy * w1 / arxy.cx, w2 = arxy.cx * h1 / arxy.cy;
  1998. // Choose by the fitting rectangle.
  1999. if (h2 + hDelta >= 280) {
  2000. w = 480;
  2001. h = h2 + hDelta;
  2002. } else {
  2003. w = w2 + wDelta;
  2004. h = 280;
  2005. }
  2006. } else {
  2007. h = lHeight + hDelta;
  2008. w = lWidth + wDelta;
  2009. }
  2010. if(bThisIsAutoZoom && 0){
  2011. double mratio = (double)lHeight/lWidth;
  2012. //SVP_LogMsg5(L"%d %d %f %d %d %f",h , w, w * mratio + (h - lHeight), lHeight, lWidth, mratio);
  2013. h = max(h , w * mratio + (h - lHeight));
  2014. }
  2015. if(bThisIsAutoZoom && lPerfWidth > 240 && lPerfHeight > 120)
  2016. {
  2017. //Only do this if its auto zoom
  2018. w = lPerfWidth;
  2019. h = lPerfHeight;
  2020. }
  2021. }
  2022. else
  2023. {
  2024. GetWindowRect(r);
  2025. //w = r.Width(); //;mmi.ptMinTrackSize.x;
  2026. //h = r.Height();//;mmi.ptMinTrackSize.y;
  2027. w = 320;
  2028. if(s.bUserAeroUI()){
  2029. w /= 0.9;
  2030. }
  2031. h = 110;
  2032. AppSettings& s = AfxGetAppSettings();
  2033. long lPerfWidth = m_last_size_of_current_kind_of_video.cx = AfxGetMyApp()->GetProfileInt(ResStr(IDS_R_SETTINGS)+L"REMENBERWNDSIZE", L"ORGSIZE0x0W", -1);
  2034. long lPerfHeight = m_last_size_of_current_kind_of_video.cy = AfxGetMyApp()->GetProfileInt(ResStr(IDS_R_SETTINGS)+L"REMENBERWNDSIZE", L"ORGSIZE0x0H", -1);
  2035. w = max(w, lPerfWidth);
  2036. h = max(h, lPerfHeight);
  2037. }
  2038. // center window
  2039. //if(!s.fRememberWindowPos)
  2040. {
  2041. CPoint cp = r.CenterPoint();
  2042. r.left = cp.x - w/2;
  2043. r.top = cp.y - h/2;
  2044. }
  2045. r.right = r.left + w;
  2046. r.bottom = r.top + h;
  2047. MONITORINFO mi;
  2048. mi.cbSize = sizeof(MONITORINFO);
  2049. 获得窗体信息
  2050. GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
  2051. if(r.right > mi.rcWork.right) r.OffsetRect(mi.rcWork.right-r.right, 0);
  2052. if(r.left < mi.rcWork.left) r.OffsetRect(mi.rcWork.left-r.left, 0);
  2053. if(r.bottom > mi.rcWork.bottom) r.OffsetRect(0, mi.rcWork.bottom-r.bottom);
  2054. if(r.top < mi.rcWork.top) r.OffsetRect(0, mi.rcWork.top-r.top);
  2055. CRect rcWork(mi.rcWork);
  2056. if(r.Width() > rcWork.Width() ){
  2057. r.left = rcWork.left;
  2058. r.right = rcWork.right;
  2059. }
  2060. if(r.Height() > rcWork.Height() ){
  2061. r.top = rcWork.top;
  2062. r.bottom = rcWork.bottom;
  2063. }
  2064. if(m_fFullScreen || !s.HasFixedWindowSize())
  2065. {
  2066. MoveWindow(r);
  2067. }
  2068. //AfxMessageBox(_T("1"));
  2069. //Sleep(200);
  2070. // ShowWindow(SW_SHOWNORMAL);
  2071. MoveVideoWindow();
  2072. }
  2073. 进入CMainFrame::ToggleFullscreen 分析
  2074. void CMainFrame::ToggleFullscreen(bool fToNearest, bool fSwitchScreenResWhenHasTo)
  2075. {
  2076. CRect r;
  2077. m_lastTimeToggleFullsreen = AfxGetMyApp()->GetPerfCounter();
  2078. // const CWnd* pWndInsertAfter;
  2079. DWORD dwRemove = 0, dwAdd = 0;
  2080. DWORD dwRemoveEx = 0, dwAddEx = 0;
  2081. HMENU hMenu;
  2082. if(!m_fFullScreen)
  2083. { 不是全屏
  2084. if(m_wndPlaylistBar.IsVisible()){
  2085. m_fPlaylistBeforeToggleFullScreen = true;
  2086. ShowControlBar(&m_wndPlaylistBar, FALSE, TRUE);
  2087. }
  2088. GetWindowRect(&m_lastWindowRect);
  2089. dispmode& dm = AfxGetAppSettings().dmFullscreenRes;
  2090. m_dmBeforeFullscreen.fValid = false;
  2091. if(dm.fValid && fSwitchScreenResWhenHasTo)
  2092. {
  2093. GetCurDispMode(m_dmBeforeFullscreen);
  2094. SetDispMode(dm);
  2095. }
  2096. MONITORINFO mi;
  2097. mi.cbSize = sizeof(MONITORINFO);
  2098. GetMonitorInfo(MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), &mi);
  2099. dwRemove = WS_CAPTION|WS_THICKFRAME;
  2100. if(fToNearest) r = mi.rcMonitor;
  2101. else GetDesktopWindow()->GetWindowRect(&r);
  2102. hMenu = NULL;
  2103. }
  2104. else
  2105. {
  2106. 全屏
  2107. if( AfxGetAppSettings().htpcmode){
  2108. return;
  2109. }
  2110. if( m_fPlaylistBeforeToggleFullScreen )
  2111. ShowControlBar(&m_wndPlaylistBar, TRUE, TRUE);
  2112. if(m_dmBeforeFullscreen.fValid)
  2113. SetDispMode(m_dmBeforeFullscreen);
  2114. dwAdd = (AfxGetAppSettings().fHideCaptionMenu ? 0 : WS_CAPTION) | WS_THICKFRAME;
  2115. r = m_lastWindowRect;
  2116. hMenu = NULL;//AfxGetAppSettings().fHideCaptionMenu ? NULL : m_hMenuDefault;
  2117. }
  2118. //bool fAudioOnly = m_fAudioOnly;
  2119. //m_fAudioOnly = true;
  2120. m_fFullScreen = !m_fFullScreen;
  2121. SetAlwaysOnTop(AfxGetAppSettings().iOnTop);
  2122. 修改属性 进行全屏
  2123. ModifyStyle(dwRemove, dwAdd, SWP_NOZORDER);
  2124. ModifyStyleEx(dwRemoveEx, dwAddEx, SWP_NOZORDER);
  2125. ::SetMenu(m_hWnd, hMenu);
  2126. SetWindowPos(NULL, r.left, r.top, r.Width(), r.Height(), SWP_NOZORDER|SWP_NOSENDCHANGING /*SWP_FRAMECHANGED*/);
  2127. RedrawNonClientArea();
  2128. KillTimer(TIMER_FULLSCREENCONTROLBARHIDER);
  2129. KillTimer(TIMER_FULLSCREENMOUSEHIDER);
  2130. if(m_fFullScreen)
  2131. {
  2132. // SVP_LogMsg5(L"Fullscreen");
  2133. m_fHideCursor = true;
  2134. SetTimer(TIMER_FULLSCREENMOUSEHIDER, 800, NULL);
  2135. ShowControls(CS_NONE, false);
  2136. }
  2137. else
  2138. {
  2139. m_lastMouseMove.x = m_lastMouseMove.y = -1;
  2140. m_fHideCursor = false;
  2141. ShowControls(AfxGetAppSettings().nCS);
  2142. }
  2143. m_wndView.SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER);
  2144. //m_fAudioOnly = fAudioOnly;
  2145. rePosOSD();
  2146. MoveVideoWindow();
  2147. // insert after the HWND_TOP if the player is not full screen
  2148. if (m_fFullScreen) 全屏的话 就置顶
  2149. ::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE);
  2150. else
  2151. ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOMOVE);
  2152. }
  2153. TIMER_STREAMPOSPOLLER: 定时事件
  2154. case TIMER_STREAMPOSPOLLER:
  2155. if (m_iMediaLoadState == MLS_LOADED)
  2156. _HandleTimer_StreamPosPoller();
  2157. break;
  2158. void CMainFrame::_HandleTimer_StreamPosPoller() 处理位置信息 比如播放进度
  2159. {
  2160. REFERENCE_TIME rtNow = 0, rtDur = 0;
  2161. if (m_iPlaybackMode == PM_FILE)
  2162. {
  2163. pMS->GetCurrentPosition(&rtNow);
  2164. pMS->GetDuration(&rtDur);
  2165. if (m_rtDurationOverride >= 0)
  2166. rtDur = m_rtDurationOverride;
  2167. m_wndSeekBar.Enable(rtDur > 0);
  2168. m_wndSeekBar.SetRange(0, rtDur);
  2169. m_wndSeekBar.SetPos(rtNow);
  2170. }
  2171. else if (m_iPlaybackMode == PM_CAPTURE)
  2172. {
  2173. if (m_fCapturing && m_wndCaptureBar.m_capdlg.m_pMux)
  2174. {
  2175. CComQIPtr<IMediaSeeking> pMuxMS = m_wndCaptureBar.m_capdlg.m_pMux;
  2176. if (!pMuxMS || FAILED(pMuxMS->GetCurrentPosition(&rtNow)))
  2177. rtNow = 0;
  2178. }
  2179. if (m_rtDurationOverride >= 0)
  2180. rtDur = m_rtDurationOverride;
  2181. m_wndSeekBar.Enable(false);
  2182. m_wndSeekBar.SetRange(0, rtDur);
  2183. m_wndSeekBar.SetPos(rtNow);
  2184. /*
  2185. if (m_fCapturing)
  2186. {
  2187. if (rtNow > 10000i64*1000*60*60*3)
  2188. m_wndCaptureBar.m_capdlg.OnRecord();
  2189. }
  2190. */
  2191. }
  2192. if (m_pCAP && (m_iPlaybackMode != PM_FILE || m_bMustUseExternalTimer))
  2193. {
  2194. g_bExternalSubtitleTime = true;
  2195. AfxGetAppSettings().bExternalSubtitleTime = true;
  2196. if (pDVDI)
  2197. {
  2198. DVD_PLAYBACK_LOCATION2 Location;
  2199. if (pDVDI->GetCurrentLocation(&Location) == S_OK)
  2200. {
  2201. double fps = Location.TimeCodeFlags == DVD_TC_FLAG_25fps ? 25.0
  2202. : Location.TimeCodeFlags == DVD_TC_FLAG_30fps ? 30.0
  2203. : Location.TimeCodeFlags == DVD_TC_FLAG_DropFrame ? 29.97
  2204. : 25.0;
  2205. LONGLONG rtTimeCode = HMSF2RT(Location.TimeCode, fps);
  2206. m_pCAP->SetTime(rtTimeCode);
  2207. }
  2208. else
  2209. m_pCAP->SetTime(/*rtNow*/m_wndSeekBar.GetPos());
  2210. }
  2211. else
  2212. m_pCAP->SetTime(/*rtNow*/m_wndSeekBar.GetPos());
  2213. }
  2214. else
  2215. {
  2216. g_bExternalSubtitleTime = false;
  2217. AfxGetAppSettings().bExternalSubtitleTime = false;
  2218. }
  2219. }
  2220. TIMER_STREAMPOSPOLLER2: 定时设置
  2221. case TIMER_STREAMPOSPOLLER2:
  2222. if (m_iMediaLoadState == MLS_LOADED) 设置位置 和 时间
  2223. {
  2224. __int64 start, stop, pos;
  2225. m_wndSeekBar.GetRange(start, stop);
  2226. pos = m_wndSeekBar.GetPosReal();
  2227. if (ABControlOn && m_bRefTime > m_aRefTime && GetMediaState() == State_Running)
  2228. {
  2229. if (pos > m_bRefTime)
  2230. //goto aRefTimer
  2231. SeekTo(m_aRefTime, 0);
  2232. }
  2233. GUID tf;
  2234. pMS->GetTimeFormat(&tf);
  2235. if (m_iPlaybackMode == PM_CAPTURE && !m_fCapturing)
  2236. {
  2237. CString str = _T("Live");
  2238. long lChannel = 0, lVivSub = 0, lAudSub = 0;
  2239. if (pAMTuner
  2240. && m_wndCaptureBar.m_capdlg.IsTunerActive()
  2241. && SUCCEEDED(pAMTuner->get_Channel(&lChannel, &lVivSub, &lAudSub)))
  2242. {
  2243. CString ch;
  2244. ch.Format(_T(" (ch%d)"), lChannel);
  2245. str += ch;
  2246. }
  2247. //m_wndStatusBar.SetStatusTimer(str);
  2248. m_wndToolBar.SetStatusTimer(str);
  2249. }
  2250. else
  2251. {
  2252. double pRate;
  2253. if (E_NOTIMPL == pMS->GetRate(&pRate))
  2254. pRate = 0;
  2255. m_wndToolBar.SetStatusTimer(pos, stop, 0, &tf, pRate);
  2256. //m_wndToolBar.SetStatusTimer(str);
  2257. }
  2258. if (m_pCAPR && GetMediaState() == State_Paused)
  2259. m_pCAPR->Paint(true);
  2260. }
  2261. break;
  2262. case TIMER_STATS: 定时 事件
  2263. _HandleTimer_Stats(); 处理事件状态
  2264. break;
  2265. void CMainFrame::_HandleTimer_Stats()
  2266. {
  2267. m_l_been_playing_sec++;
  2268. if (AfxGetMyApp()->IsWin7() && pTBL)
  2269. {
  2270. try
  2271. {
  2272. BOOL bHasValue = 0;
  2273. BOOL bSetPaused = 0;
  2274. if (IsSomethingLoaded()) 确认已经加载
  2275. {
  2276. //TBPF_PAUSED
  2277. //TBPF_NORMAL
  2278. //TBPF_INDETERMINATE
  2279. switch (GetMediaState())
  2280. {
  2281. case State_Paused:
  2282. //not using TBPF_PAUSED since it hide progress
  2283. pTBL->SetProgressState(m_hWnd,TBPF_NORMAL);
  2284. bSetPaused = true;
  2285. bHasValue = true;
  2286. break;
  2287. case State_Running:
  2288. pTBL->SetProgressState(m_hWnd,TBPF_NORMAL);
  2289. bHasValue = true;
  2290. break;
  2291. case State_Stopped:
  2292. pTBL->SetProgressState(m_hWnd,TBPF_NOPROGRESS);
  2293. break;
  2294. }
  2295. }
  2296. else
  2297. pTBL->SetProgressState(m_hWnd,TBPF_NOPROGRESS);
  2298. if (bHasValue)
  2299. {
  2300. __int64 iSeekStart, iSeekStop;
  2301. m_wndSeekBar.GetRange(iSeekStart, iSeekStop);
  2302. __int64 iSeekPos = m_wndSeekBar.GetPosReal();
  2303. pTBL->SetProgressValue(m_hWnd, iSeekPos ,(iSeekStop - iSeekStart));
  2304. }
  2305. if (bSetPaused)
  2306. pTBL->SetProgressState(m_hWnd,TBPF_PAUSED);
  2307. }
  2308. catch (...)
  2309. {
  2310. pTBL->Release();
  2311. pTBL = NULL;
  2312. }
  2313. }
  2314. if (IsSomethingLoaded() && m_fAudioOnly && (!m_Lyric.m_has_lyric || m_wndView.m_strAudioInfo.IsEmpty()))
  2315. { 已经加载 是音频 没有歌词
  2316. m_wndView.m_AudioInfoCounter++;
  2317. BOOL bHaveInfo = false;
  2318. for (int i = 0; i < 4; i++)
  2319. {
  2320. if ((m_wndView.m_AudioInfoCounter%4) == 0 || m_wndView.m_strAudioInfo.IsEmpty())
  2321. {
  2322. CString szInfo , szMusicTitle, szMusicAuthor;
  2323. szMusicTitle = GetClipInfo(IDS_INFOBAR_TITLE).c_str();
  2324. szMusicAuthor = GetClipInfo(IDS_INFOBAR_AUTHOR).c_str();
  2325. switch (m_wndView.m_AudioInfoCounter/4 %4)
  2326. {
  2327. case 0:
  2328. szInfo = szMusicTitle;
  2329. break;
  2330. case 1:
  2331. szInfo = szMusicAuthor;
  2332. break;
  2333. case 2:
  2334. szInfo = GetClipInfo(IDS_INFOBAR_DESCRIPTION).c_str();
  2335. break;
  2336. case 3:
  2337. szInfo = GetClipInfo(IDS_INFOBAR_COPYRIGHT).c_str();
  2338. break;
  2339. }
  2340. if (szInfo.IsEmpty())
  2341. {
  2342. m_wndView.m_AudioInfoCounter+=4;
  2343. continue;
  2344. }
  2345. else
  2346. {
  2347. m_wndView.m_strAudioInfo = szInfo;
  2348. CString szTitleItShouleBe = szMusicTitle + _T(" - ") + szMusicAuthor;
  2349. if (szTitleItShouleBe != m_szTitle)
  2350. {
  2351. m_szTitle = szTitleItShouleBe;
  2352. RedrawNonClientArea();
  2353. }
  2354. m_wndView.Invalidate();
  2355. bHaveInfo = true;
  2356. }
  2357. }
  2358. break;
  2359. }
  2360. }
  2361. if (m_iPlaybackMode == PM_FILE)
  2362. {
  2363. REFERENCE_TIME rtNow = 0, rtDur = 0;
  2364. pMS->GetCurrentPosition(&rtNow);
  2365. pMS->GetDuration(&rtDur);
  2366. if (m_fAudioOnly && m_Lyric.m_has_lyric)// && m_wndLycShowBox
  2367. {
  2368. int iLastingTime;
  2369. CString szLyricLine = m_Lyric.GetCurrentLyricLineByTime(rtNow, &iLastingTime);
  2370. if (!szLyricLine.IsEmpty())
  2371. {
  2372. wchar_t music_note[] = {0x266A, 0x0020, 0};
  2373. szLyricLine.Insert(0, music_note);
  2374. if (m_wndView.m_strAudioInfo != szLyricLine)
  2375. {
  2376. m_wndView.m_strAudioInfo = szLyricLine;
  2377. if (iLastingTime > 0)
  2378. m_wndView.SetLyricLasting(iLastingTime);
  2379. else
  2380. m_wndView.SetLyricLasting(15);
  2381. m_wndView.Invalidate();
  2382. }
  2383. }
  2384. }
  2385. UINT iTotalLenSec = (UINT)( (INT64) rtDur / 20000000 );
  2386. //如果视频长度大于1分钟, 而且是文件模式,而且正在播放中
  2387. if (!m_fAudioOnly && iTotalLenSec > 180 && m_iPlaybackMode == PM_FILE && GetMediaState() == State_Running)
  2388. {
  2389. time_t time_now = time(NULL);
  2390. UINT totalplayedtime = time_now - m_tPlayStartTime;
  2391. //SVP_LogMsg5(L"time_now > ( m_tLastLogTick %f %f" , (double)time_now , (double)m_tLastLogTick);
  2392. if (time_now > ( m_tLastLogTick + 180 ))
  2393. { //如果和上次检查已经超n秒
  2394. CString fnVideoFile , fnSubtitleFile;
  2395. int subDelayMS = 0;
  2396. fnVideoFile = m_fnCurPlayingFile;
  2397. fnSubtitleFile = getCurPlayingSubfile(&subDelayMS);
  2398. if (!fnSubtitleFile.IsEmpty())
  2399. { //如果有字幕
  2400. CString szLog;
  2401. //szLog.Format(_T(" %s ( with sub %s delay %d ) %d sec of %d sec ( 1/2 length video = %d ) ") , fnVideoFile, fnSubtitleFile,subDelayMS, totalplayedtime , iTotalLenSec, (UINT)(iTotalLenSec/2) );
  2402. //SVP_LogMsg(szLog);
  2403. //if time > 50%
  2404. if (totalplayedtime > (UINT)(iTotalLenSec/2))
  2405. {
  2406. if (!m_haveSubVoted && m_pCAP && rtNow > (rtDur - 3000000000i64))
  2407. {
  2408. //如果还没提示过vote
  2409. //如果时间接近最末5分钟
  2410. AppSettings& s = AfxGetAppSettings();
  2411. if (s.bIsChineseUIUser())
  2412. {
  2413. //如果是中文
  2414. if ( m_wndPlaylistBar.GetCount() <= 1)
  2415. {
  2416. //如果是1CD
  2417. int nSubPics;
  2418. REFERENCE_TIME rtSubNow, rtSubStart, rtSubStop;
  2419. m_pCAP->GetSubStats(nSubPics,rtSubNow, rtSubStart, rtSubStop);
  2420. if (rtSubNow > rtSubStop)
  2421. {
  2422. //如果没有更多字幕
  2423. SVP_LogMsg5(L"Sub Voted Event");
  2424. //vote之
  2425. m_haveSubVoted = true;
  2426. }
  2427. }
  2428. }
  2429. }
  2430. //是否已经上传过呢
  2431. if (m_fnsAlreadyUploadedSubfile.Find(fnVideoFile+fnSubtitleFile) < 0)
  2432. {
  2433. //upload subtitle
  2434. Logging(L"Uploading sub %s of %s width delay %d ms since user played %d sec of %d sec ( more than 1/2 length video ) " , fnSubtitleFile, fnVideoFile ,subDelayMS, totalplayedtime , iTotalLenSec );
  2435. SVP_UploadSubFileByVideoAndSubFilePath(fnVideoFile , fnSubtitleFile, subDelayMS);
  2436. m_fnsAlreadyUploadedSubfile.Append( fnVideoFile+fnSubtitleFile+_T(";") );
  2437. }
  2438. int subDelayMS2 = 0;
  2439. CString fnSubtitleFile2 = getCurPlayingSubfile(&subDelayMS2);
  2440. if (!fnSubtitleFile2.IsEmpty())
  2441. {
  2442. if (m_fnsAlreadyUploadedSubfile.Find( fnVideoFile+fnSubtitleFile2 ) < 0)
  2443. {
  2444. //upload subtitle
  2445. Logging((L"Uploading sub2 %s of %s width delay %d ms since user played %d sec of %d sec ( more than 1/2 length video ) ") , fnSubtitleFile2, fnVideoFile ,subDelayMS2, totalplayedtime , iTotalLenSec);
  2446. SVP_UploadSubFileByVideoAndSubFilePath(fnVideoFile , fnSubtitleFile2, subDelayMS2);
  2447. m_fnsAlreadyUploadedSubfile.Append( fnVideoFile+fnSubtitleFile2+_T(";") );
  2448. }
  2449. }
  2450. }
  2451. }
  2452. m_tLastLogTick = time_now;
  2453. //SVP_LogMsg5(L"m_tLastLogTick = time_now; %f %f" , (double)time_now , (double)m_tLastLogTick);
  2454. }
  2455. }
  2456. }
  2457. CString msg;
  2458. if (m_fBuffering)
  2459. {
  2460. BeginEnumFilters(pGB, pEF, pBF)
  2461. {
  2462. if (CComQIPtr<IAMNetworkStatus, &IID_IAMNetworkStatus> pAMNS = pBF)
  2463. {
  2464. long BufferingProgress = 0;
  2465. if (SUCCEEDED(pAMNS->get_BufferingProgress(&BufferingProgress)) && BufferingProgress > 0 && BufferingProgress < 99)
  2466. {
  2467. msg.Format(ResStr(IDS_CONTROLS_BUFFERING), BufferingProgress);
  2468. SendStatusMessage(msg,1000);
  2469. SVP_LogMsg5(msg);
  2470. }
  2471. break;
  2472. }
  2473. }
  2474. EndEnumFilters
  2475. }
  2476. else if (pAMOP)
  2477. {
  2478. __int64 t = 0, c = 0;
  2479. if(SUCCEEDED(pAMOP->QueryProgress(&t, &c)) && t > 0 && c < t)
  2480. {
  2481. msg.Format(ResStr(IDS_CONTROLS_BUFFERING), c*100/t);
  2482. SendStatusMessage(msg,1000);
  2483. SVP_LogMsg5(msg);
  2484. }
  2485. }
  2486. m_wndToolBar.m_buffering = msg;
  2487. if (m_iPlaybackMode == PM_FILE)
  2488. SetupChapters();
  2489. if (GetMediaState() == State_Running)
  2490. {
  2491. if (m_fAudioOnly)
  2492. {
  2493. UINT fSaverActive = 0;
  2494. if (SystemParametersInfo(SPI_GETPOWEROFFACTIVE, 0, (PVOID)&fSaverActive, 0))
  2495. {
  2496. SystemParametersInfo(SPI_SETPOWEROFFACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
  2497. SystemParametersInfo(SPI_SETPOWEROFFACTIVE, fSaverActive, 0, SPIF_SENDWININICHANGE);
  2498. }
  2499. SetThreadExecutionState(ES_SYSTEM_REQUIRED);
  2500. }
  2501. else
  2502. {
  2503. UINT fSaverActive = 0;
  2504. if (SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, (PVOID)&fSaverActive, 0))
  2505. {
  2506. SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
  2507. SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, fSaverActive, 0, SPIF_SENDWININICHANGE);
  2508. }
  2509. fSaverActive = 0;
  2510. if (SystemParametersInfo(SPI_GETPOWEROFFACTIVE, 0, (PVOID)&fSaverActive, 0))
  2511. {
  2512. SystemParametersInfo(SPI_SETPOWEROFFACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
  2513. SystemParametersInfo(SPI_SETPOWEROFFACTIVE, fSaverActive, 0, SPIF_SENDWININICHANGE);
  2514. }
  2515. SetThreadExecutionState(ES_DISPLAY_REQUIRED|ES_SYSTEM_REQUIRED); //this is the right way, only this work under vista . no ES_CONTINUOUS so it can goes to sleep when not playing
  2516. }
  2517. if (GetExStyle() & WS_EX_LAYERED)
  2518. {
  2519. BYTE dAlpha = 0 ;
  2520. DWORD dwFlag = 0;
  2521. if (AfxGetMyApp()->m_pGetLayeredWindowAttributes)
  2522. {
  2523. AfxGetMyApp()->m_pGetLayeredWindowAttributes(m_hWnd, NULL, &dAlpha , &dwFlag);
  2524. if (dAlpha == 255)
  2525. ModifyStyleEx(WS_EX_LAYERED , 0);
  2526. }
  2527. }
  2528. }
  2529. namespace DSObjects 操作DirectShow类库
  2530. 空间中有
  2531. 操作DirectShow D3D7
  2532. CDX7AllocatorPresenter继承ISubPicAllocatorPresenterImpl
  2533. 操作DirectShow D3D9
  2534. CDX9AllocatorPresenter继承ISubPicAllocatorPresenterImpl
  2535. CDXRAllocatorPresenter继承ISubPicAllocatorPresenterImpl
  2536. VMR7分配器
  2537. CVMR7AllocatorPresenter继承CDX7AllocatorPresenter,继承IVMRSurfaceAllocator,继承IVMRImagePresenter,继承IVMRWindowlessControl
  2538. VMR9分配器
  2539. CVMR9AllocatorPresenter继承CDX9AllocatorPresenter,继承IVMRSurfaceAllocator9,继承IVMRImagePresenter9, 继承IVMRWindowlessControl9
  2540. CGenlock 管理视频和显示的同步。
  2541. VR分配器
  2542. CmadVRAllocatorPresenter继承ISubPicAllocatorPresenterImpl
  2543. QT7分配器
  2544. CQT7AllocatorPresenter继承CDX7AllocatorPresenter,继承IQTVideoSurface
  2545. QT9分配器
  2546. CQT9AllocatorPresenter继承CDX9AllocatorPresenter,继承IQTVideoSurface
  2547. Quicktime格式绘图
  2548. CQuicktimeGraph继承CBaseGraph,继承IVideoFrameStep
  2549. Quicktime载体
  2550. CQuicktimeWindow继承CPlayerWindow
  2551. Real格式绘图
  2552. CRealMediaGraph继承CBaseGraph
  2553. Real格式播放
  2554. CRealMediaPlayer继承CUnknown,继承IRMAErrorSink,继承IRMAClientAdviseSink,继承IRMAAuthenticationManager,继承IRMASiteSupplier,继承IRMAPassiveSiteWatcher,继承IRMAAudioHook
  2555. Real格式播放载体
  2556. CRealMediaPlayerWindowed继承CRealMediaPlayer
  2557. Real格式播放载体
  2558. CRealMediaPlayerWindowless继承CRealMediaPlayer
  2559. Real格式视频面
  2560. CRealMediaVideoSurface继承CUnknown,继承IRMAVideoSurface
  2561. Real格式载体站点
  2562. CRealMediaWindowlessSite继承CUnknown,继承IRMASite,继承IRMASite2,继承IRMASiteWindowless,继承IRMAVideoSurface
  2563. RM7分配器
  2564. CRM7AllocatorPresenter继承CDX7AllocatorPresenter,继承IRMAVideoSurface
  2565. RM9分配器
  2566. CRM9AllocatorPresenter继承CDX9AllocatorPresenter,继承IRMAVideoSurface
  2567. Flash绘图
  2568. CShockwaveGraph继承CBaseGraph
  2569. 主程序有的类库:
  2570. 链接广告的类 实现了动画效果
  2571. AdController继承ThreadHelperImpl<AdController>
  2572. ButtonManage 按钮管理类
  2573. CAboutDlg继承CDialog 关于对话框
  2574. 自定义了一个映射模版类
  2575. template <class T = CString, class S = CString>
  2576. class CAtlStringMap : public CAtlMap<S, T, CStringElementTraits<S> > {};
  2577. 一个音频格式集合类
  2578. class CAudFormatArray : public CFormatArray<AUDIO_STREAM_CONFIG_CAPS>
  2579. 一个作者登陆框
  2580. class CAuthDlg : public CDialog
  2581. 视频绘画类
  2582. class CBaseGraph继承CUnknown, 继承IGraphBuilder2, public IMediaControl, 继承IMediaEventEx, 继承IMediaSeeking, 继承IVideoWindow, 继承IBasicVideo, 继承IBasicAudio, 继承IAMOpenProgress, public IGraphEngine
  2583. class CBtnAlign 按钮位置区域对齐类
  2584. 自绘了Edit类 阙套了Button
  2585. class CBtnEditCtrl继承CWindowImpl<CBtnEditCtrl, CEdit>
  2586. CChildView继承CWnd 窗体类 实现了视频载体
  2587. COM组件属性页站点
  2588. CComPropertyPageSite继承CUnknown,继承IPropertyPageSite
  2589. CConvertChapDlg继承CResizableDialog 转换章节对话框
  2590. CConvertDlg继承CResizableDialog 转换对话框
  2591. CConvertPropsDlg继承CResizableDialog 转换属性页对话框
  2592. CConvertResDlg继承CResizableDialog 转换资源对话框
  2593. 分行过滤器
  2594. CDeinterlacerFilter继承CTransformFilter
  2595. CDisplaySettingDetector 显示设置探测器
  2596. CDlgChkUpdater继承CDialog 确认更新对话框
  2597. CDropTarget 移动文件类
  2598. EVR分配器
  2599. CEVRAllocatorPresenter继承CDX9AllocatorPresenter,继承IMFGetService,继承IMFTopologyServiceLookupClient,继承IMFVideoDeviceID,继承IMFVideoPresenter,继承IDirect3DDeviceManager9,继承IMFAsyncCallback,继承IQualProp,继承IMFRateSupport,继承IMFVideoDisplayControl,继承IEVRTrustedVideoPlugin
  2600. 渐变视频解码
  2601. CFakeDirectXVideoDecoder继承CUnknown,继承IDirectXVideoDecoder
  2602. CFavoriteAddDlg继承CCmdUIDialog 收藏对话框
  2603. CFavoriteOrganizeDlg继承CResizableDialog 收藏组织对话框
  2604. CFFindByDir 目录查找类
  2605. CFFindMoreFiles 查找更多文件类
  2606. CFGAggregator继承CUnknown FG集合类
  2607. CFGFilter FG过滤类
  2608. CFGFilterFile继承CFGFilter FG过滤文件
  2609. CFGFilterInternal继承CFGFilter FG内部过滤
  2610. CFGFilterList FG过滤列表
  2611. CFGFilterRegistry继承CFGFilter FG过滤继承类
  2612. CFGFilterVideoRenderer继承CFGFilter FG过滤视频渲染类
  2613. FG管理类
  2614. CFGManager继承CUnknown, 继承IGraphBuilder2, 继承IGraphBuilderDeadEnd, 继承CCritSec
  2615. CFGManagerCapture继承CFGManagerPlayer FG捕捉管理类
  2616. CFGManagerCustom继承CFGManager FG自定义管理类
  2617. CFGManagerDVD继承CFGManagerPlayer FG_DVD管理类
  2618. CFGManagerMuxer继承CFGManagerCustom FG 混合器管理类
  2619. CFGManagerPlayer继承CFGManagerCustom FG视频管理
  2620. CFileDropTarget继承COleDropTarget 文件移动类
  2621. CFilterMapper2继承CUnknown继承IFilterMapper2 过滤映射类
  2622. CFilterTreeCtrl继承CTreeCtrl 过滤器树列表
  2623. CFloatEdit继承CEdit 浮动的编辑框
  2624. 格式模块
  2625. template<class T>
  2626. class CFormat : public CAutoPtrArray<CFormatElem<T> >
  2627. 格式数组模块
  2628. template<class T>
  2629. class CFormatArray : public CAutoPtrArray<CFormat<T> >
  2630. 格式节点
  2631. template<class T>
  2632. class CFormatElem
  2633. CGoToDlg继承CDialog 转到对话框
  2634. CGraphCore / /我们需要打开/播放暂停/寻求/关闭/ VOL控制/子控制/音频和视频切换的类
  2635. CGraphThread继承CWinThread 播放线程类
  2636. CHexEdit继承CEdit 16进制编辑框
  2637. ChkDefPlayerControlBar继承 CSVPDialog 默认播放控制航
  2638. CIfo 文件信息类
  2639. CInfoReport继承CDialog 信息报告对话框
  2640. CInPlaceComboBox继承CComboBox 阙套下拉框
  2641. CInPlaceEdit继承CEdit 阙套编辑框
  2642. CInPlaceListBox继承CListBox 阙套列表框
  2643. CIntEdit继承CEdit 整形编辑框
  2644. CKeyProvider继承CUnknown,继承IServiceProvider 键盘提供者
  2645. CLineNumberEdit继承CEdit 线数编辑框
  2646. CLineNumberStatic继承CStatic 线数静态框
  2647. CMacrovisionKicker继承CUnknown,继承IKsPropertySet
  2648. 主程序
  2649. CMainFrame继承CFrameWnd,继承CDropTarget,继承CGraphCore
  2650. CMediaFormatCategory 媒体格式分类
  2651. CMediaTypesDlg继承CResizableDialog 媒体类型对话框
  2652. CMemoryDC继承CDC 内存离屏DC
  2653. CMPlayerCApp继承CWinApp 启动类
  2654. CNEWOSDWnd继承CWnd Osd窗体
  2655. ContentTypeTemp 内容类型
  2656. COpenCapDeviceDlg继承CResizableDialog 打开捕捉设备对话框
  2657. COpenDlg继承CResizableDialog 打开对话框
  2658. COpenFileDlg继承CFileDialog 打开文件对话框
  2659. COpenURLDlg继承CResizableDialog 打开URL 对话框
  2660. 输出EVR
  2661. COuterEVR继承CUnknown,继承IVMRffdshow9,继承IVMRMixerBitmap9,继承IBaseFilter
  2662. 输出VMR9
  2663. COuterVMR9继承CUnknown,继承IVideoWindow,
  2664. 继承IBasicVideo2,继承IVMRWindowlessControl,继承IVMRffdshow9,继承IVMRMixerBitmap9
  2665. CPixelShaderCompiler 像素着色器编译器
  2666. CPlayerCaptureBar继承baseCPlayerCaptureBar 视频捕捉条
  2667. CPlayerCaptureDialog继承CResizableDialog //CDialog 视频捕捉对话框
  2668. CPlayerChannelNormalizer继承CSVPDialog 视频通道正规化对话框
  2669. CPlayerColorControlBar继承CSVPDialog 视频颜色控制条
  2670. CPlayerEQControlBar继承CSVPDialog 视频EQ控制条
  2671. CPlayerFloatToolBar继承CFrameWnd 视频浮动控制条
  2672. CPlayerListCtrl继承CListCtrl 播放器列表
  2673. CPlayerPlaylistBar继承CSizingControlBarG 播放器列表条
  2674. CPlayerSeekBar继承CDialogBar 视频跳转条
  2675. CPlayerShaderEditorBar继承baseCPlayerShaderEditorBar 视频着色编辑条
  2676. CPlayerToolBar继承CToolBar 视频工具条
  2677. CPlayerToolTopBar继承CWnd 视频上面的工具条
  2678. CPlayerWindow继承 CWnd 视频窗体
  2679. CPlaylist继承CList<CPlaylistItem> 播放列表
  2680. CPlaylistItem 播放列表节点
  2681. CPngImage继承CImage 处理png图片
  2682. CPnSPresetsDlg继承CCmdUIDialog 预设对话框
  2683. CPPageBase继承CCmdUIPropertyPage 基本属性页
  2684. CPPageFileInfoClip继承CPropertyPage 文件信息属性页
  2685. CPPageFileInfoDetails继承CPropertyPage 详细文件信息页
  2686. CPPageFileInfoRes继承CPPageBase 文件信息资源属性页
  2687. CPPageFileInfoSheet继承CPropertySheet 文件信息页
  2688. CPPageFileMediaInfo继承CPropertyPage 媒体文件信息
  2689. CPPageFormats 页格式
  2690. CResetDVD继承CDVDSession 重设DVD
  2691. CSaveDlg继承CCmdUIDialog 保存对话框
  2692. CSaveTextFileDialog继承CFileDialog 保存文本文件对话框
  2693. CSaveThumbnailsDialog继承CFileDialog 保存缩略图对话框
  2694. CSeekBarTip继承CWnd 赚到提示信息
  2695. CShaderAutoCompleteDlg继承CResizableDialog 着色自动完成对话框
  2696. CShaderCombineDlg继承CResizableDialog 着色连接对话框
  2697. CShaderEdit继承CLineNumberEdit 着色编辑框
  2698. CShaderEditorDlg继承CResizableDialog 着色编辑对话框
  2699. CShaderLabelComboBox继承CComboBox 着色下拉框
  2700. CShockwaveFlash继承CWnd flash控件
  2701. CSUIBtnList继承CList<CSUIButton*> 按钮列表
  2702. CSUIButton 自绘按钮类
  2703. CSVPButton继承CButton 自绘按钮
  2704. CSVPDialog继承CWnd 自绘对话框
  2705. CSVPSliderCtrl继承CSliderCtrl 自绘Slider
  2706. CSVPStatic继承CStatic 自绘Static
  2707. CSVPSubUploadDl继承CResizableDialog 字幕上传对话框
  2708. CSVPSubVoteControlBar继承CSVPDialog
  2709. CTextFile继承CStdioFile 操作文件类
  2710. CTextPassThruFilter继承CBaseFilter,继承CCritSec 文本直通过滤器
  2711. CTextPassThruInputPin继承CSubtitleInputPin 文本直通输入流
  2712. CTextPassThruOutputPin继承CBaseOutputPin 文本直通输出流
  2713. CTransparentControlBar继承CSVPDialog 透明控制条
  2714. CustomDrawBtn继承CButton 自定义按钮
  2715. CVidFormatArray继承CFormatArray<VIDEO_STREAM_CONFIG_CAPS> 视频格式集合
  2716. CVolumeCtrl继承CSliderCtrl 声音控件
  2717. CWebTextFile继承CTextFile 网站文本
  2718. FileAssoc 文件关联
  2719. FilterOverride 过滤器重叠
  2720. FrameCfgFileManage 窗体设置文件管理
  2721. GUIConfigManage GUI配置管理
  2722. 哈希值管理
  2723. HashController继承LazyInstanceImpl<HashController>
  2724. HotkeyCmd继承ACCEL 快捷键
  2725. HotkeyController继承LazyInstanceImpl<HotkeyController> 快捷键控制
  2726. HotkeySchemeParser 快捷键计划分析器
  2727. LayeredWindowUtils 窗体单元
  2728. 实例模版
  2729. template<class T>
  2730. class LazyInstanceImpl
  2731. template<class T>
  2732. class MainFrameSPlayerCmd
  2733. MakeMultiplyBmp
  2734. 媒体中心管理
  2735. MediaCenterController继承LazyInstanceImpl<MediaCenterController>
  2736. 媒体中心视图
  2737. MediaCenterView继承ATL::CWindowImpl<MediaCenterView>,继承MediaScrollbar,继承MediaListView
  2738. MediaCheckDB继承ThreadHelperImpl<MediaCheckDB> 媒体确认数据库
  2739. MediaDB 媒体数据库
  2740. MediaListView 媒体列表视图
  2741. MediaModel继承SourceModel<MediaData, MediaFindCondition> 媒体模式
  2742. MediaScrollbar 媒体滚动条
  2743. MediaSpiderAbstract继承ThreadHelperImpl<T> 媒体摘要
  2744. MediaSpiderFolderTree继承MediaSpiderAbstract<MediaSpiderFolderTree> 媒体摘要树
  2745. MediaSQLite 媒体SQL
  2746. MediaTreeModel 媒体树模式
  2747. MovieComment继承CDHtmlDialog 电影评论
  2748. NetworkControlerImpl 网络任务控制接口
  2749. OpenDeviceData继承OpenMediaData 设备打开方式
  2750. OpenDVDData继承OpenMediaData DVD打开方式
  2751. OpenFileData继承OpenMediaData 文件打开方式
  2752. OpenMediaData 打开方式基类
  2753. 建议选项属性页
  2754. OptionAdvancedPage继承WTL::CPropertyPageImpl<OptionAdvancedPage>,继承WTL::CWinDataExchange<OptionAdvancedPage>
  2755. 关联文件属性页
  2756. OptionAssociationPage继承WTL::CPropertyPageImpl<OptionAssociationPage>,继承WTL::CWinDataExchange<OptionAssociationPage>
  2757. 基本选项属性页
  2758. OptionBasicPage继承WTL::CPropertyPageImpl<OptionBasicPage>,继承WTL::CWinDataExchange<OptionBasicPage>
  2759. OptionDlg继承WTL::CPropertySheetImpl<OptionDlg> 选项对话框
  2760. 第二字幕选项属性页
  2761. OptionSubtitlePage继承WTL::CPropertyPageImpl<OptionSubtitlePage>,继承WTL::COwnerDraw<OptionSubtitlePage>,继承WTL::CWinDataExchange<OptionSubtitlePage>
  2762. OSDController继承LazyInstanceImpl<OSDController> OSD控制
  2763. OSDView继承ATL::CWindowImpl<OSDView>,继承LayeredWindowUtils<OSDView> OSD视图
  2764. PlayerPreference继承LazyInstanceImpl<PlayerPreference> 播放器引用
  2765. PlaylistController继承LazyInstanceImpl<PlaylistController> 播放列表控制
  2766. PlaylistParser 播放列表分析
  2767. 播放列表视图
  2768. PlaylistView继承ATL::CWindowImpl<PlaylistView>,继承WTL::COwnerDraw<PlaylistView>,继承 WTL::CCustomDraw<PlaylistView>
  2769. PlaylistViewMfcProxy继承CSizingControlBarG 播放列表代理
  2770. SkinDownload继承CDHtmlDialog,继承ThreadHelperImpl<SkinDownload> 皮肤下载
  2771. SkinFolderManager 皮肤管理类
  2772. SnapUploadController继承ThreadHelperImpl<SnapUploadController> 对齐上传控制器
  2773. 源模式模块
  2774. template<class TDATA, class TCONDITION>
  2775. class SourceModel
  2776. SPlayerGUID 播放ID
  2777. SQLliteapp 操作数据库
  2778. ssftest 测试ssf
  2779. SubtitleStyle 内部风格指数提供了实际的映射 字幕渲染设置接受外部字幕滤镜。它还提供Windows基于GDI画画的能力
  2780. 模拟渲染对话框显示的目的。
  2781. 字幕透明控制
  2782. SubTransController继承ThreadHelperImpl<SubTransController>,继承NetworkControlerImpl
  2783. SubTransFormat 字幕透明格式
  2784. SUIVoteStar
  2785. SVPLycShowBox //歌词显示面板 mouseover时显示半透明玻璃背景、关闭按钮和变色按钮,out后仅显示文字
  2786. //默认在屏幕底部区域显示,可以通过拖拽改变位置 关闭后改为在主窗口界面内显示
  2787. ThemePkg 主题背景
  2788. ThemePkgController 主题背景控制
  2789. TimeBmpManage 事件画面控制
  2790. 上传控制
  2791. UbdUploadController继承ThreadHelperImpl<UbdUploadController>,继承LazyInstanceImpl<UbdUploadController>
  2792. UnCompressZip 解压控制
  2793. 更新控制
  2794. UpdateController继承NetworkControlerImpl,继承ThreadHelperImpl<UpdateController>,继承LazyInstanceImpl<UpdateController>
  2795. 用户着色控制
  2796. UserShareController继承NetworkControlerImpl,继承ThreadHelperImpl<UserShareController>,继承LazyInstanceImpl<UserShareController>
  2797. 用户行为控制
  2798. UsrBehaviorController继承LazyInstanceImpl<UsrBehaviorController>
  2799. 用户行为数据
  2800. UsrBehaviorData
  2801. 今天主要针对 SPlayer 播放器项目的 CMPlayerc 分析
  2802. mplayerc
  2803. -->Model\appSQLite.h 主要负责操作sql
  2804. 类成员成员中有两个成员
  2805. SQLliteapp* sqlite_setting;
  2806. SQLliteapp* sqlite_local_record;
  2807. 对sqlite_setting 分析
  2808. 在StoreSettingsToIni 产生一个对象
  2809. sqlite_setting = PlayerPreference::GetInstance()->GetSqliteSettingPtr();
  2810. 保存数据前 存在 则开始输出 BEGIN
  2811. if(pApp->sqlite_setting){
  2812. pApp->sqlite_setting->begin_transaction();
  2813. }
  2814. 保存数据后 存在 则开始输出 END
  2815. if(pApp->sqlite_setting){
  2816. pApp->sqlite_setting->end_transaction();
  2817. }
  2818. 读取整形数据
  2819. if(sqlite_setting){
  2820. return sqlite_setting->GetProfileInt( lpszSection, lpszEntry, nDefault);
  2821. }else{
  2822. return __super::GetProfileInt( lpszSection, lpszEntry, nDefault);
  2823. }
  2824. }
  2825. 写入整形数据
  2826. if(sqlite_setting){
  2827. return sqlite_setting->WriteProfileInt( lpszSection, lpszEntry, nValue);
  2828. }else{
  2829. SVP_LogMsg6("dwqdwq");
  2830. return __super::WriteProfileInt( lpszSection, lpszEntry, nValue);
  2831. }
  2832. 读取字符集数据
  2833. if(sqlite_setting){
  2834. return sqlite_setting->GetProfileString( lpszSection, lpszEntry,
  2835. lpszDefault );
  2836. }else{
  2837. return __super::GetProfileString( lpszSection, lpszEntry,
  2838. lpszDefault );
  2839. }
  2840. 写入字符集数据
  2841. if(sqlite_setting){
  2842. return sqlite_setting->WriteProfileString( lpszSection, lpszEntry,
  2843. lpszValue);
  2844. }else{
  2845. return __super::WriteProfileString( lpszSection, lpszEntry,
  2846. lpszValue);
  2847. }
  2848. 读取二进制数据
  2849. if(sqlite_setting){
  2850. return sqlite_setting->GetProfileBinary( lpszSection, lpszEntry,
  2851. ppData, pBytes);
  2852. }else{
  2853. return __super::GetProfileBinary( lpszSection, lpszEntry,
  2854. ppData, pBytes);
  2855. }
  2856. 写入二进制数据
  2857. if(sqlite_setting){
  2858. return sqlite_setting->WriteProfileBinary( lpszSection, lpszEntry,
  2859. pData, nBytes);
  2860. }else{
  2861. return __super::WriteProfileBinary( lpszSection, lpszEntry,
  2862. pData, nBytes);
  2863. }
  2864. 对sqlite_setting 分析完
  2865. 对sqlite_local_record 分析
  2866. InitInstanceThreaded(INT64 CLS64) 函数中 产生对象
  2867. sqlite_local_record = new SQLliteapp(tmPath.m_strPath.GetBuffer())
  2868. 判断是否打开数据库
  2869. if(!sqlite_local_record->db_open)
  2870. {
  2871. delete sqlite_local_record;
  2872. sqlite_local_record = NULL;
  2873. }
  2874. 执行数据库 主要是创建表
  2875. if(sqlite_local_record)
  2876. {
  2877. sqlite_local_record->exec_sql(L"CREATE TABLE IF NOT EXISTS histories_stream (\"fpath\" TEXT, \"subid\" INTEGER, \"subid2\" INTEGER, \"audioid\" INTEGER, \"videoid\" INTEGER )");
  2878. sqlite_local_record->exec_sql(L"CREATE UNIQUE INDEX IF NOT EXISTS \"hispks\" on histories_stream (fpath ASC)");
  2879. sqlite_local_record->exec_sql(L"CREATE TABLE IF NOT EXISTS histories (\"fpath\" TEXT, \"subid\" INTEGER, \"subid2\" INTEGER, \"audioid\" INTEGER, \"stoptime\" INTEGER, \"modtime\" INTEGER )");
  2880. sqlite_local_record->exec_sql(L"CREATE UNIQUE INDEX IF NOT EXISTS \"hispk\" on histories (fpath ASC)");
  2881. sqlite_local_record->exec_sql(L"CREATE INDEX IF NOT EXISTS \"modtime\" on histories (modtime ASC)");
  2882. sqlite_local_record->exec_sql(L"CREATE TABLE IF NOT EXISTS settingstring (\"hkey\" TEXT, \"sect\" TEXT, \"vstring\" TEXT )");
  2883. sqlite_local_record->exec_sql(L"PRAGMA synchronous=OFF");
  2884. //sqlite_local_record->end_transaction();
  2885. }
  2886. 在退出程序的时候 ExitInstance()
  2887. if(sqlite_local_record){
  2888. CString szSQL;
  2889. szSQL.Format(L"DELETE FROM histories WHERE modtime < '%d' ", time(NULL)-3600*24*30);
  2890. // SVP_LogMsg5(szSQL);
  2891. sqlite_local_record->exec_sql(szSQL.GetBuffer());
  2892. sqlite_local_record->exec_sql(L"PRAGMA synchronous=ON");
  2893. }
  2894. if (sqlite_local_record) delete sqlite_local_record;
  2895. $(ConfigurationName)


以上是针对主程序播放视频的分析。


ChuckTest工程 是针对rar包里的测试项目,测试代码如下:

  1. int _tmain(int argc, _TCHAR* argv[])
  2. {
  3. HANDLE rar_handle = NULL;
  4. //std::wstring fn_rar = L"E:\\-=eMule=-\\1140746814_39741.rar";
  5. //std::wstring fn_rar = L"E:\\-=eMule=-\\Bride.Flight.2008.Bluray.720p.AC3.x264-CHD_新娘航班\\B2_新娘航班.part1.rar";
  6. //std::wstring fn_rar = L"D:\\xxxx.part1.rar";
  7. std::wstring fn_rar = L"E:\\-=eMule=-\\Overheard.2009.REPACK.CN.DVDRip.Xvid-XTM\\sample\\xtm-overheard.repack-sample_stored.rar";
  8. //std::wstring fn_rar = L"E:\\-=eMule=-\\Overheard.2009.REPACK.CN.DVDRip.Xvid-XTM\\sample\\xtm-overheard.repack-sample_s.part1.rar";
  9. std::wstring tmp_dir = L"C:\\Temp\\";
  10. struct RAROpenArchiveDataEx ArchiveDataEx;
  11. memset(&ArchiveDataEx, 0, sizeof(ArchiveDataEx));
  12. ArchiveDataEx.ArcNameW = (wchar_t*)fn_rar.c_str();
  13. //ArchiveDataEx.ArcName = "E:\\-=eMule=-\\1140746814_39741.rar";
  14. ArchiveDataEx.OpenMode = RAR_OM_EXTRACT;
  15. ArchiveDataEx.CmtBuf = 0;
  16. rar_handle = RAROpenArchiveEx(&ArchiveDataEx);
  17. const long buffsize = 1000;
  18. char testbuff[buffsize];
  19. if (rar_handle)
  20. {
  21. wprintf(L"RAROpenArchiveEx open successed\n");
  22. struct RARHeaderDataEx HeaderDataEx;
  23. HeaderDataEx.CmtBuf = NULL;
  24. while (RARReadHeaderEx(rar_handle, &HeaderDataEx) == 0)
  25. {
  26. // 正常解压该文件
  27. unsigned long long filesize = ((unsigned long long)HeaderDataEx.UnpSizeHigh << 32) + HeaderDataEx.UnpSize;
  28. int err = 0;
  29. std::wstring unp_tmpfile = tmp_dir + HeaderDataEx.FileNameW;
  30. err = RARProcessFileW(rar_handle, RAR_EXTRACT, (wchar_t*)tmp_dir.c_str(), HeaderDataEx.FileNameW);
  31. wprintf(L"RARProcessFileW to %s return %d size %lld %x %x\n", unp_tmpfile.c_str(), err, filesize, HeaderDataEx.UnpVer, HeaderDataEx.Method);
  32. }
  33. RARCloseArchive(rar_handle);
  34. }
  35. rar_handle = RAROpenArchiveEx(&ArchiveDataEx);
  36. if (rar_handle)
  37. {
  38. wprintf(L"RAROpenArchiveEx open successed\n");
  39. struct RARHeaderDataEx HeaderDataEx;
  40. HeaderDataEx.CmtBuf = NULL;
  41. while (RARReadHeaderEx(rar_handle, &HeaderDataEx) == 0)
  42. {
  43. unsigned long long filesize = ((unsigned long long)HeaderDataEx.UnpSizeHigh << 32) + HeaderDataEx.UnpSize;
  44. int err = 0;
  45. std::wstring unp_tmpfile = tmp_dir + HeaderDataEx.FileNameW;
  46. err = RARExtractChunkInit(rar_handle, HeaderDataEx.FileName);
  47. if (err != 0)
  48. {
  49. wprintf(L"RARExtractChunkInit return error %d\n", err);
  50. continue;
  51. }
  52. FILE* unp_filehandle = NULL;
  53. err = _wfopen_s(&unp_filehandle, unp_tmpfile.c_str(), L"rb");
  54. if (err)
  55. {
  56. wprintf(L"open extracted file fail %d %d\n", err, unp_filehandle);
  57. continue;
  58. }
  59. // 顺序测试
  60. int iExtractRet = 0;
  61. unsigned long long fpos = 0;
  62. do
  63. {
  64. iExtractRet = RARExtractChunk(rar_handle, (char*)testbuff, buffsize);
  65. // Compare
  66. if (compare_filebinary(unp_filehandle, fpos, testbuff, iExtractRet, 0))
  67. {
  68. wprintf(L"Sequence compare difference found at %lld for %d\n", fpos, buffsize);
  69. break;
  70. }
  71. //else
  72. // wprintf(L"Sequence compare is same %lld %d\n", fpos, iExtractRet);
  73. fpos += iExtractRet;
  74. } while(iExtractRet > 0);
  75. // 随机测试
  76. for (int i = 0; i < 100; i++)
  77. {
  78. unsigned long long ll_pos = rand() * filesize/RAND_MAX;
  79. RARExtractChunkSeek(rar_handle, ll_pos, SEEK_SET);
  80. RARExtractChunk(rar_handle, (char*)testbuff, buffsize);
  81. // Compare
  82. if (compare_filebinary(unp_filehandle, ll_pos, testbuff, iExtractRet, 0))
  83. {
  84. wprintf(L"Random compare difference found at %lld\n", ll_pos);
  85. break;
  86. }
  87. //else
  88. // wprintf(L"Random compare is same %lld\n", ll_pos);
  89. }
  90. wprintf(L"RARExtractChunk test for %s finished\n", unp_tmpfile.c_str());
  91. }
  92. RARCloseArchive(rar_handle);
  93. }
  94. wprintf(L"Test finished\n");
  95. scanf_s("%d");
  96. return 0;
  97. }
  1. //字符切换
  2. std::string WStringToString(const std::wstring& s)
  3. {
  4. char* ch;
  5. UINT bytes = WideCharToMultiByte(CP_ACP, 0, s.c_str(), -1, NULL, 0,
  6. NULL, NULL);
  7. ch = new char[bytes];
  8. if(ch)
  9. bytes = WideCharToMultiByte(CP_ACP, 0, s.c_str(), -1, ch, bytes,
  10. NULL, NULL);
  11. std::string str = ch;
  12. delete[] ch;
  13. return str;
  14. }
  15. //比较文件
  16. int compare_filebinary(FILE* filehandle, unsigned long long filepos, char* buff, unsigned long buffsize, int debug)
  17. {
  18. char *fbuf = (char *)malloc(buffsize);
  19. _fseeki64(filehandle, filepos, SEEK_SET);
  20. fread_s(fbuf, buffsize, sizeof(char), buffsize, filehandle);
  21. int ret = memcmp(buff, fbuf, buffsize);
  22. if (debug)
  23. {
  24. for (int i = 0;i < 100;i++)
  25. wprintf(L"%02x", (DWORD)buff[i] & 0xff);
  26. wprintf(L"\n");
  27. for (int i = 0;i < 100;i++)
  28. wprintf(L"%02x", (DWORD)fbuf[i] & 0xff);
  29. wprintf(L"\n");
  30. }
  31. free(fbuf);
  32. return ret;
  33. }


HotkeySchemeParser_UnitTest 是针对热键计划分析器单元测试,测试代码如下:

  1. //热键计划分析器单元测试
  2. int _tmain(int argc, _TCHAR* argv[])
  3. {
  4. HotkeySchemeParser parser;
  5. printf("HotkeySchemeParser unit test\n");
  6. printf("----------------------------------------------------------\n");
  7. printf("Populating default scheme (HotkeySchemeParser::PopulateDefaultScheme) ...\n");
  8. parser.PopulateDefaultScheme();
  9. printf("Attempting to write scheme file (HotkeySchemeParser::WriteToFile) ... ");
  10. if (!parser.WriteToFile(L"SPlayerHotKey.txt"))
  11. {
  12. printf("[FAILED]\n");
  13. return 0;
  14. }
  15. printf("[OK]\n");
  16. printf("Attempting to read scheme file (HotkeySchemeParser::ReadFromFile) ... ");
  17. if (!parser.ReadFromFile(L"SPlayerHotKey.txt"))
  18. {
  19. printf("[FAILED]\n");
  20. return 0;
  21. }
  22. printf("[OK]\n");
  23. //目标键
  24. HotkeySchemeParser target;
  25. target.PopulateDefaultScheme();
  26. printf("Comparing results (scheme name)... ");
  27. if (target.GetSchemeName() != parser.GetSchemeName())
  28. {
  29. printf("[ERROR]\n");
  30. return 0;
  31. }
  32. printf("[OK]\n");
  33. printf("Comparing results (list)... ");
  34. std::vector<HotkeyCmd> parser_list = parser.GetScheme();
  35. std::vector<HotkeyCmd> target_list = target.GetScheme();
  36. if (parser_list.size() != target_list.size())
  37. {
  38. printf("[SIZE MISMATCH]\n");
  39. return 0;
  40. }
  41. for (std::vector<HotkeyCmd>::iterator it1 = parser_list.begin(),
  42. it2 = target_list.begin();
  43. it1 != parser_list.end(),
  44. it2 != target_list.end();
  45. it1++, it2++)
  46. {
  47. if (it1->cmd != it2->cmd ||
  48. it1->key != it2->key ||
  49. it1->fVirt != it2->fVirt ||
  50. it1->appcmd != it2->appcmd ||
  51. it1->mouse != it2->mouse)
  52. {
  53. printf("[ERROR @ %d]\n", std::distance(parser_list.begin(), it1));
  54. return 0;
  55. }
  56. }
  57. printf("[OK]\n");
  58. return 0;
  59. }
sqliteppTest 是针对第三方库sqlitepp操作数据库的测试,测试代码如下:

  1. /* step0 init - *******************
  2. *first check del file Testsqlite.db*/
  3. const wchar_t *filename=L"./Testsqlite.db";
  4. const wchar_t *sqlc1=L"CREATE TABLE IF NOT EXISTS \"settingint\" (\"hkey\" TEXT,\"sect\" TEXT,\"sval\" INTEGER)";
  5. const wchar_t *sqlc2=L"CREATE TABLE IF NOT EXISTS \"settingstring\" (\"hkey\" TEXT, \"sect\" TEXT, \"vstring\" TEXT)";
  6. const wchar_t *sqlc3 = L"CREATE TABLE IF NOT EXISTS \"settingbin2\" (\"skey\" TEXT, \"sect\" TEXT, \"vdata\" BLOB)";
  7. const wchar_t *sqlc4 = L"CREATE UNIQUE INDEX IF NOT EXISTS \"pkey\" on settingint (hkey ASC, sect ASC)";
  8. const wchar_t *sqlc5 = L"CREATE UNIQUE INDEX IF NOT EXISTS \"pkeystring\" on settingstring (hkey ASC, sect ASC)";
  9. const wchar_t *sqlc6 = L"CREATE UNIQUE INDEX IF NOT EXISTS \"pkeybin\" on settingbin2 (skey ASC, sect ASC)";
  10. //定义
  11. TCHAR path[MAX_PATH] = {0};
  12. ::GetModuleFileName(NULL,path,MAX_PATH);
  13. CStringW strSQL(path);
  14. strSQL.Replace(_T("TestSqlite.exe"),_T("Testsqlite.db"));
  15. int i=0;
  16. std::wstring sql,sql2,sql3,sql4,sql5;
  17. SQLliteapp p(strSQL.GetBuffer()); //构造会创建数据库文件
  18. /* step1 : Create Table 执行sql语句 创建表 字段 数值*/
  19. p.exec_sql(sqlc1);
  20. p.exec_sql(sqlc2);
  21. p.exec_sql(sqlc3);
  22. p.exec_sql(sqlc4);
  23. p.exec_sql(sqlc5);
  24. p.exec_sql(sqlc6);
  25. std::wstring str1=L"hello";
  26. std::wstring str2=L"world";
  27. /* step2 int-test *******************
  28. *
  29. * write int - WriteProfileInt
  30. get int - GetProfileInt compare 写入 读取整形数值 比较
  31. ************************************/
  32. {
  33. int geti1=1;
  34. int geti2=100;
  35. geti1=p.WriteProfileInt(str2.c_str(),str1.c_str(),-10,false);
  36. int test01=p.GetProfileInt(str2.c_str(),str1.c_str(),10,false);
  37. if(geti1)
  38. printf("pass -- 1 \n");
  39. else
  40. printf("fail -- 1 \n");
  41. p.WriteProfileInt(str1.c_str(),str2.c_str(),geti2,false);
  42. geti1=p.GetProfileInt(str1.c_str(),str2.c_str(),-1,false);
  43. if(geti2==geti1)
  44. printf("pass -- 2 \n");
  45. else
  46. printf("fail -- 2 \n");
  47. }
  48. /* step3 string-test ***************
  49. *
  50. * write str - WriteProfileString
  51. get str - GetProfileString
  52. compare 写入 读取 字符集比较
  53. ************************************/
  54. {
  55. std::wstring str3s1, str3s2;
  56. str3s1 = L"ss";
  57. str3s2 = L"hello你好\n";
  58. str3s1 = p.GetProfileString(str2.c_str(), str1.c_str(),L"xx",false);
  59. if(str3s1 == L"xx")
  60. printf("pass--3\n"); // ok
  61. else
  62. printf("fail--3\n");
  63. p.WriteProfileString(str1.c_str(), str2.c_str(), str3s2.c_str());
  64. str3s1 = p.GetProfileString(str1.c_str(), str2.c_str(), L"xx",false);
  65. if(str3s1.compare(str3s2) == 0)
  66. printf("pass--4\n"); // ok
  67. else
  68. printf("fail--4\n");
  69. }
  70. /* step4 binrary-test **************
  71. *
  72. * write bin
  73. get bin - donot forget new/delete 写入 读取 二进制文件
  74. **************************************/
  75. {
  76. char *pp = 0; //donot forget new/delete
  77. char buf[100];
  78. char str3[] = "hello4";
  79. char str4[] = "world4";
  80. for(i=0;i<80;i++)
  81. {
  82. buf[i] = i * 3 % 5 + 2;
  83. }
  84. int bPass=0; //成功的话 bPass 返回个数
  85. p.GetProfileBinary(str2.c_str(), str1.c_str(),(LPBYTE*)&pp,(UINT*)&bPass,false);
  86. if( bPass == 0 )
  87. printf("pass--5 bin\n");
  88. else
  89. printf("fail--5 bin\n");
  90. if(i>0 && pp)
  91. {
  92. delete[] pp;
  93. pp = NULL;
  94. }
  95. p.WriteProfileBinary(str1.c_str(), str2.c_str(), (LPBYTE)buf, 80); //w 80 BYTE
  96. p.GetProfileBinary(str1.c_str(), str2.c_str(), (LPBYTE*)&pp, (UINT*)&bPass, false); //成功的话 bPass 返回个数
  97. if(memcmp(pp,buf,30) == 0)
  98. printf("pass--6 bin\n");
  99. else
  100. printf("fail--6 bin\n");
  101. if(bPass>0 && pp)
  102. {
  103. delete[] pp;
  104. pp = NULL;
  105. }
  106. }

 分析到此就结束了!~这是我针对这SPlayer项目的简单分析!

 学习的目标是成熟!~~~




声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/144586
推荐阅读
相关标签
  

闽ICP备14008679号