public void WriteChunk(byte[] chunk, uint timeStamp) { if (chunk.Length < 1) { return; } if (chunk[0] == 0) { // Header if (chunk.Length < 3) { return; } ulong bits = (ulong)BitConverterBE.ToUInt16(chunk, 1) << 48; _aacProfile = BitHelper.Read(ref bits, 5) - 1; _sampleRateIndex = BitHelper.Read(ref bits, 4); _channelConfig = BitHelper.Read(ref bits, 4); if ((_aacProfile < 0) || (_aacProfile > 3)) { throw new ExtractionException("Unsupported AAC profile."); } if (_sampleRateIndex > 12) { throw new ExtractionException("Invalid AAC sample rate index."); } if (_channelConfig > 6) { throw new ExtractionException("Invalid AAC channel configuration."); } } else { // Audio data int dataSize = chunk.Length - 1; ulong bits = 0; // Reference: WriteADTSHeader from FAAC's bitstream.c BitHelper.Write(ref bits, 12, 0xFFF); BitHelper.Write(ref bits, 1, 0); BitHelper.Write(ref bits, 2, 0); BitHelper.Write(ref bits, 1, 1); BitHelper.Write(ref bits, 2, _aacProfile); BitHelper.Write(ref bits, 4, _sampleRateIndex); BitHelper.Write(ref bits, 1, 0); BitHelper.Write(ref bits, 3, _channelConfig); BitHelper.Write(ref bits, 1, 0); BitHelper.Write(ref bits, 1, 0); BitHelper.Write(ref bits, 1, 0); BitHelper.Write(ref bits, 1, 0); BitHelper.Write(ref bits, 13, 7 + dataSize); BitHelper.Write(ref bits, 11, 0x7FF); BitHelper.Write(ref bits, 2, 0); _fs.Write(BitConverterBE.GetBytes(bits), 1, 7); _fs.Write(chunk, 1, dataSize); } }
public void WriteChunk(byte[] chunk, uint timeStamp, int frameType) { if (chunk.Length < 4) { return; } // Reference: decode_frame from libavcodec's h264.c if (chunk[0] == 0) { // Headers if (chunk.Length < 10) { return; } int offset, spsCount, ppsCount; offset = 8; _nalLengthSize = (chunk[offset++] & 0x03) + 1; spsCount = chunk[offset++] & 0x1F; ppsCount = -1; while (offset <= chunk.Length - 2) { if ((spsCount == 0) && (ppsCount == -1)) { ppsCount = chunk[offset++]; continue; } if (spsCount > 0) { spsCount--; } else if (ppsCount > 0) { ppsCount--; } else { break; } int len = BitConverterBE.ToUInt16(chunk, offset); offset += 2; if (offset + len > chunk.Length) { break; } _fs.Write(_startCode, 0, _startCode.Length); _fs.Write(chunk, offset, len); offset += len; } } else { // Video data int offset = 4; if (_nalLengthSize != 2) { _nalLengthSize = 4; } while (offset <= chunk.Length - _nalLengthSize) { int len = (_nalLengthSize == 2) ? BitConverterBE.ToUInt16(chunk, offset) : (int)BitConverterBE.ToUInt32(chunk, offset); offset += _nalLengthSize; if (offset + len > chunk.Length) { break; } _fs.Write(_startCode, 0, _startCode.Length); _fs.Write(chunk, offset, len); offset += len; } } }