Filter 编写自定义DirectShow RTSP/RTP源推送筛选器-来自实时源的时间戳数据
我正在编写定制的DirectShow源推送过滤器,它应该从视频服务器接收RTP数据并将它们推送到渲染器。我编写了一个CVideoPushPin类,它继承了CSourceStream和CVideoReceiveThread类,后者是从视频服务器接收RTP数据包的线程的包装器。接收器线程基本上做三件事:Filter 编写自定义DirectShow RTSP/RTP源推送筛选器-来自实时源的时间戳数据,filter,directshow,rtp,rtsp,Filter,Directshow,Rtp,Rtsp,我正在编写定制的DirectShow源推送过滤器,它应该从视频服务器接收RTP数据并将它们推送到渲染器。我编写了一个CVideoPushPin类,它继承了CSourceStream和CVideoReceiveThread类,后者是从视频服务器接收RTP数据包的线程的包装器。接收器线程基本上做三件事: 接收原始RTP数据包并收集接收器报告所需的一些数据 组装帧,将其复制到缓冲区,并将有关帧的信息存储到256 元素队列,定义如下: struct queue_elem { char *star
- 接收原始RTP数据包并收集接收器报告所需的一些数据
- 组装帧,将其复制到缓冲区,并将有关帧的信息存储到256
元素队列,定义如下:
struct queue_elem { char *start; // Pointer to a frame in a buffer int length; // Lenght of data REFERENCE_TIME recvTime; // Timestamp when the frame was received (stream time) }; struct data { struct queue_elem queue[QUEUE_LENGTH]; int qWrIdx; int qRdIdx; HANDLE mutex; };
- 每个接收到的帧都带有当前流时间的时间戳
p->StreamTime(refTime); REFERENCE_TIME rt = refTime.GetUnits();
REFERENCE_TIME thisFrameStartTime, thisFrameEndTime;
// Make sure if there are at least 4 frames in the buffer
if(noOfFrames >= 4)
{
currentQe = m_myData.queue[m_myData.qRdIdx++]; //Take current frame description
if(m_myData.qRdIdx >= QUEUE_LENGTH)
{
m_myData.qRdIdx = 0;
}
nextQe = m_myData.queue[m_myData.qRdIdx]; //Take next frame description
if(currentQe.length > 0)
{
memcpy(pData, currentQe.start, currentQe.length);
pSample->SetActualDataLength(currentQe.length);
CRefTime refTime;
m_pFilter->StreamTime(refTime);
REFERENCE_TIME rt;
rt = refTime.GetUnits();
pSample->GetTime(&thisFrameStartTime, &thisFrameEndTime);
thisFrameEndTime = thisFrameStartTime + (nextQe.recvTime - currentQe.recvTime);
pSample->SetTime(&thisFrameStartTime, &thisFrameEndTime);
}
}
else
{
pSample->SetActualDataLength(0);
}
在本例中,我注意到队列中的项目数量增长非常快(由于某些原因,FillBuffer方法无法足够快地提取数据),结果是播放视频时增加了延迟。有人知道当从实时源接收数据时应该如何进行时间戳吗?当图形的流时间达到样本对象上的时间戳时,渲染器将绘制帧。如果我正确阅读了您的代码,您将使用到达时的流时间为它们添加时间戳,因此它们在渲染时总是会迟到。这在某种程度上被音频渲染器弄糊涂了:如果音频渲染器提供图形的时钟,那么它将报告当前流时间为它当前正在播放的任何样本,这将导致一些不希望的时间行为
GGeraint,感谢您的输入。我对代码做了一些更改,但是,视频在运行后立即冻结。在日志文件中,我注意到FillBuffer方法只调用了两次。第一次调用时,流时间为3633950000,frameStartTime为3635700000,frameEndTime为3635703600。第二次调用时,stream时间是3634370000,frameStartTime是3635703600,frameEndTime是3635707200。因此,如果我理解正确,渲染器应该等待流时间到达第一帧的时间戳,然后平稳运行,但不幸的是,它没有发生。