C++程序  |  303行  |  7.99 KB

/*
* 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