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 }