LVGL笔记-使用《avilib》库播放avi视频(lvgl在windows模拟运行)

Posted hwd00001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LVGL笔记-使用《avilib》库播放avi视频(lvgl在windows模拟运行)相关的知识,希望对你有一定的参考价值。

文章目录


在github找到一个 avilib库,可以方便的读写avi文件。这里主要用到读取图片帧的功能。avi文件必须是MJPG编码,这样读取出来就是一张张的jpg图片,直接使用lvgl的第三方库《sjpg》解码。
如何生成MJPG编码的avi文件,请参考《 AVI视频封装格式(阅读笔记)》。
在windows仿真的视频:

lvgl播放avi视频

1.函数简介

这里只介绍读取avi用到的部分函数。

1.1 avi_t *AVI_open_input_file(const char *filename, int getIndex)

传入文件名,打开avi文件;返回avi_t指针,后面的操作都要用到这个指针。

1.2 long AVI_video_frames(avi_t *AVI)

获取avi文件的总帧数(有多少张jpg图片)。由视频的时长可以估算,一般是一秒20-30帧,以30帧算,如果视频是10秒长,那么总帧数是300张。

1.3 double AVI_frame_rate(avi_t *AVI)

这个函数直接返回 AVI->fps,每秒的帧数。更新图片的速度由这个参数决定。

1.4 int AVI_set_video_position(avi_t *AVI, long frame)

设置AVI->pos.
传入参数frame是帧索引,范围在0-总帧数之间。
返回值:0表示正常,非0表示出错。

1.5 long AVI_read_frame(avi_t *AVI, char *vidbuf, int *keyframe)

读取AVI->pos对应的图片,把数据存放到vidbuf,如果是关键帧,keyframe = 1,否则keyframe = 0.
返回值:本帧数据大小,单位是字节。

1.6 AVI_close((avi_t *) avi)

关闭avi文件。

2.操作流程

Created with Raphaël 2.3.0 打开视频文件:AVI_open_input_file 读取总帧数:AVI_video_frames 设置视频开始读取位置:AVI_set_video_position 读取帧数据:AVI_read_frame lvgl显示图片:lv_img_set_src 延时 确认帧数达到最大:pos==(frames-1)? 关闭视频文件:AVI_close yes no

3.源代码

这里有一个疑问,如果一开始设置帧索引为0,会闪退出;设置到10开始就正常。不知道为什么。注意下面的代码第56行。

static lv_img_dsc_t IMG1 = 
    .header.cf = LV_IMG_CF_RAW,
    .header.always_zero = 0,
    .header.reserved = 0,
    .header.w = 0,
    .header.h = 0,
    .data_size = 0,
    .data = NULL,
;
lv_obj_t * objpg;
//const	unsigned char JFIF_INFO[18]=
//0XFF ,0XE0 ,0X00 ,0X10 ,0X4A ,0X46 ,0X49 ,0X46 ,0X00 ,0X01 ,0X01 ,0X01 ,0X00 ,0X60 ,0X00 ,0X60 ,0X00 ,0X00;

lv_obj_t * g_scr;
int avi_file_is_opened=0;
char frameBuffer[20*1024];
int frameSize = 0;      //单帧的字节数
int keyFrame = 0;       //是否关键帧
int pos;                //帧索引
int frames;             //帧总数

avi_t * avi;
static void pic_timer(void)

    //lv_obj_t* bg = timer->user_data;
    if(avi_file_is_opened)
        pos++;
        if(pos<frames)
            //  avi->pos  会自动增加,不用下面的函数
            //AVI_set_video_position((avi_t *) avi,pos);
            frameSize = AVI_read_frame((avi_t *) avi, frameBuffer, &keyFrame);
            //  图片的尺寸不能大于分配的空间
            if(frameSize > sizeof(frameBuffer))     return;
            printf("pos:%d,frameSize: %d",pos, frameSize);

            IMG1.data_size = frameSize;
            memcpy(frameBuffer+2,JFIF_INFO,sizeof(JFIF_INFO));
            IMG1.data = (const uint8_t *)frameBuffer;

            lv_img_set_src(g_scr,&IMG1);
        else
            printf("avi file close.");
            avi_file_is_opened = 0;
            AVI_close((avi_t *) avi);
        
    

