Я пишу собственный исходный push-фильтр DirectShow, который должен получать данные RTP с видеосервера и отправлять их в средство визуализации. Я написал класс CVideoPushPin, который наследуется от классов CSourceStream и CVideoReceiverThread, являющихся оболочкой для потока, получающего RTP-пакеты от видеосервера. Поток получателя по существу делает три вещи:
- получает необработанные 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();
Проблема в том, что я не уверен, как мне устанавливать временные метки для каждого MediaSample в методе FillBuffer. Я пробовал несколько способов, но воспроизведение либо останавливается, либо идет слишком медленно.
В настоящее время метод FillBuffer выглядит следующим образом:
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 не может извлекать данные достаточно быстро), и в результате увеличивается задержка при воспроизведении видео. Кто-нибудь есть идеи, как я должен делать отметки времени при получении данных из живых источников?