1 /*
2 * Copyright (c) 2014 Intel Corporation.  All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17 #ifndef LOG_DUMP_HELPER_INCLUDED
18 #define LOG_DUMP_HELPER_INCLUDED
19 
20 #ifndef LOG_TAG
21 #error "Before including this file, must #define LOG_TAG and #include <utils/Log.h>"
22 #endif
23 
24 #if LOG_NDEBUG == 0
25 
26 // We have dump routines for the structures defined in the following files:
27 #include "VideoFrameInfo.h"
28 #include "ProtectedDataBuffer.h"
29 
30 // The following helps to use these dump routines from command line unit tests:
31 #ifdef ANDROID
32 #define DUMP_EOL    ""
33 #else
34 #define LOGV    printf
35 #define LOGE    printf
36 #define DUMP_EOL    "\n"
37 #endif // ANDROID
38 
39 #ifndef log_helper_min
40 #define log_helper_min(a,b) ((a) < (b) ? (a) : (b))
41 #endif // log_helper_min
42 
Copy4Bytes(void * dst,const void * src)43 static inline void Copy4Bytes(void* dst, const void* src)
44 {
45     // Don't check input pointers for NULL: this is internal function,
46     // and if you pass NULL to it, your code deserves to crash.
47 
48     uint8_t* bdst = (uint8_t*) dst ;
49     const uint8_t* bsrc = (const uint8_t*) src ;
50 
51     *bdst++ = *bsrc++ ;
52     *bdst++ = *bsrc++ ;
53     *bdst++ = *bsrc++ ;
54     *bdst = *bsrc ;
55 }
56 // End of Copy4Bytes()
57 
DumpBufferToString(char * str,uint32_t strSize,const uint8_t * start,uint32_t size)58 static void DumpBufferToString(char* str, uint32_t strSize, const uint8_t* start, uint32_t size)
59 {
60     if (str == NULL || strSize == 0 || start == NULL || size == 0)
61     {
62         LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
63         return ;
64     }
65 
66     char* s = str ;
67     char* send = str + strSize ;
68 
69     const uint8_t* byte = start ;
70     const uint8_t* end = start + size ;
71 
72     while (byte < end && s < send)
73     {
74         s += snprintf(s, strSize - (s - str), "%02x ", *byte) ;
75         ++byte ;
76     }
77 }
78 // End of DumpBufferToString()
79 
DumpNaluDataBuffer(uint32_t nalu,const uint8_t * start,uint32_t size)80 static void DumpNaluDataBuffer(uint32_t nalu, const uint8_t* start, uint32_t size)
81 {
82     if (start == NULL || size == 0)
83     {
84         LOGV("NALU-dump: error: invalid parameters to %s", __FUNCTION__) ;
85         return ;
86     }
87 
88     const uint32_t STR_SIZE = 1024 ;
89     char str[STR_SIZE] = {0} ;
90 
91     DumpBufferToString(str, STR_SIZE, start, size) ;
92 
93     LOGV("NALU-dump(nalu %u): data: %s" DUMP_EOL, nalu, str) ;
94 }
95 // End of DumpNaluDataBuffer()
96 
DumpBuffer(const char * prefix,const uint8_t * start,uint32_t size)97 static void DumpBuffer(const char* prefix, const uint8_t* start, uint32_t size)
98 {
99     if (start == NULL || size == 0)
100     {
101         LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
102         return ;
103     }
104 
105     if (prefix == NULL)
106     {
107         prefix = "" ;
108     }
109 
110     const uint32_t STR_SIZE = 1024 ;
111     char str[STR_SIZE] = {0} ;
112 
113     DumpBufferToString(str, STR_SIZE, start, size) ;
114 
115     LOGV("%s: ptr=%p, size=%u, data=%s" DUMP_EOL, prefix, start, size, str) ;
116 }
117 // End of DumpBuffer()
118 
DumpNaluHeaderBuffer(const uint8_t * const start,uint32_t size)119 static void DumpNaluHeaderBuffer(const uint8_t* const start, uint32_t size)
120 {
121     if (start == NULL || size == 0)
122     {
123         LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
124         return ;
125     }
126 
127     const uint8_t* current = start ;
128 
129     uint32_t numNALUs = 0 ;
130     Copy4Bytes(&numNALUs, current) ;
131     current += sizeof(numNALUs) ;
132 
133     LOGV("NALU-dump: num NALUs = %u\n", numNALUs) ;
134 
135     if (numNALUs > MAX_NALUS_IN_FRAME)
136     {
137         LOGE("NALU-dump: ERROR, num NALUs is too big (%u)" DUMP_EOL, numNALUs) ;
138     }
139 
140     for (uint32_t nalu = 0; nalu < numNALUs; ++nalu)
141     {
142         uint32_t imr_offset = 0 ;
143         Copy4Bytes(&imr_offset, current) ;
144         current += sizeof(imr_offset) ;
145 
146         uint32_t nalu_size = 0 ;
147         Copy4Bytes(&nalu_size, current) ;
148         current += sizeof(nalu_size) ;
149 
150         uint32_t data_size = 0 ;
151         Copy4Bytes(&data_size, current) ;
152         current += sizeof(data_size) ;
153 
154         LOGV("NALU-dump(nalu %u): imr_offset = %u, nalu_size = %u, data_size = %u" DUMP_EOL,
155             nalu, imr_offset, nalu_size, data_size) ;
156 
157         DumpNaluDataBuffer(nalu, current, data_size) ;
158 
159         // Skip past the data
160         current += data_size ;
161     }
162     // End of for
163 }
164 // End of DumpNaluHeaderBuffer()
165 
DrmSchemeToString(uint32_t drmScheme)166 static const char* DrmSchemeToString(uint32_t drmScheme)
167 {
168     switch(drmScheme)
169     {
170         case DRM_SCHEME_NONE:
171             return "None" ;
172 
173         case DRM_SCHEME_WV_CLASSIC:
174             return "WV Classic" ;
175 
176         case DRM_SCHEME_WV_MODULAR:
177             return "WV Modular" ;
178 
179 #ifdef DRM_SCHEME_MCAST_SINK
180         case DRM_SCHEME_MCAST_SINK:
181             return "MCast Sink" ;
182 #endif
183 
184 #ifdef DRM_SCHEME_PLAYREADY_ASF
185         case DRM_SCHEME_PLAYREADY_ASF:
186             return "PlayReady/ASF" ;
187 #endif
188 
189         default:
190             return "unknown" ;
191     }
192 }
193 // End of DrmSchemeToString()
194 
DumpBuffer2(const char * prefix,const uint8_t * start,uint32_t size)195 static void DumpBuffer2(const char* prefix, const uint8_t* start, uint32_t size)
196 {
197     if (start == NULL || size == 0)
198     {
199         LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
200         return ;
201     }
202 
203     if (prefix == NULL)
204     {
205         prefix = "" ;
206     }
207 
208     const uint32_t STR_SIZE = 1024 ;
209     char str[STR_SIZE] = {0} ;
210 
211     DumpBufferToString(str, STR_SIZE, start, size) ;
212 
213     LOGV("%s%s" DUMP_EOL, prefix, str) ;
214 }
215 // End of DumpBuffer2()
216 
DumpProtectedDataBuffer(const char * prefix,ProtectedDataBuffer * buf)217 static void DumpProtectedDataBuffer(const char* prefix, ProtectedDataBuffer* buf)
218 {
219     if (buf == NULL)
220     {
221         LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
222         return ;
223     }
224 
225     if (prefix == NULL) { prefix = "" ; }
226 
227     const uint32_t MAX_BUFFER_DUMP_LENGTH = 32 ;
228 
229     if (buf->magic != PROTECTED_DATA_BUFFER_MAGIC)
230     {
231         const uint8_t* p = (uint8_t*) &buf->magic ;
232         LOGV("%sWrong magic: %02x %02x %02x %02x" DUMP_EOL, prefix, p[0], p[1], p[2], p[3]) ;
233         return ;
234     }
235 
236     LOGV("%smagic: ok, drmScheme: %u (%s), clear: %u, size: %u, num PES: %u" DUMP_EOL, prefix,
237         buf->drmScheme, DrmSchemeToString(buf->drmScheme), buf->clear, buf->size, buf->numPesBuffers) ;
238 
239     if (buf->numPesBuffers == 0)
240     {
241         uint32_t dumpLength = log_helper_min(buf->size, MAX_BUFFER_DUMP_LENGTH) ;
242         DumpBuffer2("data: ", buf->data, dumpLength) ;
243     }
244     else
245     {
246         for (uint32_t i = 0; i < buf->numPesBuffers; ++i)
247         {
248             const uint32_t STR_SIZE = 1024 ;
249             char str[STR_SIZE] = {0} ;
250 
251             uint32_t dumpLength = log_helper_min(buf->pesBuffers[i].pesSize, MAX_BUFFER_DUMP_LENGTH) ;
252 
253             DumpBufferToString(str, STR_SIZE,
254                 buf->data + buf->pesBuffers[i].pesDataOffset, dumpLength) ;
255 
256             LOGV("PES %u: streamCounter: %u, inputCounter: %llu, offset: %u, size: %u, PES data: %s" DUMP_EOL,
257                 i, buf->pesBuffers[i].streamCounter, buf->pesBuffers[i].inputCounter,
258                 buf->pesBuffers[i].pesDataOffset, buf->pesBuffers[i].pesSize, str) ;
259         }
260     }
261 }
262 // End of DumpProtectedDataBuffer
263 
DumpVideoFrameInfo(frame_info_t * fInfo)264 static void DumpVideoFrameInfo(frame_info_t* fInfo)
265 {
266     if (fInfo == NULL)
267     {
268         LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
269         return ;
270     }
271 
272     LOGV("frame_info_t: data = %p, size = %u, num_nalus = %u", fInfo->data, fInfo->size, fInfo->num_nalus) ;
273 
274     for (uint32_t i = 0; i < fInfo->num_nalus; ++i)
275     {
276         LOGV("nalu_info_t: type = %#x, offset = %u (%#x), data = %p, length = %u",
277             fInfo->nalus[i].type, fInfo->nalus[i].offset, fInfo->nalus[i].offset,
278             fInfo->nalus[i].data, fInfo->nalus[i].length) ;
279 
280         if (fInfo->nalus[i].data != NULL && fInfo->nalus[i].length > 0)
281         {
282             DumpBuffer2("nalu_info_t::data: ", fInfo->nalus[i].data, fInfo->nalus[i].length) ;
283         }
284     }
285 }
286 // End of DumpVideoFrameInfo()
287 
288 #else
289 
290 // Avoid #ifdef around the dump code
291 
292 #define DumpBuffer(...)
293 #define DumpBuffer2(...)
294 #define DumpNaluHeaderBuffer(...)
295 #define DumpProtectedDataBuffer(...)
296 #define DumpVideoFrameInfo(...)
297 
298 #define DUMP_EOL
299 
300 #endif // LOG_NDEBUG == 0
301 
302 #endif // LOG_DUMP_HELPER_INCLUDED
303