更新时间:2021-03-18 GMT+08:00
实现JPEGE功能
- 使用DvppGetOutParameter接口获取内存大小,由用户指定输出内存,由用户自行释放内存,调用示例如下 。
void TEST_JPEGE_CUSTOM_MEMORY() { sJpegeIn inData; sJpegeOut outData; inData.width = g_width; inData.height = g_high; inData.heightAligned = g_high; // no need to align inData.format = (eEncodeFormat)g_format; inData.level = 100; inData.stride = ALIGN_UP(inData.width * 2, 16); inData.bufSize = inData.stride * inData.heightAligned; if (JPGENC_FORMAT_YUV420 == (inData.format & JPGENC_FORMAT_BIT)) { inData.stride = ALIGN_UP(inData.width, 16); inData.bufSize = inData.stride * inData.heightAligned * 3 / 2; } void* addrOrig = HIAI_DVPP_DMalloc(inData.bufSize); if (addrOrig == nullptr) { HIAI_ENGINE_LOG(HIAI_JPEGE_CTL_ERROR, "can not alloc input buffer"); return; } inData.buf = reinterpret_cast<unsigned char*>(addrOrig); unsigned char* tmpAddr = nullptr; do { // load img file FILE* fpIn = fopen(g_inFileName, "rb"); if (nullptr == fpIn) { HIAI_ENGINE_LOG(HIAI_OPEN_FILE_ERROR, "can not open input file"); break; } // only copy valid image data, other part is pending if (JPGENC_FORMAT_YUV420 == (inData.format & JPGENC_FORMAT_BIT)) { // for yuv420semi-planar format, like nv12 / nv21 HIAI_ENGINE_LOG("input yuv 420 data"); // for y data for (uint32_t j = 0; j < inData.height; j++) { fread(inData.buf + j * inData.stride, 1, inData.width, fpIn); } // for uv data for (uint32_t j = inData.heightAligned; j < inData.heightAligned + inData.height / 2; j++) { fread(inData.buf + j * inData.stride, 1, inData.width, fpIn); } } else { // for yuv422packed format, like uyvy / vyuy / yuyv / yvyu HIAI_ENGINE_LOG("input yuv 422 data"); for (uint32_t j = 0; j < inData.height; j++) { fread(inData.buf + j * inData.stride, 1, inData.width * 2, fpIn); } } fclose(fpIn); fpIn = nullptr; int32_t ret = DvppGetOutParameter((void*)(&inData), (void*)(&outData), GET_JPEGE_OUT_PARAMETER); if (ret != 0) { HIAI_ENGINE_LOG(HIAI_JPEGE_CTL_ERROR, "call DvppGetOutParameter process failed"); break; } // 此处获得的jpgSize为估算值,实际数据长度可能要小于这个值 // 最终jpgSize大小,以调用DvppCtl接口以后,此字段才为真正的编码后的jpgSize大小 HIAI_ENGINE_LOG("outdata size is %d", outData.jpgSize); tmpAddr = (unsigned char*)HIAI_DVPP_DMalloc(outData.jpgSize); if (tmpAddr == nullptr) { HIAI_ENGINE_LOG(HIAI_JPEGE_CTL_ERROR, "can not alloc output buffer"); break; } uint32_t size = outData.jpgSize; // call jpege process dvppapi_ctl_msg dvppApiCtlMsg; dvppApiCtlMsg.in = (void *)&inData; dvppApiCtlMsg.in_size = sizeof(inData); dvppApiCtlMsg.out = (void *)&outData; dvppApiCtlMsg.out_size = sizeof(outData); if(!IsHandleJpegeCtlSucc(dvppApiCtlMsg, tmpAddr, size, &outData)) { break; } } while (0); // for resource inData.buf if (addrOrig != nullptr) { HIAI_DVPP_DFree(addrOrig); addrOrig = nullptr; } if (tmpAddr != nullptr) { // 注意:释放内存时需要使用tmpAddr,因为outData.jpgData在JPEGE处理后会有地址偏移 HIAI_DVPP_DFree(tmpAddr); tmpAddr = nullptr; } }
- 不由用户指定输出内存时,DVPP内部申请内存,需由用户调用cbFree()回调函数释放内存,调用示例如下。
void JpegeProcess() { sJpegeIn inData; sJpegeOut outData; inData.width = g_width; inData.height = g_high; inData.heightAligned = g_high; // no need to align inData.format = (eEncodeFormat)g_format; inData.level = 100; if (JPGENC_FORMAT_YUV420 == (inData.format & JPGENC_FORMAT_BIT)) { inData.stride = ALIGN_UP(inData.width, 16); inData.bufSize = inData.stride * inData.heightAligned * 3 / 2; } else { inData.stride = ALIGN_UP(inData.width * 2, 16); inData.bufSize = inData.stride * inData.heightAligned; } void* addrOrig = HIAI_DVPP_DMalloc(inData.bufSize); if (addrOrig == nullptr) { HIAI_ENGINE_LOG(HIAI_JPEGE_CTL_ERROR, "can not alloc input buffer"); return; } inData.buf = reinterpret_cast<unsigned char*>(addrOrig); do { // load img file FILE* fpIn = fopen(g_inFileName, "rb"); if (fpIn == nullptr) { HIAI_ENGINE_LOG(HIAI_OPEN_FILE_ERROR, "can not open input file"); break; } // only copy valid image data, other part is pending if (JPGENC_FORMAT_YUV420 == (inData.format & JPGENC_FORMAT_BIT)) { // for yuv420semi-planar format, like nv12 / nv21 HIAI_ENGINE_LOG("input yuv 420 data"); // for y data for (uint32_t j = 0; j < inData.height; j++) { fread(inData.buf + j * inData.stride, 1, inData.width, fpIn); } // for uv data for (uint32_t j = inData.heightAligned; j < inData.heightAligned + inData.height / 2; j++) { fread(inData.buf + j * inData.stride, 1, inData.width, fpIn); } } else { // for yuv422packed format, like uyvy / vyuy / yuyv / yvyu HIAI_ENGINE_LOG("input yuv 422 data"); for (uint32_t j = 0; j < inData.height; j++) { fread(inData.buf + j * inData.stride, 1, inData.width * 2, fpIn ); } } fclose(fpIn); fpIn = nullptr; // call jpege process dvppapi_ctl_msg dvppApiCtlMsg; dvppApiCtlMsg.in = (void*)&inData; dvppApiCtlMsg.in_size = sizeof(inData); dvppApiCtlMsg.out = (void*)&outData; dvppApiCtlMsg.out_size = sizeof(outData); IDVPPAPI *pidvppapi = nullptr; CreateDvppApi(pidvppapi); if (pidvppapi == nullptr) { HIAI_ENGINE_LOG(HIAI_JPEGE_CTL_ERROR, "can not open dvppapi engine"); break; } JpegeProcessBranch(pidvppapi, dvppApiCtlMsg, outData); DestroyDvppApi(pidvppapi); } while (0); // for resource inData.buf if (addrOrig != nullptr) { HIAI_DVPP_DFree(addrOrig); addrOrig = nullptr; } } /* * only handle jpege process. */ void JpegeProcessBranch(IDVPPAPI*& pidvppapi, dvppapi_ctl_msg& dvppApiCtlMsg, sJpegeOut& outData) { do { for (int i = 0;i < g_loop; i++) { // same picture loop test if (DvppCtl(pidvppapi, DVPP_CTL_JPEGE_PROC, &dvppApiCtlMsg)) { HIAI_ENGINE_LOG(HIAI_JPEGE_CTL_ERROR, "call jpeg encoder fail"); break; } if (i < g_loop - 1) { outData.cbFree(); outData.jpgData = nullptr; } } stringstream outFile; outFile << g_outFileName << "_t" << std::this_thread::get_id() << ".jpg"; FILE* fpOut = fopen(outFile.str().c_str(), "wb"); if (fpOut != nullptr) { fwrite(outData.jpgData, 1, outData.jpgSize, fpOut); fflush(fpOut); fclose(fpOut); fpOut = nullptr; } else { HIAI_ENGINE_LOG(HIAI_JPEGE_CTL_ERROR, "call not save result file %s ", outFile.str().c_str()); } outData.cbFree(); outData.jpgData = nullptr; HIAI_ENGINE_LOG(HIAI_OK, "jpeg encode process completed"); } while (0); // for resource pddvppapi }
父主题: 调用示例