/// <summary>
/// Gets the H246 from ps.
/// </summary>
/// <param name="pBuffer">流數據.</param>
/// <param name="existBuffer">The exist buffer.</param>
/// <param name="action">解析後數據、是否須要下一個流數據拼接、是不是視頻,是不是音頻.</param>
public static void GetH246FromPS(byte[] pBuffer, List<byte> existBuffer, Action<byte[], bool, bool, bool> action)
{
List<byte> pH264 = new List<byte>();
byte[] searchBytes = new byte[3] { 0x00, 0x00, 0x01 };
int freamHeaderLength = 0;
int freamLength = 0;
if (pBuffer == null || pBuffer.Length <= 0)
return;
if (existBuffer.Count > 0)
{
existBuffer.AddRange(pBuffer);
pBuffer = existBuffer.ToArray();
existBuffer.Clear();
}
while (true)
{
begin:
if (pBuffer.Count() == 0)
break;
if (pBuffer.Count() < 9)
{
action(pBuffer, true, false, false);
break;
}
pH264.Clear();
if (pBuffer[0] == 0x00
&& pBuffer[1] == 0x00
&& pBuffer[2] == 0x01
&& pBuffer[3] == 0xBA/*ps_header*/)
{
//拋棄數據
if (pBuffer.Count() < 20)
{
action(pBuffer.ToArray(), true, false, false);
break;
}
pBuffer = pBuffer.Skip(20).ToArray();
goto begin;
}
if (pBuffer[0] == 0x00
&& pBuffer[1] == 0x00
&& pBuffer[2] == 0x01
&& (pBuffer[3] == 0xBD/*私有包頭*/|| pBuffer[3] == 0xBC/*psm_header*/))
{
//拋棄數據
freamHeaderLength = 9 + (int)pBuffer[8];
freamLength = BitConverter.ToUInt16(new byte[2] { pBuffer[5], pBuffer[4] }, 0);
var nH264Lenth = freamLength + 6 - freamHeaderLength;
if (pBuffer.Count() < freamHeaderLength + nH264Lenth)
{
action(pBuffer.ToArray(), true, false, false);
break;
}
pBuffer = pBuffer.Skip(6 + freamLength).ToArray();
goto begin;
}
if (pBuffer[0] == 0x00
&& pBuffer[1] == 0x00
&& pBuffer[2] == 0x01
&& (pBuffer[3] >= 0xC0 && pBuffer[3] <= 0xDF))//pes_audio_header
{
freamHeaderLength = 9 + (int)pBuffer[8];
freamLength = BitConverter.ToUInt16(new byte[2] { pBuffer[5], pBuffer[4] }, 0);
var nH264Lenth = freamLength + 6 - freamHeaderLength;
if (pBuffer.Count() < freamHeaderLength + nH264Lenth)
{
action(pBuffer.ToArray(), true, false, false);
break;
}
pH264 = pBuffer.Skip(freamHeaderLength).Take(nH264Lenth).ToList();
action(pH264.ToArray(), false, false, true);
pBuffer = pBuffer.Skip(6 + freamLength).ToArray();
goto begin;
}
if (pBuffer[0] == 0x00
&& pBuffer[1] == 0x00
&& pBuffer[2] == 0x01
&& (pBuffer[3] >= 0xE0 && pBuffer[3] <= 0xEF))//pes_video_header
{
freamHeaderLength = 9 + (int)pBuffer[8];//9個爲固定的數據包頭長度,pBuffer[8]爲填充頭部分的長度
var beginIndex = IndexOf(pBuffer, searchBytes, freamHeaderLength + 2);
if (beginIndex != -1)
{
if (pBuffer[beginIndex - 1] == 0)//0x00000001
{
beginIndex -= 1;
}
var nH264Lenth = beginIndex - freamHeaderLength;
pH264 = pBuffer.Skip(freamHeaderLength).Take(nH264Lenth).ToList();
action(pH264.ToArray(), false, true, false);
pBuffer = pBuffer.Skip(beginIndex).ToArray();
goto begin;
}
else
{
action(pBuffer.ToArray(), true, false, false);
break;
}
}
if (pBuffer[0] == 0x00
&& pBuffer[1] == 0x00
&& pBuffer[2] == 0x00
&& pBuffer[3] == 0x01)//幀數據
{
freamHeaderLength = 0;
var beginIndex = IndexOf(pBuffer, searchBytes, freamHeaderLength + 2);
if (beginIndex != -1)
{
if (pBuffer[beginIndex - 1] == 0)//0x00000001
{
beginIndex -= 1;
}
var nH264Lenth = beginIndex - freamHeaderLength;
pH264 = pBuffer.Skip(freamHeaderLength).Take(nH264Lenth).ToList();
action(pH264.ToArray(), false, true, false);
pBuffer = pBuffer.Skip(beginIndex).ToArray();
goto begin;
}
else
{
action(pBuffer.ToArray(), true, false, false);
break;
}
}
break;
}
}
/// <summary>
/// 報告指定的 System.Byte[] 在此實例中的第一個匹配項的索引。
/// </summary>
/// <param name="srcBytes">被執行查找的 System.Byte[]。</param>
/// <param name="searchBytes">要查找的 System.Byte[]。</param>
/// <returns>若是找到該字節數組,則爲 searchBytes 的索引位置;若是未找到該字節數組,則爲 -1。若是 searchBytes 爲 null 或者長度爲0,則返回值爲 -1。</returns>
private static int IndexOf(byte[] srcBytes, byte[] searchBytes, int startIndex = 0)
{
if (srcBytes == null) { return -1; }
if (searchBytes == null) { return -1; }
if (srcBytes.Count() == 0) { return -1; }
if (searchBytes.Length == 0) { return -1; }
if (srcBytes.Count() < searchBytes.Length) { return -1; }
for (int i = startIndex; i < srcBytes.Count() - searchBytes.Length + 1; i++)
{
if (srcBytes[i] == searchBytes[0])
{
if (searchBytes.Length == 1) { return i; }
bool flag = true;
for (int j = 1; j < searchBytes.Length; j++)
{
if (srcBytes[i + j] != searchBytes[j])
{
flag = false;
break;
}
}
if (flag) { return i; }
}
}
return -1;
}