void lv_100ask_demo_course_4_1_1(void)

    char *ff="./avi/hanfu03.avi";
    avi = AVI_open_input_file(ff, 1);
    if(avi != NULL)
        avi_file_is_opened = 1;
        printf("W: %d,H: %d", (int)(avi->width),(int)(avi->height));
        //将avi帧byte读取到bitmap中
        pos = 10;
        frames=AVI_video_frames(avi);

        AVI_set_video_position((avi_t *) avi,pos);
            frameSize = AVI_read_frame((avi_t *) avi, frameBuffer, &keyFrame);
        printf("pos:%d,frameSize: %d",pos, frameSize);


    else
        printf("open avi fail.");
        AVI_close((avi_t *) avi);
        return;
    

        IMG1.data_size = frameSize;
        //memcpy(frameBuffer+2,JFIF_INFO,sizeof(JFIF_INFO));
        IMG1.data = (const uint8_t *)frameBuffer;


        g_scr =  lv_img_create(lv_scr_act());
        lv_img_set_src(g_scr,&IMG1);

    lv_timer_t * timer = lv_timer_create(pic_timer, 35,  g_scr);
    lv_timer_set_repeat_count(timer, frames+1);

4.整个工程源码

测试代码工程】是在韦东山老师的开源工程上改动的。本例子在工程中的位置:

测试时,在main函数中调用该函数即可:

本文只是记录学习过程,并非教程。

C#AviFile使用(播放AVI文件,兼容性比较差)

最近在做一个视频识别项目,需要用到视频处理,在codeproject上找到了一个关于对Avi的操作库,感觉不错,在这里把一些要点记录下来

http://www.codeproject.com/Articles/7388/A-Simple-C-Wrapper-for-the-AviFile-Library

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 + 1; 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 = 0;
                IntPtr ptrRawData = waveStream.GetStreamData(ref streamInfo, ref streamFormat, ref streamLength);

                int startByteIndex = waveStream.CountSamplesPerSecond * startAtSecond * waveStream.CountBitsPerSample / 8;
                int stopByteIndex = waveStream.CountSamplesPerSecond * stopAtSecond * waveStream.CountBitsPerSample / 8;

                ptrRawData = new IntPtr(ptrRawData.ToInt32() + startByteIndex);

                byte[] rawData = new byte[stopByteIndex - startByteIndex];
                Marshal.Copy(ptrRawData, rawData, 0, rawData.Length);

                streamInfo.dwLength = rawData.Length;
                streamInfo.dwStart = 0;

                IntPtr unmanagedRawData = Marshal.AllocHGlobal(rawData.Length);
                Marshal.Copy(rawData, 0, unmanagedRawData, rawData.Length);

                newFile.AddAudioStream(unmanagedRawData, streamInfo, streamFormat, rawData.Length);
            } 
            catch (Exception ex) 
            {
                newFile.Close();
                throw ex;
            }
            return newFile;
        }

以上是关于LVGL笔记-使用《avilib》库播放avi视频(lvgl在windows模拟运行)的主要内容,如果未能解决你的问题,请参考以下文章

.avi 文件视频无法在 MPMoviePlayerController ios 播放器中播放

ARM AVI 视频播放 基于 2440 freambuffer 绘制

HTML 如何让几个视频连续并循环播放,给段代码

粤嵌GEC6818,基于LVGL和mplayer的音视频播放器

用 Java 处理视频(DVD、.avi .mkv)

在 Node.js / Electron 应用中播放本地 .avi 视频