@DaneLLL
test sample:
#include "NvJpegDecoder.h"
#include "NvJpegEncoder.h"
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <memory>
#include <cassert>
// #define JETPACK_5
// #define RECREATE
#ifdef JETPACK_5
#include <nvbufsurface.h>
#include <nvbufsurftransform.h>
#else
#include <nvbuf_utils.h>
#endif
std::string read(const std::string &path) {
std::ifstream in(path);
in.seekg(0, std::ios::end);
const std::streamsize size = in.tellg();
std::string data;
data.resize(size);
in.seekg(0, std::ios::beg);
in.read(const_cast<char *>(data.data()), size);
return data;
}
void write(const std::string &path, const char *data, int len) {
std::ofstream out(path);
out.write(data, len);
out.flush();
}
int decode(NvJPEGDecoder *dec, const std::string &data) {
int decoded_fd = -1;
uint32_t pixfmt, width, height;
int ret = dec->decodeToFd(decoded_fd, (unsigned char *) data.data(), data.size(), pixfmt, width, height);
assert(ret == 0);
#ifdef JETPACK_5
NvBufSurface *decoded_surf = nullptr;
ret = NvBufSurfaceFromFd(decoded_fd, (void **) &decoded_surf);
assert(ret == 0 && decoded_surf != nullptr);
// allocate
NvBufSurfaceAllocateParams create_params;
memset(&create_params, 0, sizeof(create_params));
create_params.params.width = width;
create_params.params.height = height;
create_params.params.memType = NVBUF_MEM_SURFACE_ARRAY;
create_params.params.layout = NVBUF_LAYOUT_PITCH;
create_params.params.colorFormat = NVBUF_COLOR_FORMAT_YUV420;
create_params.memtag = NvBufSurfaceTag_VIDEO_CONVERT;
NvBufSurface *cropped_surf;
ret = NvBufSurfaceAllocate(&cropped_surf, 1, &create_params);
assert(ret == 0);
// crop
NvBufSurfTransformParams transform_params;
memset(&transform_params, 0, sizeof(transform_params));
NvBufSurfTransformRect src_rect;
src_rect.left = 0;
src_rect.top = 0;
src_rect.width = width;
src_rect.height = height;
transform_params.transform_flag = NVBUFSURF_TRANSFORM_CROP_SRC;
transform_params.src_rect = &src_rect;
ret = NvBufSurfTransform(decoded_surf, cropped_surf, &transform_params);
assert(ret == 0);
return cropped_surf->surfaceList[0].bufferDesc;
#else
// allocate
NvBufferCreateParams create_params;
create_params.width = width;
create_params.height = height;
create_params.payloadType = NvBufferPayload_SurfArray;
create_params.layout = NvBufferLayout_Pitch;
create_params.colorFormat = NvBufferColorFormat_YUV420;
create_params.nvbuf_tag = NvBufferTag_VIDEO_CONVERT;
int cropped_fd = -1;
ret = NvBufferCreateEx(&cropped_fd, &create_params);
assert(ret == 0);
// crop
NvBufferTransformParams transform_params;
memset(&transform_params, 0, sizeof(transform_params));
transform_params.transform_flag = NVBUFFER_TRANSFORM_CROP_SRC;
transform_params.src_rect.left = 0;
transform_params.src_rect.top = 0;
transform_params.src_rect.width = width;
transform_params.src_rect.height = height;
ret = NvBufferTransform(decoded_fd, cropped_fd, &transform_params);
assert(ret == 0);
return cropped_fd;
#endif
}
void release(int fd) {
#ifdef JETPACK_5
NvBufSurface *surf = nullptr;
int ret = NvBufSurfaceFromFd(fd, (void **) &surf);
assert(ret == 0 && surf != nullptr);
ret = NvBufSurfaceDestroy(surf);
assert(ret == 0);
#else
int ret = NvBufferDestroy(fd);
assert(ret == 0);
#endif
}
int main(int argc, char *argv[]) {
std::vector<std::string> files = {
read("test1.jpg"),
read("test2.jpg"),
read("test3.jpg"),
read("test4.jpg")
};
int buf_size = 1920 * 1080 * 3;
std::unique_ptr<char[]> buf = std::unique_ptr<char[]>(new char[buf_size]);
#ifndef RECREATE
auto dec = std::shared_ptr<NvJPEGDecoder>(NvJPEGDecoder::createJPEGDecoder("dec"));
auto enc = std::shared_ptr<NvJPEGEncoder>(NvJPEGEncoder::createJPEGEncoder("enc"));
#endif
for (int i = 0; i < 200; ++i) {
#ifdef RECREATE
auto dec = std::shared_ptr<NvJPEGDecoder>(NvJPEGDecoder::createJPEGDecoder("dec"));
auto enc = std::shared_ptr<NvJPEGEncoder>(NvJPEGEncoder::createJPEGEncoder("enc"));
#endif
std::cout << "Round " << i << std::endl;
auto &data = files[i % files.size()];
int fd = decode(dec.get(), data);
unsigned char *out_buf = (unsigned char *) buf.get();
unsigned long out_buf_size = buf_size;
int ret = enc->encodeFromFd(fd, JCS_YCbCr, &out_buf, out_buf_size);
assert(ret == 0);
release(fd);
write("output" + std::to_string(i) + ".jpg", (char *) out_buf, out_buf_size);
}
return 0;
}
Note: uncomment the following line(s) to switch to JP5.x and enable recreation:
// #define JETPACK_5
// #define RECREATE
to compile on JP4.x:
g++ -std=c++11 -I/usr/src/jetson_multimedia_api/include \
-I/usr/src/jetson_multimedia_api/include/libjpeg-8b \
main.cc \
/usr/src/jetson_multimedia_api/samples/common/classes/NvBuffer.cpp \
/usr/src/jetson_multimedia_api/samples/common/classes/NvElement.cpp \
/usr/src/jetson_multimedia_api/samples/common/classes/NvElementProfiler.cpp \
/usr/src/jetson_multimedia_api/samples/common/classes/NvLogging.cpp \
/usr/src/jetson_multimedia_api/samples/common/classes/NvJpegEncoder.cpp \
/usr/src/jetson_multimedia_api/samples/common/classes/NvJpegDecoder.cpp \
-L/usr/lib/aarch64-linux-gnu/tegra \
-lnvjpeg -lnvbuf_utils -o main
to compile on JP5.x:
g++ -std=c++11 -I/usr/src/jetson_multimedia_api/include \
-I/usr/src/jetson_multimedia_api/include/libjpeg-8b \
main.cc \
/usr/src/jetson_multimedia_api/samples/common/classes/NvBuffer.cpp \
/usr/src/jetson_multimedia_api/samples/common/classes/NvElement.cpp \
/usr/src/jetson_multimedia_api/samples/common/classes/NvElementProfiler.cpp \
/usr/src/jetson_multimedia_api/samples/common/classes/NvLogging.cpp \
/usr/src/jetson_multimedia_api/samples/common/classes/NvJpegEncoder.cpp \
/usr/src/jetson_multimedia_api/samples/common/classes/NvJpegDecoder.cpp \
-L/usr/lib/aarch64-linux-gnu/tegra \
-lnvjpeg -lnvbufsurface -lnvbufsurftransform -o main
then generate test images:
gst-launch-1.0 videotestsrc num-buffers=1 ! video/x-raw,width=480,height=240 ! jpegenc ! filesink location=test1.jpg
gst-launch-1.0 videotestsrc num-buffers=1 ! video/x-raw,width=640,height=480 ! jpegenc ! filesink location=test2.jpg
gst-launch-1.0 videotestsrc num-buffers=1 ! video/x-raw,width=1280,height=720 ! jpegenc ! filesink location=test3.jpg
gst-launch-1.0 videotestsrc num-buffers=1 ! video/x-raw,width=1920,height=1080 ! jpegenc ! filesink location=test4.jpg
run the test:
time ./main
our test output:
# JP 4.5 (w/o re-creation, correct)
real 0m1.475s
user 0m0.128s
sys 0m0.352s
# JP 5.1.1 (w/o re-creation, incorrect, 2.3x slower)
real 0m3.456s
user 0m0.165s
sys 0m2.139s
# JP 5.1.1 (w/ re-creation, correct, 51x slower)
real 1m16.267s
user 0m0.585s
sys 1m13.150s