书到三回,在学习过JPEGD和resize的样例之后,再来看JPEGE的样例,话不多说,马上开始
图片缩放的开源样例
https://gitee.com/ascend/samples/tree/master/cplusplus/level2_simple_inference/0_data_process/jpege
sample_build.sh中下载的图片是dvpp_output.yuv
sample_run.sh中run命令是
./main ../data/dvpp_output.yuv 1024 688
第0个参数 ./main
第1个参数 ../data/dvpp_output.yuv
第2个参数 1024
第3个参数 688
参考main.cpp
main第227-233行解析参数,最终得到
image_path=../data/dvpp_output.yuv
image_width=1024
image_height=688
main第236-238行进行ACL初始化
main第240-246行申请Device、Context、Stream
main第248-251行定义输入图片描述信息testPic
main第253-256行确保存在output文件夹
main第259-263行创建通道描述符、创建通道
main第265-266行调用compute_encode_inputsize函数,计算输入yuv输入图片对齐后的内存大小jpegInBufferSize
main第268-272行调用get_picdevbuffer4_jpege函数
get_picdevbuffer4_jpege第55-58行检测输入图片是否存在
get_picdevbuffer4_jpege第60-64行调用fopen函数,以rb权限创建文件流fp
get_picdevbuffer4_jpege第66-75行调用fseek函数将fp从SEEK_END开始移动0个单位,即移动到文件末尾;然后调用ftell函数返回fp现在的位置作为文件大小;最后调用fseek函数将fp从SEEK_SET开始移动0个单位,即移动到文件开头;检查读取文件长度是否正常
get_picdevbuffer4_jpege第77行调用new函数分配一个char类型数组,数组中包含picBufferSize个char,并返回指向第一个char的指针给inputBuff
get_picdevbuffer4_jpege第79-86行调用fread函数,读取PicBufferSize个单元,每个单元的大小为sizeof(char),从流fp中读取,将读取到的内容存储在inputBuff所指的内存中,返回读取的数量,并检查读取是否正确
get_picdevbuffer4_jpege第88-95行调用acldvppMalloc函数在device侧申请内存,大小为PicBufferSize,由inputDevBuff指向申请下来的内存
get_picdevbuffer4_jpege第96-108行,由于runMode=ALC_HOST,触发if分支,调用alcrtMemcpy函数,从host侧将数据复制到device侧,源数据的内存指针为inputBuff,要复制的源数据的内存大小为PicBufferSize,device侧的目标内存指针为inputDevBuff,目标内存的大小为PicBufferSize
get_picdevbuffer4_jpege第110行调用fclose函数关闭流fp
get_picdevbuffer4_jpege第111行将inputDevBuff处的内存以char*类型重新解释,即认为这部分内存存储的是char类型数据,并将重新解释后的指针返回给main函数中的picDevBuffer
main第273行调用set_input4_jpege函数
main第275-282行调用了alignment_helper函数计算了对齐后的输入图片尺寸
main第283-288行调用acldvppCreatePicDesc创建输入图片描述符
main第290-296行调用了acldvppSetPicDesc系列函数,为图片描述符指定了内存、格式、原图宽高、对齐后宽高、内存大小
main第298-299行调用了acldvppCreateJpegeConfig函数创建了编码配置
main第300行调用了acldvppSetJpegeConfigLevel函数设置编码配置,其中第一个参数jpegeConfig_为之前创建的编码配置,第二个参数encodeLevel=100为编码质量,取值0-100
main第303行调用acldvppJpegPredictEncSize函数,根据输入图片描述符encodeInputDesc_,根据编码配置jpegeConfig_,预估图片编码后所需要的输出内存大小,并将其赋值给encode_outbuffer_size_,该变量在main.h中有声明为uint32_t
main第304-309行调用alcdvppMalloc函数,在device侧申请大小为encode_outbuffer_size_的内存,并使encode_out_buffer_dev_指向内存首地址,该指针在main.h声明为void*
main第312-318行调用acldvppJpegEncodeAsync函数,异步执行图片编码,第一个参数dvppChannelDesc_为用于图片编码的Channel描述符;第二个参数encodeInputDesc_为待编码图片描述符;第三个参数encode_out_buffer_dev_为输出图片内存指针;第四个参数为输出图片内存大小;第五个参数为编码配置;第六个参数为Stream
main第319-323行调用aclrtSynchronizeStream函数,阻塞程序运行,等待同步
main第327-331行创建编码结果在host侧的文件名和路径
main第335-339行调用函数
save_dvpp_outputdata第124-128行调用fopen函数,以wb+权限创建流outFileFp并检查是否创建成功
save_dvpp_outputdata第129行,由于runMode=ACL_HOST,触发if分支
save_dvpp_outputdata第130-136行调用aclrtMallocHost函数,根据dataSize,即encode_outbuffer_size_,在host侧申请内存,并使hosPtr指向申请到的内存首地址
save_dvpp_outputdata第138-144行调用aclrtMemcpy函数,从device侧向host侧复制数据,源数据地址指针为devPtr,即encode_outbuffer_dev_;源数据内存大小为dataSize,即encode_outbuffer_size_;目标内存指针为上述hostPtr;目标内存大小同为dataSize
save_dvpp_outputdata第146-153行调用fwrite函数,在outFileFp流中写入数据,待写入数据地址指针为hostPtr,以sizeof(char)为单位进行写入,共写入dataSize个单位,最后检查写入数量是否正确
save_dvpp_outputdata第154行调用aclrtFreeHost函数,释放hostPtr指向的内存
save_dvpp_outputdata第167行调用fflush函数进行刷新,强制流outFileFp中没有写入到文件中的信息完成写入
save_dvpp_outputdata第168行调用fclose函数关闭流outFileFp
回到main函数
main第341行调用destroy_encode_resource函数
destory_encode_resource函数第208-212行调用acldvppDestoryJpegeConfig函数释放编码配置jpegeConfig_
destory_encode_resource函数第213-217行调用acldvppDestoryPicDesc函数释放图片描述符encodeInputDesc_
destory_encode_resource函数第218-222行调用acldvppFree函数释放device侧内存InDevBuffer_
回到main函数
main第342行调用destory_resource函数
destory_resource第174-182行调用aclrtDestoryStream释放Stream
destory_resource第184-191行调用aclrtDestoryContext释放Context
destory_resource第193-197行调用alcrtResetDevice释放Device
destory_resource第199-203行调用aclrtFinalize去初始化
至此,main.cpp结束,最后附上文档中JPEGE的流程图