blob: 3a12977c9a02c1b572bbead1cac31ae2c0ad6743 [file] [log] [blame]
/*
* Copyright (c) 2014 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LOG_DUMP_HELPER_INCLUDED
#define LOG_DUMP_HELPER_INCLUDED
#ifndef LOG_TAG
#error "Before including this file, must #define LOG_TAG and #include <utils/Log.h>"
#endif
#if LOG_NDEBUG == 0
// We have dump routines for the structures defined in the following files:
#include "VideoFrameInfo.h"
#include "ProtectedDataBuffer.h"
// The following helps to use these dump routines from command line unit tests:
#ifdef ANDROID
#define DUMP_EOL ""
#else
#define LOGV printf
#define LOGE printf
#define DUMP_EOL "\n"
#endif // ANDROID
#ifndef log_helper_min
#define log_helper_min(a,b) ((a) < (b) ? (a) : (b))
#endif // log_helper_min
static inline void Copy4Bytes(void* dst, const void* src)
{
// Don't check input pointers for NULL: this is internal function,
// and if you pass NULL to it, your code deserves to crash.
uint8_t* bdst = (uint8_t*) dst ;
const uint8_t* bsrc = (const uint8_t*) src ;
*bdst++ = *bsrc++ ;
*bdst++ = *bsrc++ ;
*bdst++ = *bsrc++ ;
*bdst = *bsrc ;
}
// End of Copy4Bytes()
static void DumpBufferToString(char* str, uint32_t strSize, const uint8_t* start, uint32_t size)
{
if (str == NULL || strSize == 0 || start == NULL || size == 0)
{
LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
return ;
}
char* s = str ;
char* send = str + strSize ;
const uint8_t* byte = start ;
const uint8_t* end = start + size ;
while (byte < end && s < send)
{
s += snprintf(s, strSize - (s - str), "%02x ", *byte) ;
++byte ;
}
}
// End of DumpBufferToString()
static void DumpNaluDataBuffer(uint32_t nalu, const uint8_t* start, uint32_t size)
{
if (start == NULL || size == 0)
{
LOGV("NALU-dump: error: invalid parameters to %s", __FUNCTION__) ;
return ;
}
const uint32_t STR_SIZE = 1024 ;
char str[STR_SIZE] = {0} ;
DumpBufferToString(str, STR_SIZE, start, size) ;
LOGV("NALU-dump(nalu %u): data: %s" DUMP_EOL, nalu, str) ;
}
// End of DumpNaluDataBuffer()
static void DumpBuffer(const char* prefix, const uint8_t* start, uint32_t size)
{
if (start == NULL || size == 0)
{
LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
return ;
}
if (prefix == NULL)
{
prefix = "" ;
}
const uint32_t STR_SIZE = 1024 ;
char str[STR_SIZE] = {0} ;
DumpBufferToString(str, STR_SIZE, start, size) ;
LOGV("%s: ptr=%p, size=%u, data=%s" DUMP_EOL, prefix, start, size, str) ;
}
// End of DumpBuffer()
static void DumpNaluHeaderBuffer(const uint8_t* const start, uint32_t size)
{
if (start == NULL || size == 0)
{
LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
return ;
}
const uint8_t* current = start ;
uint32_t numNALUs = 0 ;
Copy4Bytes(&numNALUs, current) ;
current += sizeof(numNALUs) ;
LOGV("NALU-dump: num NALUs = %u\n", numNALUs) ;
if (numNALUs > MAX_NALUS_IN_FRAME)
{
LOGE("NALU-dump: ERROR, num NALUs is too big (%u)" DUMP_EOL, numNALUs) ;
}
for (uint32_t nalu = 0; nalu < numNALUs; ++nalu)
{
uint32_t imr_offset = 0 ;
Copy4Bytes(&imr_offset, current) ;
current += sizeof(imr_offset) ;
uint32_t nalu_size = 0 ;
Copy4Bytes(&nalu_size, current) ;
current += sizeof(nalu_size) ;
uint32_t data_size = 0 ;
Copy4Bytes(&data_size, current) ;
current += sizeof(data_size) ;
LOGV("NALU-dump(nalu %u): imr_offset = %u, nalu_size = %u, data_size = %u" DUMP_EOL,
nalu, imr_offset, nalu_size, data_size) ;
DumpNaluDataBuffer(nalu, current, data_size) ;
// Skip past the data
current += data_size ;
}
// End of for
}
// End of DumpNaluHeaderBuffer()
static const char* DrmSchemeToString(uint32_t drmScheme)
{
switch(drmScheme)
{
case DRM_SCHEME_NONE:
return "None" ;
case DRM_SCHEME_WV_CLASSIC:
return "WV Classic" ;
case DRM_SCHEME_WV_MODULAR:
return "WV Modular" ;
#ifdef DRM_SCHEME_MCAST_SINK
case DRM_SCHEME_MCAST_SINK:
return "MCast Sink" ;
#endif
#ifdef DRM_SCHEME_PLAYREADY_ASF
case DRM_SCHEME_PLAYREADY_ASF:
return "PlayReady/ASF" ;
#endif
default:
return "unknown" ;
}
}
// End of DrmSchemeToString()
static void DumpBuffer2(const char* prefix, const uint8_t* start, uint32_t size)
{
if (start == NULL || size == 0)
{
LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
return ;
}
if (prefix == NULL)
{
prefix = "" ;
}
const uint32_t STR_SIZE = 1024 ;
char str[STR_SIZE] = {0} ;
DumpBufferToString(str, STR_SIZE, start, size) ;
LOGV("%s%s" DUMP_EOL, prefix, str) ;
}
// End of DumpBuffer2()
static void DumpProtectedDataBuffer(const char* prefix, ProtectedDataBuffer* buf)
{
if (buf == NULL)
{
LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
return ;
}
if (prefix == NULL) { prefix = "" ; }
const uint32_t MAX_BUFFER_DUMP_LENGTH = 32 ;
if (buf->magic != PROTECTED_DATA_BUFFER_MAGIC)
{
const uint8_t* p = (uint8_t*) &buf->magic ;
LOGV("%sWrong magic: %02x %02x %02x %02x" DUMP_EOL, prefix, p[0], p[1], p[2], p[3]) ;
return ;
}
LOGV("%smagic: ok, drmScheme: %u (%s), clear: %u, size: %u, num PES: %u" DUMP_EOL, prefix,
buf->drmScheme, DrmSchemeToString(buf->drmScheme), buf->clear, buf->size, buf->numPesBuffers) ;
if (buf->numPesBuffers == 0)
{
uint32_t dumpLength = log_helper_min(buf->size, MAX_BUFFER_DUMP_LENGTH) ;
DumpBuffer2("data: ", buf->data, dumpLength) ;
}
else
{
for (uint32_t i = 0; i < buf->numPesBuffers; ++i)
{
const uint32_t STR_SIZE = 1024 ;
char str[STR_SIZE] = {0} ;
uint32_t dumpLength = log_helper_min(buf->pesBuffers[i].pesSize, MAX_BUFFER_DUMP_LENGTH) ;
DumpBufferToString(str, STR_SIZE,
buf->data + buf->pesBuffers[i].pesDataOffset, dumpLength) ;
LOGV("PES %u: streamCounter: %u, inputCounter: %llu, offset: %u, size: %u, PES data: %s" DUMP_EOL,
i, buf->pesBuffers[i].streamCounter, buf->pesBuffers[i].inputCounter,
buf->pesBuffers[i].pesDataOffset, buf->pesBuffers[i].pesSize, str) ;
}
}
}
// End of DumpProtectedDataBuffer
static void DumpVideoFrameInfo(frame_info_t* fInfo)
{
if (fInfo == NULL)
{
LOGV("Error: invalid parameters to %s", __FUNCTION__) ;
return ;
}
LOGV("frame_info_t: data = %p, size = %u, num_nalus = %u", fInfo->data, fInfo->size, fInfo->num_nalus) ;
for (uint32_t i = 0; i < fInfo->num_nalus; ++i)
{
LOGV("nalu_info_t: type = %#x, offset = %u (%#x), data = %p, length = %u",
fInfo->nalus[i].type, fInfo->nalus[i].offset, fInfo->nalus[i].offset,
fInfo->nalus[i].data, fInfo->nalus[i].length) ;
if (fInfo->nalus[i].data != NULL && fInfo->nalus[i].length > 0)
{
DumpBuffer2("nalu_info_t::data: ", fInfo->nalus[i].data, fInfo->nalus[i].length) ;
}
}
}
// End of DumpVideoFrameInfo()
#else
// Avoid #ifdef around the dump code
#define DumpBuffer(...)
#define DumpBuffer2(...)
#define DumpNaluHeaderBuffer(...)
#define DumpProtectedDataBuffer(...)
#define DumpVideoFrameInfo(...)
#define DUMP_EOL
#endif // LOG_NDEBUG == 0
#endif // LOG_DUMP_HELPER_INCLUDED