15AH, San Francisco

California, United States.

Send Your Mail At:

tianyingkejishe@sina.cn

Working Hours

Mon-Sat: 9.30am To 7.00pm

作者标题

Autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et dolore feugait.

Author Archive by stormwind

【Openwrt】lua的cgi响应 lua中获取GET/POST数据

一、lua的cgi响应 lua中获取GET/POST数据:

  1. 安装uhttpd包(https需要加装“uhttpd-mod-tls”和“px5g”);
  2. 修改uhttpd配置文件“/etc/config/uhttpd”,将Lua作为“interpreter”;
  3. Lua脚本写到“/www/cgi-bin/”目录下,但是不带扩展名,且可执行;
  4. Fast-CGI要求Lua脚本必须首先使用“io.write()”输出“Content-type: text/html\n\n”
  5. “/www/cgi-bin/”目录下的脚本可以调用“/usr/lib/lua/”目录下的自定义模块;
  6. Lua环境已经就绪。

二、以“读取GET和POST数据”为例,全部使用默认值的情况下,如何具体实现:

第一步:使用“opkg update”更新“.ipk”包的源,然后使用“opkg install uhttpd”安装;

第二步:使用“vi /etc/config/uhttpd”,在“config uhttpd main”下添加一行

list interpreter '.lua=/usr/bin/lua'

第三步:建立目录“/www/cgi-bin”,并增加“+x”属性;

root@OpenWrt:~# mkdir -p /www/cgi-bin/
root@OpenWrt:~# chmod +x /www/cgi-bin/

建立响应文件,并增加“+x”属性;

root@OpenWrt:~# touch /www/cgi-bin/webservice
root@OpenWrt:~# chmod +x /www/cgi-bin/webservice

将文件“/www/cgi-bin/webservice”内容修改为:

#!/usr/bin/lua
local WebService = require 'WebService'
WebService.Run()

第四步:建立Lua模块文件(不再要求“+x”属性),并读取参数,返回响应:

root@OpenWrt:~# touch /usr/lib/lua/WebService.lua

将其内容修改为如下内容:

local WebService = {}
 
function WebService.Run()
    local client = os.getenv("REMOTE_ADDR")
    local GET = os.getenv("QUERY_STRING")
    local POST = nil
    local POSTLength = tonumber(os.getenv("CONTENT_LENGTH")) or 0
    if (POSTLength > 0) then
        POST = io.read(POSTLength)
        --POST = io.read("*a")
    end
 
    -- Fast-CGI+HTTP require HEADER
    -- enable cache
    --io.write("Content-type: text/html\n\n")
    -- disable cache, especially for Internet Explorer
    io.write("Content-type: text/html\nPragma: no-cache\n\n")
 
    local reply = string.format("Client %s said: url: [%s], data: [%s]\n", client or '-', GET or '-', POST or '-')
    io.write(reply)
end
 
return WebService

第五步:重启“uhttpd”服务(为了让更改的/etc/config/uhttpd生效):

root@OpenWrt:~# /etc/init.d/uhttpd restart

第六步:使用浏览器测试:

使用浏览器访问如下地址:

http://<openwrt_ipaddr>/cgi-bin/webservice?author=qige

这里假设OpenWrt开发板的IP为192.168.1.24:

http://192.168.1.1/cgi-bin/webservice?author=qige

最终效果如下图:

通过cUrl模拟POST提交

通过form表单POST提交的浏览器结果

注意:

  1. POST数据可以由curl、Python requests等进行模拟提交,也可以自制如:<form action=”/cgi-bin/webservice” method=”POST”>提交;
  2. 根据Fast-CGI要求,必须要先使用“io.write()”输出http协议头部;再根据http协议的要求,头部和内容之间必须使用“\n\n”来隔开。因此Lua脚本必须先输出头部“Content-type: text/html\n\n”,再输出其它内容;
  3. 如果“不需要缓存”,输出立即过期,则修改头部内容为“Content-type: text/html\nPragma: no-cache\n\n”;
  4. 让uhttpd开机自动启动,需要执行“/etc/init.d/uhttpd enable”;
  5. 需要将接收到的数据输出到串口,可以再安装一个“coreutils-stty”包用于控制串口波特率
root@OpenWrt:~# opkg install coreutils
root@OpenWrt:~# opkg install coreutils-stty

再将以下内容添加到Lua模块的适当位置,并调用此函数即可:

function WebService.uartWrite(msg)
    local uartConfig = 'stty -F /dev/ttyS0 raw speed 9600\n'
    os.execute(uartConfig)
 
    local cmd = string.format("echo '%s' > /dev/ttyS0\n", msg or '')
    os.execute(cmd)
end

【ffmpeg】error: #20: identifier “AVBitStreamFilterContext” is undefined

av_bitstream_filter_init 丢弃
老版本:

//声明:	
AVBitStreamFilterContext* h264bsfc =  av_bitstream_filter_init("h264_mp4toannexb"); 
//使用
av_bitstream_filter_filter(h264bsfc, in_stream->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0);
//释放:
av_bitstream_filter_close(h264bsfc);  

