IMX8MP录像功能测试
目录
1.开发环境搭建
2.编译hello world
3.录像功能测试
4.参考资料
1.开发环境搭建
1.1 开发工具链和源码
开发环境的搭建按照手册上的命令搭建即可,可以更换其中的安装目录,其中需要sdk的目录和工具链目录统一放置在/opt/imx8/
目录下,交叉编译所需要的工具链所在目录/opt/imx8/sdk
;另一个是/opt/imx8/source
,该目录是工程的源码所在目录。
获取sdk和交叉工具链指令如下
mkdir -p /opt/imx8/sdk
cd /opt/imx8/sdk
./fsl-imx-xwayland-glibc-x86_64-meta-toolchain-qt5-aarch64-\
imx8mpevk-toolchain-5.4-zeus.sh
source ./environment-setup-aarch64-poky-linux
aarch64-poky-linux-gcc -v
![imx8mpsdktree](https://img-blog.csdnimg.cn/db828d963e7f484fa9b0c42898e5050a.png#pic_center)
编译工具在/opt/imx8/sdk/sysroots/x86_64-pokysdk-linux/usr/bin/aarch64-poky-linux/
。
源码则解压到/opt/imx8/source
目录下;
1.2编译源码
编译前需要先配置环境,使其生效
source ./environment-setup-aarch64-poky-linux
aarch64-poky-linux-gcc -v
./build.sh kernel
./build.sh kernel_clean
source ./environment-setup-aarch64-poky-linux
aarch64-poky-linux-gcc -v
./build.sh apps
./build.sh clean_apps
source ./environment-setup-aarch64-poky-linux
aarch64-poky-linux-gcc -v
./build.sh freertos_demo
./build.sh clean_freertos_demo
2.编译hello world
先编译最简单的hello
程序检查编译环境配置是否有问题,实际上是真的有问题,这个开发工具链有些bug,导致编译的时候会提示找不到一些最基本的头文件;
测试程序代码如下
#include <stdio.h>
int main()
{
printf("Hello, World!\n");
return 0;
}
编译指令
source /opt/imx8/sdk/environment-setup-aarch64-poky-linux
aarch64-poky-linux-gcc ./hello.c -o hello
会出现编译报错问题
![02imx8helloerror](https://img-blog.csdnimg.cn/a549e24928934e5086b84dbed967a581.png#pic_center)
最简单的标准库头文件都没有找到,显然环境有问题,编译配置环境,最终定位到需要指定编译链的目录;
aarch64-poky-linux-gcc --sysroot=/opt/imx8/sdk/sysroots/aarch64-poky-linux ./hello.c -o hello
3.录像功能测试
这个文件夹不仅可以测试录像的功能,也能测试其他模块功能,文件夹的目录结构如下所示;
![03imx8dirtree](https://img-blog.csdnimg.cn/6d68aafc8536466295fc66b528aec039.png#pic_center)
CC = aarch64-poky-linux-gcc
CXX = aarch64-poky-linux-g++
export CURDIR = $(shell pwd)
export INSDIR = $(CURDIR)/output
export SDKDIR = /opt/imx8/sdk
TARGET = testRec
SRCS += $(CURDIR)/src/*
OBJS := $(SRCS:%.c=%.o)
OBJS += $(SRCPPS:%.cpp=%.o)
export BUILD_SH = $(CURDIR)/script/BUILD.sh
CFLAGS =
CFLAGS += --sysroot=$(SDKDIR)/sysroots/aarch64-poky-linux
CFLAGS += -I$(CURDIR)/include
CFLAGS += -Wall -g
LD_FLAGS += -lpthread -lm
LD_FLAGS += -L$(CURDIR)/lib
$(TARGET):$(OBJS)
@/bin/echo "************ Compiling Start ***********"
$(CC) $(CFLAGS) $(LD_FLAGS) $^ -o $@
@/bin/echo "************ Compiling Finish ***********"
$(OBJS):
ifneq ($(SRCS), )
for x in $(SRCS); \
do \
$(CC) -MM -MT"$${x%.c}.o" $(CFLAGS) $$x >> $@;\
done
endif
ifneq ($(SRCPPS), )
for x in $(SRCPPS); \
do \
$(CXX) -MM -MT "$${x%.cpp}.o" $(CPPFLAGS) $$x >> $@;\
done
endif
clean:
$(RM) *.o $(TARGET) -r
install:
cp -rf $(TARGET) $(INSDIR)
$(RM) $(CURDIR)/$(TARGET)
# vim:noet:sw=4:ts=4
直接执行指令,即可在安装目录下获取到测试的目标文件,将其拷贝到板端即可在板端运行;
make
make install
#include <stdio.h>
#include <pthread.h>
#include <stdbool.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <time.h>
#include <sys/time.h>
#include <string.h>
#include <sys/types.h>
#define THREAD_NUM 3
#define WRITE_SIZE (256*1024)
static long long int microtime(void)
{
struct timeval time;
gettimeofday(&time, NULL);
long long int microsec = ((long long)time.tv_sec * 1000000) + time.tv_usec;
return microsec;
}
void *write_file_body(void *arg)
{
int *pChn = (int *)arg;
char szPath[64] = {0};
char szCmd[128] = {0};
long long s64CurTime = 0;
long long s64LastTime = 0;
char data[WRITE_SIZE] = {0};
int ret = 0;
int cnt = 0;
sprintf(szPath, "/run/media/sda1/testRec/test%d",*pChn);
sprintf(szCmd, "rm -rf %s",szPath);
system(szCmd);
FILE* fp = fopen(szPath, "ab+");
if (NULL == fp)
{
printf("open file %s filed \n",szPath);
}
while(1)
{
s64LastTime = microtime();
sprintf(data, "%d",cnt);
if (cnt <= 1000)
{
ret = fwrite(data, WRITE_SIZE, 1,fp);
if (0 == ret)
{
printf("write failed\n");
}
}
else
{
break;
}
if(cnt == 1000)
{
fclose(fp);
printf("close file %d\n",*pChn);
}
cnt++;
s64CurTime = microtime();
printf("chn[%d] %lld us\n",*pChn, (s64CurTime - s64LastTime));
}
return NULL;
}
int main()
{
pthread_t thread_id;
static int num[3] = {0};
int ret = 0;
int i = 0;
for(i=0; i<THREAD_NUM; i++)
{
num[i] = i;
ret = pthread_create(&thread_id, NULL, write_file_body, &num[i]);
if (0 != ret)
{
printf("pthread[%d] create failed! [err=%d]\n",i, ret);
return ret;
}
}
while(1)
{
usleep(1000000);
}
return 0;
}
(1)256k (2)128k (3)64k
![64k](https://img-blog.csdnimg.cn/7da65e0e091444c68c72226d56d483aa.png)
上图分别为256*1024
128*1024
和64*1024
字节写入卡内,显然,256k
和128k
的三路同时写入耗时超过40ms,对于视频的帧率而言会导致丢帧的问题,而64k
字节写入会出现写入不太稳定的问题,这个不稳定是快到尾部的时候写入同步数据到卡上引起的,另一方面,写入卡耗时还由于这张卡是通过USB Hub连接到读卡器上的sd卡,因此耗时也会比在设备端的sd卡耗时更长,具体的可以根据硬件设计完再测试。
在主循环中通过手动定时调用sync
定时将数据回写,在128k
的写入速度写测试,如果添加定时回写,在写1000帧快结束的时候,大部分情况会有耗时比不添加的要少一些,但这个不是绝对的,与系统当前的负载有关,但是大部分情况还是会比不添加手动同步的要耗时少,在64k
的写入速度下效果不太明显。
(1) 256k定时手动同步 (2)128k定时手动同步 (3)64k定时手动同步
![128k](https://img-blog.csdnimg.cn/3730fc4d19344055900fd4fcc28149f0.png)
![64k](https://img-blog.csdnimg.cn/1e86ea1280ca4a28874512ecff907b0b.png)
既然同步在一定情况下可以平均负载,降低部分写数据的耗时,那是否可以不停的同步呢?经过测试发现,降低同步时间在一定范围内是可以降低写数据耗时,但是会降低系统处理其他操作的性能,同时当负载过大的情况下,不断的同步会增加操作系统的负担,不利于整体的性能,因此同步操作需要实际测试指定一个比较合适的时间范围;
4.参考资料
*** 不足之处,敬请指出,谢谢! ***
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)