0xAA55 发表于 2014-10-3 06:26:50

【DirectShow】视频内置播放器Video Internal Player

这个视频内置播放器的作用,是用来将视频实时渲染成位图的图像并放到内存,以用作其它用途,比如做成OpenGL或DirectX的动态纹理、做成视频播放器、将视频图像一帧一帧生成BMP、搞成网络播放视频的工具等。

我这个东西的用法很简单。包含VIP.H,建立VIP结构体,然后调用InitVIP,这个函数可以设定你要播放视频的文件位置,以及你接收视频图像数据的方式。
有两种方式,一种方式是VIP自动帮你把图像数据拷贝到你给的缓冲区,另一种方式则是每次渲染完就调用你给的回调函数,然后你就可以自己去取图像数据了。

用户只需要VIP.H和VIPConf.h还有<streams.h>。
其中<streams.h>是DirectShow的头文件,来自BaseClasses。//=============================================================================
//VIP.H:
//Video Internal Player
//在Windows下借助DirectShow将视频文件播放到内部缓冲区,以用作其它用途。
//
//有两种用法:
//1、在FnOnGetInfo回调函数里,指定pWriteTo指向一个缓冲区。然后VIP每次渲染时都会
//   将图像数据写入这个缓冲区。
//2、直接在FnOnRender回调函数里从pBits参数读取位图数据。
//
//第一种方法略慢(因为拷贝了一次缓冲区数据),但是不容易出错。
//第二种方法省去了一次拷贝操作,但是因为框架变动,容易出现错误。
//(VB不能用第二种方法)
//
//作者:0xAA55
//论坛:http://www.0xaa55.com/
//版权所有 (C) 2013-2014 技术宅的结界
//请保留原作者信息,否则视为侵权。
//-----------------------------------------------------------------------------

#ifndef _VIDEO_INTERNAL_PLAYER_
#define        _VIDEO_INTERNAL_PLAYER_

#include"VIPConf.h"
#include<streams.h>

//=============================================================================
//载入视频文件时取得参数时调用的回调函数
//
//用户可以在回调函数里通过给(*ppWriteTo)赋值来指定VIP的图像缓冲区。
//当(*ppWriteTo)==NULL的时候,VIP不会将图像数据写入任何缓冲区。
//-----------------------------------------------------------------------------
typedef void(VIPCallbackP FnOnGetInfo)
(
        size_t Width,//视频宽度
        size_t Height,//视频高度
        size_t Pitch,//视频每行字节数
        void**ppWriteTo,//用户指定要写入图像数据的缓冲区
        void*pUserData//用户的自定义信息
);

//=============================================================================
//解码器完成一帧渲染时调用的回调函数
//-----------------------------------------------------------------------------
typedef void(VIPCallbackP FnOnRender)
(
        size_t Width,//视频宽度
        size_t Height,//视频高度
        size_t Pitch,//视频每行字节数
        void*pBits,//图像数据
        void*pUserData
);

//=============================================================================
//VIP的结构体。
//-----------------------------------------------------------------------------
typedef struct
{
        IGraphBuilder        *m_pGB;                        //图表构建器
        IMediaControl        *m_pMC;                        //多媒体控制
        IMediaPosition        *m_pMP;                        //多媒体播放位置
        IMediaEvent                *m_pME;                        //多媒体事件
        IBaseFilter                *m_pRenderer;        //渲染器
        void                        *pUserData;                //用户自定义信息
}VIP,*VIPP;

//=============================================================================
//InitVIP;
//初始化VIP。返回一个HRESULT
//
//其中FnOnGetInfo和FnOnRender都可以为NULL。
//加载视频的时候,FnOnGetInfo会被调用。视频解码器每渲染一帧,FnOnRender会被调用
//一次。而如果FnOnGetInfo在调用的时候(*ppWriteTo)被改写,则每渲染一帧,VIP都会
//将图像数据复制到(*ppWriteTo)
//
//找不到视频文件时报错是VFW_E_NOT_FOUND(值为0x80040216)
//并不是所有的视频格式都支持将数据输出到内存,因此对于有些格式的视频将无法打开
//会报错VFW_E_NOT_FOUND
//-----------------------------------------------------------------------------
VIPFunc(HRESULT)InitVIP
(
        VIPP,                                                //对象
        WCHAR*szVideoFilePath,                //视频文件的路径
        FnOnGetInfo,                                //取得信息的回调函数,可为NULL
        FnOnRender,                                        //每渲染一帧的回调函数,可为NULL
        BOOL bRenderAudio,                        //是否渲染声音
        void*pUserData                                //用户自定义信息
);

//=============================================================================
//CleanupVIP;
//清理VIP。用完后必须调用一次。
//-----------------------------------------------------------------------------
VIPFunc(void)CleanupVIP(VIPP);

//=============================================================================
//播放控制类:
//-----------------------------------------------------------------------------
VIPFunc(HRESULT)VIPPlay(VIPP);//播放
VIPFunc(HRESULT)VIPStop(VIPP);//停止
VIPFunc(HRESULT)VIPSetRate(VIPP,double);//设置播放速度
VIPFunc(HRESULT)VIPGetRate(VIPP,double*);//取得播放速度
VIPFunc(HRESULT)VIPSetTime(VIPP,REFTIME);//设置播放位置
VIPFunc(HRESULT)VIPGetTime(VIPP,REFTIME*);//取得播放位置
VIPFunc(HRESULT)VIPCheckCompleted(VIPP,BOOL*pCompleted);//检查是否播放完

#endif // !_VIDEO_INTERNAL_PLAYER_代码是用C++写的,但是是C的接口方式。其实C++也还是很不错的语言,但是需要用户合理使用它,别它有什么特性你就用什么特性,你只用最应该用的特性才是。

没有范例的工程下载:
http://pan.baidu.com/s/1mg826E0(访问密码:8xyn)

有范例的工程下载:(有个敖厂长的MC视频所以比较大。。但是它能直接用源码教你怎么用。)
http://pan.baidu.com/s/1qWLR9W4(访问密码:96q7)

好像bilibili的HLV格式的视频直接下载下来后不能用这个播放,必须用格式工厂转换成别的格式才行(搞成AVI、MP4、WMV或RMVB等)
这个程序并不带任何解码器,它只是一个使用了DirectShow的播放器,以及一个用来提取BMP的傀儡解码器。
建议大家先装好解码器,再使用这个东西播放,否则可能会遇到因为格式问题无法播放(缺少解码器)。
大家如果要用这个东西编写自己的播放器,我觉得你们可以考虑给自己的程序带上几个解码器,然后用regsvr32注册这些解码器,这样大概就能啥都播放了。

0xAA55 发表于 2014-10-3 16:09:16

页: [1]
查看完整版本: 【DirectShow】视频内置播放器Video Internal Player