DM365上运行jpegdec程序记录
1. 说明
DVSDK版本:dvsdk_2_10_00_17
路径:ROOTDIR = /opt/dvsdk_2_10_00_17/dm365_codecs_01_00_06/packages/ti/sdo/codecs/jpegdec/
源代码:$(ROOTDIR)/apps/Client/Test/Src
头文件:$(ROOTDIR)/apps/Client/Test/Inc
2. 源代码部分
关于源代码可以简单看一下jpgdTestApp.c
而头文件需要注意定义内存大小的地方,如:testFramework.h
其中一段:
#define MAX_WIDTH 1280
#define MAX_HEIGHT 960
#define JPEG_MAX_NUM_JPEG_BYTES (3*MAX_WIDTH*MAX_HEIGHT) // Max stream size 1M byte
#define RINGBUF_SIZE (1024*4096) // (20*4096) // Ring buffer size
#define JPEG_MAX_NUM_YCC_BYTES (3*MAX_WIDTH*MAX_HEIGHT)
#define AIM_START_ADDRESS (0x10000)
#define INTERNAL_DATA_MEM_SIZE (4096)
#define EXTERNAL_DATA_MEM_SIZE (16*1024)
#define JPEG_MAX_NUM_RGB_BUFFER_LINES (16)
#define JPEG_MAX_NUM_SAMPLES_PER_LINE (5000+32) // Width
#define STRING_SIZE 256 //!< Size of strings used for filenames
应用在jpgdTestApp.c中,如:
CMEM_init();
ExternalGlobalMemPool = ExternalGlobalMemPoolBase = CMEM_alloc(EXTERNAL_DATA_MEM_SIZE,&memParams);
ringbuf = CMEM_alloc(RINGBUF_SIZE,&memParams);
bJpegStream = CMEM_alloc(JPEG_MAX_NUM_JPEG_BYTES,&memParams);
bDecodedYCC = CMEM_alloc(JPEG_MAX_NUM_YCC_BYTES,&memParams);
从上面代码可以看出:
需要4块连续内存,即CMEM,如下:
EXTERNAL_DATA_MEM_SIZE: 16*1024 = 16384
RINGBUF_SIZE: 1024*4096 = 4194304
JPEG_MAX_NUM_JPEG_BYTES: 3*1280*960 = 3686400
JPEG_MAX_NUM_YCC_BYTES: 3*1280*960 = 3686400
3. 写loadmodules.sh脚本
#!/bin/sh
rmmod cmemk 2>/dev/null
rmmod irqk 2>/dev/null
rmmod edmak 2>/dev/null
rmmod dm365mmap 2>/dev/null
# Pools configuration
#insmod cmemk.ko phys_start=0x85000000 phys_end=0x88000000 pools=6x4096,2x8192,1x11908,2x13184,1x2697152,6x4096,1x30720,3x81920, 1x3185664,64x56,1x320,1x640,1x81920,1x6650880,2x608,1x296,1x28,2x24,23x1548288,1x154288,2x3686400 allowOverlap=1 phys_start_1=0x00001000 phys_end_1=0x00008000 pools_1=1x28672
#上面注释的是demo演示程序中的配置,下面是根据分析写的3个pool,虽然物理地址不需要那么多,先写着。
insmod cmemk.ko phys_start=0x85000000 phys_end=0x88000000 pools=1x16384,1x4194304,2x3686400
insmod irqk.ko
insmod edmak.ko
insmod dm365mmap.ko
4. 准备运行
4.1. 修改Testvecs.cfg文件
2
./TestVecs/Config/Testparams.cfg
./TestVecs/Input/frida_720x480.jpeg
./TestVecs/Input/frida_720x480_dec.yuv
而Testparams.cfg文件中的宽度和长度分别是720x480,所以不用修改。
4.2. 修改源代码并进行编译
修改jpgdTestApp.c的第261行代码如下:
Int8 *fileCfgName = "./TestVecs/Config/Testvecs.cfg";
Int8 *fileLogName = "./TestVecs/Config/log.txt";
先执行make clean
再make
注:直接make不行,因为有几个c文件的时间戳是未来的,就不编译了。
最后会生成jpgdec-r可执行文件。
4.3. 所需文件
如果在ARM端运行,则需要的文件如下:
Testparams.cfg Testvecs.cfg JPG文件
下面是本人的文件结构:
myJpgDec
|-jpgdec-r
|-TestVecs
| |-Config
| | |-Testparams.cfg
| | |-Testvecs.cfg
| |-Input
| | |-frida_720x480.jpeg
| |-Output
| |-module
| | |-cmemk.ko
| | |-dm365mmap.ko
| | |-edmak.ko
| | |-irqk.ko
| | |-loadmodules.sh
注:如果你找不到cmemk.ko、dm365mmap.ko、edmak.ko、irqk.ko等4个文件,启动365板子,在demo演示程序中就有,直接拿来用就可以了。但是loadmodules.sh文件需修改过,见第3章。
5. 开始运行
如何在365板子上运行,有几种方法:
1. 把myJpgDec打包,通过网络(tftp)下载下去,在板子上解压,然后运行。
2. 考虑到nandflash的大小只有128MB,启动板子,然后用df -h命令查看,可用的也就37MB左右,所以不建议在flash上运行。那么有两种方法:
1) 在U盘或SD卡上运行
2) 挂载nfs
下面分别介绍两种方式的挂载:
1. 挂载U盘
插入U盘,默认的Linux内核中有驱动,所以能自动识别出来。但是会一直停在那里,用(CTRL+C)退出。
然后使用下面命令进行查看:
# fdisk -l /dev/sda
本人2G的朗科U盘,显示如下:
Disk /dev/sda: 2003 MB, 2003828736 bytes
...
注:试过有些U盘显示的是Disk /dev/sda1:
下面根据上面的显示,进行挂载:
# mount -t msdos /dev/sda /mnt/usb (fat16格式)
# mount -t vfat /dev/sda /mnt/usb (fat32格式)
# mount -t ext2 /dev/sda /mnt/usb (ext2格式)
2. 挂载NFS
命令如下:
# mount -t nfs 192.168.1.109:/opt/nfs /nfsclient/
如果出现下列错误:
mount: RPC: Program not registered
请重启Linux服务器端的nfsserver:
# /etc/init.d/nfsserver restart
关于Linux服务器端的NFSServer建立,这里不讲。
运行比较简单:(如挂载U盘)
# mount -t vfat /dev/sda /mnt/usb
# cd /mnt/usb/myJpgDec/
# cd module
# ./loadmodules.sh
# cd ../
# ./jpgdec-r
6. 进行200万像素的JPEG图片解码
因工作需要,需要对200万像素和500万像素的JPG图片进行编解码。
200万像素的图片大小为1600x1200。
500万像素的图片大小为2448x2048。
6.1. 单张200万像素的JPG图片解码
1. 修改Testvecs.cfg文件,如下:
2
./TestVecs/Config/Testparams.cfg
./TestVecs/Input/pic2m_001.jpg
./TestVecs/Input/pic2m_001_dec.yuv
2. 修改Testparams.cfg文件,如下:
Resize = 0 # 0: No resizing, 1: resize by 1/8, 2: resize by 2/8, etc
DisplayWidth = 0 # 0: display width = image output width
rotation = 0
areaDecode = 0
maxWidth = 1600
maxHeight = 1200
# forceChromaFormat = 4 # 4: 422
forceChromaFormat = 9 # 9: 420
dataEndianness = 1
subRegionUpLeftY = 0
subRegionUpLeftX = 0
subRegionDownRightX = 0
subRegionDownRightY = 0
3. 在Input目录下添加JPG文件。
4. 开始运行:(为调试方便,以下测试都是挂载NFS的方式)
# mount -t nfs 192.168.1.109:/opt/nfs /nfsclient/
# cd /nfsclient/myJpgDec/
# cd module
# ./loadmodules.sh
# cd ../
# ./jpgdec-r
解码成功。
6.2. 多张200万像素JPG图片的解码
1. 修改Testvecs.cfg文件,如下:
2
./TestVecs/Config/Testparams.cfg
./TestVecs/Input/pic2m_001.jpg
./TestVecs/Input/pic2m_001_dec.yuv
./TestVecs/Config/Testparams.cfg
./TestVecs/Input/pic2m_002.jpg
./TestVecs/Input/pic2m_002_dec.yuv
./TestVecs/Config/Testparams.cfg
./TestVecs/Input/pic2m_003.jpg
./TestVecs/Input/pic2m_003_dec.yuv
...
./TestVecs/Config/Testparams.cfg
./TestVecs/Input/pic2m_017.jpg
./TestVecs/Input/pic2m_017_dec.yuv
2. 在Input目录中添加JPG图片。
3. 运行
惊喜,17张图片解码成功。
7. 进行500万像素的JPEG图片解码
500万像素的图片大小为2448x2048。
7.1. 单张500万像素的JPG图片解码
1. 修改Testvecs.cfg文件,如下:
2
./TestVecs/Config/Testparams.cfg
./TestVecs/Input/pic5m_001.jpg
./TestVecs/Input/pic5m_001_dec.yuv
2. 修改Testparams.cfg文件,如下:
Resize = 0 # 0: No resizing, 1: resize by 1/8, 2: resize by 2/8, etc
DisplayWidth = 0 # 0: display width = image output width
rotation = 0
areaDecode = 0
maxWidth = 2448
maxHeight = 2048
# forceChromaFormat = 4 # 4: 422
forceChromaFormat = 9 # 9: 420
dataEndianness = 1
subRegionUpLeftY = 0
subRegionUpLeftX = 0
subRegionDownRightX = 0
subRegionDownRightY = 0
3. 在Input目录下添加JPG文件。
4. 开始运行,出现错误,如下:
*******************************************
Read Configuration Set 1
*******************************************
Opened file ./TestVecs/Input/pic5m_001.jpg
FileSize = 502832, Reading file ...done
CMEMK Error: get_phys: Unable to find phys addr for 0x40f97000
CMEMK Error: get_phys: get_user_pages() failed: -14
CMEMK Error: GETPHYS: Failed to convert virtual 0x40f97000 to physical.
CMEMK Error: get_phys: Unable to find phys addr for 0x40f97000
CMEM Error: getPCMEMK Error: get_phys: get_user_pages() failed: -14
hys: Failed to gCMEMK Error: GETPHYS: Failed to convert virtual 0x40f97000 to physical.
et physical address of 0x40f97000
CMEM Error: getPhys: Failed to get physical address of 0x40f97000
!!!! Error during jpeg decode !!!!
End of test
突然出现这么个问题,一点头绪都没有,google了一阵,确实有很多人遇到过此类问题,但是真正给出解答的却没有几个。
没办法,自己折腾。
下面是折腾以后运行正确的修改:
1. 修改testFramework.h:
#define MAX_WIDTH 1920 //1280
#define MAX_HEIGHT 1440 //960
重新make clean和make,生成jpgdec-r
注:其中改这个大小的时候比较奇怪,随便改的大一点好像也不行的。我搜索过源代码(不包括库),没有用到这两个宏定义的。
2. 改了大小,就要重新修改pools了(loadmodules.sh),如下:
insmod cmemk.ko phys_start=0x85000000 phys_end=0x88000000 pools=1x16384,1x4194304,2x8294400
重新运行,就成功了。
7.2. 多张500万像素JPG图片的解码
1. 修改Testvecs.cfg文件,如下:
2
./TestVecs/Config/Testparams.cfg
./TestVecs/Input/pic5m_001.jpg
./TestVecs/Input/pic5m_001_dec.yuv
./TestVecs/Config/Testparams.cfg
./TestVecs/Input/pic5m_002.jpg
./TestVecs/Input/pic5m_002_dec.yuv
./TestVecs/Config/Testparams.cfg
./TestVecs/Input/pic5m_003.jpg
./TestVecs/Input/pic5m_003_dec.yuv
...
./TestVecs/Config/Testparams.cfg
./TestVecs/Input/pic5m_017.jpg
./TestVecs/Input/pic5m_017_dec.yuv
2. 在Input目录中添加JPG图片。
3. 运行,运行到第10张的时候报错如下(前面几张都是正确解码的):
*******************************************
Read Configuration Set 10
*******************************************
Opened file ../jpg_source/jpg5m/pic5m_010.jpg
FileSize = 990000, Reading file ...done
989997 bytes 2448 x 2048 10.13:1
================Test Summary======================
Total bytes consumed 989997
status.imageWidth = 2448...
status.imageHeight = 2048...
==================================================
Segmentation fault
又是一个头疼的问题,就连怎么去google都不知道。
只能自己折腾。
注:出现上面的错误之后,不能继续运行任何应用程序了,都会报这个错,只能重启板子。
下面是折腾以后运行正确的修改:
1. 分析loadmodules.sh:
insmod cmemk.ko phys_start=0x85000000 phys_end=0x88000000 pools=1x16384,1x4194304,2x8294400
pools的大小为:16364 + 4194304 + 8294400*2 = 20799468 (19.8MB左右,算20MB)
而实际分配的物理地址是从0x85000000到0x88000000,有48MB
修改如下:
insmod cmemk.ko phys_start=0x86C00000 phys_end=0x88000000 pools=1x16384,1x4194304,2x8294400
2. 修改uboot中的启动参数bootargs
> setenv bootargs mem=108M console=ttyS0,115200n8 noinitrd rw ip=192.168.1.144:255.255.255.0:192.168.1.254 root=/dev/mtdblock3 rootfstype=yaffs video=davincifb:osd0=720x576x16,4050K dm365_imp.oper_mode=0 davinci_capture.device_type=4
> saveenv
> boot
重新运行,17张图片解码成功。
8. 小结
另外,如果解码的图片数量再往上增加,还是会出错的,如下错误信息:
oom-killer: gfp_mask=0x200d2, order=0
Mem-info:
DMA per-cpu:
cpu 0 hot: high 42, batch 7 used:6
cpu 0 cold: high 14, batch 3 used:11
DMA32 per-cpu: empty
Normal per-cpu: empty
HighMem per-cpu: empty
Free pages: 1364kB (0kB HighMem)
Active:13185 inactive:41 dirty:0 writeback:0 unstable:0 free:341 slab:684 mapped:1 pagetables:57
DMA free:1364kB min:1328kB low:1660kB high:1992kB active:52740kB inactive:164kB present:110592kB pages_scanned:16452 all_unreclaimable? no
lowmem_reserve[]: 0 0 0 0
DMA32 free:0kB min:0kB low:0kB high:0kB active:0kB inactive:0kB present:0kB pages_scanned:0 all_unreclaimable? no
lowmem_reserve[]: 0 0 0 0
Normal free:0kB min:0kB low:0kB high:0kB active:0kB inactive:0kB present:0kB pages_scanned:0 all_unreclaimable? no
lowmem_reserve[]: 0 0 0 0
HighMem free:0kB min:128kB low:128kB high:128kB active:0kB inactive:0kB present:0kB pages_scanned:0 all_unreclaimable? no
lowmem_reserve[]: 0 0 0 0
DMA: 9*4kB 10*8kB 2*16kB 0*32kB 3*64kB 0*128kB 0*256kB 0*512kB 1*1024kB 0*2048kB 0*4096kB 0*8192kB 0*16384kB = 1364kB
DMA32: empty
Normal: empty
HighMem: empty
Swap cache: add 0, delete 0, find 0/0, race 0+0
Free swap = 0kB
Total swap = 0kB
Free swap: 0kB
27648 pages of RAM
416 free pages
13081 reserved pages
683 slab pages
0 pages shared
0 pages swap cached
Out of Memory: Kill process 708 (sh) score 652 and children.
Out of memory: Killed process 732 (jpgdec-r).
Killed
所以我有理由怀疑,这个应用程序没有写好,至少在内存这一块没有处理好。
不然再多的图片进行解码,只要一张处理好以后释放内存,再进行下一张解码。对吧?
还有,通过NFS读写数据是,一直报下面这个错,但是数据还是读写正确的。
ERROR: davinci_emac: WARN: emac_dev_tx: Out of TX BD's
EMAC: TX Complete: Starting queue
不知道,上面的错误是不是由这里引起的?
对于嵌入式写软件的人来说,内存管理是很现实和很重要的问题。但是对于DAVINCI的这一块却很生疏,想找资料也不容易,以下是一个CMEM的介绍,用处不大。
http://processors.wiki.ti.com/index.php/CMEM_Overview
希望大家多多帮助,多介绍一下资料或网站,这里先谢过了。
本人也是刚开始接触DAVINCI系列的DSP,很多东西都不懂,写文章只是为了记录一下,肯定有不少错误的地方。
另外,对于最后两个问题,如果有高手看到,望赐教,本人不胜感激。