private async Task ProcessTag(Tag tag)
{
int CurrentTimestamp=tag.TimeStamp;
int LastTimestamp=PreviousVideoTimestamp >=PreviousAudioTimestamp ? PreviousVideoTimestamp : PreviousAudioTimestamp;
int FixedTimestamp = LastTimestamp + FRAMEFIX_STEP;
if (BaseTimestamp==INVALID && (tag.Type==AUDIO_PACKET || tag.Type==VIDEO_PACKET))
BaseTimestamp=tag.TimeStamp;
if (BaseTimestamp > FixedWindow && tag.TimeStamp >= BaseTimestamp)
tag.TimeStamp = BaseTimestamp;
if (LastTimestamp != INVALID)
{
int timeShift = tag.TimeStamp - LastTimestamp;
if (timeShift > FixedWindow)
{
if (BaseTimestamp < tag.TimeStamp)
BaseTimestamp += timeShift - FRAMEFIX_STEP;
else
BaseTimestamp -= timeShift - FRAMEFIX_STEP;
tag.TimeStamp = FixedTimestamp;
}
else
{
LastTimestamp = tag.Type == VIDEO_PACKET ? PreviousVideoTimestamp : PreviousAudioTimestamp;
if (tag.TimeStamp < (LastTimestamp - FixedWindow))
{
if ((NegativeTimestamp != INVALID) &&
((tag.TimeStamp + NegativeTimestamp) < (LastTimestamp - FixedWindow)))
NegativeTimestamp = INVALID;
if (NegativeTimestamp == INVALID)
{
NegativeTimestamp = FixedTimestamp - tag.TimeStamp;
tag.TimeStamp = FixedTimestamp;
}
else
{
if ((tag.TimeStamp + NegativeTimestamp) <= (LastTimestamp + FixedWindow))
tag.TimeStamp += NegativeTimestamp;
else
{
NegativeTimestamp = FixedTimestamp - tag.TimeStamp;
tag.TimeStamp = FixedTimestamp;
}
}
}
}
}
switch (tag.Type)
{
case AUDIO_PACKET:
if (tag.TimeStamp > PreviousAudioTimestamp - FixedWindow)
{
int frameinfo = tag.Packet[0];
int codec = (frameinfo & 0xF0) >> 4;
byte ptype = tag.Packet[1];
if (codec == CODEC_ID_AAC)
{
if (ptype == AAC_SEQUENCE_HEADER)
{
if (aacHeaderWritten)
break;
aacHeaderWritten = true;
}
else if (!aacHeaderWritten)
break;
}
if (tag.PacketSize > 0)
{
if (!((codec == CODEC_ID_AAC) && ((ptype == AAC_SEQUENCE_HEADER) || prevAacHeader)))
{
if ((PreviousAudioTimestamp != INVALID) && (tag.TimeStamp <= PreviousAudioTimestamp))
tag.TimeStamp += (FRAMEFIX_STEP/5) + (PreviousAudioTimestamp - tag.TimeStamp);
}
await WriteTag(tag);
prevAacHeader = ((codec == CODEC_ID_AAC) && (ptype == AAC_SEQUENCE_HEADER));
PreviousAudioTimestamp = tag.TimeStamp;
}
}
hasAudio = true;
break;
case VIDEO_PACKET:
if (tag.TimeStamp > PreviousVideoTimestamp - FixedWindow)
{
int frameinfo = tag.Packet[0];
int ftype = (frameinfo & 0xF0) >> 4;
int codec = frameinfo & 0xF;
byte ptype = tag.Packet[1];
if (codec == CODEC_ID_AVC)
{
if (ptype == AVC_SEQUENCE_HEADER)
{
if (avcHeaderWritten)
break;
avcHeaderWritten = true;
}
else if (!avcHeaderWritten)
break;
}
if (tag.PacketSize > 0)
{
if (!((codec == CODEC_ID_AVC) && ((ptype == AVC_SEQUENCE_HEADER) || (ptype == AVC_SEQUENCE_END) || prevAvcHeader)))
{
if ((PreviousVideoTimestamp != INVALID) && (tag.TimeStamp <= PreviousVideoTimestamp))
{
tag.TimeStamp += (FRAMEFIX_STEP/5) | (PreviousVideoTimestamp - tag.TimeStamp);
}
}
await WriteTag(tag);
prevAvcHeader = ((codec == CODEC_ID_AVC) && (ptype == AVC_SEQUENCE_HEADER));
PreviousVideoTimestamp = tag.TimeStamp;
}
}
hasVideo = true;
break;
}
}
private async Task ProcessTags(List<Tag> tags)