Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Video DirectShow音频/视频PTS时钟计算_Video_Audio_Synchronization_Directshow - Fatal编程技术网

Video DirectShow音频/视频PTS时钟计算

Video DirectShow音频/视频PTS时钟计算,video,audio,synchronization,directshow,Video,Audio,Synchronization,Directshow,您好 我已经编写了一个directshow源过滤器,它从ATSC-153广播中获取AVC/AAC视频帧/AAC访问单元,并在WinCE/ARM视频处理器上编写。输出引脚(其中两个,一个用于视频,一个用于音频)连接到相应的解码器和渲染器。目前,我正在从适当的RTP头中获取PTS,并将它们传递到源过滤器,然后执行directshow时钟的计算。视频PTS的频率为90Khz,音频PTS的频率不同,我当前的测试流的音频频率为55.2Khz 下面是convert_to_dshow_timestamp()和

您好

我已经编写了一个directshow源过滤器,它从ATSC-153广播中获取AVC/AAC视频帧/AAC访问单元,并在WinCE/ARM视频处理器上编写。输出引脚(其中两个,一个用于视频,一个用于音频)连接到相应的解码器和渲染器。目前,我正在从适当的RTP头中获取PTS,并将它们传递到源过滤器,然后执行directshow时钟的计算。视频PTS的频率为90Khz,音频PTS的频率不同,我当前的测试流的音频频率为55.2Khz

下面是convert_to_dshow_timestamp()和FillBuffer()例程。当我打印转换后的时间戳时,视频/音频由过滤器检索,时间差在100-200ms之间。这不会太糟糕,可以一起工作。但是,视频会比音频慢2-3秒

/*将时钟速率转换为directshow时钟速率的例程*/ 静态无符号长-长转换为显示时间戳( 未签名的长ts, 无符号长期利率 ) { 长双频; 长双多; 长双tmp

if (rate == 0)
{
    return 0;
}

hz = (long double) 1.0 / rate;
multi = hz / 1e-7;

tmp = ((long double) ts * multi) + 0.5;
return (unsigned long long) tmp;
}

