void IAviStreamWriteHandler.WriteStreamFormat(AviVideoStream videoStream) { // See BITMAPINFOHEADER structure fileWriter.Write(40U); // size of structure fileWriter.Write(videoStream.Width); fileWriter.Write(videoStream.Height); fileWriter.Write((short)1); // planes fileWriter.Write((ushort)videoStream.BitsPerPixel); // bits per pixel fileWriter.Write((uint)videoStream.Codec); // compression (codec FOURCC) var sizeInBytes = videoStream.Width * videoStream.Height * (((int)videoStream.BitsPerPixel) / 8); fileWriter.Write((uint)sizeInBytes); // image size in bytes fileWriter.Write(0); // X pixels per meter fileWriter.Write(0); // Y pixels per meter // Writing grayscale palette for 8-bit uncompressed stream // Otherwise, no palette if (videoStream.BitsPerPixel == BitsPerPixel.Bpp8 && videoStream.Codec == KnownFourCCs.Codecs.Uncompressed) { fileWriter.Write(256U); // palette colors used fileWriter.Write(0U); // palette colors important for (int i = 0; i < 256; i++) { fileWriter.Write((byte)i); fileWriter.Write((byte)i); fileWriter.Write((byte)i); fileWriter.Write((byte)0); } } else { fileWriter.Write(0U); // palette colors used fileWriter.Write(0U); // palette colors important } }
/// <summary>Adds new video stream.</summary> /// <param name="width">Frame's width.</param> /// <param name="height">Frame's height.</param> /// <param name="bitsPerPixel">Bits per pixel.</param> /// <returns>Newly added video stream.</returns> /// <remarks> /// Stream is initialized to be ready for uncompressed video (bottom-up BGR) with specified parameters. /// However, properties (such as <see cref="IAviVideoStream.Codec"/>) can be changed later if the stream is /// to be fed with pre-compressed data. /// </remarks> public IAviVideoStream AddVideoStream(int width = 1, int height = 1, BitsPerPixel bitsPerPixel = BitsPerPixel.Bpp32) { Argument.IsPositive(width, nameof(width)); Argument.IsPositive(height, nameof(height)); Argument.IsEnumMember(bitsPerPixel, nameof(bitsPerPixel)); return(AddStream <IAviVideoStreamInternal>(index => { var stream = new AviVideoStream(index, this, width, height, bitsPerPixel); var asyncStream = new AsyncVideoStreamWrapper(stream); return asyncStream; })); }
/// <summary>Adds new encoding video stream.</summary> /// <param name="encoder">Encoder to be used.</param> /// <param name="ownsEncoder">Whether encoder should be disposed with the writer.</param> /// <param name="width">Frame's width.</param> /// <param name="height">Frame's height.</param> /// <returns>Newly added video stream.</returns> /// <remarks> /// <para> /// Stream is initialized to be to be encoded with the specified encoder. /// Method <see cref="IAviVideoStream.WriteFrame"/> expects data in the same format as encoders, /// that is top-down BGR32 bitmap. It is passed to the encoder and the encoded result is written /// to the stream. /// Parameters <c>isKeyFrame</c> and <c>length</c> are ignored by encoding streams, /// as encoders determine on their own which frames are keys, and the size of input bitmaps is fixed. /// </para> /// <para> /// Properties <see cref="IAviVideoStream.Codec"/> and <see cref="IAviVideoStream.BitsPerPixel"/> /// are defined by the encoder, and cannot be modified. /// </para> /// </remarks> public IAviVideoStream AddEncodingVideoStream(IVideoEncoder encoder, bool ownsEncoder = true, int width = 1, int height = 1) { Contract.Requires(encoder != null); Contract.Requires(Streams.Count < 100); Contract.Ensures(Contract.Result <IAviVideoStream>() != null); return(AddStream <IAviVideoStreamInternal>(index => { var stream = new AviVideoStream(index, this, width, height, BitsPerPixel.Bpp32); var encodingStream = new EncodingVideoStreamWrapper(stream, encoder, ownsEncoder); var asyncStream = new AsyncVideoStreamWrapper(encodingStream); return asyncStream; })); }
/// <summary>Adds new encoding video stream.</summary> /// <param name="encoder">Encoder to be used.</param> /// <param name="ownsEncoder">Whether encoder should be disposed with the writer.</param> /// <param name="width">Frame's width.</param> /// <param name="height">Frame's height.</param> /// <returns>Newly added video stream.</returns> /// <remarks> /// <para> /// Stream is initialized to be to be encoded with the specified encoder. /// Method <see cref="IAviVideoStream.WriteFrame"/> expects data in the same format as encoders, /// that is top-down BGR32 bitmap. It is passed to the encoder and the encoded result is written /// to the stream. /// Parameters <c>isKeyFrame</c> and <c>length</c> are ignored by encoding streams, /// as encoders determine on their own which frames are keys, and the size of input bitmaps is fixed. /// </para> /// <para> /// Properties <see cref="IAviVideoStream.Codec"/> and <see cref="IAviVideoStream.BitsPerPixel"/> /// are defined by the encoder, and cannot be modified. /// </para> /// </remarks> public IAviVideoStream AddEncodingVideoStream(IVideoEncoder encoder, bool ownsEncoder = true, int width = 1, int height = 1) { Argument.IsNotNull(encoder, nameof(encoder)); Argument.IsPositive(width, nameof(width)); Argument.IsPositive(height, nameof(height)); return(AddStream <IAviVideoStreamInternal>(index => { var stream = new AviVideoStream(index, this, width, height, BitsPerPixel.Bpp32); var encodingStream = new EncodingVideoStreamWrapper(stream, encoder, ownsEncoder); var asyncStream = new AsyncVideoStreamWrapper(encodingStream); return asyncStream; })); }
/// <summary>Adds new video stream.</summary> /// <param name="width">Frame's width.</param> /// <param name="height">Frame's height.</param> /// <param name="bitsPerPixel">Bits per pixel.</param> /// <returns>Newly added video stream.</returns> /// <remarks> /// Stream is initialized to be ready for uncompressed video (bottom-up BGR) with specified parameters. /// However, properties (such as <see cref="IAviVideoStream.Codec"/>) can be changed later if the stream is /// to be fed with pre-compressed data. /// </remarks> public IAviVideoStream AddVideoStream(int width = 1, int height = 1, BitsPerPixel bitsPerPixel = BitsPerPixel.Bpp32) { Contract.Requires(width > 0); Contract.Requires(height > 0); Contract.Requires(Enum.IsDefined(typeof(BitsPerPixel), bitsPerPixel)); Contract.Requires(Streams.Count < 100); Contract.Ensures(Contract.Result <IAviVideoStream>() != null); return(AddStream <IAviVideoStreamInternal>(index => { var stream = new AviVideoStream(index, this, width, height, bitsPerPixel); var asyncStream = new AsyncVideoStreamWrapper(stream); return asyncStream; })); }
void IAviStreamWriteHandler.WriteStreamHeader(AviVideoStream videoStream) { // See AVISTREAMHEADER structure fileWriter.Write((uint)videoStream.StreamType); fileWriter.Write((uint)videoStream.Codec); fileWriter.Write(0U); // StreamHeaderFlags fileWriter.Write((ushort)0); // priority fileWriter.Write((ushort)0); // language fileWriter.Write(0U); // initial frames fileWriter.Write(frameRateDenominator); // scale (frame rate denominator) fileWriter.Write(frameRateNumerator); // rate (frame rate numerator) fileWriter.Write(0U); // start fileWriter.Write((uint)streamsInfo[videoStream.Index].FrameCount); // length fileWriter.Write((uint)streamsInfo[videoStream.Index].MaxChunkDataSize); // suggested buffer size fileWriter.Write(0U); // quality fileWriter.Write(0U); // sample size fileWriter.Write((short)0); // rectangle left fileWriter.Write((short)0); // rectangle top short right = (short)(videoStream != null ? videoStream.Width : 0); short bottom = (short)(videoStream != null ? videoStream.Height : 0); fileWriter.Write(right); // rectangle right fileWriter.Write(bottom); // rectangle bottom }
void IAviStreamWriteHandler.WriteVideoFrame(AviVideoStream stream, bool isKeyFrame, byte[] frameData, int startIndex, int count) { WriteStreamFrame(stream, isKeyFrame, frameData, startIndex, count); }
void IAviStreamWriteHandler.WriteVideoFrame(AviVideoStream stream, bool isKeyFrame, ReadOnlySpan <byte> frameData) => WriteStreamFrame(stream, isKeyFrame, frameData);