xref: /rockchip-linux_mpp/test/vpu_api_test.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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