diff --git a/SharpAvi/Codecs/IVideoEncoderExtraData.cs b/SharpAvi/Codecs/IVideoEncoderExtraData.cs
new file mode 100644
index 0000000..a3d9326
--- /dev/null
+++ b/SharpAvi/Codecs/IVideoEncoderExtraData.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SharpAvi.Codecs
+{
+ ///
+ /// Export extra data for some codecs
+ ///
+ public interface IVideoEncoderExtraData
+ {
+ ///
+ /// Encoded images header with extra data
+ ///
+ byte[] BitmapInfoHeader { get; }
+ }
+}
diff --git a/SharpAvi/Codecs/SingleThreadedVideoEncoderWrapper.cs b/SharpAvi/Codecs/SingleThreadedVideoEncoderWrapper.cs
index d4305da..a662f1f 100644
--- a/SharpAvi/Codecs/SingleThreadedVideoEncoderWrapper.cs
+++ b/SharpAvi/Codecs/SingleThreadedVideoEncoderWrapper.cs
@@ -14,7 +14,7 @@ namespace SharpAvi.Codecs
/// like asynchronous encoding.
///
///
- public class SingleThreadedVideoEncoderWrapper : IVideoEncoder, IDisposable
+ public class SingleThreadedVideoEncoderWrapper : IVideoEncoder, IVideoEncoderExtraData, IDisposable
{
private readonly IVideoEncoder encoder;
private readonly SingleThreadTaskScheduler scheduler;
@@ -65,6 +65,21 @@ public void Dispose()
///
public int MaxEncodedSize => SchedulerInvoke(() => encoder.MaxEncodedSize);
+ ///
+ /// Encoded images header
+ ///
+ public byte[] BitmapInfoHeader => SchedulerInvoke(() =>
+ {
+ if (encoder is IVideoEncoderExtraData extraData)
+ {
+ return extraData.BitmapInfoHeader;
+ }
+ else
+ {
+ return null;
+ }
+ });
+
///
/// Encodes a video frame.
///
diff --git a/SharpAvi/Output/AviVideoStream.cs b/SharpAvi/Output/AviVideoStream.cs
index a749bb3..9384330 100644
--- a/SharpAvi/Output/AviVideoStream.cs
+++ b/SharpAvi/Output/AviVideoStream.cs
@@ -13,6 +13,7 @@ internal class AviVideoStream : AviStreamBase, IAviVideoStreamInternal
private int height;
private BitsPerPixel bitsPerPixel;
private int framesWritten;
+ private byte[] bitmapInfoHeader;
public AviVideoStream(int index, IAviStreamWriteHandler writeHandler,
int width, int height, BitsPerPixel bitsPerPixel)
@@ -71,6 +72,16 @@ public FourCC Codec
}
}
+ public byte[] BitmapInfoHeader
+ {
+ get { return bitmapInfoHeader; }
+ set
+ {
+ CheckNotFrozen();
+ bitmapInfoHeader = value;
+ }
+ }
+
public void WriteFrame(bool isKeyFrame, byte[] frameData, int startIndex, int count)
{
Argument.IsNotNull(frameData, nameof(frameData));
diff --git a/SharpAvi/Output/AviWriter.cs b/SharpAvi/Output/AviWriter.cs
index ead4b69..9f7d24a 100644
--- a/SharpAvi/Output/AviWriter.cs
+++ b/SharpAvi/Output/AviWriter.cs
@@ -537,39 +537,47 @@ void IAviStreamWriteHandler.WriteStreamHeader(AviAudioStream audioStream)
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)
- // 0 size is safer for uncompressed formats not to bother with stride calculation
- var sizeInBytes = videoStream.Codec == CodecIds.Uncompressed
- ? 0
- : 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 == CodecIds.Uncompressed)
+ var bitmapInfoHeader = videoStream.BitmapInfoHeader;
+ if (bitmapInfoHeader != null)
{
- 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);
- }
+ fileWriter.Write(bitmapInfoHeader);
}
else
{
- fileWriter.Write(0U); // palette colors used
- fileWriter.Write(0U); // palette colors important
+ // 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)
+ // 0 size is safer for uncompressed formats not to bother with stride calculation
+ var sizeInBytes = videoStream.Codec == CodecIds.Uncompressed
+ ? 0
+ : 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 == CodecIds.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
+ }
}
}
diff --git a/SharpAvi/Output/EncodingVideoStreamWrapper.cs b/SharpAvi/Output/EncodingVideoStreamWrapper.cs
index 2414f2a..6fd843d 100644
--- a/SharpAvi/Output/EncodingVideoStreamWrapper.cs
+++ b/SharpAvi/Output/EncodingVideoStreamWrapper.cs
@@ -56,6 +56,22 @@ public override BitsPerPixel BitsPerPixel
set => ThrowPropertyDefinedByEncoder();
}
+ public override byte[] BitmapInfoHeader
+ {
+ get
+ {
+ if (encoder is IVideoEncoderExtraData extraData)
+ {
+ return extraData.BitmapInfoHeader;
+ }
+ else
+ {
+ return BaseStream.BitmapInfoHeader;
+ }
+ }
+ set => ThrowPropertyDefinedByEncoder();
+ }
+
/// Encodes and writes a frame.
public override void WriteFrame(bool isKeyFrame, byte[] frameData, int startIndex, int length)
{
@@ -94,6 +110,10 @@ public override void PrepareForWriting()
// Set properties of the base stream
BaseStream.Codec = encoder.Codec;
BaseStream.BitsPerPixel = encoder.BitsPerPixel;
+ if (encoder is IVideoEncoderExtraData extraData)
+ {
+ BaseStream.BitmapInfoHeader = extraData.BitmapInfoHeader;
+ }
base.PrepareForWriting();
}
diff --git a/SharpAvi/Output/IAviVideoStreamInternal.cs b/SharpAvi/Output/IAviVideoStreamInternal.cs
index 9450af3..359b6aa 100644
--- a/SharpAvi/Output/IAviVideoStreamInternal.cs
+++ b/SharpAvi/Output/IAviVideoStreamInternal.cs
@@ -2,5 +2,6 @@
{
internal interface IAviVideoStreamInternal : IAviVideoStream, IAviStreamInternal
{
+ byte[] BitmapInfoHeader { get; set; }
}
}
diff --git a/SharpAvi/Output/VideoStreamWrapperBase.cs b/SharpAvi/Output/VideoStreamWrapperBase.cs
index 9813d99..1e043dc 100644
--- a/SharpAvi/Output/VideoStreamWrapperBase.cs
+++ b/SharpAvi/Output/VideoStreamWrapperBase.cs
@@ -47,6 +47,12 @@ public virtual FourCC Codec
set { BaseStream.Codec = value; }
}
+ public virtual byte[] BitmapInfoHeader
+ {
+ get { return BaseStream.BitmapInfoHeader; }
+ set { BaseStream.BitmapInfoHeader = value; }
+ }
+
public virtual void WriteFrame(bool isKeyFrame, byte[] frameData, int startIndex, int length)
{
Argument.IsNotNull(frameData, nameof(frameData));