1 /*--------------------------------------------------------------------------
2 Copyright (c) 2013 - 2020, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6     * Redistributions of source code must retain the above copyright
7       notice, this list of conditions and the following disclaimer.
8     * Redistributions in binary form must reproduce the above copyright
9       notice, this list of conditions and the following disclaimer in the
10       documentation and/or other materials provided with the distribution.
11     * Neither the name of The Linux Foundation nor
12       the names of its contributors may be used to endorse or promote
13       products derived from this software without specific prior written
14       permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28 
29 #ifndef __VIDC_DEBUG_H__
30 #define __VIDC_DEBUG_H__
31 
32 #ifdef _ANDROID_
33 
34 #include <cstdio>
35 #include <string.h>
36 #include <pthread.h>
37 #include <sys/mman.h>
38 extern "C" {
39 #include <utils/Log.h>
40 }
41 
42 #include <linux/videodev2.h>
43 #include "OMX_Core.h"
44 #include "vidc_common.h"
45 #include <color_metadata.h>
46 #define STRINGIFY_ENUMS
47 #include "media/hardware/VideoAPI.h"
48 #include "media/msm_vidc_utils.h"
49 
50 using android::ColorAspects;
51 using android::HDRStaticInfo;
52 
53 enum {
54    PRIO_ERROR=0x1,
55    PRIO_INFO=0x1,
56    PRIO_HIGH=0x2,
57    PRIO_LOW=0x4,
58    PRIO_TRACE_HIGH = 0x10,
59    PRIO_TRACE_LOW = 0x20,
60 };
61 
62 extern int debug_level;
63 
64 #undef DEBUG_PRINT_ERROR
65 #define DEBUG_PRINT_ERROR(fmt, args...) ({ \
66       if (debug_level & PRIO_ERROR) \
67           ALOGE(fmt,##args); \
68       })
69 #undef DEBUG_PRINT_INFO
70 #define DEBUG_PRINT_INFO(fmt, args...) ({ \
71       if (debug_level & PRIO_INFO) \
72           ALOGI(fmt,##args); \
73       })
74 #undef DEBUG_PRINT_LOW
75 #define DEBUG_PRINT_LOW(fmt, args...) ({ \
76       if (debug_level & PRIO_LOW) \
77           ALOGD(fmt,##args); \
78       })
79 #undef DEBUG_PRINT_HIGH
80 #define DEBUG_PRINT_HIGH(fmt, args...) ({ \
81       if (debug_level & PRIO_HIGH) \
82           ALOGD(fmt,##args); \
83       })
84 #else
85 #define DEBUG_PRINT_ERROR printf
86 #define DEBUG_PRINT_INFO printf
87 #define DEBUG_PRINT_LOW printf
88 #define DEBUG_PRINT_HIGH printf
89 #endif
90 
91 struct debug_cap {
92     bool in_buffer_log;
93     bool out_buffer_log;
94     bool out_cc_buffer_log;
95     bool out_meta_buffer_log;
96     char infile_name[PROPERTY_VALUE_MAX + 36];
97     char outfile_name[PROPERTY_VALUE_MAX + 36];
98     char ccoutfile_name[PROPERTY_VALUE_MAX + 36];
99     char out_ymetafile_name[PROPERTY_VALUE_MAX + 36];
100     char out_uvmetafile_name[PROPERTY_VALUE_MAX + 36];
101     char log_loc[PROPERTY_VALUE_MAX];
102     FILE *infile;
103     FILE *outfile;
104     FILE *ccoutfile;
105     FILE *out_ymeta_file;
106     FILE *out_uvmeta_file;
107     int64_t session_id;
108     int seq_count;
109 };
110 
111 #define VALIDATE_OMX_PARAM_DATA(ptr, paramType)                                \
112     {                                                                          \
113         if (ptr == NULL) { return OMX_ErrorBadParameter; }                     \
114         paramType *p = reinterpret_cast<paramType *>(ptr);                     \
115         if (p->nSize < sizeof(paramType)) {                                    \
116             ALOGE("Insufficient object size(%u) v/s expected(%zu) for type %s",\
117                     (unsigned int)p->nSize, sizeof(paramType), #paramType);    \
118             return OMX_ErrorBadParameter;                                      \
119         }                                                                      \
120     }                                                                          \
121 
122 /*
123  * Validate OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE type param
124  * *assumes* VALIDATE_OMX_PARAM_DATA checks have passed
125  * Checks for nParamCount cannot be generalized here. it is imperative that
126  *  the calling code handles it.
127  */
128 #define VALIDATE_OMX_VENDOR_EXTENSION_PARAM_DATA(ext)                                             \
129     {                                                                                             \
130         if (ext->nParamSizeUsed < 1 || ext->nParamSizeUsed > OMX_MAX_ANDROID_VENDOR_PARAMCOUNT) { \
131             ALOGE("VendorExtension: sub-params(%u) not in expected range(%u - %u)",               \
132                     ext->nParamSizeUsed, 1, OMX_MAX_ANDROID_VENDOR_PARAMCOUNT);                   \
133             return OMX_ErrorBadParameter;                                                         \
134         }                                                                                         \
135         OMX_U32 expectedSize = (OMX_U32)sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) +         \
136                 ((ext->nParamSizeUsed - 1) * (OMX_U32)sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE));\
137         if (ext->nSize < expectedSize) {                                                          \
138             ALOGE("VendorExtension: Insifficient size(%u) v/s expected(%u)",                      \
139                     ext->nSize, expectedSize);                                                    \
140             return OMX_ErrorBadParameter;                                                         \
141         }                                                                                         \
142     }                                                                                             \
143 
144 void print_debug_color_aspects(ColorAspects *a, const char *prefix);
145 void print_debug_hdr_color_info(HDRStaticInfo *hdr_info, const char *prefix);
146 void print_debug_hdr_color_info_mdata(ColorMetaData* color_mdata);
147 void print_debug_hdr10plus_metadata(ColorMetaData& color_mdata);
148 
print_omx_buffer(const char * str,OMX_BUFFERHEADERTYPE * pHeader)149 static inline void print_omx_buffer(const char *str, OMX_BUFFERHEADERTYPE *pHeader)
150 {
151     if (!pHeader)
152         return;
153 
154     DEBUG_PRINT_HIGH("%s: Header %p buffer %p alloclen %d offset %d filledlen %d timestamp %lld flags %#x",
155         str, pHeader, pHeader->pBuffer, pHeader->nAllocLen,
156         pHeader->nOffset, pHeader->nFilledLen,
157         pHeader->nTimeStamp, pHeader->nFlags);
158 }
159 
print_v4l2_buffer(const char * str,struct v4l2_buffer * v4l2)160 static inline void print_v4l2_buffer(const char *str, struct v4l2_buffer *v4l2)
161 {
162     if (!v4l2)
163         return;
164 
165     if (v4l2->length == 1)
166         DEBUG_PRINT_HIGH(
167             "%s: %s: idx %2d userptr %#lx fd %d off %d size %d filled %d flags %#x\n",
168             str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
169             "OUTPUT" : "CAPTURE", v4l2->index,
170             v4l2->m.planes[0].m.userptr, v4l2->m.planes[0].reserved[MSM_VIDC_BUFFER_FD],
171             v4l2->m.planes[0].reserved[MSM_VIDC_DATA_OFFSET], v4l2->m.planes[0].length,
172             v4l2->m.planes[0].bytesused, v4l2->flags);
173     else
174         DEBUG_PRINT_HIGH(
175             "%s: %s: idx %2d userptr %#lx fd %d off %d size %d filled %d flags %#x, extradata: fd %d off %d size %d filled %d\n",
176             str, v4l2->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ?
177             "OUTPUT" : "CAPTURE", v4l2->index,
178             v4l2->m.planes[0].m.userptr, v4l2->m.planes[0].reserved[MSM_VIDC_BUFFER_FD],
179             v4l2->m.planes[0].reserved[MSM_VIDC_DATA_OFFSET], v4l2->m.planes[0].length,
180             v4l2->m.planes[0].bytesused, v4l2->flags, v4l2->m.planes[1].reserved[MSM_VIDC_BUFFER_FD],
181             v4l2->m.planes[1].reserved[MSM_VIDC_DATA_OFFSET], v4l2->m.planes[1].length,
182             v4l2->m.planes[1].bytesused);
183 }
184 
185 class auto_lock {
186     public:
auto_lock(pthread_mutex_t & lock)187         auto_lock(pthread_mutex_t &lock)
188             : mLock(lock) {
189                 pthread_mutex_lock(&mLock);
190             }
~auto_lock()191         ~auto_lock() {
192             pthread_mutex_unlock(&mLock);
193         }
194     private:
195         pthread_mutex_t &mLock;
196 };
197 
198 class Signal {
199     bool signalled;
200     pthread_mutex_t mutex;
201     pthread_cond_t condition;
202 public:
Signal()203     Signal() {
204         pthread_condattr_t attr;
205         signalled = false;
206         pthread_condattr_init(&attr);
207         pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
208         pthread_cond_init(&condition, &attr);
209         pthread_mutex_init(&mutex, NULL);
210     }
211 
~Signal()212     ~Signal() {
213             pthread_cond_destroy(&condition);
214             pthread_mutex_destroy(&mutex);
215     }
216 
signal()217     void signal() {
218         pthread_mutex_lock(&mutex);
219         signalled = true;
220         pthread_cond_signal(&condition);
221         pthread_mutex_unlock(&mutex);
222     }
223 
wait(uint64_t timeout_nsec)224     int wait(uint64_t timeout_nsec) {
225         struct timespec ts;
226 
227         pthread_mutex_lock(&mutex);
228         if (signalled) {
229             signalled = false;
230             pthread_mutex_unlock(&mutex);
231             return 0;
232         }
233         clock_gettime(CLOCK_MONOTONIC, &ts);
234         ts.tv_sec += timeout_nsec / 1000000000;
235         ts.tv_nsec += timeout_nsec % 1000000000;
236         if (ts.tv_nsec >= 1000000000) {
237             ts.tv_nsec -= 1000000000;
238             ts.tv_sec  += 1;
239         }
240         int ret = pthread_cond_timedwait(&condition, &mutex, &ts);
241         //as the mutex lock is released inside timedwait first
242         //the singalled variant maybe changed by the main thread in some rare cases
243         //meanwhile still returns wait time out
244         //need to double check it and return 0 to process the last cmd/event during time out
245         if (signalled)
246             ret = 0;
247         signalled = false;
248         pthread_mutex_unlock(&mutex);
249         return ret;
250     }
251 };
252 
253 #ifdef _ANDROID_
254 #define ATRACE_TAG ATRACE_TAG_VIDEO
255 #include <cutils/trace.h>
256 #include <utils/Trace.h>
257 
258 class AutoTracer {
259     int mPrio;
260 public:
AutoTracer(int prio,const char * msg)261     AutoTracer(int prio, const char* msg)
262         : mPrio(prio) {
263         if (debug_level & prio) {
264             ATRACE_BEGIN(msg);
265         }
266     }
~AutoTracer()267     ~AutoTracer() {
268         if (debug_level & mPrio) {
269             ATRACE_END();
270         }
271     }
272 };
273 
274 struct __attribute__((packed)) IvfFileHeader {
275     uint8_t signature[4];
276     uint16_t version;
277     uint16_t size;
278     uint8_t fourCC[4];
279     uint16_t width;
280     uint16_t height;
281     uint32_t rate;
282     uint32_t scale;
283     uint32_t frameCount;
284     uint32_t unused;
285 
286     IvfFileHeader();
287     IvfFileHeader(bool isVp9, int width, int height,
288                 int rate, int scale, int nFrameCount);
289 };
290 
291 struct __attribute__((packed)) IvfFrameHeader {
292     uint32_t filledLen;
293     uint64_t timeStamp;
294 
295     IvfFrameHeader();
296     IvfFrameHeader(uint32_t size, uint64_t timeStamp);
297 };
298 
299 #define VIDC_TRACE_NAME_LOW(_name) AutoTracer _tracer(PRIO_TRACE_LOW, _name);
300 #define VIDC_TRACE_NAME_HIGH(_name) AutoTracer _tracer(PRIO_TRACE_HIGH, _name);
301 
302 #define VIDC_TRACE_INT_LOW(_name, _int) \
303     if (debug_level & PRIO_TRACE_LOW) { \
304         ATRACE_INT(_name, _int);        \
305     }
306 
307 #define VIDC_TRACE_INT_HIGH(_name, _int) \
308     if (debug_level & PRIO_TRACE_HIGH) { \
309         ATRACE_INT(_name, _int);        \
310     }
311 
312 #else // _ANDROID_
313 
314 #define VIDC_TRACE_NAME_LOW(_name)
315 #define VIDC_TRACE_NAME_HIGH(_name)
316 #define VIDC_TRACE_INT_LOW(_name, _int)
317 #define VIDC_TRACE_INT_HIGH(_name, _int)
318 
319 #endif // !_ANDROID_
320 
321 #endif
322