Salutations,DirectShow Audio/Vidéo PTS Pointant Calcul
J'ai écrit un filtre source DirectShow qui prend les unités d'accès aux images vidéo AVC/AAC/AAC de l'émission ATSC-153, écrit sur le processeur vidéo WinCE/ARM. Les broches de sortie (2 d'entre elles, une pour la vidéo, une pour l'audio) sont connectées aux décodeurs et aux moteurs de rendu appropriés. Actuellement, je prends le PTS à partir des en-têtes RTP appropriés, et je les passe au filtre source et j'effectue le calcul sur l'horloge DirectShow. Video PTS est au taux de 90Khz, le taux de PTS audio varie, mon flux de test actuel a le ticking audio à 55,2Khz.
Ce qui suit est les routines convert_to_dshow_timestamp() et FillBuffer(). Lorsque j'imprime les horodatages convertis lorsque la vidéo/l'audio est récupérée par le filtre, les temps sont compris entre 100 et 200 ms. Ce ne serait pas mauvais, quelque chose avec lequel travailler. Cependant, la vidéo suit l'audio de 2 à 3 secondes.
/* routine pour convertir une fréquence d'horloge à DirectShow fréquence d'horloge */ statique unsigned long long convert_to_dshow_timestamp ( longs ts unsigned long, taux unsigned long ) { long double hz; long double multi; long double 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;
}
/* Filtre source routine FillBuffer() */ HRESULT OutputPin :: FillBuffer (IMediaSample * pSamp) { BYTE * pData; DWORD dataSize; pipeStream stream; BOOL retVal; DWORD returnBytes; HRESULT hr; DWORD discont; REFERENCE_TIME ts; REFERENCE_TIME df; difPts longs non signés; unsigned long long 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;
} /* Fin code */
J'ai essayé le réglage de la PTS de vidéo, en ajoutant simplement (90000 * 10), pour voir si la vidéo irait loin de l'audio, Cependant, ce n'est pas le cas. La vidéo suit toujours l'audio de 2 secondes ou plus. Je ne comprends vraiment pas pourquoi cela ne marcherait pas. Chaque image vidéo devrait présenter 10 secondes d'avance. Est-ce que ce ne serait pas correct?
Leur principale question est, fondamentalement, sont les algorithmes sonores? Ils semblent fonctionner correctement la vidéo/audio indépendamment.
Le filtre source n'est pas un filtre poussoir, je ne suis pas sûr si cela fera une différence. Je n'ai pas de problèmes avec les décodeurs qui ne sont pas synchronisés avec les données de l'émission.
Merci beaucoup.
Est-ce que le suivi se produit au fil du temps ou commence-t-il immédiatement avec le délai de 2-3 secondes? En outre, reformatez le code pour qu'il soit plus lisible. – BeemerGuy
Désolé pour le format du code. Je vais essayer de faire mieux la prochaine fois. – davroslyrad