DirectShow中响应事件

首先我们先讲讲事件通报是怎样工作的
在DirectShow应用程序运行过程中,过滤器状态是会变化的。例如,它可能会从暂停编程播放,或在流中遇到一个错误,或者请求视频窗口重绘等等。为了让过滤图形管理器可以得到这些变化,过滤器会发一个事件通报,由个相应的事件码组成,它代表了一个类型的事件。下面就列出了所有的事件通报码:
EC_ACTIVATE 视频窗口被激活或者转为非激活状态
EC_BUFFERING_DATA 过滤图形包含缓冲数据
EC_CLOCK_CHANGED 参考时钟被改变
EC_CLOCK_UNSET 时钟提供者被断开
EC_COMPLETE 所有数据被渲染完毕
EC_DEVICE_LOST 一个即插即用设备被移除或者变为有效.
EC_DISPLAY_CHANGED 显示模式被改变
EC_END_OF_SEGMENT 到达段的末尾.
EC_ERROR_STILLPLAYING 一个异步命令失败
EC_ERRORABORT 一个操作被放弃
EC_EXTDEVICE_MODE_CHANGE 不支持
EC_FULLSCREEN_LOST 一个视频渲染窗口被切换出全屏模式.
EC_GRAPH_CHANGED 过滤器图被改变
EC_LENGTH_CHANGED 源的长度被改变.
EC_NEED_RESTART 过滤器请求过滤图重新开始.
EC_NOTIFY_WINDOW 通报一个视频渲染窗口的过滤器
EC_OLE_EVENT 过滤器传递一个字符串给应用程序。.
EC_OPENING_FILE 过滤图打开一个文件,或者已经完成了打开文件操作
EC_PALETTE_CHANGED 视频调色板被改变.
EC_PAUSED 一个暂停请求被处理.
EC_QUALITY_CHANGE 过滤图为了质量控制丢桢
EC_REPAINT 一个视频渲染器要求重绘.
EC_SEGMENT_STARTED 一个新段开始
EC_SHUTTING_DOWN 过滤器图被关闭
EC_SNDDEV_IN_ERROR 一个音频设备的输入引脚错误.
EC_SNDDEV_OUT_ERROR 一个音频设备的输出引脚错误.
EC_STARVATION 过滤器没有得到足够的数据.
EC_STATE_CHANGE 过滤器图状态改变
EC_STEP_COMPLETE 一个过滤器执行了单桢渐进
EC_STREAM_CONTROL_STARTED 流控制开始命令产生效果.
EC_STREAM_CONTROL_STOPPED 一个流控制的停止命令产生效果
EC_STREAM_ERROR_STILLPLAYING 在流中产生了一个错误,但流还是在运行中.
EC_STREAM_ERROR_STOPPED 一个流因错误而停止
EC_TIMECODE_AVAILABLE 不支持
EC_USERABORT 用户中断回放.
EC_VIDEO_SIZE_CHANGED 本地视频尺寸改变.
EC_WINDOW_DESTROYED 视频渲染器被销毁,或者从过滤器图中移除.
过滤图形管理器有时候处理一些事件并不通报给应用程序,例如,请求重绘视频窗口的事件。DirectShow的事件响应机制很象Windows下的消息循环。其实当一个新的事件发生时,你可以发送一个windows消息到指定的窗口。然后应用程序会从windows消息循环中处理这个事件。
使用事件通报
下面的例子代码处理了一个来自主窗口的消息循环。这个消息是用户自己定义的,WM_APP是一个用户消息的底线标志,应用程序可以使用的消息标识的数字范围是WM_APP到0xBFFF。如下:
#define WM_GRAPHNOTIFY  WM_APP + 1
下来设定过滤图形管理器来给应用程序的主窗口提交这个消息:
pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);
ImediaEventEx::SetNotifyWindow方法指定了一个窗口(g_hwnd)作为接收消息的容器。这个方法需要在创建完过滤图形管理器和指定播放窗口之后调用,但一定要在播放之前。
为了响应消息我们需要在WindowProc中添加这个消息的处理:
case WM_GRAPHNOTIFY:
    HandleEvent();
    break;
