Directshow里面的Transform filter的问题

mlhy20060406 2011-03-14 05:08:09
DS的Transform filter的问题:
Transform(IMediaSample *pIn, IMediaSample *pOut)中
long lSourceSize = pIn->GetActualDataLength();
long lDestSize = pOut->GetSize();
lDestSiz大小总是320X240,而lSourceSize=720X576,因为一开始设置的视频大小是720X576。从而导致视频大小不能超过320X240,一旦超过此尺寸,导致了后面的CopyMemory( (PVOID) pDestBuffer,(PVOID) pSourceBuffer,lSourceSize)内存错误。怪就怪在如果是USB摄像头到是可以,如果是PCI采集卡连接的CCD摄像机,就出现了上述问题。 这个视频处理的filter,如果一开始设定的视频大小不超过320x240是可以正常运行的,如果在开始的时候设定视频的大小为640x480,程序就运行不起来。就出现了刚开始我给您发送的那样错误了。

我在这个函数CheckTransfrom(const CMediaType *mtIn, const CMediaType *mtOut)里跟踪调试如下语句:
VIDEOINFO *pInput = (VIDEOINFO *) mtIn->Format();
VIDEOINFO *pOutput = (VIDEOINFO *) mtOut->Format();
long mInputWidth = pInput->bmiHeader.biWidth;
long mInputHeight = pInput->bmiHeader.biHeight;
long mOutputWidth = pOutput->bmiHeader.biWidth;
long mOutputHeight = pOutput->bmiHeader.biHeight;
看到的视频大小都是720x576

我在CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)中发现in的大小为720x576,out的大小也为720x576,为什么到Transform(IMediaSample *pSource, IMediaSample *pDest)中发现in的大小还是720x576,而out的大小变为了320x240了呢。

有位高人说是媒体类型改变,在Tranform()函数里重新分配out的内存大小,我是新手尝试很多次都是失败,被这个问题困扰了有两个星期了!哪位高人可以贴出动态媒体类型改变,重新设置out的媒体媒体类,并重新分配out内存大小的代码。或者发给兄弟一个类似的transform filter的源码,我的邮箱是:809279480@qq.com 。很愁啊,兄弟们帮帮忙。
...全文
562 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
hegu 2011-04-11
  • 打赏
  • 举报
回复
顶这个。感觉现在问这个动态改变格式的帖子,很多。要是有个详细点的说明或者例子就好了。:)

[Quote=引用 7 楼 mlhy20060406 的回复:]
谢谢【rageliu】的回复。
rageliu高人,如果能针对这三种情况能给出相关的示例代码参考,理论结合一下实际,可能效果会更好。
我现在刚接触这一块,看起来很容易做起来很难。我希望高人【rageliu】如果有时间写一篇详细的媒体动态类型改变的blog,并提供示例源码下载,为我们刚接触着这一块的人一个指引。
我可能有点得寸进尺了,我根据您的指点尝试一下看看能不能完成。
[/Quote]
mlhy20060406 2011-03-21
  • 打赏
  • 举报
回复
提出的问题,最终还是没有完美解决。
mlhy20060406 2011-03-21
  • 打赏
  • 举报
回复
hr = ((CVideoProcessorOutputPin *)m_pOutput)->ChangeMediaType(&mt);总是返回失败,也不知道什么原因。
提出的问题,最终还是完美解决。暂时的解决方案是设置好以后,退出程序,重新进入。不能实时动态改变视频分辨率的大小。
感谢上面几位高人的帮助,特别是【tufaqing】提供参考代码学习。先结贴,以后在慢慢钻研!
mlhy20060406 2011-03-17
  • 打赏
  • 举报
回复
感谢楼上的回复。DS文档也看了一部分,但是媒体类型的动态变化、视频分辨率的由小到大或者有大到小的变化目前还是没有解决。哪位高人可以贴一个完整的filter源码看看吗?谢谢了。发我邮箱也可以809279480@qq.com 。我希望高人能再出来指点指点。
mlhy20060406 2011-03-17
  • 打赏
  • 举报
