找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 762|回复: 4

【嵌入式】F1C100S「单片机」播放(软解)MP4 视频 480x272

[复制链接]
发表于 2024-5-11 14:24:19 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×

F1C100S「单片机」播放(软解)MP4 视频 480x272

继上回 折腾荔枝派 播放视频无果,这回群友推荐我购买另一块大一点的板子来开发 F1C200S,应该就能达到我想要的效果了——折腾出一个小电视机出来,可以播放视频。

重新选「派」,这次选了「芒果派」

按照群友的推荐,我购买了「芒果派」作为这次开发用的开发板。
芒果派正面

芒果派反面

烧写镜像

「芒果派」厂商给了我一些资料,说要烧写镜像。于是我开始折腾 zadig.exe 去 「Create USB Device」。这里面遇到了一些问题,不过基本上来讲都不是什么大问题,此处列举这么几个问题:

创建 FEL Device 的时候,无论如何也创建不成功。

设备管理器打开看不到任何设备。结果群友「喵叫专攻」提醒了一下「你可能要把 USB 线反过来插一下看看」。插上后,成功识别设备,sunxi-fel.exe -l 也能看到设备了。

#sunxi-fel.exe -l
USB device 001:035   Allwinner F1C100s

干!我特么以为我的是 F1C200s!
总之按住 BOOT 然后按住 RST 后,可以看到液晶屏变为白屏,它进入了 FEL 模式。我双击「from-fel-to-dfu.bat」后,看到它的液晶屏好像进了 u-boot,设备管理器也看到「FEL Device」是「拔出状态」。
FEL Device 显示出来了

在 zadig.exe 里创建了半天的 DFU Device,后面发现它自己把自己改名为「USB download gadget」了

我是靠它的 ID:1f3A:1010 发现它就是 DFU 设备的。于是开始烧写。

烧写后,才发现卖家早就帮我烧写好了。

DFU Device 的镜像下载过程

在烧写的过程中我不断和卖家沟通如何烧写、怎么连不上、怎么不能显示 FEL 设备或者 DFU 设备、我要退货等各种问题,但是毕竟买了已经有 5 个多月了,卖家不愿意退货,并且也无法提供更多的资料,我只能自己继续研究。

不管怎样,我有两块板子,这块板子被我重复烧写了以下,另一块板子没动,最后发现两块板子的上电后行为一致,就先这样吧。

连接 OTG,稍等片刻,会有新设备冒出来

MangoPi R3 设备冒出来了

它显示为「rootfs」

双击打开

咦,这不是 Linux 么?哦不对,这应该是 buildroot。

大问题基本搞定,接下来是开发的问题

如何开发

首先我们需要确定它的 CPU 使用什么样的指令集,然后我可以使用 gcc 或者 gcc-arm-toolchain 去给它编译程序软件。

询问 gcc 编译目标
回答1:gccv5xxxt
回答2:gccv5

感觉这样询问的话,我得弄清楚「什么什么带t的那种」,于是运行了一下 uname -a,得到了合适的答案:

# uname -a /bin/gpio                                                            
Linux mangopi-r3 5.4.92 #1 Tue May 11 10:39:00 CST 2021 armv5tejl GNU/Linux 

啊,原来是 armv5tejl

控制 F1C100s 的 GPIO

经过一番简单的谷式搜索,我找到了这个库:

f1c100s-gpio-tools

一件很棒的事是这个小工程的代码简单易读,而且作者上传了 bin gpio,只要放到 /bin 里,给个可执行权限就可以使用了。

看看都有啥 GPIO

它的接口让我想起了 WiringPi。像啊,很像啊。

播放视频

我现在最想做的事情是让它 能够播放视频

于是我连接上串口,然后在 /dev 里面瞄一眼看看都有些啥。

看看都有啥设备

很眼熟地看到了 cedar_dev 和 ion,以及 fb0 。赶紧去群里问了 Aodzip 大佬。经过一番沟通,我放弃了 使用硬件外设解码 H264 视频 的这一想法,决定尝试 CPU 软件解码视频

