クロッキング私はひるみ/ ARMビデオプロセッサ上で書かれたATSC-153の放送からAVC/AACビデオフレーム/ AACアクセスユニットをとるDirectShowのソースフィルタを書かれています。出力ピン(2つはビデオ用、1つはオーディオ用)は適切なデコーダとレンダラに接続されています。現在、私は適切なRTPヘッダーからPTSを取り出し、ソースフィルターに渡して、directshowクロックに計算を実行しています。ビデオPTSは90Khzのレートで、オーディオのPTSレートはさまざまで、私の現在のテストストリームは55.2Khzでオーディオティックを持っています。
以下は、convert_to_dshow_timestamp()およびFillBuffer()ルーチンです。ビデオ/オーディオがフィルタによって取り出されるときに、変換されたタイムスタンプをプリントアウトするので、時間は100〜200msの差の範囲内にあります。これは悪いことではありません。ただし、ビデオはオーディオを2〜3秒間追跡します。
/* DirectShowのクロックレートにクロック・レートを変換するルーチン*/ スタティック符号なしの長い長いconvert_to_dshow_timestamp( のunsigned long長いTS、 unsigned long型レート ) {長い二ヘルツ。 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;
}
/*ソースフィルタFillBuffer()ルーチン*/ HRESULT OutputPin :: FillBuffer(IMediaSample * PSAMP) {BYTE * pDataを。 DWORD dataSize; pipeStreamストリーム。 BOOL retVal; DWORD returnBytes; HRESULT hr; DWORDが無効です。 REFERENCE_TIME ts; REFERENCE_TIME df; 符号なしlong long difPts; 符号なし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;
} /*コードの終了*/
私は、ビデオがはるか先のオーディオの行くかどうかを確認するために、単純に(* 10 90000)を追加することにより、ビデオPTSを調整しようとしていますしかしそれはしません。ビデオはまだオーディオを2秒以上たどります。なぜこれがうまくいかないのか分かりません。各ビデオフレームは10秒先に表示されます。これは正しくないでしょうか?
主な質問は、基本的にアルゴリズムの音ですか?彼らはビデオ/オーディオを独立して動作させても問題ないようです。
ソースフィルタはプッシュフィルタではありません。違いがあるかどうかはわかりません。私は、デコーダが放送からの入力と同期しなくなるという問題はない。
多くのありがとうございます。
時間の経過に伴って後続処理が行われるのですか、またはすぐに2-3秒の遅延で開始されますか?また、読みやすいようにコードを再フォーマットしてください。 – BeemerGuy
コードフォーマットは残念です。私は次回よりもうまくやってみよう。 – davroslyrad