回复
TO【tufaqing】:
您的代码文件我我重新加载在VC6.0工程下面出现了编译以下问题:
videoprocessor.cpp(125) : error C2664: 'CTransformInputPin::CTransformInputPin' : cannot convert parameter 1 from 'const char *' to 'char *' Conversion loses qualifiers
videoprocessor.cpp(159) : error C2664: 'CTransformOutputPin::CTransformOutputPin' : cannot convert parameter 1 from 'const char *' to 'char *' Conversion loses qualifiers
我把类型LPCTSTR pObjectName 改为 TChar * pObjectName 应该不会出现啥问题吧?我把这句#include "stdafx.h"包含头文件也给注释掉了,我的VC不是好,半路出嫁过来的,有些基本的东西我不是很了解。我慢慢调试编译,先看一下功能效果,然后在慢慢消化功能代码。
tufaqing 2011-03-17
  • 打赏
  • 举报
回复
而且硬件一般不知道运行中改变视频大小的 -> 不支持
mlhy20060406 2011-03-17
  • 打赏
  • 举报
回复
TO【tufaqing】:
盼星星,盼月亮的终于把您给盼来了,有您的支持我看到希望了。感谢您无私的奉献,我先学习一下您代码。问题解决了立刻来结贴。
tufaqing 2011-03-17
  • 打赏
  • 举报
回复
不知道你想实现什么功能,抛开功能,通过TransformFilter写一个仅仅是数据拷贝往后传的filter而不用实现任何功能是比较简单的。动态改变是运行过程中改变视频大小的,你这个运行前设置好就可以不用管那么多了,而且硬件一般不知道运行中改变视频大小的,要停下来设置,最好再重连一下。你这个貌似和动态改变没有太大关系。
不管怎样,给你一份我的视频缩放处理filter供参考,处理时只支持YV12视频的。
mlhy20060406 2011-03-17
  • 打赏
  • 举报
回复
transform filter里面实现了旋转90度,宽高长度互换,现在想取消旋转,恢复原来的视频显示的状态(也就是没有进行视频旋转90度之前的状态)。是不是又牵涉到了媒体类型的动态改变了呢?
高人最好能贴出源码参考!
  • 打赏
  • 举报
回复
哎~~你问的问题感觉不是很明确哦~~
如果你是想知道如何实现动态媒体类型改变,我给你贴出DS帮助文档里的专门描述这一技术的文章:
Dynamic Format Changes
When two filters connect, they agree on a media type, which describes the format of the data that the upstream filter will deliver. In most cases, the media type is fixed for the duration of the connection. However, DirectShow does offer limited support for filters to change the media type. When a filter switches media types, it is called a dynamic format change. If you are writing a DirectShow filter, you should be aware of the mechanisms for dynamic format changes. Even if your filter does not support such changes, it should respond correctly if another filter requests a new format.

DirectShow defines several distinct mechanisms for dynamic format changes, depending on the state of filter graph and the type of change that is required.

If the graph is stopped, the pins can reconnect and renegotiate the media type. For more information, see Reconnecting Pins.
Some filters can reconnect pins even while the graph is active (running or paused). For more information about this mechanism, see Dynamic Reconnection.
Otherwise, if the graph is active, but the filters in question do not support dynamic pin reconnections, there are three possible mechanisms for changing the format:

QueryAccept (Downstream) is used when If an output pin proposes a format change to its downstream peer, but only if the new format does not require a larger buffer.
QueryAccept (Upstream) is used when an input pin proposes a format change to its upstream peer. The new format can be the same size, or it can be larger.
ReceiveConnection is used when an output pin proposes a format change to its downstream peer, and the new format requires a larger buffer.

如果需要知道的更详细点,你自己去DS帮助文档里查找《Dynamic Format Changes》这个文章,它还包括了4个子文章。
mlhy20060406 2011-03-15
  • 打赏
  • 举报
