AVI视频库 http://download.csdn.net/download/qc_id_01/9970151

Avi视频文件的编码有很多,这个库只支持部分Avi文件,有些Avi文件不支持,具体哪些不支持还没搞清楚

AviFile库提供了

  1、从视频流中图片的处理

  2、视频中音频的处理

  3、压缩和解压视频流

1、使用

  1、从视频读取图片,还有一些参数可以通过aviStream查看到,可以把当前流信息输出到文件

 
            //Avi文件读取
string filepath = @"D:\test.avi";
AviManager aviManager = new AviManager(filepath, true);
VideoStream aviStream = aviManager.GetVideoStream(); //获取和保存音频流到文件
AudioStream audioStream = aviManager.GetWaveStream();
audioStream.ExportStream(@"D:\test.wav"); aviStream.GetFrameOpen();
//获取视频总帧数
int framecount = aviStream.CountFrames;
//获取第5帧的图片
Bitmap bmp = aviStream.GetBitmap(5);
//视频速度
double rate = aviStream.FrameRate;
//直接保存帧图片到文件
//aviStream.ExportBitmap(5, @"D:\frame_05.jpg");
//保存当前流到文件
//aviStream.ExportStream(@"D:\currenttest.avi") aviStream.GetFrameClose();
aviManager.Close();
 

  2、把图片和音频写入视频流(部分参数后面会说到,这里只是简单的演示)

 
            //读取图片文件
