AV synchronization problem of AVStream driver

Hi all,
I am writing a AVStream base PCI driver. I use avshws and avssamp as my sample.
There are a capture pin and an audio pin in my driver. The capture pin sends H.264 format data and audio pin sends ADPCM format data.
I use graphedit to test my driver. If the AVI file I saved have only compressed audio data or compressed video data, it works fine.
In addition, if the connection is as following:
capture pin –> AVI Descompressor –> AVI Mux –> File writer ( a.avi)
(output h.264) (output RGB24)
audio pin –> ADPCM decoder –> AVI Mux –> File writer (a.avi) (audio/video saved into a file)
(ouotput adpcm) (output PCM)

Then the a.avi also works fine. That is, if I save non compress video and non compress audio into a file, there is no synchronization problem.

However, if I save compressed video data or compressed audio data into AVI file. The sound will be slow or strange.
For example, if I connect as following:
capture pin –> AVI Mux –> File writer ( a.avi)
(output h.264)
audio pin –> ADPCM decoder –> AVI Mux –> File writer (a.avi)
(ouotput adpcm) (output PCM)

or as following:
capture pin –> AVI Descompressor –> AVI Mux –> File writer ( a.avi)
(output h.264) (output RGB24)
audio pin –> AVI Mux –> File writer (a.avi)
(ouotput adpcm)

Then the audio may finish first and the remained part only have video data.
Does anyone know how to fix the AV sync problem? Should I deal with the time stamp or time duration flag?
Any suggestion would be greatly appreciated!
Thanks a lot!
Gordon

Following is my PinProcess routines:
NTSTATUS
CCapturePin::
Process(
IN LARGE_INTEGER &liTimeout
)
{

pStreamPointer = KsPinGetLeadingEdgeStreamPointer(m_Pin,
KSSTREAM_POINTER_STATE_LOCKED );
if( pStreamPointer != NULL )
{
PKSSTREAM_HEADER pHeader = pStreamPointer->StreamHeader;
PBYTE pData = static_cast< PBYTE >( pHeader->Data );

RtlCopyMemory( pData,(char *) pAVHeader+pAVHeader->uVideoDataAddrOffset,
pAVHeader->uVideoDataLen);
pHeader->DataUsed = pAVHeader->uVideoDataLen;

// If a clock has been assigned, timestamp the packets with the
// time shown on the clock.
if( m_Clock != NULL )
{
PKS_FRAME_INFO FrameInfo = reinterpret_cast
<pks_frame_info>(pHeader + 1);
LONGLONG llClockTime = m_Clock->GetTime();
llClockTime = m_Clock->GetCorrelatedTime(&llClockTime);
pHeader->PresentationTime.Time = llClockTime;
pHeader->Duration = -liTimeout.QuadPart;
pHeader->PresentationTime.Numerator =
pHeader->PresentationTime.Denominator = 1;
pHeader->OptionsFlags = KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
if( pHeader->Size >= sizeof(KSSTREAM_HEADER) + sizeof(KS_FRAME_INFO))
{
FrameInfo->ExtendedHeaderSize = sizeof (KS_FRAME_INFO);
FrameInfo->PictureNumber = m_nFrameNum;
FrameInfo->DropCount = 0;
}
switch(DMAV_FRAMETYPE(pAVHeader))
{
case 0:
FrameInfo->dwFrameFlags |= KS_VIDEO_FLAG_I_FRAME;
pHeader->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT;
break;

}
}
else
{
// If there is no clock, don’t time stamp the packets.
pHeader->PresentationTime.Time = 0;
pHeader->Duration = 0;
pHeader->OptionsFlags = 0;
}
KsStreamPointerUnlock( pStreamPointer, TRUE );
}
return STATUS_SUCCESS;
}

NTSTATUS
CAudioCapturePin::
Process(
IN LARGE_INTEGER &liTimeout
)
{

pStreamPointer = KsPinGetLeadingEdgeStreamPointer( m_Pin,
KSSTREAM_POINTER_STATE_LOCKED );

PKSSTREAM_HEADER pHeader = pStreamPointer->StreamHeader;
PBYTE pData = static_cast< PBYTE >( pHeader->Data );
RtlCopyMemory( pData, pAudio, dwAudioLen);
pHeader->DataUsed = dwAudioLen;

// If a clock has been assigned, timestamp the packets with the
// time shown on the clock.
if( m_Clock != NULL )
{
PKS_FRAME_INFO FrameInfo = reinterpret_cast
<pks_frame_info>(pHeader + 1);
LONGLONG llClockTime = m_Clock->GetTime();
llClockTime = m_Clock->GetCorrelatedTime(&llClockTime);
pHeader -> PresentationTime.Numerator =
pHeader -> PresentationTime.Denominator = 1;
pHeader->PresentationTime.Time = llClockTime;
pHeader->Duration = -liTimeout.QuadPart;
pHeader -> OptionsFlags =
KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
if( pHeader->Size >= sizeof(KSSTREAM_HEADER) + sizeof(KS_FRAME_INFO))
{
FrameInfo->ExtendedHeaderSize = sizeof (KS_FRAME_INFO);
FrameInfo->PictureNumber = m_nAudioFrameNum;
FrameInfo->DropCount = 0;
}
}
else
{
// If there is no clock, don’t time stamp the packets.
pHeader->PresentationTime.Time = 0;
pHeader->Duration = 0;
pHeader->OptionsFlags = 0;
}
KsStreamPointerUnlock( pStreamPointer, TRUE );
}
return STATUS_SUCCESS;
}</pks_frame_info></pks_frame_info>