1*437bfbebSnyanmisaka /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2*437bfbebSnyanmisaka /*
3*437bfbebSnyanmisaka * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4*437bfbebSnyanmisaka */
5*437bfbebSnyanmisaka
6*437bfbebSnyanmisaka #include <stdio.h>
7*437bfbebSnyanmisaka #include <stdlib.h>
8*437bfbebSnyanmisaka #include <string.h>
9*437bfbebSnyanmisaka #include <dlfcn.h>
10*437bfbebSnyanmisaka #include <unistd.h>
11*437bfbebSnyanmisaka
12*437bfbebSnyanmisaka #include "vpu_api.h"
13*437bfbebSnyanmisaka
14*437bfbebSnyanmisaka #define FOR_TEST_ENCODE 1
15*437bfbebSnyanmisaka
16*437bfbebSnyanmisaka #define BSWAP32(x) \
17*437bfbebSnyanmisaka ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
18*437bfbebSnyanmisaka (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
19*437bfbebSnyanmisaka
20*437bfbebSnyanmisaka #define DEMO_ERR_RET(err) do { ret = err; goto DEMO_OUT; } while (0)
21*437bfbebSnyanmisaka #define DECODE_ERR_RET(err) do { ret = err; goto DECODE_OUT; } while (0)
22*437bfbebSnyanmisaka #define ENCODE_ERR_RET(err) do { ret = err; goto ENCODE_OUT; } while (0)
23*437bfbebSnyanmisaka
24*437bfbebSnyanmisaka typedef enum VPU_API_DEMO_RET {
25*437bfbebSnyanmisaka VPU_DEMO_OK = 0,
26*437bfbebSnyanmisaka VPU_DEMO_PARSE_HELP_OK = 1,
27*437bfbebSnyanmisaka
28*437bfbebSnyanmisaka VPU_DEMO_ERROR_BASE = -100,
29*437bfbebSnyanmisaka ERROR_INVALID_PARAM = VPU_DEMO_ERROR_BASE - 1,
30*437bfbebSnyanmisaka ERROR_INVALID_STREAM = VPU_DEMO_ERROR_BASE - 2,
31*437bfbebSnyanmisaka ERROR_IO = VPU_DEMO_ERROR_BASE - 3,
32*437bfbebSnyanmisaka ERROR_MEMORY = VPU_DEMO_ERROR_BASE - 4,
33*437bfbebSnyanmisaka ERROR_INIT_VPU = VPU_DEMO_ERROR_BASE - 5,
34*437bfbebSnyanmisaka
35*437bfbebSnyanmisaka ERROR_VPU_DECODE = VPU_DEMO_ERROR_BASE - 90,
36*437bfbebSnyanmisaka } VPU_API_DEMO_RET;
37*437bfbebSnyanmisaka
38*437bfbebSnyanmisaka typedef struct VpuApiDemoCmdContext {
39*437bfbebSnyanmisaka RK_U32 width;
40*437bfbebSnyanmisaka RK_U32 height;
41*437bfbebSnyanmisaka CODEC_TYPE codec_type;
42*437bfbebSnyanmisaka OMX_RK_VIDEO_CODINGTYPE coding;
43*437bfbebSnyanmisaka char input_file[200];
44*437bfbebSnyanmisaka char output_file[200];
45*437bfbebSnyanmisaka RK_U8 have_input;
46*437bfbebSnyanmisaka RK_U8 have_output;
47*437bfbebSnyanmisaka RK_U32 record_frames;
48*437bfbebSnyanmisaka RK_S64 record_start_ms;
49*437bfbebSnyanmisaka } VpuApiDemoCmdContext_t;
50*437bfbebSnyanmisaka
51*437bfbebSnyanmisaka typedef struct VpuApiEncInput {
52*437bfbebSnyanmisaka EncInputStream_t stream;
53*437bfbebSnyanmisaka RK_U32 capability;
54*437bfbebSnyanmisaka } VpuApiEncInput;
55*437bfbebSnyanmisaka
56*437bfbebSnyanmisaka typedef struct VpuApiOptionInfo_t {
57*437bfbebSnyanmisaka const char* name;
58*437bfbebSnyanmisaka const char* argname;
59*437bfbebSnyanmisaka const char* help;
60*437bfbebSnyanmisaka } VpuApiOptionInfo;
61*437bfbebSnyanmisaka
62*437bfbebSnyanmisaka static VpuApiOptionInfo vpuApiCmd[] = {
63*437bfbebSnyanmisaka { "i", "input_file", "input bitstream file" },
64*437bfbebSnyanmisaka { "o", "output_file", "output bitstream file, " },
65*437bfbebSnyanmisaka { "w", "width", "the width of input bitstream" },
66*437bfbebSnyanmisaka { "h", "height", "the height of input bitstream" },
67*437bfbebSnyanmisaka { "t", "codec_type", "the codec type, dec: deoder, enc: encoder, default: decoder" },
68*437bfbebSnyanmisaka { "coding", "coding_type", "encoding type of the bitstream" },
69*437bfbebSnyanmisaka { "vframes", "number", "set the number of video frames to record" },
70*437bfbebSnyanmisaka { "ss", "time_off", "set the start time offset, use Ms as the unit." },
71*437bfbebSnyanmisaka };
72*437bfbebSnyanmisaka
73*437bfbebSnyanmisaka static void *vpuapi_hdl = NULL;
74*437bfbebSnyanmisaka static VpuCodecContext_t *ctx;
75*437bfbebSnyanmisaka RK_S32 (*vpuapi_open_ctx)(VpuCodecContext_t **ctx);
76*437bfbebSnyanmisaka RK_S32 (*vpuapi_close_ctx)(VpuCodecContext_t **ctx);
77*437bfbebSnyanmisaka RK_S32 (*vpuapi_mem_link)(VPUMemLinear_t *p);
78*437bfbebSnyanmisaka RK_S32 (*vpuapi_mem_free)(VPUMemLinear_t *p);
79*437bfbebSnyanmisaka
show_usage()80*437bfbebSnyanmisaka static void show_usage()
81*437bfbebSnyanmisaka {
82*437bfbebSnyanmisaka printf("usage: vpu_apiDemo [options] input_file, \n\n");
83*437bfbebSnyanmisaka
84*437bfbebSnyanmisaka printf("Getting help:\n");
85*437bfbebSnyanmisaka printf("-help --print options of vpu api demo\n");
86*437bfbebSnyanmisaka }
87*437bfbebSnyanmisaka
show_help()88*437bfbebSnyanmisaka static RK_S32 show_help()
89*437bfbebSnyanmisaka {
90*437bfbebSnyanmisaka RK_S32 i;
91*437bfbebSnyanmisaka RK_S32 count = sizeof(vpuApiCmd) / sizeof(vpuApiCmd[0]);
92*437bfbebSnyanmisaka VpuApiOptionInfo *opt = vpuApiCmd;
93*437bfbebSnyanmisaka
94*437bfbebSnyanmisaka printf("usage: vpu_apiDemo [opt] input_file, \n\n");
95*437bfbebSnyanmisaka for (i = 0; i < count; i++)
96*437bfbebSnyanmisaka printf("-%s %-16s\t%s\n", opt[i].name, opt[i].argname, opt[i].help);
97*437bfbebSnyanmisaka
98*437bfbebSnyanmisaka return 0;
99*437bfbebSnyanmisaka }
100*437bfbebSnyanmisaka
parse_options(int argc,char ** argv,VpuApiDemoCmdContext_t * cmdCxt)101*437bfbebSnyanmisaka static RK_S32 parse_options(int argc, char **argv, VpuApiDemoCmdContext_t *cmdCxt)
102*437bfbebSnyanmisaka {
103*437bfbebSnyanmisaka char *opt;
104*437bfbebSnyanmisaka RK_S32 optindex, handleoptions = 1, ret = 0;
105*437bfbebSnyanmisaka
106*437bfbebSnyanmisaka if ((argc < 2) || (cmdCxt == NULL)) {
107*437bfbebSnyanmisaka printf("vpu api demo, input parameter invalid\n");
108*437bfbebSnyanmisaka show_usage();
109*437bfbebSnyanmisaka return ERROR_INVALID_PARAM;
110*437bfbebSnyanmisaka }
111*437bfbebSnyanmisaka
112*437bfbebSnyanmisaka /* parse options */
113*437bfbebSnyanmisaka optindex = 1;
114*437bfbebSnyanmisaka while (optindex < argc) {
115*437bfbebSnyanmisaka opt = argv[optindex++];
116*437bfbebSnyanmisaka
117*437bfbebSnyanmisaka if (handleoptions && opt[0] == '-' && opt[1] != '\0') {
118*437bfbebSnyanmisaka if (opt[1] == '-') {
119*437bfbebSnyanmisaka if (opt[2] != '\0') {
120*437bfbebSnyanmisaka opt++;
121*437bfbebSnyanmisaka } else {
122*437bfbebSnyanmisaka handleoptions = 0;
123*437bfbebSnyanmisaka continue;
124*437bfbebSnyanmisaka }
125*437bfbebSnyanmisaka }
126*437bfbebSnyanmisaka
127*437bfbebSnyanmisaka opt++;
128*437bfbebSnyanmisaka
129*437bfbebSnyanmisaka switch (*opt) {
130*437bfbebSnyanmisaka case 'i':
131*437bfbebSnyanmisaka if (argv[optindex]) {
132*437bfbebSnyanmisaka memcpy(cmdCxt->input_file, argv[optindex], strlen(argv[optindex]));
133*437bfbebSnyanmisaka cmdCxt->input_file[strlen(argv[optindex])] = '\0';
134*437bfbebSnyanmisaka cmdCxt->have_input = 1;
135*437bfbebSnyanmisaka } else {
136*437bfbebSnyanmisaka printf("input file is invalid\n");
137*437bfbebSnyanmisaka ret = -1;
138*437bfbebSnyanmisaka goto PARSE_OPINIONS_OUT;
139*437bfbebSnyanmisaka }
140*437bfbebSnyanmisaka break;
141*437bfbebSnyanmisaka case 'o':
142*437bfbebSnyanmisaka if (argv[optindex]) {
143*437bfbebSnyanmisaka memcpy(cmdCxt->output_file, argv[optindex], strlen(argv[optindex]));
144*437bfbebSnyanmisaka cmdCxt->output_file[strlen(argv[optindex])] = '\0';
145*437bfbebSnyanmisaka cmdCxt->have_output = 1;
146*437bfbebSnyanmisaka break;
147*437bfbebSnyanmisaka } else {
148*437bfbebSnyanmisaka printf("out file is invalid\n");
149*437bfbebSnyanmisaka ret = -1;
150*437bfbebSnyanmisaka goto PARSE_OPINIONS_OUT;
151*437bfbebSnyanmisaka }
152*437bfbebSnyanmisaka case 'w':
153*437bfbebSnyanmisaka if (argv[optindex]) {
154*437bfbebSnyanmisaka cmdCxt->width = atoi(argv[optindex]);
155*437bfbebSnyanmisaka break;
156*437bfbebSnyanmisaka } else {
157*437bfbebSnyanmisaka printf("input width is invalid\n");
158*437bfbebSnyanmisaka ret = -1;
159*437bfbebSnyanmisaka goto PARSE_OPINIONS_OUT;
160*437bfbebSnyanmisaka }
161*437bfbebSnyanmisaka case 'h':
162*437bfbebSnyanmisaka if ((*(opt + 1) != '\0') && !strncmp(opt, "help", 4)) {
163*437bfbebSnyanmisaka show_help();
164*437bfbebSnyanmisaka ret = VPU_DEMO_PARSE_HELP_OK;
165*437bfbebSnyanmisaka goto PARSE_OPINIONS_OUT;
166*437bfbebSnyanmisaka } else if (argv[optindex]) {
167*437bfbebSnyanmisaka cmdCxt->height = atoi(argv[optindex]);
168*437bfbebSnyanmisaka } else {
169*437bfbebSnyanmisaka printf("input height is invalid\n");
170*437bfbebSnyanmisaka ret = -1;
171*437bfbebSnyanmisaka goto PARSE_OPINIONS_OUT;
172*437bfbebSnyanmisaka }
173*437bfbebSnyanmisaka break;
174*437bfbebSnyanmisaka case 't':
175*437bfbebSnyanmisaka if (argv[optindex]) {
176*437bfbebSnyanmisaka cmdCxt->codec_type = atoi(argv[optindex]);
177*437bfbebSnyanmisaka break;
178*437bfbebSnyanmisaka } else {
179*437bfbebSnyanmisaka printf("input codec_type is invalid\n");
180*437bfbebSnyanmisaka ret = -1;
181*437bfbebSnyanmisaka goto PARSE_OPINIONS_OUT;
182*437bfbebSnyanmisaka }
183*437bfbebSnyanmisaka
184*437bfbebSnyanmisaka default:
185*437bfbebSnyanmisaka if ((*(opt + 1) != '\0') && argv[optindex]) {
186*437bfbebSnyanmisaka if (!strncmp(opt, "coding", 6)) {
187*437bfbebSnyanmisaka printf("coding, argv[optindex]: %s",
188*437bfbebSnyanmisaka argv[optindex]);
189*437bfbebSnyanmisaka cmdCxt->coding = atoi(argv[optindex]);
190*437bfbebSnyanmisaka } else if (!strncmp(opt, "vframes", 7)) {
191*437bfbebSnyanmisaka cmdCxt->record_frames = atoi(argv[optindex]);
192*437bfbebSnyanmisaka } else if (!strncmp(opt, "ss", 2)) {
193*437bfbebSnyanmisaka cmdCxt->record_start_ms = atoi(argv[optindex]);
194*437bfbebSnyanmisaka } else {
195*437bfbebSnyanmisaka ret = -1;
196*437bfbebSnyanmisaka goto PARSE_OPINIONS_OUT;
197*437bfbebSnyanmisaka }
198*437bfbebSnyanmisaka } else {
199*437bfbebSnyanmisaka ret = -1;
200*437bfbebSnyanmisaka goto PARSE_OPINIONS_OUT;
201*437bfbebSnyanmisaka }
202*437bfbebSnyanmisaka break;
203*437bfbebSnyanmisaka }
204*437bfbebSnyanmisaka
205*437bfbebSnyanmisaka optindex += ret;
206*437bfbebSnyanmisaka }
207*437bfbebSnyanmisaka }
208*437bfbebSnyanmisaka
209*437bfbebSnyanmisaka PARSE_OPINIONS_OUT:
210*437bfbebSnyanmisaka if (ret < 0) {
211*437bfbebSnyanmisaka printf("vpu api demo, input parameter invalid\n");
212*437bfbebSnyanmisaka show_usage();
213*437bfbebSnyanmisaka return ERROR_INVALID_PARAM;
214*437bfbebSnyanmisaka }
215*437bfbebSnyanmisaka return ret;
216*437bfbebSnyanmisaka }
217*437bfbebSnyanmisaka
readBytesFromFile(RK_U8 * buf,RK_S32 aBytes,FILE * file)218*437bfbebSnyanmisaka static RK_S32 readBytesFromFile(RK_U8 *buf, RK_S32 aBytes, FILE *file)
219*437bfbebSnyanmisaka {
220*437bfbebSnyanmisaka RK_S32 ret = 0;
221*437bfbebSnyanmisaka
222*437bfbebSnyanmisaka if ((NULL == buf) || (NULL == file) || (0 == aBytes)) {
223*437bfbebSnyanmisaka return -1;
224*437bfbebSnyanmisaka }
225*437bfbebSnyanmisaka
226*437bfbebSnyanmisaka ret = (RK_S32)fread(buf, 1, aBytes, file);
227*437bfbebSnyanmisaka if (ret != aBytes) {
228*437bfbebSnyanmisaka printf("read %d bytes from file fail\n", aBytes);
229*437bfbebSnyanmisaka return -1;
230*437bfbebSnyanmisaka }
231*437bfbebSnyanmisaka
232*437bfbebSnyanmisaka return 0;
233*437bfbebSnyanmisaka }
234*437bfbebSnyanmisaka
vpu_encode_demo(VpuApiDemoCmdContext_t * cmd)235*437bfbebSnyanmisaka static RK_S32 vpu_encode_demo(VpuApiDemoCmdContext_t *cmd)
236*437bfbebSnyanmisaka {
237*437bfbebSnyanmisaka FILE *pInFile = NULL;
238*437bfbebSnyanmisaka FILE *pOutFile = NULL;
239*437bfbebSnyanmisaka RK_S32 nal = 0x00000001;
240*437bfbebSnyanmisaka RK_S32 fileSize;
241*437bfbebSnyanmisaka RK_S32 ret = 0;
242*437bfbebSnyanmisaka RK_S32 size;
243*437bfbebSnyanmisaka RK_U32 readOneFrameSize = 0;
244*437bfbebSnyanmisaka EncoderOut_t enc_out_yuv;
245*437bfbebSnyanmisaka EncoderOut_t *enc_out = NULL;
246*437bfbebSnyanmisaka VpuApiEncInput enc_in_strm;
247*437bfbebSnyanmisaka VpuApiEncInput *api_enc_in = &enc_in_strm;
248*437bfbebSnyanmisaka EncInputStream_t *enc_in = NULL;
249*437bfbebSnyanmisaka EncParameter_t *enc_param = NULL;
250*437bfbebSnyanmisaka RK_S64 fakeTimeUs = 0;
251*437bfbebSnyanmisaka RK_U32 w_align = 0;
252*437bfbebSnyanmisaka RK_U32 h_align = 0;
253*437bfbebSnyanmisaka
254*437bfbebSnyanmisaka int Format = ENC_INPUT_YUV420_PLANAR;
255*437bfbebSnyanmisaka
256*437bfbebSnyanmisaka if (cmd == NULL) {
257*437bfbebSnyanmisaka return -1;
258*437bfbebSnyanmisaka }
259*437bfbebSnyanmisaka
260*437bfbebSnyanmisaka if ((cmd->have_input == 0) || (cmd->width <= 0) || (cmd->height <= 0)
261*437bfbebSnyanmisaka || (cmd->coding <= OMX_RK_VIDEO_CodingAutoDetect)) {
262*437bfbebSnyanmisaka printf("Warning: missing needed parameters for vpu api demo\n");
263*437bfbebSnyanmisaka }
264*437bfbebSnyanmisaka
265*437bfbebSnyanmisaka if (cmd->have_input) {
266*437bfbebSnyanmisaka printf("input bitstream w: %d, h: %d, coding: %d(%s), path: %s\n",
267*437bfbebSnyanmisaka cmd->width, cmd->height, cmd->coding,
268*437bfbebSnyanmisaka cmd->codec_type == CODEC_DECODER ? "decode" : "encode",
269*437bfbebSnyanmisaka cmd->input_file);
270*437bfbebSnyanmisaka
271*437bfbebSnyanmisaka pInFile = fopen(cmd->input_file, "rb");
272*437bfbebSnyanmisaka if (pInFile == NULL) {
273*437bfbebSnyanmisaka printf("input file not exsist\n");
274*437bfbebSnyanmisaka ENCODE_ERR_RET(ERROR_INVALID_PARAM);
275*437bfbebSnyanmisaka }
276*437bfbebSnyanmisaka } else {
277*437bfbebSnyanmisaka printf("please set input bitstream file\n");
278*437bfbebSnyanmisaka ENCODE_ERR_RET(ERROR_INVALID_PARAM);
279*437bfbebSnyanmisaka }
280*437bfbebSnyanmisaka
281*437bfbebSnyanmisaka if (cmd->have_output) {
282*437bfbebSnyanmisaka printf("vpu api demo output file: %s\n",
283*437bfbebSnyanmisaka cmd->output_file);
284*437bfbebSnyanmisaka pOutFile = fopen(cmd->output_file, "wb");
285*437bfbebSnyanmisaka if (pOutFile == NULL) {
286*437bfbebSnyanmisaka printf("can not write output file\n");
287*437bfbebSnyanmisaka ENCODE_ERR_RET(ERROR_INVALID_PARAM);
288*437bfbebSnyanmisaka }
289*437bfbebSnyanmisaka }
290*437bfbebSnyanmisaka
291*437bfbebSnyanmisaka #ifdef FOR_TEST_ENCODE
292*437bfbebSnyanmisaka ctx = (struct VpuCodecContext *)malloc(sizeof(struct VpuCodecContext));
293*437bfbebSnyanmisaka if (!ctx) {
294*437bfbebSnyanmisaka printf("Input context has not been properly allocated");
295*437bfbebSnyanmisaka return -1;
296*437bfbebSnyanmisaka }
297*437bfbebSnyanmisaka memset(ctx, 0, sizeof(struct VpuCodecContext));
298*437bfbebSnyanmisaka
299*437bfbebSnyanmisaka ctx->videoCoding = OMX_RK_VIDEO_CodingAVC;
300*437bfbebSnyanmisaka ctx->codecType = CODEC_ENCODER;
301*437bfbebSnyanmisaka ctx->width = cmd->width;
302*437bfbebSnyanmisaka ctx->height = cmd->height;
303*437bfbebSnyanmisaka #endif
304*437bfbebSnyanmisaka
305*437bfbebSnyanmisaka fseek(pInFile, 0L, SEEK_END);
306*437bfbebSnyanmisaka fileSize = ftell(pInFile);
307*437bfbebSnyanmisaka fseek(pInFile, 0L, SEEK_SET);
308*437bfbebSnyanmisaka
309*437bfbebSnyanmisaka memset(&enc_in_strm, 0, sizeof(VpuApiEncInput));
310*437bfbebSnyanmisaka enc_in = &enc_in_strm.stream;
311*437bfbebSnyanmisaka enc_in->buf = NULL;
312*437bfbebSnyanmisaka
313*437bfbebSnyanmisaka memset(&enc_out_yuv, 0, sizeof(EncoderOut_t));
314*437bfbebSnyanmisaka enc_out = &enc_out_yuv;
315*437bfbebSnyanmisaka enc_out->data = (RK_U8 *)malloc(cmd->width * cmd->height);
316*437bfbebSnyanmisaka if (enc_out->data == NULL) {
317*437bfbebSnyanmisaka ENCODE_ERR_RET(ERROR_MEMORY);
318*437bfbebSnyanmisaka }
319*437bfbebSnyanmisaka
320*437bfbebSnyanmisaka ret = vpuapi_open_ctx(&ctx);
321*437bfbebSnyanmisaka if (ret || (ctx == NULL)) {
322*437bfbebSnyanmisaka ENCODE_ERR_RET(ERROR_MEMORY);
323*437bfbebSnyanmisaka }
324*437bfbebSnyanmisaka
325*437bfbebSnyanmisaka /*
326*437bfbebSnyanmisaka ** now init vpu api context. codecType, codingType, width ,height
327*437bfbebSnyanmisaka ** are all needed before init.
328*437bfbebSnyanmisaka */
329*437bfbebSnyanmisaka ctx->codecType = cmd->codec_type;
330*437bfbebSnyanmisaka ctx->videoCoding = cmd->coding;
331*437bfbebSnyanmisaka ctx->width = cmd->width;
332*437bfbebSnyanmisaka ctx->height = cmd->height;
333*437bfbebSnyanmisaka ctx->no_thread = 1;
334*437bfbebSnyanmisaka
335*437bfbebSnyanmisaka ctx->private_data = malloc(sizeof(EncParameter_t));
336*437bfbebSnyanmisaka memset(ctx->private_data, 0, sizeof(EncParameter_t));
337*437bfbebSnyanmisaka
338*437bfbebSnyanmisaka enc_param = (EncParameter_t *)ctx->private_data;
339*437bfbebSnyanmisaka enc_param->width = cmd->width;
340*437bfbebSnyanmisaka enc_param->height = cmd->height;
341*437bfbebSnyanmisaka enc_param->format = ENC_INPUT_YUV420_PLANAR;
342*437bfbebSnyanmisaka enc_param->rc_mode = 0;
343*437bfbebSnyanmisaka enc_param->bitRate = 4000000;
344*437bfbebSnyanmisaka enc_param->framerate = 25;
345*437bfbebSnyanmisaka enc_param->enableCabac = 1;
346*437bfbebSnyanmisaka enc_param->cabacInitIdc = 0;
347*437bfbebSnyanmisaka enc_param->intraPicRate = 30;
348*437bfbebSnyanmisaka enc_param->profileIdc = 100;
349*437bfbebSnyanmisaka enc_param->levelIdc = 40;
350*437bfbebSnyanmisaka
351*437bfbebSnyanmisaka if ((ret = ctx->init(ctx, NULL, 0)) != 0) {
352*437bfbebSnyanmisaka printf("init vpu api context fail, ret: 0x%X\n", ret);
353*437bfbebSnyanmisaka ENCODE_ERR_RET(ERROR_INIT_VPU);
354*437bfbebSnyanmisaka }
355*437bfbebSnyanmisaka
356*437bfbebSnyanmisaka /*
357*437bfbebSnyanmisaka ** init of VpuCodecContext while running encode, it returns
358*437bfbebSnyanmisaka ** sps and pps of encoder output, you need to save sps and pps
359*437bfbebSnyanmisaka ** after init.
360*437bfbebSnyanmisaka */
361*437bfbebSnyanmisaka printf("encode init ok, sps len: %d\n", ctx->extradata_size);
362*437bfbebSnyanmisaka if (pOutFile && (ctx->extradata_size > 0)) {
363*437bfbebSnyanmisaka printf("dump %d bytes enc output stream to file\n",
364*437bfbebSnyanmisaka ctx->extradata_size);
365*437bfbebSnyanmisaka
366*437bfbebSnyanmisaka /* save sps and pps */
367*437bfbebSnyanmisaka fwrite(ctx->extradata, 1, ctx->extradata_size, pOutFile);
368*437bfbebSnyanmisaka fflush(pOutFile);
369*437bfbebSnyanmisaka }
370*437bfbebSnyanmisaka
371*437bfbebSnyanmisaka ret = ctx->control(ctx, VPU_API_ENC_SETFORMAT, &Format);
372*437bfbebSnyanmisaka if (ret)
373*437bfbebSnyanmisaka printf("VPU_API_ENC_SETFORMAT ret %d\n", ret);
374*437bfbebSnyanmisaka
375*437bfbebSnyanmisaka ret = ctx->control(ctx, VPU_API_ENC_GETCFG, enc_param);
376*437bfbebSnyanmisaka if (ret)
377*437bfbebSnyanmisaka printf("VPU_API_ENC_GETCFG ret %d\n", ret);
378*437bfbebSnyanmisaka
379*437bfbebSnyanmisaka enc_param->rc_mode = 1;
380*437bfbebSnyanmisaka
381*437bfbebSnyanmisaka ret = ctx->control(ctx, VPU_API_ENC_SETCFG, enc_param);
382*437bfbebSnyanmisaka if (ret)
383*437bfbebSnyanmisaka printf("VPU_API_ENC_SETCFG ret %d\n", ret);
384*437bfbebSnyanmisaka
385*437bfbebSnyanmisaka /*
386*437bfbebSnyanmisaka ** vpu api encode process.
387*437bfbebSnyanmisaka */
388*437bfbebSnyanmisaka printf("init vpu api context ok, input yuv stream file size: %d\n", fileSize);
389*437bfbebSnyanmisaka w_align = ((ctx->width + 15) & (~15));
390*437bfbebSnyanmisaka h_align = ((ctx->height + 15) & (~15));
391*437bfbebSnyanmisaka size = w_align * h_align * 3 / 2;
392*437bfbebSnyanmisaka readOneFrameSize = ctx->width * ctx->height * 3 / 2;
393*437bfbebSnyanmisaka printf("%d %d %d %d %d", ctx->width, ctx->height, w_align, h_align, size);
394*437bfbebSnyanmisaka nal = BSWAP32(nal);
395*437bfbebSnyanmisaka
396*437bfbebSnyanmisaka do {
397*437bfbebSnyanmisaka if (ftell(pInFile) >= fileSize) {
398*437bfbebSnyanmisaka printf("read end of file, complete\n");
399*437bfbebSnyanmisaka break;
400*437bfbebSnyanmisaka }
401*437bfbebSnyanmisaka
402*437bfbebSnyanmisaka if (enc_in && (enc_in->size == 0)) {
403*437bfbebSnyanmisaka if (enc_in->buf == NULL) {
404*437bfbebSnyanmisaka enc_in->buf = (RK_U8 *)(malloc)(size);
405*437bfbebSnyanmisaka if (enc_in->buf == NULL) {
406*437bfbebSnyanmisaka ENCODE_ERR_RET(ERROR_MEMORY);
407*437bfbebSnyanmisaka }
408*437bfbebSnyanmisaka api_enc_in->capability = size;
409*437bfbebSnyanmisaka }
410*437bfbebSnyanmisaka
411*437bfbebSnyanmisaka if (api_enc_in->capability < ((RK_U32)size)) {
412*437bfbebSnyanmisaka enc_in->buf = (RK_U8 *)(realloc)((void *)(enc_in->buf), size);
413*437bfbebSnyanmisaka if (enc_in->buf == NULL) {
414*437bfbebSnyanmisaka ENCODE_ERR_RET(ERROR_MEMORY);
415*437bfbebSnyanmisaka }
416*437bfbebSnyanmisaka api_enc_in->capability = size;
417*437bfbebSnyanmisaka }
418*437bfbebSnyanmisaka
419*437bfbebSnyanmisaka if (readBytesFromFile(enc_in->buf, readOneFrameSize, pInFile)) {
420*437bfbebSnyanmisaka break;
421*437bfbebSnyanmisaka } else {
422*437bfbebSnyanmisaka enc_in->size = size;
423*437bfbebSnyanmisaka enc_in->timeUs = fakeTimeUs;
424*437bfbebSnyanmisaka fakeTimeUs += 40000;
425*437bfbebSnyanmisaka }
426*437bfbebSnyanmisaka
427*437bfbebSnyanmisaka printf("read one frame, size: %d, timeUs: %lld, filePos: %ld\n",
428*437bfbebSnyanmisaka enc_in->size, enc_in->timeUs, ftell(pInFile));
429*437bfbebSnyanmisaka }
430*437bfbebSnyanmisaka
431*437bfbebSnyanmisaka if ((ret = ctx->encode(ctx, enc_in, enc_out)) < 0) {
432*437bfbebSnyanmisaka ENCODE_ERR_RET(ERROR_VPU_DECODE);
433*437bfbebSnyanmisaka } else {
434*437bfbebSnyanmisaka enc_in->size = 0; // TODO encode completely, and set enc_in->size to 0
435*437bfbebSnyanmisaka printf("vpu encode one frame, out len: %d, left size: %d\n",
436*437bfbebSnyanmisaka enc_out->size, enc_in->size);
437*437bfbebSnyanmisaka
438*437bfbebSnyanmisaka /*
439*437bfbebSnyanmisaka ** encoder output stream is raw bitstream, you need to add nal
440*437bfbebSnyanmisaka ** head by yourself.
441*437bfbebSnyanmisaka */
442*437bfbebSnyanmisaka if ((enc_out->size) && (enc_out->data)) {
443*437bfbebSnyanmisaka if (pOutFile) {
444*437bfbebSnyanmisaka printf("dump %d bytes enc output stream to file\n",
445*437bfbebSnyanmisaka enc_out->size);
446*437bfbebSnyanmisaka //fwrite((RK_U8*)&nal, 1, 4, pOutFile); // because output stream have start code, so here mask this code
447*437bfbebSnyanmisaka fwrite(enc_out->data, 1, enc_out->size, pOutFile);
448*437bfbebSnyanmisaka fflush(pOutFile);
449*437bfbebSnyanmisaka }
450*437bfbebSnyanmisaka
451*437bfbebSnyanmisaka enc_out->size = 0;
452*437bfbebSnyanmisaka }
453*437bfbebSnyanmisaka }
454*437bfbebSnyanmisaka
455*437bfbebSnyanmisaka usleep(3000);
456*437bfbebSnyanmisaka } while (1);
457*437bfbebSnyanmisaka
458*437bfbebSnyanmisaka ENCODE_OUT:
459*437bfbebSnyanmisaka if (enc_in && enc_in->buf) {
460*437bfbebSnyanmisaka free(enc_in->buf);
461*437bfbebSnyanmisaka enc_in->buf = NULL;
462*437bfbebSnyanmisaka }
463*437bfbebSnyanmisaka if (enc_out && (enc_out->data)) {
464*437bfbebSnyanmisaka free(enc_out->data);
465*437bfbebSnyanmisaka enc_out->data = NULL;
466*437bfbebSnyanmisaka }
467*437bfbebSnyanmisaka if (ctx) {
468*437bfbebSnyanmisaka if (ctx->private_data) {
469*437bfbebSnyanmisaka free(ctx->private_data);
470*437bfbebSnyanmisaka ctx->private_data = NULL;
471*437bfbebSnyanmisaka }
472*437bfbebSnyanmisaka vpuapi_close_ctx(&ctx);
473*437bfbebSnyanmisaka ctx = NULL;
474*437bfbebSnyanmisaka }
475*437bfbebSnyanmisaka if (pInFile) {
476*437bfbebSnyanmisaka fclose(pInFile);
477*437bfbebSnyanmisaka pInFile = NULL;
478*437bfbebSnyanmisaka }
479*437bfbebSnyanmisaka if (pOutFile) {
480*437bfbebSnyanmisaka fclose(pOutFile);
481*437bfbebSnyanmisaka pOutFile = NULL;
482*437bfbebSnyanmisaka }
483*437bfbebSnyanmisaka
484*437bfbebSnyanmisaka if (ret) {
485*437bfbebSnyanmisaka printf("encode demo fail, err: %d\n", ret);
486*437bfbebSnyanmisaka } else {
487*437bfbebSnyanmisaka printf("encode demo complete OK.\n");
488*437bfbebSnyanmisaka }
489*437bfbebSnyanmisaka return ret;
490*437bfbebSnyanmisaka
491*437bfbebSnyanmisaka }
492*437bfbebSnyanmisaka
vpu_decode_demo(VpuApiDemoCmdContext_t * cmd)493*437bfbebSnyanmisaka static RK_S32 vpu_decode_demo(VpuApiDemoCmdContext_t *cmd)
494*437bfbebSnyanmisaka {
495*437bfbebSnyanmisaka FILE *pInFile = NULL;
496*437bfbebSnyanmisaka FILE *pOutFile = NULL;
497*437bfbebSnyanmisaka RK_S32 fileSize = 0, pkt_size = 0;
498*437bfbebSnyanmisaka RK_S32 ret = 0;
499*437bfbebSnyanmisaka RK_U32 frame_count = 0;
500*437bfbebSnyanmisaka DecoderOut_t decOut;
501*437bfbebSnyanmisaka VideoPacket_t demoPkt;
502*437bfbebSnyanmisaka VideoPacket_t *pkt = NULL;
503*437bfbebSnyanmisaka DecoderOut_t *pOut = NULL;
504*437bfbebSnyanmisaka VPU_FRAME *frame = NULL;
505*437bfbebSnyanmisaka RK_S64 fakeTimeUs = 0;
506*437bfbebSnyanmisaka RK_U8 *pExtra = NULL;
507*437bfbebSnyanmisaka RK_U32 extraSize = 0;
508*437bfbebSnyanmisaka RK_U32 wAlign16 = 0;
509*437bfbebSnyanmisaka RK_U32 hAlign16 = 0;
510*437bfbebSnyanmisaka RK_U32 frameSize = 0;
511*437bfbebSnyanmisaka
512*437bfbebSnyanmisaka if (cmd == NULL) {
513*437bfbebSnyanmisaka return -1;
514*437bfbebSnyanmisaka }
515*437bfbebSnyanmisaka
516*437bfbebSnyanmisaka if ((cmd->have_input == 0) || (cmd->width <= 0) || (cmd->height <= 0)
517*437bfbebSnyanmisaka || (cmd->coding <= OMX_RK_VIDEO_CodingAutoDetect)) {
518*437bfbebSnyanmisaka printf("Warning: missing needed parameters for vpu api demo\n");
519*437bfbebSnyanmisaka }
520*437bfbebSnyanmisaka
521*437bfbebSnyanmisaka if (cmd->have_input) {
522*437bfbebSnyanmisaka printf("input bitstream w: %d, h: %d, coding: %d(%s), path: %s\n",
523*437bfbebSnyanmisaka cmd->width, cmd->height, cmd->coding,
524*437bfbebSnyanmisaka cmd->codec_type == CODEC_DECODER ? "decode" : "encode",
525*437bfbebSnyanmisaka cmd->input_file);
526*437bfbebSnyanmisaka
527*437bfbebSnyanmisaka pInFile = fopen(cmd->input_file, "rb");
528*437bfbebSnyanmisaka if (pInFile == NULL) {
529*437bfbebSnyanmisaka printf("input file not exsist\n");
530*437bfbebSnyanmisaka DECODE_ERR_RET(ERROR_INVALID_PARAM);
531*437bfbebSnyanmisaka }
532*437bfbebSnyanmisaka } else {
533*437bfbebSnyanmisaka printf("please set input bitstream file\n");
534*437bfbebSnyanmisaka DECODE_ERR_RET(ERROR_INVALID_PARAM);
535*437bfbebSnyanmisaka }
536*437bfbebSnyanmisaka
537*437bfbebSnyanmisaka if (cmd->have_output) {
538*437bfbebSnyanmisaka printf("vpu api demo output file: %s\n",
539*437bfbebSnyanmisaka cmd->output_file);
540*437bfbebSnyanmisaka pOutFile = fopen(cmd->output_file, "wb");
541*437bfbebSnyanmisaka if (pOutFile == NULL) {
542*437bfbebSnyanmisaka printf("can not write output file\n");
543*437bfbebSnyanmisaka DECODE_ERR_RET(ERROR_INVALID_PARAM);
544*437bfbebSnyanmisaka }
545*437bfbebSnyanmisaka if (cmd->record_frames == 0)
546*437bfbebSnyanmisaka cmd->record_frames = 5;
547*437bfbebSnyanmisaka }
548*437bfbebSnyanmisaka
549*437bfbebSnyanmisaka fseek(pInFile, 0L, SEEK_END);
550*437bfbebSnyanmisaka fileSize = ftell(pInFile);
551*437bfbebSnyanmisaka fseek(pInFile, 0L, SEEK_SET);
552*437bfbebSnyanmisaka
553*437bfbebSnyanmisaka memset(&demoPkt, 0, sizeof(VideoPacket_t));
554*437bfbebSnyanmisaka pkt = &demoPkt;
555*437bfbebSnyanmisaka pkt->data = NULL;
556*437bfbebSnyanmisaka pkt->pts = VPU_API_NOPTS_VALUE;
557*437bfbebSnyanmisaka pkt->dts = VPU_API_NOPTS_VALUE;
558*437bfbebSnyanmisaka
559*437bfbebSnyanmisaka memset(&decOut, 0, sizeof(DecoderOut_t));
560*437bfbebSnyanmisaka pOut = &decOut;
561*437bfbebSnyanmisaka
562*437bfbebSnyanmisaka ret = vpuapi_open_ctx(&ctx);
563*437bfbebSnyanmisaka if (ret || (ctx == NULL)) {
564*437bfbebSnyanmisaka DECODE_ERR_RET(ERROR_MEMORY);
565*437bfbebSnyanmisaka }
566*437bfbebSnyanmisaka
567*437bfbebSnyanmisaka /*
568*437bfbebSnyanmisaka ** read codec extra data from input stream file.
569*437bfbebSnyanmisaka */
570*437bfbebSnyanmisaka if (readBytesFromFile((RK_U8 *)(&extraSize), 4, pInFile)) {
571*437bfbebSnyanmisaka DECODE_ERR_RET(ERROR_IO);
572*437bfbebSnyanmisaka }
573*437bfbebSnyanmisaka
574*437bfbebSnyanmisaka printf("codec extra data size: %d\n", extraSize);
575*437bfbebSnyanmisaka
576*437bfbebSnyanmisaka pExtra = (RK_U8 *)(malloc)(extraSize);
577*437bfbebSnyanmisaka if (pExtra == NULL) {
578*437bfbebSnyanmisaka DECODE_ERR_RET(ERROR_MEMORY);
579*437bfbebSnyanmisaka }
580*437bfbebSnyanmisaka memset(pExtra, 0, extraSize);
581*437bfbebSnyanmisaka
582*437bfbebSnyanmisaka if (readBytesFromFile(pExtra, extraSize, pInFile)) {
583*437bfbebSnyanmisaka DECODE_ERR_RET(ERROR_IO);
584*437bfbebSnyanmisaka }
585*437bfbebSnyanmisaka
586*437bfbebSnyanmisaka /*
587*437bfbebSnyanmisaka ** now init vpu api context. codecType, codingType, width ,height
588*437bfbebSnyanmisaka ** are all needed before init.
589*437bfbebSnyanmisaka */
590*437bfbebSnyanmisaka ctx->codecType = cmd->codec_type;
591*437bfbebSnyanmisaka ctx->videoCoding = cmd->coding;
592*437bfbebSnyanmisaka ctx->width = cmd->width;
593*437bfbebSnyanmisaka ctx->height = cmd->height;
594*437bfbebSnyanmisaka ctx->no_thread = 1;
595*437bfbebSnyanmisaka
596*437bfbebSnyanmisaka if ((ret = ctx->init(ctx, pExtra, extraSize)) != 0) {
597*437bfbebSnyanmisaka printf("init vpu api context fail, ret: 0x%X\n", ret);
598*437bfbebSnyanmisaka DECODE_ERR_RET(ERROR_INIT_VPU);
599*437bfbebSnyanmisaka }
600*437bfbebSnyanmisaka
601*437bfbebSnyanmisaka /*
602*437bfbebSnyanmisaka ** vpu api decoder process.
603*437bfbebSnyanmisaka */
604*437bfbebSnyanmisaka printf("init vpu api context ok, fileSize: %d\n", fileSize);
605*437bfbebSnyanmisaka
606*437bfbebSnyanmisaka do {
607*437bfbebSnyanmisaka if (ftell(pInFile) >= fileSize) {
608*437bfbebSnyanmisaka printf("read end of file, complete\n");
609*437bfbebSnyanmisaka break;
610*437bfbebSnyanmisaka }
611*437bfbebSnyanmisaka
612*437bfbebSnyanmisaka if (pkt && (pkt->size == 0)) {
613*437bfbebSnyanmisaka if (readBytesFromFile((RK_U8 *)(&pkt_size), 4, pInFile)) {
614*437bfbebSnyanmisaka break;
615*437bfbebSnyanmisaka }
616*437bfbebSnyanmisaka
617*437bfbebSnyanmisaka if (pkt->data == NULL) {
618*437bfbebSnyanmisaka pkt->data = (RK_U8 *)(malloc)(pkt_size);
619*437bfbebSnyanmisaka if (pkt->data == NULL) {
620*437bfbebSnyanmisaka DECODE_ERR_RET(ERROR_MEMORY);
621*437bfbebSnyanmisaka }
622*437bfbebSnyanmisaka pkt->capability = pkt_size;
623*437bfbebSnyanmisaka }
624*437bfbebSnyanmisaka
625*437bfbebSnyanmisaka if (pkt->capability < ((RK_U32)pkt_size)) {
626*437bfbebSnyanmisaka pkt->data = (RK_U8 *)(realloc)((void *)(pkt->data), pkt_size);
627*437bfbebSnyanmisaka if (pkt->data == NULL) {
628*437bfbebSnyanmisaka DECODE_ERR_RET(ERROR_MEMORY);
629*437bfbebSnyanmisaka }
630*437bfbebSnyanmisaka pkt->capability = pkt_size;
631*437bfbebSnyanmisaka }
632*437bfbebSnyanmisaka
633*437bfbebSnyanmisaka if (readBytesFromFile(pkt->data, pkt_size, pInFile)) {
634*437bfbebSnyanmisaka break;
635*437bfbebSnyanmisaka } else {
636*437bfbebSnyanmisaka pkt->size = pkt_size;
637*437bfbebSnyanmisaka pkt->pts = fakeTimeUs;
638*437bfbebSnyanmisaka fakeTimeUs += 40000;
639*437bfbebSnyanmisaka }
640*437bfbebSnyanmisaka
641*437bfbebSnyanmisaka printf("read one packet, size: %d, pts: %lld, filePos: %ld\n",
642*437bfbebSnyanmisaka pkt->size, pkt->pts, ftell(pInFile));
643*437bfbebSnyanmisaka }
644*437bfbebSnyanmisaka
645*437bfbebSnyanmisaka /* note: must set out put size to 0 before do decoder. */
646*437bfbebSnyanmisaka pOut->size = 0;
647*437bfbebSnyanmisaka
648*437bfbebSnyanmisaka if (ctx->decode_sendstream(ctx, pkt) != 0) {
649*437bfbebSnyanmisaka printf("send packet failed");
650*437bfbebSnyanmisaka DECODE_ERR_RET(ERROR_VPU_DECODE);
651*437bfbebSnyanmisaka }
652*437bfbebSnyanmisaka
653*437bfbebSnyanmisaka
654*437bfbebSnyanmisaka if ((ret = ctx->decode_getframe(ctx, pOut)) != 0) {
655*437bfbebSnyanmisaka printf("get decoded data failed\n");
656*437bfbebSnyanmisaka DECODE_ERR_RET(ERROR_VPU_DECODE);
657*437bfbebSnyanmisaka } else {
658*437bfbebSnyanmisaka printf("vpu decode one frame, out len: %d, left size: %d\n",
659*437bfbebSnyanmisaka pOut->size, pkt->size);
660*437bfbebSnyanmisaka
661*437bfbebSnyanmisaka /*
662*437bfbebSnyanmisaka ** both virtual and physical address of the decoded frame are contained
663*437bfbebSnyanmisaka ** in structure named VPU_FRAME, if you want to use virtual address, make
664*437bfbebSnyanmisaka ** sure you have done VPUMemLink before.
665*437bfbebSnyanmisaka */
666*437bfbebSnyanmisaka if ((pOut->size) && (pOut->data)) {
667*437bfbebSnyanmisaka frame = (VPU_FRAME *)(pOut->data);
668*437bfbebSnyanmisaka vpuapi_mem_link(&frame->vpumem);
669*437bfbebSnyanmisaka wAlign16 = ((frame->DisplayWidth + 15) & (~15));
670*437bfbebSnyanmisaka hAlign16 = ((frame->DisplayHeight + 15) & (~15));
671*437bfbebSnyanmisaka frameSize = wAlign16 * hAlign16 * 3 / 2;
672*437bfbebSnyanmisaka
673*437bfbebSnyanmisaka if (pOutFile && (frame_count++ < cmd->record_frames)) {
674*437bfbebSnyanmisaka printf("write %d frame(yuv420sp) data, %d bytes to file\n",
675*437bfbebSnyanmisaka frame_count, frameSize);
676*437bfbebSnyanmisaka
677*437bfbebSnyanmisaka fwrite((RK_U8 *)(frame->vpumem.vir_addr), 1, frameSize, pOutFile);
678*437bfbebSnyanmisaka fflush(pOutFile);
679*437bfbebSnyanmisaka }
680*437bfbebSnyanmisaka
681*437bfbebSnyanmisaka /*
682*437bfbebSnyanmisaka ** remember use VPUFreeLinear to free, other wise memory leak will
683*437bfbebSnyanmisaka ** give you a surprise.
684*437bfbebSnyanmisaka */
685*437bfbebSnyanmisaka vpuapi_mem_free(&frame->vpumem);
686*437bfbebSnyanmisaka // NOTE: pOut->data is malloc from vpu_api we need to free it.
687*437bfbebSnyanmisaka free(pOut->data);
688*437bfbebSnyanmisaka pOut->data = NULL;
689*437bfbebSnyanmisaka pOut->size = 0;
690*437bfbebSnyanmisaka }
691*437bfbebSnyanmisaka }
692*437bfbebSnyanmisaka
693*437bfbebSnyanmisaka usleep(3000);
694*437bfbebSnyanmisaka } while (!(ctx->decoder_err));
695*437bfbebSnyanmisaka
696*437bfbebSnyanmisaka DECODE_OUT:
697*437bfbebSnyanmisaka if (pkt && pkt->data) {
698*437bfbebSnyanmisaka free(pkt->data);
699*437bfbebSnyanmisaka pkt->data = NULL;
700*437bfbebSnyanmisaka }
701*437bfbebSnyanmisaka if (pOut && (pOut->data)) {
702*437bfbebSnyanmisaka free(pOut->data);
703*437bfbebSnyanmisaka pOut->data = NULL;
704*437bfbebSnyanmisaka }
705*437bfbebSnyanmisaka if (pExtra) {
706*437bfbebSnyanmisaka free(pExtra);
707*437bfbebSnyanmisaka pExtra = NULL;
708*437bfbebSnyanmisaka }
709*437bfbebSnyanmisaka if (ctx) {
710*437bfbebSnyanmisaka vpuapi_close_ctx(&ctx);
711*437bfbebSnyanmisaka ctx = NULL;
712*437bfbebSnyanmisaka }
713*437bfbebSnyanmisaka if (pInFile) {
714*437bfbebSnyanmisaka fclose(pInFile);
715*437bfbebSnyanmisaka pInFile = NULL;
716*437bfbebSnyanmisaka }
717*437bfbebSnyanmisaka if (pOutFile) {
718*437bfbebSnyanmisaka fclose(pOutFile);
719*437bfbebSnyanmisaka pOutFile = NULL;
720*437bfbebSnyanmisaka }
721*437bfbebSnyanmisaka
722*437bfbebSnyanmisaka if (ret) {
723*437bfbebSnyanmisaka printf("decode demo fail, err: %d\n", ret);
724*437bfbebSnyanmisaka } else {
725*437bfbebSnyanmisaka printf("encode demo complete OK.\n");
726*437bfbebSnyanmisaka }
727*437bfbebSnyanmisaka return ret;
728*437bfbebSnyanmisaka }
729*437bfbebSnyanmisaka
730*437bfbebSnyanmisaka /* vpu_api is only on Android platform */
main(int argc,char ** argv)731*437bfbebSnyanmisaka int main(int argc, char **argv)
732*437bfbebSnyanmisaka {
733*437bfbebSnyanmisaka RK_S32 ret = 0;
734*437bfbebSnyanmisaka VpuApiDemoCmdContext_t demoCmdCtx;
735*437bfbebSnyanmisaka VpuApiDemoCmdContext_t *cmd = NULL;
736*437bfbebSnyanmisaka
737*437bfbebSnyanmisaka printf("/******* vpu api demo in *******/\n");
738*437bfbebSnyanmisaka if (argc == 1) {
739*437bfbebSnyanmisaka show_usage();
740*437bfbebSnyanmisaka return 0;
741*437bfbebSnyanmisaka }
742*437bfbebSnyanmisaka
743*437bfbebSnyanmisaka /* open library for access */
744*437bfbebSnyanmisaka vpuapi_hdl = dlopen("libvpu.so", RTLD_LAZY | RTLD_GLOBAL);
745*437bfbebSnyanmisaka if (NULL == vpuapi_hdl) {
746*437bfbebSnyanmisaka printf("failed to open libvpu.so\n");
747*437bfbebSnyanmisaka ret = -1;
748*437bfbebSnyanmisaka goto DEMO_OUT;
749*437bfbebSnyanmisaka }
750*437bfbebSnyanmisaka
751*437bfbebSnyanmisaka vpuapi_open_ctx = (RK_S32 (*)(VpuCodecContext_t **ctx))dlsym(vpuapi_hdl, "vpu_open_context");
752*437bfbebSnyanmisaka vpuapi_close_ctx = (RK_S32 (*)(VpuCodecContext_t **ctx))dlsym(vpuapi_hdl, "vpu_close_context");
753*437bfbebSnyanmisaka vpuapi_mem_link = (RK_S32 (*)(VPUMemLinear_t * p))dlsym(vpuapi_hdl, "VPUMemLink");
754*437bfbebSnyanmisaka vpuapi_mem_free = (RK_S32 (*)(VPUMemLinear_t * p))dlsym(vpuapi_hdl, "VPUFreeLinear");
755*437bfbebSnyanmisaka
756*437bfbebSnyanmisaka if (NULL == vpuapi_open_ctx || NULL == vpuapi_close_ctx ||
757*437bfbebSnyanmisaka NULL == vpuapi_mem_link || NULL == vpuapi_mem_free) {
758*437bfbebSnyanmisaka printf("failed to open vpu_open_context %p vpu_close_context %p\n",
759*437bfbebSnyanmisaka vpuapi_open_ctx, vpuapi_close_ctx);
760*437bfbebSnyanmisaka printf("failed to open VPUMemLink %p VPUFreeLinear %p\n",
761*437bfbebSnyanmisaka vpuapi_mem_link, vpuapi_mem_free);
762*437bfbebSnyanmisaka ret = -1;
763*437bfbebSnyanmisaka goto DEMO_OUT;
764*437bfbebSnyanmisaka }
765*437bfbebSnyanmisaka
766*437bfbebSnyanmisaka printf("get vpuapi handle %p vpu_open_context %p vpu_close_context %p\n",
767*437bfbebSnyanmisaka vpuapi_hdl, vpuapi_open_ctx, vpuapi_close_ctx);
768*437bfbebSnyanmisaka
769*437bfbebSnyanmisaka cmd = &demoCmdCtx;
770*437bfbebSnyanmisaka memset(cmd, 0, sizeof(VpuApiDemoCmdContext_t));
771*437bfbebSnyanmisaka cmd->codec_type = CODEC_DECODER;
772*437bfbebSnyanmisaka if ((ret = parse_options(argc, argv, cmd)) != 0) {
773*437bfbebSnyanmisaka if (ret == VPU_DEMO_PARSE_HELP_OK) {
774*437bfbebSnyanmisaka return 0;
775*437bfbebSnyanmisaka }
776*437bfbebSnyanmisaka
777*437bfbebSnyanmisaka printf("parse_options fail\n\n");
778*437bfbebSnyanmisaka show_usage();
779*437bfbebSnyanmisaka DEMO_ERR_RET(ERROR_INVALID_PARAM);
780*437bfbebSnyanmisaka }
781*437bfbebSnyanmisaka
782*437bfbebSnyanmisaka switch (cmd->codec_type) {
783*437bfbebSnyanmisaka case CODEC_DECODER : {
784*437bfbebSnyanmisaka ret = vpu_decode_demo(cmd);
785*437bfbebSnyanmisaka } break;
786*437bfbebSnyanmisaka case CODEC_ENCODER : {
787*437bfbebSnyanmisaka ret = vpu_encode_demo(cmd);
788*437bfbebSnyanmisaka } break;
789*437bfbebSnyanmisaka default : {
790*437bfbebSnyanmisaka ret = ERROR_INVALID_PARAM;
791*437bfbebSnyanmisaka } break;
792*437bfbebSnyanmisaka }
793*437bfbebSnyanmisaka
794*437bfbebSnyanmisaka DEMO_OUT:
795*437bfbebSnyanmisaka if (ret) {
796*437bfbebSnyanmisaka printf("vpu api demo fail, err: %d\n", ret);
797*437bfbebSnyanmisaka if (vpuapi_hdl) {
798*437bfbebSnyanmisaka dlclose(vpuapi_hdl);
799*437bfbebSnyanmisaka vpuapi_hdl = NULL;
800*437bfbebSnyanmisaka }
801*437bfbebSnyanmisaka } else {
802*437bfbebSnyanmisaka printf("vpu api demo complete OK.\n");
803*437bfbebSnyanmisaka }
804*437bfbebSnyanmisaka return ret;
805*437bfbebSnyanmisaka }
806