新版本:

//声明  
AVBSFContext *bsf_ctx = nullptr;
const AVBitStreamFilter *pfilter = av_bsf_get_by_name("h264_mp4toannexb");
av_bsf_alloc(pfilter, &bsf_ctx);
//使用:
av_bsf_send_packet(bsf_ctx, &packet);
av_bsf_receive_packet(bsf_ctx, &packet);
//释放:
av_bsf_free(&bsf_ctx);

【uboot】通过uboot指令实现GPIO控制

一:在uboot下的defconfig 打开如下配置

CONFIG_DM=y
CONFIG_DM_GPIO=y
CONFIG_DWAPB_GPIO=y
CONFIG_CMD_GPIO=y

二:重新编译u-boot后会生成cmd:gpio

(板子上电时连续按回车键)进入到板端uboot cmdline下执行” gpio status -a ” 查看板端对应的gpio numbe

三:利用 uboot gpio 命令操作GPIO 做测试

  • gpio c 0 ; 将第0根PIN清零(拉低)
  • gpio s 0 ; 将第0根PIN设为output同时拉高

四:gpio 操作demo

直接以下demo code添加到uboot/cmd路径下,再在uboot/cmd/Makefile中添加编译选项,编译完成后可以直接操作gpio

#include <command.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <asm/gpio.h>

