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

news/2024/10/24 8:27:56/

文章目录

  • 1.函数简介
    • 1.1 avi_t *AVI_open_input_file(const char *filename, int getIndex)
    • 1.2 long AVI_video_frames(avi_t *AVI)
    • 1.3 double AVI_frame_rate(avi_t *AVI)
    • 1.4 int AVI_set_video_position(avi_t *AVI, long frame)
    • 1.5 long AVI_read_frame(avi_t *AVI, char *vidbuf, int *keyframe)
    • 1.6 AVI_close((avi_t *) avi)
  • 2.操作流程
  • 3.源代码
  • 4.整个工程源码

在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函数中调用该函数即可:
在这里插入图片描述
本文只是记录学习过程,并非教程。


http://www.ppmy.cn/news/904221.html

相关文章

使用OPENCV播放AVI视频

本次讲解如何使用OPENCV播放AVI视频&#xff0c;不过在写程序之前得告诉大家一声&#xff0c;OPENCV只支持AVI格式的视频播放。 首先&#xff0c;源代码基本格式&#xff1a; #include<highgui.h>int main(int argc,char** argv){ cvNamedWindow("Michael",CV_…

opencv入门—播放AVI视频

文章目录 一、前言二、函数解析1、VideoCapture函数2、isOpened函数3、release函数 三、代码实例四、运行结果 一、前言 使用Opencv播放视频&#xff0c;几乎与使用它来显示图像一样容易。播放视频时只需要处理的新问题是如何循环地读取视频中的每一帧&#xff0c;以及如何从枯…

PostgreSQL考试难不难 ?

当涉及到PostgreSQL考试的详细难度&#xff0c;以下是一些可能涉及的主题和考点&#xff0c;这些主题在不同的考试中可能有所不同&#xff1a; 1.数据库基础知识&#xff1a;数据库的基本概念、关系型数据库模型、表、字段、主键、外键等。 2.SQL语言&#xff1a;对SQL语言的掌…

SQL篇-03_SQL必知必会-06_创建计算字段

SQL79 别名 描述 别名的常见用法是在检索出的结果中重命名表的列字段&#xff08;为了符合特定的报表要求或客户需求&#xff09;。有表Vendors代表供应商信息&#xff0c;vend_id供应商id、vend_name供应商名称、vend_address供应商地址、vend_city供应商城市。 vend_id ven…

【Kubernetes】K8S到底是什么,最近怎么这么火

前言 kubernetes&#xff0c;简称K8s&#xff0c;是用8代替名字中间的8个字符“ubernete”而成的缩写。是一个开源的&#xff0c;用于管理云平台中多个主机上的容器化的应用&#xff0c;Kubernetes的目标是让部署容器化的应用简单并且高效&#xff08;powerful&#xff09;,Kub…

(简单)剑指Offer II 056. 二叉搜索树中两个节点的和 Java

方法一&#xff1a;深度优先搜索哈希表 使用深度优先搜索的方式遍历整棵树&#xff0c;用哈希表记录遍历过的节点的值 对于一个值为x的节点&#xff0c;检查哈希表中是否存在k-x即可。如果存在对应的元素&#xff0c;那么我们就可以在该树上找到两个节点的和为k&#xff1b;否…

win11已卸载软件任务栏托盘图标管理开关残留清理

具体步骤如下&#xff1a; 1、右键开始菜单&#xff0c;选择“运行”&#xff0c;输入regedit&#xff0c;打开注册表编辑器。 2、找到\HKEY_CLASSES_ROOT\LocalSettings\Software\Microsoft\Windows\CurrentVersion\TrayNotify右键删除“IconStreams”和“PastIconsStream”这…

Win10的explorer.exe在哪,怎么重启资源管理器

使用windows7或者以前更早的windows XP系统的时候&#xff0c;大家都知道电脑中有一个比较重要的进程explorer.exe资源管理器&#xff0c;这个进程用来负责电脑的图形界面&#xff0c;有时候我们电脑出现桌面卡死等状况的时候&#xff0c;我们需要对这个进程重启&#xff0c;但…