回复
谢谢【rageliu】的回复。
rageliu高人,如果能针对这三种情况能给出相关的示例代码参考,理论结合一下实际,可能效果会更好。
我现在刚接触这一块,看起来很容易做起来很难。我希望高人【rageliu】如果有时间写一篇详细的媒体动态类型改变的blog,并提供示例源码下载,为我们刚接触着这一块的人一个指引。
我可能有点得寸进尺了,我根据您的指点尝试一下看看能不能完成。

rageliu 2011-03-15
  • 打赏
  • 举报
回复
CheckTransfrom只是在连接的时候判断格式,而格式的改变,一般是在连接完成后,开始运行的时候出现的。
常见的几种情况:
A。在Trans函数里,对in的sample做GetMediaType,成功取得的话,说明上游有改变。这时候上游的Sample大小已经由上游的out pin重新分配好了,不用你管。你要做的就是根据这个新格式,重新分配你自己的out sample的内存大小。成功分配后,还必须把in的类型设置给out,由out继续往你的下游传递。

B。当你取得你的out的sample的时候,也要做GetMediaType的判断,如果成功取得。说明下游有格式改变的请求。这个一般出现在render的要求,而且一般99.9%会有。这时候你要重新分配你的in的sample,并且设置新格式,传递给你的上游。

C。还是有就ReceiveConnection的处理了,这个就会有QueryAccept,DynamicQueryAccept等的预调用判断。

总之只要有改变,判断sample size是否足够,不够就重新分配。
而且一般需要向你的上/下游传递新的请求格式。
当然可以不传,这时候就要求你的filter的in out是不同格式,也就是你自己处理了格式改变
mlhy20060406 2011-03-15
  • 打赏
  • 举报
回复
我还发现一个怪问题,我在获得这个PCI采集卡所支持的所有视频分辨率大小的时候,总是只能获得一种大小320x240,即使用GetNumberOfCapabilities和GetStreamCaps来枚举支持的媒体格式时,只能列出每一种类型格式的一种分辩率,例如:针对RGB24,它只列出了MEDIASUBTYPE_RGB24的320*240这一种。
但实际上!仅在MEDIASUBTYPE_RGB24也是有多种分辩率支持的。如:640*480,352*288,160*120等等!并且在AMCap程序的视频接口设置对话框也可以看到这些分辩率),另一个证明是:在随后代码的pVih->bmiHeader.biWidth = 640; pVih->bmiHeader.biHeight = 480; 也是可以设置到640*480的。
求问:

1。为什么不能列出所有支持的格式分辩率,原因是什么?(为什么设置框可以检出,但GetNumberOfCapabilities不行)

2。如何解决这个问题!

我上述说的这个视频处理filter总是不支持大于320x240的视频分辨率,是不是和这个问题也有关系呢?

上路的视频源设置的媒体类型大小语句如下:
AM_MEDIA_TYPE *pmt = NULL;
pmt = SelectMediaType();
if(pmt)
{
if(pmt->formattype == FORMAT_VideoInfo)
{
long width,height;
mLiveCapture->GetImageSize(&width,&height);//获得ini配置文件中视频的宽度和高度
VIDEOINFOHEADER *pvi =(VIDEOINFOHEADER *)pmt->pbFormat;//cbFormat;
pvi->AvgTimePerFrame = avgTimePerFrame;//帧率
pvi->bmiHeader.biWidth = width;//640
pvi->bmiHeader.biHeight = height;//480
pvi->bmiHeader.biSizeImage = width * height * pvi->bmiHeader.biBitCount / 8;
pvi->rcSource.right = width;
pvi->rcTarget.right = width;
pvi->rcSource.bottom = height;
pvi->rcTarget.bottom = height;
IAMStreamConfig * pCfg = GetStreamConfig(&PIN_CATEGORY_CAPTURE);
hr = pCfg->SetFormat(pmt);//调试时返回值设置成功

if (mHasPreviewPin)
{
pCfg = GetStreamConfig(&PIN_CATEGORY_PREVIEW);
hr = pCfg->SetFormat(pmt);//调试时返回值设置成功
}
DeleteMediaType(pmt);
}
}
为什么数据到了transfrom filter 里面GetMediaType(int iPosition, CMediaType *pMediaType)函数中调试发现
long lnInputSampleSize =m_pInput->CurrentMediaType().GetSampleSize();
VIDEOINFOHEADER* hrIn = (VIDEOINFOHEADER*)pMediaType->pbFormat;
long width =hrIn->bmiHeader.biWidth;
long height =hrIn->bmiHeader.biHeight;
上述四条语句中lnInputSampleSize的值为320x240,width=640,height=480。
为什么lnInputSampleSize 不是640x480呢?
rageliu 2011-03-15
  • 打赏
  • 举报
