平台:R-Car V4H WhitHawk all in 1
copy以下文件到TFTP server文件存放目录下:
copy以下文件到NFS server文件存放目录下:
在u-boot命令终端,更改环境变量参数:
=> setenv ethaddr xx:xx:xx:xx:xx:xx
=> setenv ipaddr 192.168.0.20
=> setenv serverip 192.168.0.1
=> setenv bootargs 'rw root=/dev/nfs nfsroot=192.168.0.1:/export/rfs,nfsvers=3 ip=192.168.0.20:::::eth0 cma=560M@0x80000000 clk_ignore_unused'
=> setenv bootcmd 'tftp 0x48080000 Image;tftp 0x48000000 r8a779g0-whitehawk.dtb;booti 0x48080000 - 0x48000000'
=> saveenv
N:ICUMX Loader Rev.0.21.1
N:Built : 11:46:15, Apr 19 2023
N:PRR is R-Car V4H Ver2.0
N:Boot device is QSPI Flash(40MHz)
...
U-Boot 2022.01 (Apr 23 2023 - 17:07:21 +0000)
CPU: Renesas Electronics R8A779G0 rev 2.0
Model: Renesas White Hawk CPU and Breakout boards based on r8a779g0
DRAM: 7.9 GiB
RAM Configuration:
Bank #0: 0x048000000 - 0x0bfffffff, 1.9 GiB
Bank #1: 0x480000000 - 0x4ffffffff, 2 GiB
Bank #2: 0x600000000 - 0x6ffffffff, 4 GiB
MMC: mmc@ee140000: 0
Loading Environment from MMC... OK
In: serial@e6540000
Out: serial@e6540000
Err: serial@e6540000
Net:
Dummy RTOS Program
Dummy RTOS Program boot end
eth0: ethernet@e6800000
Hit any key to stop autoboot: 0
ethernet@e6800000 Waiting for PHY auto negotiation to complete.......... done
Using ethernet@e6800000 device
TFTP from server 192.168.0.1; our IP address is 192.168.0.20
Filename 'Image'.
Load address: 0x48080000
Loading: #################################################################
#################################################################
#################################################################
...
###############################
1.7 MiB/s
done
Bytes transferred = 33839616 (2045a00 hex)
Using ethernet@e6800000 device
TFTP from server 192.168.0.1; our IP address is 192.168.0.20
Filename 'r8a779g0-whitehawk.dtb'.
Load address: 0x48000000
Loading: #########
2.5 MiB/s
done
Bytes transferred = 121766 (1dba6 hex)
Moving Image from 0x48080000 to 0x48200000, end=4a2d0000
## Flattened Device Tree blob at 48000000
Booting using the fdt blob at 0x48000000
Loading Device Tree to 0000000057fdf000, end 0000000057fffba5 ... OK
Starting kernel ...
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x414fd0b1]
...
[ 15.925227] systemd[1]: Detected architecture arm64.
Welcome to Poky (Yocto Project Reference Distro) 3.1.11 (dunfell)!
[ 15.989781] systemd[1]: Set hostname to <v4x>.
...
Poky (Yocto Project Reference Distro) 3.1.11 v4x ttySC0
v4x login:
$ fdisk /dev/mmcblk0
n for new partition
p for primary
1 for partition one
use defaults
a for boot-able
w for write and exit
$ mkfs.ext4 /dev/mmcblk0p1
# mount
root@v4x:/# mount /dev/mmcblk0p1 /mnt
# 在虚拟机上,提前copy
# (1) Image
# (2) r8a779g0-whitehawk.dtb
# (3)rcar-image-adas-v4h.tar.bz2
# 到nfstserver存放的文件目录下
root@v4x:/# ls
Image boot etc lib mnt r8a779g0-whitehawk.dtb run sys usr
bin dev home media proc rcar-image-adas-v4h.tar.bz2 sbin tmp var
# extract
root@v4x:/# tar xvf rcar-image-adas-v4h.tar.bz2 -C /mnt
root@v4x:/# cd mnt/
root@v4x:/mnt# ls
bin boot dev etc home lib lost+found media mnt proc run sbin sys tmp usr var
root@v4x:/mnt# cp ../Image boot/
root@v4x:/mnt# cp ../r8a779g0-whitehawk.dtb boot/
=> setenv bootargs 'console=ttySC0,115200 rootfstype=ext4 root=/dev/mmcblk0p1 rw rootwait'
=> setenv bootcmd 'ext4load mmc 0 0x48080000 boot/Image;ext4load mmc 0 0x48000000 boot/r8a779g0-whitehawk.dtb;booti 0x48080000 - 0x48000000'
=> saveenv
=> run bootcmd
N:ICUMX Loader Rev.0.21.1
N:Built : 11:46:15, Apr 19 2023
N:PRR is R-Car V4H Ver2.0
N:Boot device is QSPI Flash(40MHz)
...
MMC: mmc@ee140000: 0
Loading Environment from MMC... OK
In: serial@e6540000
Out: serial@e6540000
Err: serial@e6540000
Net:
Dummy RTOS Program
Dummy RTOS Program boot end
eth0: ethernet@e6800000
Hit any key to stop autoboot: 0
33839616 bytes read in 188 ms (171.7 MiB/s)
121766 bytes read in 2 ms (58.1 MiB/s)
Moving Image from 0x48080000 to 0x48200000, end=4a2d0000
## Flattened Device Tree blob at 48000000
Booting using the fdt blob at 0x48000000
Loading Device Tree to 0000000057fdf000, end 0000000057fffba5 ... OK
Starting kernel ...
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x414fd0b1]
...
[ 6.679449] Marvell 88Q2110 e6810000.ethernet-ffffffff:00: attached PHY driver [Marvell 88Q2110] (mii_bus:phy_addr=e6810000.ethernet-ffffffff:00, irq=POLL)
Poky (Yocto Project Reference Distro) 3.1.11 v4x ttySC0
v4x login:
参考:
官方解释:当您想记录工作目录和索引的当前状态,但又想返回一个干净的工作目录时,请使用git stash。该命令将保存本地修改,并恢复工作目录以匹配头部提交。
stash 命令能够将还未 commit 的代码存起来,让你的工作目录变得干净。
某一天你正在 feature 分支开发新需求,突然产品经理跑过来说线上有bug,必须马上修复。而此时你的功能开发到一半,于是你急忙想切到 master 分支。。。
# 保存当前未commit的代码
$ git stash
# 当你修复完线上问题,切回 feature 分支,想恢复代码时
$ git stash apply
相关命令
# 保存当前未commit的代码
$ git stash
# 保存当前未commit的代码并添加备注
$ git stash save "备注的内容"
# 列出stash的所有记录
$ git stash list
# 删除stash的所有记录
$ git stash clear
# 应用最近一次的stash
$ git stash apply
# 应用最近一次的stash,随后删除该记录
$ git stash pop
# 删除最近的一次stash
$ git stash drop
回退你已提交的 commit,并将 commit 的修改内容放回到暂存区。
一般我们在使用 reset 命令时,git reset –hard会被提及的比较多,它能让 commit 记录强制回溯到某一个节点。
而git reset –soft的作用正如其名,–soft(柔软的) 除了回溯节点外,还会保留节点的修改内容。
应用场景1:有时候手滑不小心把不该提交的内容 commit 了,这时想改回来,只能再 commit 一次,又多一条“黑历史”。
应用场景2:规范些的团队,一般对于 commit 的内容要求职责明确,颗粒度要细,便于后续出现问题排查。本来属于两块不同功能的修改,一起 commit 上去,这种就属于不规范。这次恰好又手滑了,一次性 commit 上去。
# 恢复最近一次 commit
$ git reset --soft HEAD^
reset –soft相当于后悔药,给你重新改过的机会。对于上面的场景,就可以再次修改重新提交,保持干净的 commit 记录。
以上说的是还未 push 的commit。对于已经 push 的 commit,也可以使用该命令,不过再次 push 时,由于远程分支和本地分支有差异,需要强制推送git push -f来覆盖被 reset 的 commit。
还有一点需要注意,在reset –soft指定 commit 号时,会将该 commit 到最近一次 commit 的所有修改内容全部恢复,而不是只针对该 commit。
将已经提交的 commit,复制出新的 commit 应用到分支里。
应用场景1:有时候版本的一些优化需求开发到一半,可能其中某一个开发完的需求要临时上,或者某些原因导致待开发的需求卡住了已开发完成的需求上线。这时候就需要把 commit 抽出来,单独处理。
应用场景2:有时候开发分支中的代码记录被污染了,导致开发分支合到线上分支有问题,这时就需要拉一条干净的开发分支,再从旧的开发分支中,把 commit 复制到新分支。
现在有一条feature分支,commit 记录如下:
commit a51cfd09f6f346a2b55226ba8a3aca53f35b9919 (HEAD -> support_ar0231_camera_moudle)
Author: tiezhuangdong <tiezhuang.dong.yh@renesas.com>
Date: Mon Aug 7 13:20:38 2023 +0800
add ar0231 init ----------- c
commit 3c613c4c9cf84a2c25f698c49a5750599bf7e7be
Author: tiezhuangdong <tiezhuang.dong.yh@renesas.com>
Date: Thu Jul 27 11:14:36 2023 +0800
only display camera link0 ----------- b
commit 1849850ea14dd31605f726418601492206822587 (tag: RECN_220629, origin/main, origin/HEAD, main)
Author: Tiezhuang Dong <tiezhuang.dong.yh@renesas.com>
Date: Thu May 12 02:56:06 2022 +0000
Add fatfs app for cr7 solution ----------- a
Signed-off-by: tiezhuangdong <tiezhuang.dong.yh@renesas.com>
需要把 b 复制到另一个分支,首先把 commitHash 复制下来,然后切到 main 分支。使用cherry-pick把 b 应用到当前分支。
$ git switch main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
$ git log
commit 1849850ea14dd31605f726418601492206822587 (HEAD -> main, tag: RECN_220629, origin/main, origin/HEAD)
Author: Tiezhuang Dong <tiezhuang.dong.yh@renesas.com>
Date: Thu May 12 02:56:06 2022 +0000
Add fatfs app for cr7 solution
Signed-off-by: tiezhuangdong <tiezhuang.dong.yh@renesas.com>
$ git cherry-pick 3c613c4c9cf84a2c25f698c49a5750599bf7e7be
以上是单个 commit 的复制,下面再来看看 cherry-pick 多个 commit 要如何操作。
$ git cherry-pick commit1 commit2
$ git cherry-pick commit1^..commit2
# 如果cherry-pick 提示 发生冲突
$ git cherry-pick commit1
# 解决冲突,重新提交到暂存区。
# 让cherry-pick继续进行下去
cherry-pick --continue
# 放弃 cherry-pick --- 回到操作前的样子,就像什么都没发生过。
$ git cherry-pick --abort
# 退出 cherry-pick --- 不回到操作前的样子。即保留已经cherry-pick成功的 commit,并退出cherry-pick流程。
$ git cherry-pick --quit
将现有的提交还原,恢复提交的内容,并生成一条还原记录。
有一天测试突然跟你说,你开发上线的功能有问题,需要马上撤回,否则会影响到系统使用。这时可能会想到用 reset 回退,可是你看了看分支上最新的提交还有其他同事的代码,用 reset 会把这部分代码也撤回了。由于情况紧急,又想不到好方法,还是任性的使用 reset,然后再让同事把他的代码合一遍(同事听到想打人),于是你的技术形象在同事眼里一落千丈。
commit a51cfd09f6f346a2b55226ba8a3aca53f35b9919 (HEAD -> support_ar0231_camera_moudle)
Author: tiezhuangdong <tiezhuang.dong.yh@renesas.com>
Date: Mon Aug 7 13:20:38 2023 +0800
add ar0231 init ----------- 同事的提交
commit 3c613c4c9cf84a2c25f698c49a5750599bf7e7be
Author: tiezhuangdong <tiezhuang.dong.yh@renesas.com>
Date: Thu Jul 27 11:14:36 2023 +0800
only display camera link0 ----------- 自己的提交
commit 1849850ea14dd31605f726418601492206822587 (tag: RECN_220629, origin/main, origin/HEAD, main)
Author: Tiezhuang Dong <tiezhuang.dong.yh@renesas.com>
Date: Thu May 12 02:56:06 2022 +0000
Add fatfs app for cr7 solution ----------- a
Signed-off-by: tiezhuangdong <tiezhuang.dong.yh@renesas.com>
# revert掉自己提交的commit
# 因为 revert 会生成一条新的提交记录,这时会让你编辑提交信息,编辑完后 :wq 保存退出就好了。
git revert 3c613c4c9cf84a2c25f698c49a5750599bf7e7be
# 看下最新的 log,生成了一条 revert 记录,虽然自己之前的提交记录还是会保留着,但你修改的代码内容已经被撤回了。
还是上面的log信息
# revert掉自己提交的commit
$ git revert 3c613c4c9cf84a2c25f698c49a5750599bf7e7be
# revert掉同事的提交
# 使用刚刚同样的 revert 方法,会发现命令行报错了。
# 通常无法 revert 合并,因为您不知道合并的哪一侧应被视为主线。此选项指定主线的父编号(从1开始),并允许 revert 反转相对于指定父编号的更改
$ git revert a51cfd09f6f346a2b55226ba8a3aca53f35b9919
# -m 后面要跟一个 parent number 标识出"主线",一般使用 1 保留主分支代码。
$ git revert -m 1 <commitHash>
revert 合并提交后,再次合并分支会失效
还是上面的场景,在 master 分支 revert 合并提交后,然后切到 feature 分支修复好 bug,再合并到 master 分支时,会发现之前被 revert 的修改内容没有重新合并进来。
因为使用 revert 后, feature 分支的 commit 还是会保留在 master 分支的记录中,当你再次合并进去时,git 判断有相同的 commitHash,就忽略了相关 commit 修改的内容。
这时就需要 revert 掉之前 revert 的合并提交,有点拗口,接下来看操作吧。
再次使用 revert,之前被 revert 的修改内容就又回来了。
此命令管理重录中记录的信息。
如果说reset –soft是后悔药,那 reflog 就是强力后悔药。它记录了所有的 commit 操作记录,便于错误操作后找回记录。
某天你眼花,发现自己在其他人分支提交了代码还推到远程分支,这时因为分支只有你的最新提交,就想着使用reset –hard,结果紧张不小心记错了 commitHash,reset 过头,把同事的 commit 搞没了。
没办法,reset –hard是强制回退的,找不到 commitHash 了,只能让同事从本地分支再推一次(同事瞬间拳头就硬了,怎么又是你)。于是,你的技术形象又一落千丈。
commit 8631553fbd0c8c3dfd321a9e1e927377d6c218d6 (HEAD -> master)
Author: ChanWahFung <552095989@qq.com>
Date: Sat Mar 5 21:10:56 2022 +0800
update(c):自己的错误提交
commit 1fc4ea10756198d4bc464a32b23b9cd1d091dd5b
Author: ChanWahFung <552095989@qq.com>
Date: Sat Mar 5 10:26:46 2022 +0800
update(b): b
commit 1a900ac29eba73ce817bf959f82ffcbøbfa38f75
Author: ChanWahFung <552095989@qq.com>
Date: Fri Mar 4 00:17:53 2022 +0800
update(a): a
分支记录如上,想要 reset 到 b。
误操作 reset 过头,b 没了,最新的只剩下 a。
# 这时用git reflog查看历史记录,把错误提交的那次 commitHash 记下。
$ git reflog
la900ac (HEAD -> Master) HEAD@{0}: reset:moving to 1a900ac29eba73ce81
8631553 HEAD@{1}: commit:update(c):自己的错误提交
# 再次 reset 回去,就会发现 b 回来了。
$ git reset --hard 8631553
HEAD is now at 8631553 update(c):自己的错误提交
$ git 1og
commit 8631553fbdøc8c3dfd321a9e1e927377d6c218d6 (HEAD ->master)
Author: ChanWahFung<552095989@qq.com>
Date: Sat Mar 5 21:10:56 2022 +0800
update(c):自己的错误提交
commit 1fc4ea10756198d4bc464a32b23b9cd1d091dd5b
Author:ChanWahFung<552095989@qq.com>
Date: Sat Mar 5 10:26:46 2022 +0800
update(b):b
commit 1a900ac29eba73ce817bf959f82ffcbobfa38f75
Author:ChanWahFung <552095989@qq.com>
Date: Fri Mar 4 00:17:53 2022 +0800
update(a):a
5个在开发中实用的 Git 命令:
存储临时代码。
软回溯,回退 commit 的同时保留修改内容。
复制 commit。
撤销 commit 的修改内容。
记录了 commit 的历史操作。
参考:
在.c中实现module_init和module_exit这两个函数,然后在module_init的函数里加个printk,输出个hello world。
把.c编译成.ko,然后insmod加载驱动,看到有打印,就算成功了。
加载dtb和.ko驱动,看到有打印,又成功了。心想,设备树应该就是这样吧。
要把一个.ko驱动在系统启动完成前就加载,这时才知道原来可以把命令放到/etc/init.d/rcS里。
作为驱动工程师,可以不用把文件系统了解的太深,但起码要知道inittab、rcS、passwd和shadow这几个文件的作用,还有就是前面说的C库。
rcS是文件系统启动时要执行的一些命令,inittab、passwd和shadow主要是修改系统登录时的用户名和密码,包括设置免密登录等等。
通常把文件系统提供给客户前,都会把用户名改为root,密码改为自己公司的名字,这时就会用到这几个文件。
Linux内核源码中每个目录下都有一个Makefile,我以为改个Makefile就行了。
但一运行,驱动没生效。后来才知道,原来还要修改Kconfig。
把驱动编进内核,其实正确的做法应该是通过menconfig菜单能够配置这个驱动是否编译,即修改Kconfig。
Makefile和Kconfig都修改了,驱动还是没生效?
这时就要看.o文件是否编译出来了,如果编译出来了。进一步看这个驱动的初始化级别,看是module_init、arch_initcall还是其他的级别。
然后加打印,把内核initcall的等级打印出来,看内核是否已经跑了该等级的初始化。如果已经跑到了,再把该等级的initcall执行函数的地址打印出来,然后反汇编vmlinux,看是否已经执行了新加驱动的probe函数。
编译内核时,通常都会用厂商提供的一个默认配置文件,例如make xxx_defconfig。
但是,如果我们想这个配置文件中加一个自己的宏,例如CONFIG_XXX=y,然后在代码中判断#ifdef CONFIG_XXX,你会发现并没有生效,并且原来写的CONFIG_XXX=y也没了。
这是很多新手改defconfig都会遇到的问题,其实是没有搞懂如何正确修改defconfig文件。
在defconfig中定义了CONFIG_XXX=y后,还要在Kconfig文件中添加一个config XXX的配置才会生效。
另外,如何某个配置选项存在依赖关系,但依赖的配置选项没打开,也会出现这种不生效的情况。
所以,还是建议通过menconfig菜单进行配置,除非真的弄清楚了这些关系,才能去手动修改defconfig。
虽然有一些比较有用的内核调试技巧,但真正常用的,还是加打印跟踪,其它调试技巧归根到底还是辅助性的,很多情况下还是靠加打印分析问题。
跟踪一些函数传参过程,关注是否正确使用、是否正确传参问题,因为最终解决问题可能只是一个很简单的操作。
会多少驱动,这其实是一个进阶的过程。没有说一定要会多少个,但随着工作经验的增长,自身所掌握的驱动也会越来越多,承担的责任也越大。
参考:
图像采集的过程为:光照在成像物体被反射 -> 镜头汇聚 -> Sensor光电转换-> ADC转换为rawRGB。
因为sensor上每个像素只采集特定颜色的光的强度,因此sensor每个像素只能为R或G或B,形成的数据就成为了rawRGB数据。
rawRGB数据是sensor的经过光电转换后通过ADC采样后直接输出数据,是未经处理过的数据,表示sensor接受到的各种光的强度。
Raw数据在输出的时候是有一定的顺序的,一般为以下四种: 00:GR/BG 01: RG/GB 10: BG/GR 11: GB/RG
为什么每种情况里有两个G分量呢?这时因为人的眼睛对绿色比较敏感,所以增加了对绿色的采样。其中每个分量代表一个piexl。所以GR/BG就代表四个piexl,在物理sensor上就表示4个晶体管,用一个晶体管只采样一个颜色分量,然后通过插值计算得到每个piexl,这样做的主要目的是降低功耗。
假设一个sensor的像素是88(分辨率为88),那么这个sensor就有8*8个感光点,每个感光点就是一个晶体管。那么对于上表中四种排列格式的rawRGB数据如下图所示:
由上图可以看出,每一种格式的rawRGB数据的G分量都是B、R分量的两倍,是因为人眼对于绿色的更加敏感,所以加重了其在感光点的权重,增加了对绿色信息的采样。
那么,这里还有一个问题:在rawRGB数据中,每个像素只有R、G、B颜色三分量中一个分量,那么这一个分量用多少bit来表示呢?答案如下表:
之所以有个rawRGB这种格式的数据,这样做的目的一般是为了降低感光器件的物理工艺难度,然后通过ISP处理还原出更真实的图像信息。
sensor输出的数据一般要送到ISP中处理才会得到一个好的效果,这就需要ISP知道sensor输出的raw数据的顺序与大小,其中顺序一般通过配置ISP的pattern寄存器来实现,大小一般配置在ISP的输入格式控制寄存器中。
raw数据几种常用的格式:
RAW8: Raw8即是用8bits表示G/R/B/G中的一个分量,而不是使用8bits表示RG/GB四个分量。在sensor中,为了降低功耗,使用一个晶体来表示一种颜色,然后利用差值计算出相邻像素的值。
Raw10: Raw10就是使用10bit表示上述的一个G/R/B/G,但是数据中是16bit的,高6位没用。
Raw12: Raw12: 就是使用12bit表示上述的一个G/R/B/G,但是数据中是16bit的,高4位没用
看raw数据的工具:picasa、irfanview、photoshop
在数字化的时代,需要一种标准来量化自然界的各种颜色。RGB就是一种在数字化领域表示颜色的标准,也称作一种色彩空间,通过用三原色R、G、B的不同的亮度值组合来表示某一种具体的颜色。注意,RGB里面存的是颜色的亮度值,而不是色度值。
在实际应用中,RGB存在着许多的格式,之所以存在着这些格式,是因为随着技术的进步,系统的更迭,不同的应用场景和设备环境,对颜色表达的需求是不同的。
常用的RGB格式如下表所示:
格式 | 描述 |
---|---|
RGB565 | 每个像素用16位表示,RGB分量分别使用5位、6位、5位。 内存中排列(高字节->低字节):R R R R R G G G G G G B B B B B |
RGB555 | 每个像素用16位表示,RGB分量都使用5位(剩下1位不用) 内存中排列(高字节->低字节):X R R R R G G G G G B B B B B(X表示不用,可以忽略) |
RGB24(RGB888) | 每个像素用24位表示,RGB分量各使用8位。 内存中排列(高字节->低字节):B B B B B B B B G G G G G G G G R R R R R R R R |
RGB32 | 每个像素用32位表示,RGB分量各使用8位(剩下8位不用) 内存中排列(高字节->低字节):B B B B B B B B G G G G G G G G R R R R R R R R X X X X X X X X (X表示不用,可以忽略) |
ARGB32 | 每个像素用32位表示,RGB分量各使用8位(剩下的8位用于表示Alpha通道值) 内存中排列(高字节->低字节):B B B B B B B B G G G G G G G G R R R R R R R R A A A A A A A A |
YUV是一种色彩编码方法,Y表示亮度,U和V表示色度。只有Y就是黑白图像,再加上UV就是彩色图像了。YUV的一个好处就是让彩色系统和传统黑白系统很好的兼容,同时利用了人类视觉系统对亮度的敏感度比对色度高。
在一般应用中,人们所说的YUV就是YCbCr,这我认为是从狭义的角度理解(毕竟现在是数字信号的天下,YCbCr恰好是描述数字信号的)。广义上说,YUV是一种色彩空间分类,一种颜色模型,具体的类型有Y’UV, YUV, YCbCr,YPbPr等,目前市场上常用数字的视频信号和视频/图片文件中的编码格式,用YCbCr来描述,于是人们口中的YUV就代指的是YCbCr,常见应用如H.264/H.265码流、MPEG、JPEG等。
YCbCr中的Cb指蓝色色度分量,而Cr指红色色度分量。
YUV和RGB的相同点:都是用来表达颜色的数学方法;
YUV和RGB的相同点:对颜色的描述思路和方法不同。RGB将一个颜色拆解为3个纯色的亮度组合,YUV将一个颜色分解为一个亮度和2个色度的组合。
那引入YUV这种色彩空间的好处具体有啥呢?
(1)YUV提取Y亮度信号,可以直接给黑白电视使用,兼容黑白电视
(2)人眼对UV的敏感性小于亮度,这样我们适当减少uv的量,而不影响人的感官。所以才会有多种格式的 YUV描述,如420、422、444。
(3)伴随显示设备分辨率的提升,bt组织也针对yuv2rgb设定了不同的系数,来最好的从YUV转换到RGB。
(4)YUV格式可以比RGB格式储存空间小。
那RGB存在的作用是什么呢?
目前人类发明的所有彩色的输入输出设备,本质上都只支持RGB数据。哪怕设备允许YUV的输入输出,那也是经过内部的数据转换而间接支持。
(1)YUV 4:4:4 采样
全采样,对每个像素点的的YUV分量都进行采样,这样的三个分量信息量完整。
(2)YUV 4:2:2 采样
部分采样,可节省1/3存储空间和1/3的数据传输量。UV分量是Y分量采样的一半,Y分量和UV 分量按照2 : 1的比例采样。如果水平方向有10个像素点,那么采样了10个Y分量,而只采样了5个UV分量。其中,每采样过一个像素点,都会采样其Y分量,而U、V分量就会间隔一个采集一个。
(3)YUV 4:2:0 采样
部分采样,可节省1/2存储空间和1/2的数据传输量。YUV 420采样,并不是指只采样U分量而不采样V分量。而是指,在每一行扫描时,只扫描一种色度分量(U或者V),和Y分量按照2 : 1的方式采样。比如,第一行扫描时,YU 按照 2 : 1的方式采样,那么第二行扫描时,YV分量按照 2:1的方式采样。对于每个色度分量来说,它的水平方向和竖直方向的采样和Y分量相比都是2:1 。
YUV存储格式通常有两大类:打包(packed)格式和平面(planar)格式。前者将YUV分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel);而后者使用三个数组分开放 YUV 三个分量,就像是一个三维平面一样。
(1) YUV422 Planar (YUV422P,也称为I422格式)
这里,Y\U\V数据是分开存放的,每两个水平Y采样点,有一个U和一个V采样点,如下图:
也就是说,U0V0由Y0、Y1共用,这样整幅图像较RGB就减少了1/3的存储空间。
YUV 422P 格式,又叫做 I422格式,采用的是平面格式进行存储,先存储所有的 Y 分量,再存储所有的 U 分量,再存储所有的 V 分量。
假如一个8*2像素的图像的该格式的存储分布如下图:
(2) YUV422 packed
此格式有两种情况:分为YUYV格式和UYVY格式。
YUYV格式:
YUYV 格式是采用打包格式进行存储的,指每个像素点都采用 Y 分量,但是每隔一个像素采样它的UV分量。
假如一个8*2像素的图像的该格式的存储分布如下图:
UYVY格式:
UYVY 格式也是采用打包格式进行存储,它的顺序和YUYV相反,先采用U分量再采样Y分量。
假如一个8*2像素的图像的该格式的存储分布如下图:
(3) YUV420 Planar (YUV420P)
这个格式跟YUV422 Planar 类似,但对于U和V的采样在水平和垂直方向都减少为2:1,根据采样规则如下图:
也就是说,U0V0由Y0、Y1、YW、YW+1共用,这样整幅图像较RGB就减少了1/2的存储空间。
YU12和YV12格式都属于YUV 420P类型,即先存储Y分量,再存储U、V 分量,区别在于:YU12是先Y再U后V,而YV12是先Y再V后U 。
YU12格式(也称为I420格式)
YU12是先Y再U后V。
假如一个8*2像素的图像的该格式的存储分布如下图:
YV12格式
YV12是先Y再V后U
假如一个8*2像素的图像的该格式的存储分布如下图:
(4) YUV422 Semi-Planar (YUV422SP)
Semi 是“半”的意思,个人理解这个是半平面模式,这个格式的数据量跟YUV422 Planar的一样,但是U、V是交叉存放的。
假如一个8*2像素的图像的该格式的存储分布如下图:
(5) YUV420 Semi-Planar (YUV420SP)
这个格式的数据量跟YUV420 Planar的一样,但是U、V是交叉存放的。
NV12和NV21格式都属于 YUV420SP 类型。它也是先存储了Y分量,但接下来并不是再存储所有的U或者V分量,而是把UV分量交替连续存储。
NV12
NV12是IOS中有的模式,它的存储顺序是先存Y分量,再UV进行交替存储。
假如一个8*2像素的图像的该格式的存储分布如下图:
NV21
NV21是安卓中有的模式,它的存储顺序是先存Y分量,在VU交替存储。
假如一个8*2像素的图像的该格式的存储分布如下图:
由于YUV有这数字信号和模拟信号的YUV类型,于是RGB与YUV转换方式多种多样,大致分为模拟和数字两种。每种方式下,不同的清晰度视频信号的转换公式也是有所不同。
这里仅仅列出数字YUV(YCbCr)与数字RGB相互转换的BT601(标清国际定义)的转换公式:
“汽车芯片”(FuSa,Security)与“人身安全”密切相关
汽车芯片,有明显的领域应用特色,有门槛要求。
像手机、消费品芯片强行进入该行业,要持有谨慎态度。
从“参数内卷(Parametric In-Roll)”(智能驾驶——高精度地图、激光雷达、高算力芯片)向“落地/注重体验”转变
从“感知(Perception)”到“认知(Cognition)”,感知足够,认知还不成。
终究,美梦还是会屈从于现实。
从“简单”(卡车、巴士、物流)向“复杂”(自动驾驶)的发展路线,不会被颠覆
总想背离基本的逻辑,却被时间教训的服服帖帖。
目前看,发展趋势
功能合并-》域控-》自动驾驶,趋势不可避免。
汽车应用——
座舱 —— Renesas-Gen3、Gen3e
智驾 —— Renesas-V4H
网联 —— Renesas-S4