/*源筛选器FillBuffer()例程*/ HRESULT OutputPin::FillBuffer(IMediaSample*pSamp) { 字节*pData; DWORD数据大小; 管道流; 布尔-雷特瓦尔; DWORD返回字节; HRESULT-hr; 德沃德·安索特; 参考时间ts; 参考时间df; 无符号长DIFPT; 无符号长difTimeRef

pSamp->GetPointer(&pData);
dataSize = pSamp->GetSize();

ZeroMemory(pData, dataSize);

stream.lBuf = pData;
stream.dataSize = dataSize;

/* Pin type 1 is H.264 AVC video frames */
if (m_iPinType == 1)
{
    retVal = DeviceIoControl(
                                ghMHTune,
                                IOCTL_MHTUNE_RVIDEO_STREAM,
                                NULL,
                                0,
                                &stream,
                                sizeof(pipeStream),
                                &returnBytes,
                                NULL
                            );
    if (retVal == TRUE)
    {
        /* Get the data */
        /* Check for the first of the stream, if so, set the start time */
        pSamp->SetActualDataLength(returnBytes);
        hr = S_OK;
        if (returnBytes > 0)
        {
            /* The discontinuety is set in upper layers, when an RTP
             * sequence number has been lost.
             */
            discont = stream.discont;

            /* Check for another break in stream time */
            if (
                m_PrevTimeRef &&
                ((m_PrevTimeRef > (stream.timeRef + 90000 * 10)) ||
                ((m_PrevTimeRef + 90000 * 10) < stream.timeRef))
               )
            {
                dbg_log(TEXT("MY:DISC HERE\n"));
                 if (m_StartStream > 0)
                {
                    discont = 1;
                }
            }

            /* If the stream has not started yet, or there is a
             * discontinuety then reset the stream time.
             */
            if ((m_StartStream == 0) || (discont != 0))
            {
                sys_time = timeGetTime() - m_ClockStartTime;
                m_OtherSide->sys_time = sys_time;

                /* For Video, the clockRate is 90Khz */
                m_RefGap = (sys_time * (stream.clockRate / 1000)) +
                                                    (stream.clockRate / 2);

                /* timeRef is the PTS for the frame from the RTP header */
                m_TimeGap = stream.timeRef;
                m_StartStream = 1;
                difTimeRef = 1;
                m_PrevPTS = 0;
                m_PrevSysTime = timeGetTime();
                dbg_log(
                        TEXT("MY:StartStream %lld: %lld: %lld\n"),
                        sys_time,
                        m_RefGap,
                        m_TimeGap
                       );
            }
            else
            {
                m_StartStream++;
            }

            difTimeRef = stream.timeRef - m_PrevTimeRef;
            m_PrevTimeRef = stream.timeRef;

            /* Difference in 90 Khz clocking */
            ts = stream.timeRef - m_TimeGap + m_RefGap;
            ts = convert_to_dshow_timestamp(ts, stream.clockRate);

            if (discont != 0)
            {
                dbg_log(TEXT("MY:VDISC TRUE\n"));
                pSamp->SetDiscontinuity(TRUE);
            }
            else
            {
                pSamp->SetDiscontinuity(FALSE);
                pSamp->SetSyncPoint(TRUE);
            }

            difPts = ts - m_PrevPTS;

            df = ts + 1;
            m_PrevPTS = ts;
            dbg_log(
                    TEXT("MY:T %lld: %lld = %lld: %d: %lld\n"),
                    ts,
                    m_OtherSide->m_PrevPTS,
                    stream.timeRef,
                    (timeGetTime() - m_PrevSysTime),
                    difPts
                   );

            pSamp->SetTime(&ts, &df);
            m_PrevSysTime = timeGetTime();
        }
        else
        {
            Sleep(10);
        }
    }
    else
    {
        dbg_log(TEXT("MY:  Fill FAIL\n"));
        hr = E_FAIL;
    }
}
else if (m_iPinType == 2)
{
    /* Pin Type 2 is audio AAC Access units, with ADTS headers */
    retVal = DeviceIoControl(
                                ghMHTune,
                                IOCTL_MHTUNE_RAUDIO_STREAM,
                                NULL,
                                0,
                                &stream,
                                sizeof(pipeStream),
                                &returnBytes,
                                NULL
                            );

    if (retVal == TRUE)
    {
        /* Get the data */
        /* Check for the first of the stream, if so, set the start time */
        hr = S_OK;
        if (returnBytes > 0)
        {
            discont = stream.discont;
            if ((m_StartStream == 0) || (discont != 0))
            {
                sys_time = timeGetTime() - m_ClockStartTime;
                m_RefGap = (sys_time * (stream.clockRate / 1000)) +
                                                    (stream.clockRate / 2);

                /* Mark the first PTS from stream.  This PTS is from the
                 * RTP header, and is usually clocked differently than the
                 * video clock.
                 */
                m_TimeGap = stream.timeRef;
                m_StartStream = 1;
                difTimeRef = 1;
                m_PrevPTS = 0;
                m_PrevSysTime = timeGetTime();
                dbg_log(
                        TEXT("MY:AStartStream %lld: %lld: %lld\n"),
                        sys_time,
                        m_RefGap,
                        m_TimeGap
                       );
            }

            /* Let the video side stream in first before letting audio
             * start to flow.
             */
            if (m_OtherSide->m_StartStream < 32)
            {
                pSamp->SetActualDataLength(0);
                Sleep(10);
                return hr;
            }
            else
            {
                pSamp->SetActualDataLength(returnBytes);
            }

            difTimeRef = stream.timeRef - m_PrevTimeRef;
            m_PrevTimeRef = stream.timeRef;

            if (discont != 0)
            {
                dbg_log(TEXT("MY:ADISC TRUE\n"));
                pSamp->SetDiscontinuity(TRUE);
            }
            else
            {
                pSamp->SetDiscontinuity(FALSE);
                pSamp->SetSyncPoint(TRUE);
            }

            /* Difference in Audio PTS clock, TESTING AT 55.2 Khz */
            ts = stream.timeRef - m_TimeGap + m_RefGap;
            ts = convert_to_dshow_timestamp(ts, stream.clockRate);

            difPts = ts - m_PrevPTS;

            df = ts + 1;
            m_PrevPTS = ts;
            dbg_log(
                    TEXT("MY:AT %lld = %lld: %d: %lld\n"),
                    ts,
                    stream.timeRef,
                    (timeGetTime() - m_PrevSysTime),
                    difPts
                   );

            pSamp->SetTime(&ts, &df);
            m_PrevSysTime = timeGetTime();
        }
        else
        {
            pSamp->SetActualDataLength(0);
            Sleep(10);
        }
    }
}
return hr;
pSamp->GetPointer(&pData);
dataSize=pSamp->GetSize();
零内存(pData、数据大小);
stream.lBuf=pData;
stream.dataSize=dataSize;
/*引脚类型1是H.264 AVC视频帧*/
如果(m_i类型==1)
{
retVal=设备控制(
ghMHTune,
IOCTL_MHTUNE_RVIDEO_流,
无效的
0,
&溪流,
sizeof(管道流),
&返回字节,
无效的
);
如果(retVal==TRUE)
{
/*获取数据*/
/*检查流的第一个,如果是,设置开始时间*/
pSamp->SetActualDataLength(返回字节);
hr=S_OK;
如果(返回字节>0)
{
/*当RTP
*序列号已丢失。
*/
不连续=流。不连续;
/*检查流时间中是否有另一个中断*/
如果(
m_PrevTimeRef&&
((m_PrevTimeRef>(stream.timeRef+90000*10))||
((m_PrevTimeRef+90000*10)0)
{
不连续=1;
}
}
/*如果流尚未启动,或存在
*中断,然后重置流时间。
*/
如果((m_StartStream==0)| |(不连续!=0))
{
sys_time=timeGetTime()-m_ClockStartTime;
m_OtherSide->sys_time=sys_time;
/*对于视频,时钟频率为90Khz*/
m_RefGap=(系统时间*(stream.clockRate/1000))+
(stream.clockRate/2);
/*timeRef是来自RTP标头的帧的PTS*/
m_TimeGap=stream.timeRef;
m_StartStream=1;
difTimeRef=1;
m_PrevPTS=0;
m_PrevSysTime=timeGetTime();
dbg_测井(
文本(“MY:StartStream%lld:%lld:%lld\n”),
系统时间,
m_RefGap,
m_时间间隔
);
}
其他的
{
m_StartStream++;
}
difTimeRef=stream.timeRef-m_PrevTimeRef;
m_PrevTimeRef=stream.timeRef;
/*90 Khz时钟中的差异*/
ts=stream.timeRef-m_TimeGap+m_RefGap;
ts=将时间戳转换为时间戳(ts,流.时钟速率);
如果(不连续!=0)
{
dbg_日志(文本(“MY:VDISC TRUE”);
pSamp->设置不连续性(真);
}
其他的
{
pSamp->设置不连续性(假);
pSamp->SetSyncPoint(真);
}
difPts=ts-m_PrevPTS;
df=ts+1;
m_PrevPTS=ts;
dbg_测井(
文本(“我的:T%lld:%lld=%lld:%d:%lld\n”),
ts,
m_OtherSide->m_PrevPTS,
stream.timeRef,
(timeGetTime()-m_PrevSysTime),
差别
);
pSamp->设置时间(&ts和&df);
m_PrevSysTime=timeGetTime();
}
其他的
{
睡眠(10);
}
}
其他的
{
dbg_日志(文本(“MY:Fill FAIL\n”);
hr=E_失败;
}
}
else如果(m_iPinType==2)
{
/*引脚类型2是音频AAC访问单元,带有ADTS头*/
retVal=设备控制(
ghMHTune,
IOCTL_MHTUNE_RAUDIO_溪流,
无效的
0,
&溪流,
PTS = RTCP_SR_NTP_timestamp + (RTP_timestamp - RTCP_SR_RTP_timestamp) / media_clock_rate