回复
呵,没时间写的
mlhy20060406 2011-03-14
  • 打赏
  • 举报
回复
我在GetMediaType(int iPosition, CMediaType *pMediaType)函数中调试发现long lnInputSampleSize =m_pInput->CurrentMediaType().GetSampleSize();
VIDEOINFOHEADER* hrIn = (VIDEOINFOHEADER*)pMediaType->pbFormat;
long width =hrIn->bmiHeader.biWidth;
long height =hrIn->bmiHeader.biHeight;
上述四条语句中lnInputSampleSize的值为320x240,width=720,height=576。为什么lnInputSampleSize 不是720x576呢?
同理上述的四条语句在CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)中
VIDEOINFO *pInput = (VIDEOINFO *) mtIn->Format();
VIDEOINFO *pOutput = (VIDEOINFO *) mtOut->Format();
long lnInputSampleSize =m_pInput->CurrentMediaType().GetSampleSize();
long lnOutputSampleSize =m_pOutput->CurrentMediaType().GetSampleSize();
long mInputWidth = pInput->bmiHeader.biWidth;
long mInputHeight = pInput->bmiHeader.biHeight;
long mOutputWidth = pOutput->bmiHeader.biWidth;
long mOutputHeight = pOutput->bmiHeader.biHeight;
上述语句测试发现lnInputSampleSize = lnOutputSampleSize =320x240,mInputWidth =mOutputWidth=720,mOutputHeight =mOutputHeight =576
在函数DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)也是发现上述现象。
lnInputSampleSize =mInputWidth x mInputHeight =720X576是不是才是正确的结果,上述的现象是不是异常现象呢?
mlhy20060406 2011-03-14
  • 打赏
  • 举报
回复
To OExpress:
这两个帖子我都看了,可能是我基础薄弱,按照他们的思想总是不能改变。
Transform(IMediaSample *pIn, IMediaSample *pOut)中
long lDestSize = pOut->GetSize();这个lDestSize的大小(320x240),因为是PCI采集卡连接的CCD摄像机,如果用USB摄像头,这个f long lDestSize = pOut->GetSize()是可以改变。
CyberLogix 2011-03-14
  • 打赏
  • 举报
回复
这个是动态改变视频尺寸的问题了,清参考一下面两个帖子;
http://topic.csdn.net/u/20110118/18/a9d46505-5b77-46e8-a6ec-43dbc7304348.html?9631

http://topic.csdn.net/u/20101202/16/1f35d89a-8047-418f-b5d1-663a3f159d4e.html
mlhy20060406 2011-03-14
  • 打赏
  • 举报
回复
在网上CSDN blog上寻找到【tufaqing】高人的一段HRESULT CVideoProcessor::Receive(IMediaSample *pSample)
{
BYTE* pData = NULL;
HRESULT hr = pSample->GetPointer(&pData);
if(FAILED(hr))
{
return hr;
}
………………………………………………
}使用,运行软件就直接卡死。
期盼【tufaqing】高人出现能解答一下疑惑

2,543

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