在处理函数中我们可以调用ImediaEvent::GetEvent方法来从循环中获得事件:
long evCode, param1, param2;
HRESULT hr;
if (pEvent == NULL)
    return;
while (hr = pEvent->GetEvent(&evCode, &param1, &param2, 0), SUCCEEDED(hr))
{
    hr = pEvent->FreeEventParams(evCode, param1, param2);
    if ((EC_COMPLETE == evCode) || (EC_USERABORT == evCode))
    {
        CleanUp();
        break;
    }
}
因为事件是异步处理的,因此可能会有很多消息需要处理,我们要一直调用GetEvent来获得消息,直到它的返回值为失败码,这样就证明消息信号已经空了。
由于它们的参数有可能会是BSTR类型的数据(这是ATL里需要分配资源的数据类型)。因此我们要释放它们(ImediaEvent::FreeEventParams)。
当一个EC_COMPLETE事件发生,过滤图形管理器不会自动的切换到停止状态。这个必须由应用程序来控制。
在应用程序释放ImediaEventEx指针的时候,它必须要设置SetNotifyWindow为NULL来取消事件通报。
pEvent->SetNotifyWindow(NULL, 0, 0);
pEvent->Release();
pEvent = NULL;
下面是一个完整的例子:
#include <windows.h>
#include <dshow.h>

#define WM_GRAPHNOTIFY  WM_APP + 1
#define CLASSNAME "EventNotify"

IGraphBuilder   *pGraph = NULL;
IMediaControl   *pMediaControl = NULL;
IMediaEventEx   *pEvent = NULL;
IVideoWindow    *pVidWin = NULL;
HWND            g_hwnd;

void PlayFile(void)
{
    CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
                     IID_IGraphBuilder, (void **)&pGraph);
    pGraph->RenderFile(L"C://Media//Boys.avi", NULL);

    pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin);
    pVidWin->put_Owner((OAHWND)g_hwnd);
    pVidWin->put_WindowStyle( WS_CHILD | WS_CLIPSIBLINGS);

    pGraph->QueryInterface(IID_IMediaEventEx, (void **)&pEvent);
    pEvent->SetNotifyWindow((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0);

    pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
    pMediaControl->Run();
}

void CleanUp(void)
{
    pVidWin->put_Visible(OAFALSE);
    pVidWin->put_Owner(NULL);

    pEvent->SetNotifyWindow(NULL, 0, 0);
    pEvent->Release();
    pEvent = NULL;

    // Stop the graph.
    pMediaControl->Stop();

    pMediaControl->Release();
    pVidWin->Release();
    pGraph->Release();
    PostQuitMessage(0);
}

void HandleEvent()
{
    long evCode, param1, param2;
    HRESULT hr;

    if (pEvent == NULL)
        return;
    while (hr = pEvent->GetEvent(&evCode, &param1, &param2, 0), SUCCEEDED(hr))
    {
        hr = pEvent->FreeEventParams(evCode, param1, param2);
        if ((EC_COMPLETE == evCode) || (EC_USERABORT == evCode))
        {
            CleanUp();
            break;
        }
    }
}