解码视频后如何播放呢,很简单,直接写 /dev/fb0,液晶屏就会有显示。每 open() 一次 /dev/fb0,写一帧画面,写的时候就能看到液晶屏显示内容。用 close() 关闭设备,再重新 open() 打开再写就又是新的一帧画面。 从编程 IO 上它是这么个逻辑 。打开设备时,写的像素量如果超出了 480x272 这个分辨率,就会写入失败(写文件的函数返回一个错误码),因为它的 Framebuffer 就这么大。可以用 cat /dev/urandom > /dev/fb0 来欣赏花屏和写超出范围的报错(注意是 正常报错 而不是 Segmentation Fault

在使用 FFmpeg 的时候,指定 -pix_fmt bgra -f fbdev /dev/fb0 就能使 ffmpeg 输出每一帧到  /dev/fb0 ,看到动画的播放效果。理论上是这样。

然而没有 ffmpeg 啊!

那就得自己编译 ffmpeg。经过一番折腾,我是编译出了 ffmpeg,大约 34 MB,直接塞 /bin 里,别忘了 chmod +x /bin/ffmpeg

结果在试用的时候报错了: glibc 版本不符

GLIBC 版本不符

我用的是 gcc13,但看起来这个 buildroot 的镜像是 2020 年编译的。当年最新的 gcc 就是 gcc9,因此要用 gcc9 编译 ffmpeg.

我放弃了自己编译 ffmpeg,虽然我找到了 gcc-arm-toolchain9,但是这玩意儿前缀名太长了,懒得弄。

我于是从 ffmpeg 官网找到 Linux 的 bin 的下载入口,然后打算根据日期挑选符合我的 glibc 版本的 ffmpeg 二进制。考虑到目标机器是 armv5tejl,但是人家不一定有,于是我按照最可能的情况来猜出适合我的机器的 ffmpeg 二进制。

先找 Linux 的静态编译版

再找 Linux 的 Arm 版

应该就是这里面的这几个

可能是这个

ffmpeg-4.3.1-armel-static.tar.xz           2020-07-22 16:39   12M

下载后解压 ffmpeg/bin 里,然后 chmod +x /bin/ffmpeg ,再执行一下 ffmpeg 看看,果然打印出了信息:

就是这个

进行视频播放

一开始只是为了测试,我没管视频文件本身的大小和它输出的帧数,想直接先跑起来看看,于是拔了 TF 卡,传了个 PV 上去,然后用 ffmpeg 播放,不过我需要先挂载 TF 卡到特定位置才行。

TF 卡的设备是 /dev/mmcblk0 ,我的 TF 卡只有一个分区,这个分区的设备是 /dev/mmcblk0p0。因此在 /etc/fstab 里使用这条语句来挂载:

/dev/mmcblk0p0  /mnt/sdcard     vfat    defaults        0       0 

然后运行以下命令:

mount -a

成功挂载。接下来播放视频:

ffmpeg -i /mnt/sdcard/testvideo.mp4 -pix_fmt bgra -f fbdev /dev/fb0

帧数只有 1 fps,而且只能看到视频左上角,看不全。重新用命令设置一下输出分辨率后,可以看到极其卡顿的视频。

ffmpeg -i /mnt/sdcard/testvideo.mp4 -s 480x272 -pix_fmt bgra -f fbdev /dev/fb0

ずっと真夜中でいいのに。『お勉強しといてよ』

解决卡顿问题

我试过唯一能解决卡顿问题的方法是 预处理视频 ,预先把视频压缩到 480x272 分辨率,然后使用 xvid 编码格式, 不使用 h264





音频播放

按照卖家给的「产测工具」,我发现播放音频使用的命令是 tinyplay。我尝试过使用 FFmpeg 以直接输出 ALSA 的方式来把音频推流到声卡驱动,结果发现不成功,FFmpeg 提示「[ALSA @Xxxxx]: Could not open device: No such file or directory.」(或者差不多类似的内容)。上网搜了一通,发现 FFmpeg 能把音频输出到管道里。那就有可能利用管道通信来实现音频的播放了。我于是尝试了一下 tinyplay 的管道输入功能,发现:

tinyplay 不支持管道输入

这简直是傻卵设计,气得我直接翻出它的源码:
tinyalsa

tinyplay 不支持管道输入,但是它的源码里面有打开管道进行输入的功能。

理想的情况是这样的
  • tinyplay 支持从管道读取音频然后播放。
实际情况是这样的:
  • int main() 里,它 parse options 的时候,它的逻辑是认为所有的横杠 - 开头的都是命令参数。
  • 在过完 options parsing 后,它的 ctx_init() 会检测文件名是不是 -,是的话,打开 stdin 进行读取,然后进行音频播放。
  • 命令行参数 - 会被过滤掉,ctx->filename 值是 NULL
  • 它先判断 ctx->filename 值是不是 NULL ,然后提示:「Filename not specified.」并退出。
  • 过了这一关后(假设它没有退出),它判断 ctx->filename 是不是 - ,是的话打开 stdin 进行一个管道输入播放。

简直是个傻卵 bug。气得我直接改它的源码。我的思路是:

  • 首先 stdin 被我视作特殊文件名,一般人不会使用这个文件名。
  • 其次 stdin 可以过它的 options parsing,被视作文件名。
  • 我检测 ctx->filename ,如果是 stdin 我就打开 stdin 标准输入文件。

(其实也是一种傻卵设计)

我提了 PR

编译 tinyplay

需要先编译 tinyalsa

编译的过程花费了我很多精力,最最最主要的原因是:

GLIBC 版本太高。

不能使用 none-eabi 编译工具链,因为 tinyalsa 库依赖 <poll.h> 。需要使用 linux-gnueabi 编译工具链。但是网上没有 2020 年的二进制的 arm-linux-gnueabi 工具链。我尝试过使用 Debian 添加 bullseye 或者 buster 源来安装 arm-linux-gnueabi-gcc-9、arm-linux-gnueabi-gcc-8,结果发现 不论 gcc 版本是多少,编译出来的 tinyplay 都依赖 GLIBC 2.34

使用卖家提供的 Ubuntu 16.04 虚拟机编译 tinyalsa

虚拟机下载

通过拖拽文件到虚拟机里,然后虚拟机安装 gcc-arm-linux-gnueabi(其中 gcc 版本是 5,可喜可贺),再修改源码。

虚拟机 Ubuntu 16 系统

再用以下命令编译,就得到了能用的 tinyplay

CROSS_COMPILE=arm-linux-gnueabi- make -j

使用管道进行音视频同时播放

tinymix set 1 63 #设置音量
tinymix set 2 1 #开音频输出
tinymix set 13 0 #关麦
ffmpeg -i /mnt/sdcard/要播放的文件.mp4 -s 480x272 -pix_fmt bgra -f fbdev /dev/fb0 -vn -ar 44100 -ac 1 -f wav pipe:1 | tinyplay stdin -r 44100 -c 1

播放不流畅,音频卡顿的解决方案

需要使用 FFmpeg 对原视频文件进行预处理,命令行如下:

ffmpeg -y -i 原始视频.mp4 -c:v libxvid -s 480x272 -r 12 -b:v 100K -c:a aac -b:a 64k -ac 1 -ar 44100 处理后的视频.mp4


gpio.zip

11.33 KB, 下载次数: 0

tinyplay.zip

16.98 KB, 下载次数: 0

ffmpeg.z01

2 MB, 下载次数: 0

ffmpeg.z02

2 MB, 下载次数: 0

ffmpeg.z03

2 MB, 下载次数: 0

ffmpeg.z04

2 MB, 下载次数: 0

ffmpeg.z05

2 MB, 下载次数: 0

ffmpeg.z06

2 MB, 下载次数: 0

ffmpeg.z07

2 MB, 下载次数: 0

回复

使用道具 举报

发表于 2024-5-11 17:28:28 | 显示全部楼层
这屏幕看起来也没必要bgra输出啊
回复 赞! 靠!

使用道具 举报

 楼主| 发表于 2024-5-11 23:11:37 | 显示全部楼层
AyalaRs 发表于 2024-5-11 17:28
这屏幕看起来也没必要bgra输出啊

你给别的参数,它就说“不支持。请使用 bgra”
回复 赞! 靠!

使用道具 举报

发表于 2024-5-16 14:16:58 | 显示全部楼层
这是不是自己做了一台山寨MP4播放器。
回复 赞! 靠!

使用道具 举报

 楼主| 发表于 2024-5-17 09:33:24 | 显示全部楼层
美俪女神 发表于 2024-5-16 14:16
这是不是自己做了一台山寨MP4播放器。

我想把它做成类似古代苹果电脑那样的设计,大背头显示器,下部插 SD 卡,就像软盘一样,然后可以播放视频,可以有个桌面,可以做各种事。
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-12-4 00:35 , Processed in 0.043429 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表