int do_gpio_test(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
{
    if (argc < 2) {
        printf("usage: gpio_test [requ/out/on/off]\n");
        return 0;
    }

    if (strcmp("requ", argv[1]) == 0) {
        gpio_request(126, "ir_a");
        gpio_request(127, "ir_b");
        mdelay(10);
    } else if (strcmp("out", argv[1]) == 0) {
        gpio_direction_output(126, 1);
        gpio_direction_output(127, 1);
        mdelay(10);
    } else if (strcmp("on", argv[1]) == 0) {
        gpio_set_value(126, 0);
        gpio_set_value(127, 1);
        mdelay(100);
        gpio_set_value(126, 1);
        gpio_set_value(127, 1);
    } else if (strcmp("off", argv[1]) == 0) {
        gpio_set_value(126, 1);
        gpio_set_value(127, 0);
        mdelay(100);
        gpio_set_value(126, 1);
        gpio_set_value(127, 1);
    }

    return 0;
}

U_BOOT_CMD(
    gpio_test, 4, 1, do_gpio_test,
    "u-boot gpio cmd test",
    "gpio - just for test\n"
);

五、测试

编译完成升级后,进入到uboot会有gpio_test命令
gpio_test requ
初始化gpio
gpio_test out
设置gpio direction
gpio_test on
设置 ir_cur (的两根PIN) 状态

【图像】YUV 常用图像格式 NV12、NV2、I420、YV12、YUYV 像素分布

常用图像像素格式 RGB 和 YUV
近期由于项目需要,开始接触图像像素格式,因此在这里做一个小结。

像素格式描述了像素数据存储所用的格式,定义了像素在内存中的编码方式。RGB 和 YUV 为两种经常使用的像素格式。

RGB 和 RGBA 格式
RGB 图像具有三个通道 R、G、B,分别对应红、绿、蓝三个分量,由三个分量的值决定颜色,一般也叫做 RGB24;
RGBA 是 RGB 图像加一个通道 alpha,即透明度,于是共有四个分量共同控制颜色,一般也叫做 RGB32。

YUV 格式
YUV 图像是指将亮度参量 Y 和色度参量 U/V 分开表示的像素格式,主要用于优化彩色视频信号的传输。
YUV 像素格式来源于 RGB 像素格式,通过公式运算,YUV 三分量可以还原出 RGB,YUV 转 RGB 的公式如下:

    R = Y + 1.403V
    G = Y - 0.344U - 0.714V
    B = Y + 1.770U

一般,将 RGB 和 YUV 的范围均限制在 [0, 255] 间,则有如下转换公式:

R = Y + 1.403(V - 128)
G = Y - 0.344(U - 128) - 0.714(V - 128)
B = Y + 1.770(U - 128)

鉴于 RGB 格式已经见得见多,本文主要总结 YUV 常见的几种像素格式。

YUV 采样
YUV 相比于 RGB 格式最大的好处是可以做到在保持图像质量降低不明显的前提下,减小文件大小。YUV 格式之所以能够做到,是因为进行了采样操作。

YUV 码流的存储格式与其采样方式密切相关,主流的采样方式有三种:YUV 4:4:4(YUV444),YUV 4:2:2(YUV422),YUV 4:2:0(YUV420)。

若以以黑点表示采样该像素点的 Y 分量,以空心圆圈表示采用该像素点的 UV 分量,则这三种采样方式如下:

即:

YUV 4:4:4 采样,每一个 Y 对应一组 UV 分量。
YUV 4:2:2 采样,每两个 Y 共用一组 UV 分量。
YUV 4:2:0 采样,每四个 Y 共用一组 UV 分量。
YUV 存储格式
YUV 存储可以分为两种:packed(打包)和 planar(平面);

packed:Y、U、V 分量穿插着排列,三个分量存在一个 Byte 型数组里;

planar:Y、U、V 分量分别存在三个 Byte 型数组中;

常见的像素格式
YUV422:YUYV、YVYU、UYVY、VYUY
这四种格式每一种又可以分为 2 类(packed和planar),以 YUYV 为例,一个 6*4 的图像的存储方式如下:

	Y Y Y Y Y Y                   
	Y Y Y Y Y Y                  
	Y Y Y Y Y Y                   
	Y Y Y Y Y Y                    
	U U U U U U                  Y U Y V Y U Y V Y U Y V
	U U U U U U                  Y U Y V Y U Y V Y U Y V
        V V V V V V                  Y U Y V Y U Y V Y U Y V
	V V V V V V                  Y U Y V Y U Y V Y U Y V
	- Planar -                          - Packed - 

YUV420:I420(YU12)、YV12、NV12、NV21

  • YUV420p: I420、YV12
  • YUV420sp: NV12、NV21

同样,对于一个6*4的图像,这四种像素格式的存储方式如下:

	Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y
	Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y
	Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y
	Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y      Y Y Y Y Y Y
	U U U U U U      V V V V V V      U V U V U V      V U V U V U
	V V V V V V      U U U U U U      U V U V U V      V U V U V U
     - I420 -          - YV12 -         - NV12 -         - NV21 -
  • I420、YV12 三个分量均为平面格式,即分别存在三个数组中;
  • NV12、NV21 的存储格式为 Y 平面,UV 打包,即 Y 信息存储在一个数组中,UV 信息存储在一个另一个数组中。

【shell】脚本实现字符串操作

1、获取字符串长度

abc="huihuiuhiihu"
echo ${#abc}

利用#号实现字符串长度统计

2、截取字符串内容

${hui:5}

利用:加数字的形式截取固定长度字符串内容

3、实现固定长度字符串拼接

hui="sssdsdsdsjkdhskhdksd"
abc="12346"
kji=${abc}${hui:${#abc}}

echo $kji

【Lx2160】双系统启动设计

一、启动分析

uboot启动后会通过检测lx2160ardb_boot.scr配置文件,实现默认启动引导。此系列芯片引导方式一样。

打开./configs/board/lx2160ardb_rev2/manifest文件分析

vim ./configs/board/lx2160ardb_rev2/manifest
distroboot=\
'env exists dtb || setenv dtb fsl-lx2160a-rdb.dtb;'\
'env exists kernel_image || setenv kernel_image Image;'\
'env exists devpart_boot || setenv devpart_boot 2;'\
'env exists devpart_root || setenv devpart_root 4;'\
'part uuid $devtype $devnum:$devpart_root partuuidr;'\
'setenv bootargs console=ttyAMA0,115200 earlycon=pl011,mmio32,0x21c0000 root=PARTUUID=$partuuidr rw rootwait pci=pcie_bus_perf $othbootargs;'\
'load $devtype $devnum:$devpart_boot $kernel_addr_r $kernel_image;'\
'load $devtype $devnum:$devpart_boot $fdt_addr_r $dtb;'\
'env exists secureboot && echo validating secureboot && run secureboot_validate;'\
'booti $kernel_addr_r - $fdt_addr_r'


distroboot_ima=\
'env exists dtb || setenv dtb fsl-lx2160a-rdb.dtb;'\
'env exists kernel_image || setenv kernel_image Image;'\
'env exists devpart_boot || setenv devpart_boot 2;'\
'env exists devpart_root || setenv devpart_root 4;'\
'part uuid $devtype $devnum:$devpart_root partuuidr;'\
'load $devtype $devnum:$devpart_boot $kernel_addr_r $kernel_image;'\
'load $devtype $devnum:$devpart_boot $fdt_addr_r $dtb;'\
'setenv initramfs_addr_r 0xb0000000; setenv initramfsheader_addr_r 0x80300000;'\
'load $devtype $devnum:$devpart_boot $initramfs_addr_r initramfs.img;'\
'env exists secureboot && echo validating secureboot && run secureboot_validate;'\
'setenv bootargs console=ttyAMA0,115200 earlycon=pl011,mmio32,0x21c0000 root=PARTUUID=$partuuidr rw rootwait pci=pcie_bus_perf $othbootargs;'\
'booti $kernel_addr_r $initramfs_addr_r $fdt_addr_r'

通过分析配置文件,发现Linux和rootfs的引导取决于devpart_boot和devpart_root两个变量,所以通过修改这两个变量值,便可动态实现,分区引导切换。

二、手动引导切换

进入uboot命令行

setenv devpart_boot  2
setenv devpart_root  4
saveenv

2和4代表分区号

三、动态引导切换

如实现动态引导切换需要通过fw_env工具实现。请参照《fw-env开启文件系统设置uboot环境变量》http://www.recologypower.com:9080/?p=1247

四、分区处理

flex-installer -i pf -p 6P=200M:1536M:128M:13G:1536M:-1 -d /dev/sdx

五、烧录程序