xref: /OK3568_Linux_fs/external/rknpu2/examples/rknn_yolov5_demo/utils/mpp_decoder.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 #include <stdio.h>
2 #include <sys/time.h>
3 
4 #include "mpp_decoder.h"
5 #include <unistd.h>
6 #include <pthread.h>
7 #include <sys/syscall.h>
8 
9 // #define LOGD printf
10 #define LOGD
11 
GetCurrentTimeMS()12 static unsigned long GetCurrentTimeMS() {
13     struct timeval tv;
14     gettimeofday(&tv, NULL);
15     return tv.tv_sec*1000+tv.tv_usec/1000;
16 }
17 
MppDecoder()18 MppDecoder::MppDecoder()
19 {
20 
21 }
22 
~MppDecoder()23 MppDecoder::~MppDecoder() {
24     if (loop_data.packet) {
25         mpp_packet_deinit(&loop_data.packet);
26         loop_data.packet = NULL;
27     }
28     if (frame) {
29         mpp_frame_deinit(&frame);
30         frame = NULL;
31     }
32     if (mpp_ctx) {
33         mpp_destroy(mpp_ctx);
34         mpp_ctx = NULL;
35     }
36 
37     if (loop_data.frm_grp) {
38         mpp_buffer_group_put(loop_data.frm_grp);
39         loop_data.frm_grp = NULL;
40     }
41 }
42 
Init(int video_type,int fps,void * userdata)43 int MppDecoder::Init(int video_type, int fps, void* userdata)
44 {
45     MPP_RET ret         = MPP_OK;
46     this->userdata = userdata;
47     this->fps = fps;
48     this->last_frame_time_ms = 0;
49     if(video_type == 264) {
50         mpp_type  = MPP_VIDEO_CodingAVC;
51     } else if (video_type == 265) {
52         mpp_type  =MPP_VIDEO_CodingHEVC;
53     } else {
54         LOGD("unsupport video_type %d", video_type);
55         return -1;
56     }
57     LOGD("mpi_dec_test start ");
58     memset(&loop_data, 0, sizeof(loop_data));
59     LOGD("mpi_dec_test decoder test start mpp_type %d ", mpp_type);
60 
61     MppDecCfg cfg       = NULL;
62 
63     MppCtx mpp_ctx          = NULL;
64     ret = mpp_create(&mpp_ctx, &mpp_mpi);
65     if (MPP_OK != ret) {
66         LOGD("mpp_create failed ");
67         return 0;
68     }
69 
70     ret = mpp_init(mpp_ctx, MPP_CTX_DEC, mpp_type);
71     if (ret) {
72         LOGD("%p mpp_init failed ", mpp_ctx);
73         return -1;
74     }
75 
76     mpp_dec_cfg_init(&cfg);
77 
78     /* get default config from decoder context */
79     ret = mpp_mpi->control(mpp_ctx, MPP_DEC_GET_CFG, cfg);
80     if (ret) {
81         LOGD("%p failed to get decoder cfg ret %d ", mpp_ctx, ret);
82         return -1;
83     }
84 
85     /*
86      * split_parse is to enable mpp internal frame spliter when the input
87      * packet is not aplited into frames.
88      */
89     ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split);
90     if (ret) {
91         LOGD("%p failed to set split_parse ret %d ", mpp_ctx, ret);
92         return -1;
93     }
94 
95     ret = mpp_mpi->control(mpp_ctx, MPP_DEC_SET_CFG, cfg);
96     if (ret) {
97         LOGD("%p failed to set cfg %p ret %d ", mpp_ctx, cfg, ret);
98         return -1;
99     }
100 
101     mpp_dec_cfg_deinit(cfg);
102 
103     loop_data.ctx            = mpp_ctx;
104     loop_data.mpi            = mpp_mpi;
105     loop_data.eos            = 0;
106     loop_data.packet_size    = packet_size;
107     loop_data.frame          = 0;
108     loop_data.frame_count    = 0;
109     return 1;
110 }
111 
Reset()112 int MppDecoder::Reset() {
113     if (mpp_mpi != NULL) {
114         mpp_mpi->reset(mpp_ctx);
115     }
116     return 0;
117 }
118 
Decode(uint8_t * pkt_data,int pkt_size,int pkt_eos)119 int MppDecoder::Decode(uint8_t* pkt_data, int pkt_size, int pkt_eos)
120 {
121     MpiDecLoopData *data=&loop_data;
122     RK_U32 pkt_done = 0;
123     RK_U32 err_info = 0;
124     MPP_RET ret = MPP_OK;
125     MppCtx ctx  = data->ctx;
126     MppApi *mpi = data->mpi;
127 
128     size_t read_size = 0;
129     size_t packet_size = data->packet_size;
130 
131     LOGD("receive packet size=%d ", pkt_size);
132 
133     if (packet == NULL) {
134         ret = mpp_packet_init(&packet, NULL, 0);
135     }
136 
137     ///////////////////////////////////////////////
138     // ret = mpp_packet_init(&packet, frame_data, frame_size);
139     mpp_packet_set_data(packet, pkt_data);
140     mpp_packet_set_size(packet, pkt_size);
141     mpp_packet_set_pos(packet, pkt_data);
142     mpp_packet_set_length(packet, pkt_size);
143     // setup eos flag
144     if (pkt_eos)
145         mpp_packet_set_eos(packet);
146     do {
147 
148         RK_S32 times = 5;
149         // send the packet first if packet is not done
150         if (!pkt_done) {
151             ret = mpi->decode_put_packet(ctx, packet);
152             if (MPP_OK == ret)
153                 pkt_done = 1;
154         }
155         // then get all available frame and release
156         do {
157             RK_S32 get_frm = 0;
158             RK_U32 frm_eos = 0;
159 
160             try_again:
161             ret = mpi->decode_get_frame(ctx, &frame);
162             if (MPP_ERR_TIMEOUT == ret) {
163                 if (times > 0) {
164                     times--;
165                     usleep(2000);
166                     goto try_again;
167                 }
168                 LOGD("decode_get_frame failed too much time ");
169             }
170 
171             if (MPP_OK != ret) {
172                 LOGD("decode_get_frame failed ret %d ", ret);
173                 break;
174             }
175 
176             if (frame) {
177                 RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
178                 RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
179                 RK_U32 hor_width = mpp_frame_get_width(frame);
180                 RK_U32 ver_height = mpp_frame_get_height(frame);
181                 RK_U32 buf_size = mpp_frame_get_buf_size(frame);
182                 RK_S64 pts = mpp_frame_get_pts(frame);
183                 RK_S64 dts = mpp_frame_get_dts(frame);
184 
185                 LOGD("decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d pts=%ld dts=%ld ",
186                         hor_width, ver_height, hor_stride, ver_stride, buf_size, pts, dts);
187 
188                 if (mpp_frame_get_info_change(frame)) {
189 
190                     LOGD("decode_get_frame get info changed found ");
191                     // ret = mpp_buffer_group_get_internal(&data->frm_grp, MPP_BUFFER_TYPE_DRM);
192                     // if (ret) {
193                     //     LOGD("get mpp buffer group  failed ret %d ", ret);
194                     //     break;
195                     // }
196                     // mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, data->frm_grp);
197                     // mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
198                     if (NULL == data->frm_grp) {
199                         /* If buffer group is not set create one and limit it */
200                         ret = mpp_buffer_group_get_internal(&data->frm_grp, MPP_BUFFER_TYPE_DRM);
201                         if (ret) {
202                             LOGD("%p get mpp buffer group failed ret %d ", ctx, ret);
203                             break;
204                         }
205 
206                         /* Set buffer to mpp decoder */
207                         ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, data->frm_grp);
208                         if (ret) {
209                             LOGD("%p set buffer group failed ret %d ", ctx, ret);
210                             break;
211                         }
212                     } else {
213                         /* If old buffer group exist clear it */
214                         ret = mpp_buffer_group_clear(data->frm_grp);
215                         if (ret) {
216                             LOGD("%p clear buffer group failed ret %d ", ctx, ret);
217                             break;
218                         }
219                     }
220 
221                     /* Use limit config to limit buffer count to 24 with buf_size */
222                     ret = mpp_buffer_group_limit_config(data->frm_grp, buf_size, 24);
223                     if (ret) {
224                         LOGD("%p limit buffer group failed ret %d ", ctx, ret);
225                         break;
226                     }
227 
228                     /*
229                      * All buffer group config done. Set info change ready to let
230                      * decoder continue decoding
231                      */
232                     ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
233                     if (ret) {
234                         LOGD("%p info change ready failed ret %d ", ctx, ret);
235                         break;
236                     }
237 
238                     this->last_frame_time_ms = GetCurrentTimeMS();
239                 } else {
240                     err_info = mpp_frame_get_errinfo(frame) | mpp_frame_get_discard(frame);
241                     if (err_info) {
242                         LOGD("decoder_get_frame get err info:%d discard:%d. ",
243                                 mpp_frame_get_errinfo(frame), mpp_frame_get_discard(frame));
244                     }
245                     data->frame_count++;
246                     struct timeval tv;
247                     gettimeofday(&tv, NULL);
248                     LOGD("get one frame %ld ",  (tv.tv_sec * 1000 + tv.tv_usec/1000));
249                     // mpp_frame_get_width(frame);
250                     // char *input_data =(char *) mpp_buffer_get_ptr(mpp_frame_get_buffer(frame));
251                     if (callback != nullptr) {
252                         MppFrameFormat format = mpp_frame_get_fmt(frame);
253                         char *data_vir =(char *) mpp_buffer_get_ptr(mpp_frame_get_buffer(frame));
254                         int fd = mpp_buffer_get_fd(mpp_frame_get_buffer(frame));
255                         LOGD("data_vir=%p fd=%d ", data_vir, fd);
256                         callback(this->userdata, hor_stride, ver_stride, hor_width, ver_height, format, fd, data_vir);
257                     }
258                     unsigned long cur_time_ms = GetCurrentTimeMS();
259                     long time_gap = 1000/this->fps - (cur_time_ms - this->last_frame_time_ms);
260                     LOGD("time_gap=%ld", time_gap);
261                     if (time_gap > 0) {
262                         usleep(time_gap * 1000);
263                     }
264                     this->last_frame_time_ms = GetCurrentTimeMS();
265                 }
266                 frm_eos = mpp_frame_get_eos(frame);
267 
268                 ret = mpp_frame_deinit(&frame);
269                 frame = NULL;
270 
271                 // if(frame_pre!=NULL)
272                 // {
273                 //     mpp_frame_deinit(&frame_pre);
274                 // }
275                 // &frame_pre=&frame;
276 
277                 get_frm = 1;
278             }
279 
280             // try get runtime frame memory usage
281             if (data->frm_grp) {
282                 size_t usage = mpp_buffer_group_usage(data->frm_grp);
283                 if (usage > data->max_usage)
284                     data->max_usage = usage;
285             }
286 
287             // if last packet is send but last frame is not found continue
288             if (pkt_eos && pkt_done && !frm_eos) {
289                 usleep(1*1000);
290                 continue;
291             }
292 
293             if (frm_eos) {
294                 LOGD("found last frame ");
295                 break;
296             }
297 
298             if (data->frame_num > 0 && data->frame_count >= data->frame_num) {
299                 data->eos = 1;
300                 break;
301             }
302 
303             if (get_frm)
304                 continue;
305             break;
306         } while (1);
307 
308         if (data->frame_num > 0 && data->frame_count >= data->frame_num) {
309             data->eos = 1;
310             LOGD("reach max frame number %d ", data->frame_count);
311             break;
312         }
313 
314         if (pkt_done)
315             break;
316 
317         /*
318          * why sleep here:
319          * mpi->decode_put_packet will failed when packet in internal queue is
320          * full,waiting the package is consumed .Usually hardware decode one
321          * frame which resolution is 1080p needs 2 ms,so here we sleep 3ms
322          * * is enough.
323          */
324         usleep(3*1000);
325     } while (1);
326     mpp_packet_deinit(&packet);
327 
328     return ret;
329 }
330 
SetCallback(MppDecoderFrameCallback callback)331 int MppDecoder::SetCallback(MppDecoderFrameCallback callback) {
332     this->callback = callback;
333     return 0;
334 }