/// <param name="payload">frame data</param> /// <param name="payLoadLen">actual length of frame data</param> /// <param name="pts">presentation timestamp</param> /// <param name="ptsNum">numerator of timebase</param> /// <param name="ptsDen">denominator of timebase</param> /// <param name="ptsIndex">which timestamp base is used, assumed to be also stream number</param> public NutFrame(byte[] payload, int payLoadLen, ulong pts, ulong ptsNum, ulong ptsDen, int ptsIndex, ReusableBufferPool <byte> pool) { _pts = pts; _ptsNum = ptsNum; _ptsDen = ptsDen; _pool = pool; _data = pool.GetBufferAtLeast(payLoadLen + 2048); var frame = new MemoryStream(_data); // create syncpoint var sync = new NutPacket(NutPacket.StartCode.Syncpoint, frame); WriteVarU(pts * 2 + (ulong)ptsIndex, sync); // global_key_pts WriteVarU(1, sync); // back_ptr_div_16, this is wrong sync.Flush(); var frameHeader = new MemoryStream(); frameHeader.WriteByte(0); // frame_code // frame_flags = FLAG_CODED, so: int flags = 0; flags |= 1 << 0; // FLAG_KEY if (payLoadLen == 0) { flags |= 1 << 1; // FLAG_EOR } flags |= 1 << 3; // FLAG_CODED_PTS flags |= 1 << 4; // FLAG_STREAM_ID flags |= 1 << 5; // FLAG_SIZE_MSB flags |= 1 << 6; // FLAG_CHECKSUM WriteVarU(flags, frameHeader); WriteVarU(ptsIndex, frameHeader); // stream_id WriteVarU(pts + 256, frameHeader); // coded_pts = pts + 1 << msb_pts_shift WriteVarU(payLoadLen, frameHeader); // data_size_msb var frameHeaderArr = frameHeader.ToArray(); frame.Write(frameHeaderArr, 0, frameHeaderArr.Length); WriteBe32(NutCRC32(frameHeaderArr), frame); // checksum frame.Write(payload, 0, payLoadLen); _actualLength = (int)frame.Position; }