private bool FeedVideoData(Stream pData, uint dataLength, uint absoluteTimestamp)
{
var nalType = (NaluType)pData.ReadByte();
var oldPosition = pData.Position;
switch (nalType)
{
case NaluType.NALU_TYPE_SPS:
//1. Prepare the SPS part from video codec
if (dataLength > 128)
{
FATAL("SPS too big");
return false;
}
pData.Read(_pSPSPPS, 6, 3);
_pSPSPPS.Write(11,(ushort)dataLength);
pData.Position = oldPosition;
pData.Read(_pSPSPPS, 13, (int) dataLength);
_PPSStart = 13 + dataLength;
_spsAvailable = true;
pData.Position = oldPosition;
return true;
case NaluType.NALU_TYPE_PPS:
//2. Prepare the PPS part from video codec
if (dataLength > 128)
{
FATAL("PPS too big");
return false;
}
if (!_spsAvailable)
{
WARN("No SPS available yet");
return true;
}
_pSPSPPS[_PPSStart] = 1;
_pSPSPPS.Write((int) (_PPSStart+1), (ushort)dataLength);
pData.Position = oldPosition;
pData.Read(_pSPSPPS, (int)(_PPSStart + 3), (int)dataLength);
_spsAvailable = false;
//3. Send the video codec
if (!base.FeedData(
new MemoryStream(_pSPSPPS), //pData
_PPSStart + 1 + 2 + dataLength, //dataLength
0, //processedLength
_PPSStart + 1 + 2 + dataLength, //totalLength
absoluteTimestamp, //absoluteTimestamp
false //isAudio
))
{
FATAL("Unable to send video codec setup");
return false;
}
_videoCodecSent = true;
pData.Position = oldPosition;
return true;
default:
//1. Create timestamp reference
if (_lastVideoTimestamp < 0)
_lastVideoTimestamp = absoluteTimestamp;
//2. Send over the accumulated stuff if this is a new packet from a
//brand new sequence of packets
if (_lastVideoTimestamp != absoluteTimestamp)
{
if (!base.FeedData(
_videoBuffer, //pData
(uint) _videoBuffer.GetAvaliableByteCounts(), //dataLength
0, //processedLength
(uint) _videoBuffer.GetAvaliableByteCounts(), //totalLength
(uint) _lastVideoTimestamp, //absoluteTimestamp
false //isAudio
))
{
FATAL("Unable to send video");
return false;
}
_videoBuffer.IgnoreAll();
_isKeyFrame = false;
}
_lastVideoTimestamp = absoluteTimestamp;
//put the 5 bytes header
if (_videoBuffer.GetAvaliableByteCounts() == 0)
{
_videoBuffer.WriteByte(0);
_videoBuffer.WriteByte(1);
_videoBuffer.WriteByte(0);
_videoBuffer.WriteByte(0);
_videoBuffer.WriteByte(0);
}
if (nalType == NaluType.NALU_TYPE_IDR || nalType == NaluType.NALU_TYPE_SLICE ||
nalType == NaluType.NALU_TYPE_SEI)
{//put the length
_videoBuffer.Write(dataLength);
//put the data
pData.CopyTo(_videoBuffer);
//setup the frame type
_isKeyFrame |= (nalType == NaluType.NALU_TYPE_IDR);
var temp = _videoBuffer.GetBuffer();
temp[0] = (byte) (_isKeyFrame? 0x17: 0x27);
}//6. make sure the packet doesn't grow too big
if (_videoBuffer.GetAvaliableByteCounts() >= 4*1024*1024)
{
WARN("Big video frame. Discard it");
_videoBuffer.IgnoreAll();
_isKeyFrame = false;
_lastVideoTimestamp = -1;
}
pData.Position = oldPosition;
return true;
}
}