/* WindowProc 函数在这里:
        case WM_GRAPHNOTIFY:
            HandleEvent();
            break;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
画质最好的视频批量转成rmvb或rm格式的工具Easy RealMedia Producer 1.94 & Editor 1.73文绿色版(内含教程) xzpd2012评语:这是我用过最好的一个rmvb转换软件,现在网上大多数rmvb电影都是用它转的,画质几乎无损。转换速度也快,还可以批量压制,强烈推荐! 以下是介绍: Easy Realmedia Producer(以下简称ERP)可以说是当今Real多媒体文件压缩软件的一个突破。它不仅支持的源文件格式多(DirectShow接口播放的格式基本上都可以导入,包括音频),还具有丰富的参数设置和极为实用的批处理功能,可以说是集百家之长,而且占用资源少,速度快。ERP是全免费软件。它支持批量压制。采用全新的RealVideo9&RealVideo10内核软件根据实际使用的需要提供了比Helix RealMedia Producer和RealProducer10还要多的过滤设置。基本上可以用它来替代Helix RealMedia Producer和RealProducer10,使用Real10内核时,全面支持Real10文件编码,并提供Real8、Real9兼容的编码支持。具体的功能有:可以设定压缩列表,软件按照列表自动顺序压缩。可以选择压缩完成后关闭机器。 特性: 每个文件可以进行单独设置。提供了Helix Real Producer9.1还要多的过滤设置 如: 1.可以 进行音频和视频同步调整。 2.可以 设置每个影片的压缩时间长度(略过结尾序幕)。 3.直接支持使用avs. 4.支持调节画面颜色/亮度. ...... 自动关机前有30秒响应时间,用户可以取消关机。 任务结束后有详细的信息报告。   1.RM文件的压缩   启动ERP,然后点添加来选择要压缩的文件,接下来点参数设置。压缩设置可以决定采用老的固定码率的RM还是现在流行的动态码率的RMVB格式。如用动态编码建议大家最大码率不超过750KB,平均码率不要低于300KB。为了获得更好的画面质量片源质量高时平均码率相应也要提高,但最高也不宜超过550KB。在视频编码这一栏,ERP提供了Real Video8/9/10这三种编码核心(也就是Real Player8、Real one Player9和Real Player10分别采用的编码核心),这里我建议大家用比较成熟的RealVideo9编码格式。   我们来看图像质量和帧速率FPS的设置,这二者其实存在反比关系,当维持帧速率较为重要时,可以适当降低图像质量,一般说来把图像质量定在85,FPS定在23左右是个不错的搭配。在过滤设置可以通过音频“+延迟/-提前”选项对音频和视频的不同步问题进行调整;在高质量调整画面大小后的更多选项里,我们还能够对画面大小进行裁剪,去掉多余的边缘部分。   如果是把其他的音频格式(例如WAV、MP3、WMA)转换为RM格式的话,则只需要在参数设置里对音频编码进行设置即可。   2.RM文件编辑   ERP还附带了Easy Realmedia Editor这个小软件,可以对Real文件进行简单的合并和分割操作。启动后,其主界面和ERP基本相同载入需编辑的文件后点参数设置。提取影片片段只要在编辑单个文件下确定好起始和结束时间。如果是要合并文件就在选择多个文件合并后依次在左边的小窗口添加上要追加合并的文件,这里要特别注意的是所有被合并的文件必须保证编码率和分辨率都要完全相同。   此外,ERP还通过插件支持对字幕、Ogg音频以及VOB文件的直接压缩,装上了Real Media Spilter后还可以对RM和RMVB进行二次再压缩。总之,Easy Realmedia Producer是一款功能非常强大的real格式文件压缩软件,有兴趣的朋友赶紧试试吧! 绿化说明: 由于两个软件使用了一个载体,而Easy RealMedia Editor 1.73又是寄生的部分,所以只能写个BAT脚本来启动了。打开后有个黑洞洞的DOS命令行界面,程序打开后就可以关掉它了。 还有,虽然在“关于”里显示的是前一个版本,但是实际上这个是真正的Easy RealMedia Producer 1.94 & Editor 1.73(可以看两个软件启动时的窗口那里)。具体为什么会是这样,就要问作者了。 最后,为了方便使用,偶已经把参数设置成最佳参数,没必要的话请不要随意改动,否则压出来的片不是太大就是太差,那时候就表吼偶哦~~ 绿化手记: 前段时间在网上学习了字幕制作,并接触了这个软件,但是苦苦等了8个月都没见绿化版本。于是在昨天晚上,试着对其进行安装监测,发现这个东西居然完全可以进行绿化的操作,而且还不是一般的容易。 在绿化过程偶发现一个奇怪又好玩的问题:Easy RealMedia Editor 1.73没有执行文件!那它是怎么运行的呢? 好奇之下我看了看安装目录下的Easy RealMedia Editor 1.73快捷方式的属性,然后才恍然大悟:Easy RealMedia Editor 1.73跟Easy RealMedia Producer 1.94其实是一个软件,它们共同拥有一个载体,只是一个直接启动,另外一个需要用参数启动而已(Easy RealMedia Editor 1.73的启动参数是:主程序DOS名 -run:rmeditor)。 同一程序用不同参数调出不同平台可以节省下不少安装体积,想不到作者这么厉害,呵呵~~ 绿化:龙梦秋 2006.09.14

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值