string[] files = Directory.GetFiles(@"D:\test\", "*.jpg");
AviManager aviManager = new AviManager(@"D:\newtest.avi", false); //添加音频
String fileName = @"D:\audio.wav";
aviManager.AddAudioStream(fileName, 0); //读取第一张图片,设置每秒3帧
VideoStream aviStream = aviManager.AddVideoStream(true, 3, new Bitmap(files[0]));
for (int i = 1; i < files.Length; i++)
{
aviStream.AddFrame(new Bitmap(files[i]));
}
aviManager.Close();
 

  3、从视频截取一段保存到AviManager

            AviManager aviManager = new AviManager(filepath, true);
float startSecond = 0;
float stopSecond = 10;
//截取0-10s放到newManager
AviManager newManager = aviManager.CopyTo(@"D:\newtest_0-10.avi", startSecond, stopSecond);

  4、对已压缩的视频进行解压缩,放到另一个VideoStream中

            VideoStream newstream;
AviManager newManager = aviStream.DecompressToNewFile(@"D:\01.avi", false, out newstream);
newstream.GetFrameOpen();
Bitmap bitmap = newstream.GetBitmap(10);
newstream.GetFrameClose();

  5、向视频流中添加一张图片帧,对于未压缩的视频流,我们可以直接进行添加,但是对于已经压缩过的视频流,添加的图片帧不能重新进行压缩,所以我们需要对其进行解压缩,操作完后在进行压缩

 
           //读取图片文件
string[] files = Directory.GetFiles(@"D:\test\", "*.jpg"); //打开一个已存在的视频
AviManager aviManager = new AviManager(@"D:\test.avi", true);
VideoStream avistream = aviManager.GetVideoStream();
VideoStream newstream;
//解压视频到newstream中,最后已压缩的形式保存
AviManager newManager = avistream.DecompressToNewFile(@"newtest.avi", true, out newstream);
avistream = newManager.GetOpenStream(0); for (int i = 1; i < files.Length; i++)
{
avistream.AddFrame(new Bitmap(files[i]));
}
aviManager.Close();
//关闭和保存文件newtest.avi
newManager.Close();
 

  6、编辑视频流 EditableVideoStream (可以对视频流的帧,进行cut,delete,paste等早错)

 
            //打开一个已存在的视频
AviManager aviManager = new AviManager(@"D:\test.avi", true);
VideoStream avistream = aviManager.GetVideoStream(); EditableVideoStream editableStream = new EditableVideoStream(avistream);
int start = 0;
int length =10;
int position = 10;
//Copy
IntPtr copiedData = editableStream.Copy(start, length);
//Insert
editableStream.Paste(copiedData, 0, position, length);
//Delete
IntPtr deletedData = editableStream.Cut(start, length);
 

  同时也可以把一个 VideoStream 流 Paste 到 EditableVideoStream  

            editableStream.Paste(stream, 0, position, stream.CountFrames);   

  7、对视频流进行一些参数设置

            Avi.AVISTREAMINFO info = editableStream.StreamInfo;
//设置播放速度:每秒 3帧
info.dwRate = 3;
editableStream.SetInfo(info);

2、AviFile后台工作

  AviManager 管理Avi文件的stream,构造函数传入文件名,当调用Close函数时,关闭所有打开的流和文件,并保存。

可以使用 AddVideoStream 和 AddAudioStream 把视频里和音频流添加到一个新的AviManager中,音频流只支持wav文件

Create a video stream

  VideoStream 有两个构造函数

 
            public VideoStream AddVideoStream(
bool isCompressed, //display the compression dialog, create a compressed stream
int frameRate, //frames per second
int frameSize, //size of one frame in bytes
int width, int height, PixelFormat format //format of the bitmaps
)
{ VideoStream stream = new VideoStream(aviFile, isCompressed, frameRate, frameSize, width, height, format);
streams.Add(stream);
return stream;
} public VideoStream AddVideoStream(
bool isCompressed, //display the compression dialog, create a compressed stream
int frameRate, //frames per second
Bitmap firstFrame //get the format from this image and add it to the new stream
)
{
VideoStream stream = new VideoStream(aviFile, isCompressed, frameRate, firstFrame);
streams.Add(stream);
return stream;
}
 

  VideoStream使用格式化的数据创建新的流,调用 AVIFileCreateStream,如果 isCompressed参数为true,则调用 AVIMakeCompressedStream

 
        public VideoStream(int aviFile, bool writeCompressed, int frameRate, ...)
{
//store format information
//... //create the stream
CreateStream();
} private void CreateStream()
{
//fill stream information
Avi.AVISTREAMINFO strhdr = new Avi.AVISTREAMINFO();
strhdr.fccType = Avi.mmioStringToFOURCC("vids", 0);
strhdr.fccHandler = Avi.mmioStringToFOURCC("CVID", 0);
strhdr.dwScale = 1;
strhdr.dwRate = frameRate;
strhdr.dwSuggestedBufferSize = frameSize;
strhdr.dwQuality = -1; //default
strhdr.rcFrame.bottom = (uint)height;
strhdr.rcFrame.right = (uint)width;
strhdr.szName = new UInt16[64]; //create the stream
int result = Avi.AVIFileCreateStream(aviFile, out aviStream, ref strhdr); if(writeCompressed)
{
//create a compressed stream from
CreateCompressedStream();
}
} private void CreateCompressedStream()
{
Avi.AVICOMPRESSOPTIONS_CLASS options = new Avi.AVICOMPRESSOPTIONS_CLASS();
options.fccType = (uint)Avi.streamtypeVIDEO;
options.lpParms = IntPtr.Zero;
options.lpFormat = IntPtr.Zero; //display the compression options dialog
Avi.AVISaveOptions(IntPtr.Zero, Avi.ICMF_CHOOSE_KEYFRAME | Avi.ICMF_CHOOSE_DATARATE, 1, ref aviStream, ref options); //get a compressed stream
Avi.AVICOMPRESSOPTIONS structOptions = options.ToStruct();
int result = Avi.AVIMakeCompressedStream(out compressedStream, aviStream, ref structOptions, 0); //format the compressed stream
SetFormat(compressedStream);
}
 

    其中使用 AVICOMPRESSOPTIONS_CLASS 类代替 AVICOMPRESSOPTIONS 结构体,使用类代替结构体在使用指针的时候更加容易,如果你看不懂,你可能没在.Net使用过 AVISaveOptions 或 AVISaveV,下面看看 AVISaveOptions 的声明

        BOOL AVISaveOptions(
HWND hwnd,
UINT uiFlags,
int nStreams,
PAVISTREAM * ppavi,
LPAVICOMPRESSOPTIONS * plpOptions);

    LPAVICOMPRESSOPTIONS 是一个指向  AVICOMPRESSOPTIONS 结构体指针的指针(指向指针的指针)

    在C#中,结构体是值传递的,如果使用ref来传递结构体,则传递的是指向结构体的指针

    而类使用的是引用,实际传递的是指针,地址,所以使用ref传递类时,实际传递的是指向类指针的指针(指向指针的指针),

    所以这里使用类代替结构体,下面是在C#中声明 AVISaveOptions 和 AVICOMPRESSOPTIONS

 
            [DllImport("avifil32.dll")]
public static extern bool AVISaveOptions(
IntPtr hwnd,
UInt32 uiFlags,
Int32 nStreams,
ref IntPtr ppavi,
ref AVICOMPRESSOPTIONS_CLASS plpOptions
); [StructLayout(LayoutKind.Sequential, Pack=1)]
public struct AVICOMPRESSOPTIONS
{
public UInt32 fccType;
public UInt32 fccHandler;
public UInt32 dwKeyFrameEvery;
public UInt32 dwQuality;
public UInt32 dwBytesPerSecond;
public UInt32 dwFlags;
public IntPtr lpFormat;
public UInt32 cbFormat;
public IntPtr lpParms;
public UInt32 cbParms;
public UInt32 dwInterleaveEvery;
} [StructLayout(LayoutKind.Sequential, Pack=1)]
public class AVICOMPRESSOPTIONS_CLASS
{
public UInt32 fccType;
public UInt32 fccHandler;
public UInt32 dwKeyFrameEvery;
public UInt32 dwQuality;
public UInt32 dwBytesPerSecond;
public UInt32 dwFlags;
public IntPtr lpFormat;
public UInt32 cbFormat;
public IntPtr lpParms;
public UInt32 cbParms;
public UInt32 dwInterleaveEvery; public AVICOMPRESSOPTIONS ToStruct()
{
AVICOMPRESSOPTIONS returnVar = new AVICOMPRESSOPTIONS();
returnVar.fccType = this.fccType;
returnVar.fccHandler = this.fccHandler;
returnVar.dwKeyFrameEvery = this.dwKeyFrameEvery;
returnVar.dwQuality = this.dwQuality;
returnVar.dwBytesPerSecond = this.dwBytesPerSecond;
returnVar.dwFlags = this.dwFlags;
returnVar.lpFormat = this.lpFormat;
returnVar.cbFormat = this.cbFormat;
returnVar.lpParms = this.lpParms;
returnVar.cbParms = this.cbParms;
returnVar.dwInterleaveEvery = this.dwInterleaveEvery;
return returnVar;
}
}
 

  在这个工作区,可以调用 AVISaveOptions ,来设置Avi文件的一些参数

  通过AddFrame函数可以用图片填充视频流

 
            public void AddFrame(Bitmap bmp)
{
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); if (countFrames == 0)
{
// the format of the first frame defines the format of the stream
CopyPalette(bmp.Palette);
SetFormat(writeCompressed ? compressedStream : aviStream,
countFrames);
} //lock the memory block
BitmapData bmpDat = bmp.LockBits(
new Rectangle(0,0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly, bmp.PixelFormat); //add the bitmap to the (un-)compressed stream
int result = Avi.AVIStreamWrite(
writeCompressed ? compressedStream : aviStream,
countFrames, 1,
bmpDat.Scan0,
(Int32)(bmpDat.Stride * bmpDat.Height),
0, 0, 0); //unlock the memory block
bmp.UnlockBits(bmpDat); //count the frames, so that we don't have to call AVIStreamLength for every new frame
countFrames++;
}
 

Add frames to an existing stream

 
        public VideoStream(int aviFile, IntPtr aviStream)
{
this.aviFile = aviFile;
this.aviStream = aviStream; //read the stream's format
Avi.BITMAPINFOHEADER bih = new Avi.BITMAPINFOHEADER();
int size = Marshal.SizeOf(bih);
Avi.AVIStreamReadFormat(aviStream, 0, ref bih, ref size);
Avi.AVISTREAMINFO streamInfo = GetStreamInfo(aviStream); //store the important format values
this.frameRate = streamInfo.dwRate / streamInfo.dwScale;
this.width = (int)streamInfo.rcFrame.right;
this.height = (int)streamInfo.rcFrame.bottom;
this.frameSize = bih.biSizeImage;
this.countBitsPerPixel = bih.biBitCount; //get the count of frames that are already there
int firstFrame = Avi.AVIStreamStart(aviStream.ToInt32());
countFrames =
firstFrame + Avi.AVIStreamLength(aviStream.ToInt32());
}
 

  如果视频流是未压缩的,可以直接调用AddFrame,否则,需要对其进行解压缩,并重新压缩到一个新的流

 
        public AviManager DecompressToNewFile(String fileName, bool recompress)
{
//create a new AVI file
AviManager newFile = new AviManager(fileName, false); //create a video stream in the new file
this.GetFrameOpen();
Bitmap frame = GetBitmap(0);
VideoStream newStream = newFile.AddVideoStream(recompress, frameRate, frame); //decompress each frame and add it to the new stream
for(int n=1; n<countFrames; n++)
{
frame = GetBitmap(n);
newStream.AddFrame(frame);
}
this.GetFrameClose();
return newFile;
}
 

  DecompressToNewFile 创建一个可编辑的拷贝到一个新的文件流,可以添加frames到该流

Separate a stream

  有时,我们可能只想要视频的声音,或是只要没有声音的视频,我们没有必要重新创建视频,添加每一帧到视频流中,可以通过使用 AviSaveV 把当前流到处到文件,AVISaveV只是所有类型的流,只是压缩参数不一样而已

 
        public override void ExportStream(String fileName)
{
Avi.AVICOMPRESSOPTIONS_CLASS opts = new Avi.AVICOMPRESSOPTIONS_CLASS(); //for video streams
opts.fccType = (UInt32)Avi.mmioStringToFOURCC("vids", 0);
opts.fccHandler = (UInt32)Avi.mmioStringToFOURCC("CVID", 0); //for audio streams
//opts.fccType = (UInt32)Avi.mmioStringToFOURCC("auds", 0);
//opts.fccHandler = (UInt32)Avi.mmioStringToFOURCC("CAUD", 0); //export the stream
Avi.AVISaveV(fileName, 0, 0, 1, ref aviStream, ref opts);
}
 

Import sound from a Wave file

  现在,我们可以通过Bitmap来生成视频,也可以从视频中导出声音,那么当我们导入wav文件的时候,底层是如何工作的呢,我们还是可以用 AVISaveV 这个方法,来组合视频和音频成一个文件,但这里我们有更简单的方法,打开音频文件作为Avi文件,然后拷贝到另一个流中

 
            public void AddAudioStream(String waveFileName)
{
//open the wave file
AviManager audioManager = new AviManager(waveFileName, true);
//get the wave sound as an audio stream...
AudioStream newStream = audioManager.GetWaveStream();
//...and add it to the file
AddAudioStream(newStream);
audioManager.Close();
} public void AddAudioStream(AudioStream newStream)
{
Avi.AVISTREAMINFO streamInfo = new Avi.AVISTREAMINFO();
Avi.PCMWAVEFORMAT streamFormat = new Avi.PCMWAVEFORMAT();
int streamLength = 0; //read header info, format and length,
//and get a pointer to the wave data
IntPtr waveData = newStream.GetStreamData(
ref streamInfo,
ref streamFormat,
ref streamLength); //create new stream
IntPtr aviStream;
Avi.AVIFileCreateStream(aviFile, out aviStream, ref streamInfo); //add format new stream
Avi.AVIStreamSetFormat(
aviStream, 0,
ref streamFormat,
Marshal.SizeOf(streamFormat)); //copy the raw wave data into the new stream
Avi.AVIStreamWrite(
aviStream, 0,
streamLength,
waveData,
streamLength,
Avi.AVIIF_KEYFRAME, 0, 0); Avi.AVIStreamRelease(aviStream);
}
 

    截取视频流

   public AviManager CopyTo(String newFileName, int startAtSecond, int stopAtSecond)
{
AviManager newFile = new AviManager(newFileName, false);
try
{
//copy video stream
VideoStream videoStream = GetVideoStream(); int startFrameIndex = videoStream.FrameRate * startAtSecond;
int stopFrameIndex = videoStream.FrameRate * stopAtSecond; videoStream.GetFrameOpen();
Bitmap bmp = videoStream.GetBitmap(startFrameIndex); VideoStream newStream = newFile.AddVideoStream(false, videoStream.FrameRate, bmp); for (int n = startFrameIndex + ; n <= stopFrameIndex; n++)
{
bmp = videoStream.GetBitmap(n);
newStream.AddFrame(bmp);
}
videoStream.GetFrameClose(); //copy audio stream
AudioStream waveStream = GetWaveStream(); Avi.AVISTREAMINFO streamInfo = new Avi.AVISTREAMINFO();
Avi.PCMWAVEFORMAT streamFormat = new Avi.PCMWAVEFORMAT();
int streamLength = ;
IntPtr ptrRawData = waveStream.GetStreamData(ref streamInfo, ref streamFormat, ref streamLength); int startByteIndex = waveStream.CountSamplesPerSecond * startAtSecond * waveStream.CountBitsPerSample / ;
int stopByteIndex = waveStream.CountSamplesPerSecond * stopAtSecond * waveStream.CountBitsPerSample / ; ptrRawData = new IntPtr(ptrRawData.ToInt32() + startByteIndex); byte[] rawData = new byte[stopByteIndex - startByteIndex];
Marshal.Copy(ptrRawData, rawData, , rawData.Length); streamInfo.dwLength = rawData.Length;
streamInfo.dwStart = ; IntPtr unmanagedRawData = Marshal.AllocHGlobal(rawData.Length);
Marshal.Copy(rawData, , unmanagedRawData, rawData.Length); newFile.AddAudioStream(unmanagedRawData, streamInfo, streamFormat, rawData.Length);
}
catch (Exception ex)
{
newFile.Close();
throw ex;
}
return newFile;
}

转自:http://blog.csdn.net/jane_sl/article/details/8693395

C# AVI Image 转换的更多相关文章

  1. 使用ffmpeg 对视频截图,和视频转换格式

    //执行CMD命令方法 public static void CmdProcess(string command)//调用CMD        {            //实例化一个进程类      ...

  2. ffmpeg转换参数和对几种视频格式的转换分析

    我们在将多种格式的视频转换成flv格式的时候,我们关注的就是转换后的flv视频的品质和大小.下面就自己的实践所得来和大家分享一下,主要针对avi.3gp.mp4和wmv四种格式来进行分析.通常在使用f ...

  3. ffmpeg.exe dos下怎么用 放在哪里

    系统:windows 7 1.先看dos界面,win7下这里输入cmd, 看路径 2.把下载的ffmpeg.exe复制到这个路径下  3.这就可以用命令了 1.mp4说明这个文件是跟ffmpeg.ex ...

  4. 转载:ffmpeg 音视频合成分割

    http://blog.csdn.net/jixiuffff/article/details/5709976 当然先安装了 gentoo 下一条命令搞定 emerge  ffmpeg 格式转换 (将f ...

  5. ffmpeg 命令的使用

    当然先安装了 gentoo 下一条命令搞定 emerge  ffmpeg 格式转换 (将file.avi 转换成output.flv) ffmpeg -i  file.avi  output.flv ...

  6. windows下使用ffmpeg进行视频转换和截图。

    author:fanfq(xiaoban) Email:fangqing.fan#gmail.comlink:http://fanfq.iteye.com/admin/blogs/655569chan ...

  7. videoconverter转换

    以前录制的avi用vfw可以解码的,但是现在变成win7系统了,无法解码了.只好用视频转换软件把avi转成无压缩的. 选择losses uncompressed avi,点进去选UYVY就行了.

  8. 视频文件写入转换之图像处理-OpenCV应用学习笔记五

    在<笔记二>中我们做了视频播放和控制的实现,仅仅算是完成了对视频文件的读取操作:今天我们来一起练习下对视频文件的写入操作:格式转换. 实现功能: 打开一个视频文件play.avi,读取文件 ...

  9. IO流(三)__字节流 标准输入输出流 转换流

    一.字节流:FileInputStream 和FileOutputStream 基本操作和字符流类相同,没有flush,但是close还是要的 复制一个字节流文件 private static voi ...

随机推荐

  1. Java中String连接性能的分析

    总结:如果String的数量小于4(不含4),使用String.concat()来连接String,否则首先计算最终结果的长度,再用该长度来创建一个StringBuilder,最后使用这个String ...

  2. MVVM 和 VUE三要素:响应式、模板引擎、渲染

    MVVM 和 VUE三要素:响应式.模板引擎.渲染:https://blog.csdn.net/weixin_37644989/article/details/94409430

  3. python_0基础开始_day08

    第八节 1,文件操作 文件操作目的: 持久化,永久存储 (数据库之前 -- 文件操作就是代替数据库) 读 1,找到文件位 2,双击打开 3,进行一些操作 4,关闭文件 open() 打开,通过pyth ...

  4. CSS(上)

    目录 CSS(上) 什么是CSS? CSS的优点 CSS的引入方式 行内样式 内部样式 外部样式 CSS的两大特性 CSS选择器 基本选择器 组合选择器 更多选择器 选择器的优先级 CSS(上) 什么 ...

  5. jQuery扁平化风格手风琴菜单

    在线演示 本地下载

  6. 使用zookeeper报错 stat is not executed because it is not in the whitelist. envi is not executed because it is not in the whitelist.

    在使用四字命令或者zk ui界面查看zookeeper集群时,出现如下提示: stat is not executed because it is not in the whitelist. envi ...

  7. (转)MQTT 入门介绍

    原文链接:https://blog.csdn.net/qq_2887... MQTT 入门介绍 一.简述 MQTT(Message Queuing Telemetry Transport,消息队列遥测 ...

  8. (转载)sublime3安装markdown插件

    原文链接 http://www.jianshu.com/p/335b7d1be39e?utm_source=tuicool&utm_medium=referral 最近升级到了 Sublime ...

  9. 导出excel-模版

    后台代码 public void ToExcel(){ //第一步:获取模版文件物理路径 string file_0 = Server.MapPath("/Content/Excel/Exp ...

  10. JVM--对象访问和OutOfMemoryError异常

        对象访问: 使用句柄访问方式: 使用直接指针访问方式: OutOfMemoryError异常: 设置堆的最小最大容量:-Xms20m -Xmx20m 设置一样推不可自动扩展. 设置出现内存溢出 ...