xref: /OK3568_Linux_fs/external/mpp/mpp/mpp_impl.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *
3  * Copyright 2015 Rockchip Electronics Co. LTD
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #define MODULE_TAG "mpp_impl"
19 
20 #include <time.h>
21 #include <stdarg.h>
22 #include <sys/types.h>
23 #include <sys/syscall.h>
24 
25 #include "rk_mpi_cmd.h"
26 
27 #include "mpp_env.h"
28 #include "mpp_mem.h"
29 #include "mpp_time.h"
30 #include "mpp_debug.h"
31 #include "mpp_thread.h"
32 #include "mpp_common.h"
33 
34 #include "mpp_impl.h"
35 
36 #define MAX_FILE_NAME_LEN   512
37 #define MAX_DUMP_WIDTH      960
38 #define MAX_DUMP_HEIGHT     540
39 
40 #define ops_log(fp, fmt, ...)   _ops_log(fp, fmt, ## __VA_ARGS__)
41 
42 typedef enum MppOpsType_e {
43     MPP_DEC_OPS_BASE        = 0,
44     MPP_DEC_INIT            = MPP_DEC_OPS_BASE,
45     MPP_DEC_SE
46 } MppOpsType;
47 
48 /* dump data */
49 typedef struct MppDumpImpl_t {
50     Mutex                   *lock;
51     RK_U32                  log_version;
52     RK_U32                  debug;
53     pid_t                   tid;
54     RK_S64                  time_base;
55 
56     MppCtxType              type;
57     MppCodingType           coding;
58 
59     FILE                    *fp_in;    // file for MppPacket
60     FILE                    *fp_out;    // file for MppFrame
61     FILE                    *fp_ops;    // file for decoder / encoder extra info
62 
63     RK_U8                   *fp_buf;    // for resample frame
64     RK_U32                  pkt_offset;
65     RK_U32                  dump_width;
66     RK_U32                  dump_height;
67     RK_U32                  dump_size;
68 
69     RK_U32                  idx;
70 } MppDumpImpl;
71 
72 typedef struct MppOpsInfo_t {
73     RK_U32                  idx;
74     RK_U32                  id;
75     RK_S64                  time;
76 
77     union OpsArgs_u {
78         struct MppOpsInitArg_t {
79             MppCtxType      type;
80             MppCodingType   coding;
81         };
82 
83         struct MppOpsPktArg_t {
84             RK_U32          offset;         // offset in packet file
85             RK_U32          length;         // pakcet length
86             RK_S64          pts;
87         };
88 
89         struct MppOpsFrmArg_t {
90             RK_U32          fd;
91             RK_U32          info_change;
92             RK_U32          error;
93             RK_U32          discard;
94             RK_S64          pts;
95         };
96 
97         struct MppOpCtrlArg_t {
98             MpiCmd          cmd;
99         };
100     };
101 } MppOpsInfo;
102 
103 /*
104  * decoder file dump:
105  * dec_pkt - decoder input byte raw stream file
106  * dec_cfg - decoder input stream offset and size info in format [u32 offset|u32 size]
107  * dec_frm - decoder output frame file with snapshot method
108  */
109 static const char dec_pkt_path[] = "/data/mpp_dec_in.bin";
110 static const char dec_ops_path[] = "/data/mpp_dec_ops.bin";
111 static const char dec_frm_path[] = "/data/mpp_dec_out.bin";
112 
113 static const char enc_frm_path[] = "/data/mpp_enc_in.bin";
114 static const char enc_ops_path[] = "/data/mpp_enc_ops.bin";
115 static const char enc_pkt_path[] = "/data/mpp_enc_out.bin";
116 
try_env_file(const char * env,const char * path,pid_t tid)117 static FILE *try_env_file(const char *env, const char *path, pid_t tid)
118 {
119     const char *fname = NULL;
120     FILE *fp = NULL;
121     char name[MAX_FILE_NAME_LEN];
122 
123     mpp_env_get_str(env, &fname, path);
124     if (fname == path) {
125         snprintf(name, sizeof(name) - 1, "%s-%d", path, tid);
126         fname = name;
127     }
128 
129     fp = fopen(fname, "w+b");
130     mpp_log("open %s %p for dump\n", fname, fp);
131 
132     return fp;
133 }
134 
fetch_data(RK_U32 fmt,RK_U8 * line,RK_U32 num)135 static RK_U8 fetch_data(RK_U32 fmt, RK_U8 *line, RK_U32 num)
136 {
137     RK_U32 offset = 0;
138     RK_U32 value = 0;
139 
140     if (fmt == MPP_FMT_YUV420SP_10BIT) {
141         offset = (num * 2) & 7;
142         value = (line[num * 10 / 8] >> offset) |
143                 (line[num * 10 / 8 + 1] << (8 - offset));
144 
145         value = (value & 0x3ff) >> 2;
146     } else if (fmt == MPP_FMT_YUV420SP) {
147         value = line[num];
148     }
149 
150     return RK_U8(value);
151 }
152 
dump_frame(FILE * fp,MppFrame frame,RK_U8 * tmp,RK_U32 w,RK_U32 h)153 static void dump_frame(FILE *fp, MppFrame frame, RK_U8 *tmp, RK_U32 w, RK_U32 h)
154 {
155     RK_U32 i = 0, j = 0;
156     RK_U32 fmt = (mpp_frame_get_fmt(frame) & MPP_FRAME_FMT_MASK);
157     RK_U32 width = mpp_frame_get_width(frame);
158     RK_U32 height = mpp_frame_get_height(frame);
159     RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
160     RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
161     RK_U8 *p_buf = (RK_U8 *) mpp_buffer_get_ptr(mpp_frame_get_buffer(frame));
162 
163     RK_U8 *psrc = p_buf;
164     RK_U8 *pdes = tmp;
165     RK_U32 size = 0;
166 
167     if (pdes) {
168         if (hor_stride > w || ver_stride > h) {
169             RK_U32 step = MPP_MAX((hor_stride + w - 1) / w,
170                                   (ver_stride + h - 1) / h);
171             RK_U32 img_w = width / step;
172             RK_U32 img_h = height / step;
173 
174             img_w -= img_w & 0x1;
175             img_h -= img_h & 0x1;
176             for (i = 0; i < img_h; i++) {
177                 for (j = 0; j < img_w; j++)
178                     pdes[j] = fetch_data(fmt, psrc, j * step);
179                 pdes += img_w;
180                 psrc += step * hor_stride;
181             }
182             psrc = p_buf + hor_stride * ver_stride;
183             pdes = tmp + img_w * img_h;
184             for (i = 0; i < (img_h / 2); i++) {
185                 for (j = 0; j < (img_w / 2); j++) {
186                     pdes[2 * j + 0] = fetch_data(fmt, psrc, 2 * j * step + 0);
187                     pdes[2 * j + 1] = fetch_data(fmt, psrc, 2 * j * step + 1);
188                 }
189                 pdes += img_w;
190                 psrc += step * hor_stride;
191             }
192             width = img_w;
193             height = img_h;
194         } else if (fmt == MPP_FMT_YUV420SP_10BIT) {
195             for (i = 0; i < height; i++) {
196                 for (j = 0; j < width; j++)
197                     pdes[j] = fetch_data(fmt, psrc, j);
198                 pdes += width;
199                 psrc += hor_stride;
200             }
201             psrc = p_buf + hor_stride * ver_stride;
202             pdes = tmp + width * height;
203             for (i = 0; i < height / 2; i++) {
204                 for (j = 0; j < width; j++)
205                     pdes[j] = fetch_data(fmt, psrc, j);
206                 pdes += width;
207                 psrc += hor_stride;
208             }
209         }
210         size = width * height * 1.5;
211     } else {
212         tmp = p_buf;
213         switch (fmt) {
214         case MPP_FMT_YUV420SP :
215         case MPP_FMT_YUV420P : {
216             size = hor_stride * ver_stride * 3 / 2;
217         } break;
218         case MPP_FMT_YUV422SP : {
219             size = hor_stride * ver_stride * 2;
220         } break;
221         case MPP_FMT_YUV444SP : {
222             size = hor_stride * ver_stride * 3;
223         } break;
224         default : break;
225         }
226     }
227     mpp_log("dump_yuv: w:h [%d:%d] stride [%d:%d] pts %lld\n",
228             width, height, hor_stride, ver_stride, mpp_frame_get_pts(frame));
229     fwrite(tmp, 1, size, fp);
230     fflush(fp);
231 }
232 
_ops_log(FILE * fp,const char * fmt,...)233 void _ops_log(FILE *fp, const char *fmt, ...)
234 {
235     struct tm tm_buf;
236     struct tm* ptm;
237     struct timespec tp;
238     char logs[64];
239     size_t len = 0;
240     va_list args;
241     va_start(args, fmt);
242 
243     clock_gettime(CLOCK_REALTIME_COARSE, &tp);
244     ptm = localtime_r(&tp.tv_sec, &tm_buf);
245     len = strftime(logs, sizeof(logs), "%m-%d %H:%M:%S", ptm);
246     mpp_assert(len < sizeof(logs));
247     fprintf(fp, "%s.%03ld,", logs, tp.tv_nsec / 1000000);
248     vfprintf(fp, fmt, args);
249     fflush(fp);
250 
251     va_end(args);
252 }
253 
mpp_dump_init(MppDump * info)254 MPP_RET mpp_dump_init(MppDump *info)
255 {
256     if (!(mpp_debug & (MPP_DBG_DUMP_IN | MPP_DBG_DUMP_OUT | MPP_DBG_DUMP_CFG))) {
257         *info = NULL;
258         return MPP_OK;
259     }
260 
261     MppDumpImpl *p = mpp_calloc(MppDumpImpl, 1);
262 
263     mpp_env_get_u32("mpp_dump_width", &p->dump_width, 0);
264     mpp_env_get_u32("mpp_dump_height", &p->dump_height, 0);
265     p->dump_size = p->dump_width * p->dump_height * 3 / 2;
266 
267     p->lock = new Mutex();
268     p->debug = mpp_debug;
269     p->tid = syscall(SYS_gettid);
270     p->log_version = 0;
271     p->time_base = mpp_time();
272 
273     *info = p;
274 
275     return MPP_OK;
276 }
277 
mpp_dump_deinit(MppDump * info)278 MPP_RET mpp_dump_deinit(MppDump *info)
279 {
280     if (info && *info) {
281         MppDumpImpl *p = (MppDumpImpl *)*info;
282 
283         MPP_FCLOSE(p->fp_in);
284         MPP_FCLOSE(p->fp_out);
285         MPP_FCLOSE(p->fp_ops);
286         MPP_FREE(p->fp_buf);
287 
288         if (p->lock) {
289             delete p->lock;
290             p->lock = NULL;
291         }
292     }
293 
294     return MPP_OK;
295 }
296 
mpp_ops_init(MppDump info,MppCtxType type,MppCodingType coding)297 MPP_RET mpp_ops_init(MppDump info, MppCtxType type, MppCodingType coding)
298 {
299     if (NULL == info)
300         return MPP_OK;
301 
302     MppDumpImpl *p = (MppDumpImpl *)info;
303     AutoMutex auto_lock(p->lock);
304 
305     p->type = type;
306     p->coding = coding;
307 
308     if (type == MPP_CTX_DEC) {
309         if (p->debug & MPP_DBG_DUMP_IN)
310             p->fp_in = try_env_file("mpp_dump_in", dec_pkt_path, p->tid);
311 
312         if (p->debug & MPP_DBG_DUMP_OUT) {
313             p->fp_out = try_env_file("mpp_dump_out", dec_frm_path, p->tid);
314             if (p->dump_size)
315                 p->fp_buf = mpp_malloc(RK_U8, p->dump_size);
316         }
317 
318         if (p->debug & MPP_DBG_DUMP_CFG)
319             p->fp_ops = try_env_file("mpp_dump_ops", dec_ops_path, p->tid);
320     } else {
321         if (p->debug & MPP_DBG_DUMP_IN) {
322             p->fp_in = try_env_file("mpp_dump_in", enc_frm_path, p->tid);
323             if (p->dump_size)
324                 p->fp_buf = mpp_malloc(RK_U8, p->dump_size);
325         }
326 
327         if (p->debug & MPP_DBG_DUMP_OUT)
328             p->fp_out = try_env_file("mpp_dump_out", enc_pkt_path, p->tid);
329 
330         if (p->debug & MPP_DBG_DUMP_CFG)
331             p->fp_ops = try_env_file("mpp_dump_ops", enc_ops_path, p->tid);
332     }
333 
334     if (p->fp_ops)
335         ops_log(p->fp_ops, "%d,%s,%d,%d\n", p->idx++, "init", type, coding);
336 
337     return MPP_OK;
338 }
339 
mpp_ops_dec_put_pkt(MppDump info,MppPacket pkt)340 MPP_RET mpp_ops_dec_put_pkt(MppDump info, MppPacket pkt)
341 {
342     MppDumpImpl *p = (MppDumpImpl *)info;
343     if (NULL == p || NULL == pkt || NULL == p->fp_in)
344         return MPP_OK;
345 
346     RK_U32 length = mpp_packet_get_length(pkt);
347     AutoMutex auto_lock(p->lock);
348 
349     if (p->fp_in) {
350         fwrite(mpp_packet_get_data(pkt), 1, length, p->fp_in);
351         fflush(p->fp_in);
352     }
353 
354     if (p->fp_ops) {
355         ops_log(p->fp_ops, "%d,%s,%d,%d\n", p->idx++, "pkt", p->pkt_offset, length);
356 
357         p->pkt_offset += length;
358     }
359 
360     return MPP_OK;
361 }
362 
mpp_ops_dec_get_frm(MppDump info,MppFrame frame)363 MPP_RET mpp_ops_dec_get_frm(MppDump info, MppFrame frame)
364 {
365     MppDumpImpl *p = (MppDumpImpl *)info;
366     if (NULL == p || NULL == frame || NULL == p->fp_out)
367         return MPP_OK;
368 
369     AutoMutex auto_lock(p->lock);
370 
371     MppBuffer buf = mpp_frame_get_buffer(frame);
372     RK_S32 fd = (buf) ? mpp_buffer_get_fd(buf) : (-1);
373     RK_U32 info_change = mpp_frame_get_info_change(frame);
374     RK_U32 error = mpp_frame_get_errinfo(frame);
375     RK_U32 discard = mpp_frame_get_discard(frame);
376 
377     if (p->fp_ops) {
378         ops_log(p->fp_ops, "%d,%s,%d,%d,%d,%d,%lld\n", p->idx, "frm", fd,
379                 info_change, error, discard, mpp_frame_get_pts(frame));
380     }
381 
382     if (NULL == buf || fd < 0) {
383         mpp_err("failed to dump frame\n");
384         return MPP_NOK;
385     }
386 
387     dump_frame(p->fp_out, frame, p->fp_buf, p->dump_width, p->dump_height);
388 
389     if (p->debug & MPP_DBG_DUMP_LOG) {
390         RK_S64 pts = mpp_frame_get_pts(frame);
391         RK_U32 width = mpp_frame_get_hor_stride(frame);
392         RK_U32 height = mpp_frame_get_ver_stride(frame);
393 
394         mpp_log("yuv_info: [%d:%d] pts %lld", width, height, pts);
395     }
396 
397     return MPP_OK;
398 }
399 
mpp_ops_enc_put_frm(MppDump info,MppFrame frame)400 MPP_RET mpp_ops_enc_put_frm(MppDump info, MppFrame frame)
401 {
402     MppDumpImpl *p = (MppDumpImpl *)info;
403     if (NULL == p || NULL == frame || NULL == p->fp_in)
404         return MPP_OK;
405 
406     AutoMutex auto_lock(p->lock);
407 
408     dump_frame(p->fp_in, frame, p->fp_buf, p->dump_width, p->dump_height);
409 
410     if (p->debug & MPP_DBG_DUMP_LOG) {
411         RK_S64 pts = mpp_frame_get_pts(frame);
412         RK_U32 width = mpp_frame_get_hor_stride(frame);
413         RK_U32 height = mpp_frame_get_ver_stride(frame);
414 
415         mpp_log("yuv_info: [%d:%d] pts %lld", width, height, pts);
416     }
417 
418     return MPP_OK;
419 }
420 
mpp_ops_enc_get_pkt(MppDump info,MppPacket pkt)421 MPP_RET mpp_ops_enc_get_pkt(MppDump info, MppPacket pkt)
422 {
423     MppDumpImpl *p = (MppDumpImpl *)info;
424     if (NULL == p || NULL == pkt)
425         return MPP_OK;
426 
427     RK_U32 length = mpp_packet_get_length(pkt);
428     AutoMutex auto_lock(p->lock);
429 
430     if (p->fp_out) {
431         fwrite(mpp_packet_get_data(pkt), 1, length, p->fp_out);
432         fflush(p->fp_out);
433     }
434 
435     return MPP_OK;
436 }
437 
mpp_ops_ctrl(MppDump info,MpiCmd cmd)438 MPP_RET mpp_ops_ctrl(MppDump info, MpiCmd cmd)
439 {
440     MppDumpImpl *p = (MppDumpImpl *)info;
441     if (NULL == p)
442         return MPP_OK;
443 
444     AutoMutex auto_lock(p->lock);
445 
446     if (p->fp_ops)
447         ops_log(p->fp_ops, "%d,%s,%d\n", p->idx, "ctrl", cmd);
448 
449     return MPP_OK;
450 }
451 
mpp_ops_reset(MppDump info)452 MPP_RET mpp_ops_reset(MppDump info)
453 {
454     MppDumpImpl *p = (MppDumpImpl *)info;
455     if (NULL == p)
456         return MPP_OK;
457 
458     AutoMutex auto_lock(p->lock);
459 
460     if (p->fp_ops)
461         ops_log(p->fp_ops, "%d,%s\n", p->idx, "rst");
462 
463     return MPP_OK;
464 }
465