Home | History | Annotate | Download | only in libhwcomposer
      1 /*
      2  * Copyright (c) 2012-2014, 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
      6  * met:
      7  *   * Redistributions of source code must retain the above copyright
      8  *     notice, this list of conditions and the following disclaimer.
      9  *   * Redistributions in binary form must reproduce the above
     10  *     copyright notice, this list of conditions and the following
     11  *     disclaimer in the documentation and/or other materials provided
     12  *     with the distribution.
     13  *   * Neither the name of Linux Foundation nor the names of its
     14  *     contributors may be used to endorse or promote products derived
     15  *     from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #ifndef LOG_TAG
     31 #define LOG_TAG "qsfdump"
     32 #endif
     33 #define LOG_NDEBUG 0
     34 #include <hwc_utils.h>
     35 #include <hwc_dump_layers.h>
     36 #include <cutils/log.h>
     37 #include <sys/stat.h>
     38 #include <comptype.h>
     39 #ifdef QCOM_BSP
     40 // Ignore Wconversion errors for external headers
     41 #pragma GCC diagnostic push
     42 #pragma GCC diagnostic ignored "-Wconversion"
     43 #include <SkBitmap.h>
     44 #include <SkImageEncoder.h>
     45 #pragma GCC diagnostic pop
     46 #endif
     47 #ifdef STDC_FORMAT_MACROS
     48 #include <inttypes.h>
     49 #endif
     50 
     51 namespace qhwc {
     52 
     53 // MAX_ALLOWED_FRAMEDUMPS must be capped to (LONG_MAX - 1)
     54 // 60fps => 216000 frames per hour
     55 // Below setting of 216000 * 24 * 7 => 1 week or 168 hours of capture.
     56   enum {
     57     MAX_ALLOWED_FRAMEDUMPS = (216000 * 24 * 7)
     58   };
     59 
     60 bool HwcDebug::sDumpEnable = false;
     61 
     62 HwcDebug::HwcDebug(uint32_t dpy):
     63   mDumpCntLimRaw(0),
     64   mDumpCntrRaw(1),
     65   mDumpCntLimPng(0),
     66   mDumpCntrPng(1),
     67   mDpy(dpy) {
     68     char dumpPropStr[PROPERTY_VALUE_MAX];
     69     if(mDpy) {
     70         strlcpy(mDisplayName, "external", sizeof(mDisplayName));
     71     } else {
     72         strlcpy(mDisplayName, "primary", sizeof(mDisplayName));
     73     }
     74     snprintf(mDumpPropKeyDisplayType, sizeof(mDumpPropKeyDisplayType),
     75              "debug.sf.dump.%s", (char *)mDisplayName);
     76 
     77     if ((property_get("debug.sf.dump.enable", dumpPropStr, NULL) > 0)) {
     78         if(!strncmp(dumpPropStr, "true", strlen("true"))) {
     79             sDumpEnable = true;
     80         }
     81     }
     82 }
     83 
     84 void HwcDebug::dumpLayers(hwc_display_contents_1_t* list)
     85 {
     86     // Check need for dumping layers for debugging.
     87     if (UNLIKELY(sDumpEnable) && UNLIKELY(needToDumpLayers()) && LIKELY(list)) {
     88         logHwcProps(list->flags);
     89         for (size_t i = 0; i < list->numHwLayers; i++) {
     90             logLayer(i, list->hwLayers);
     91             dumpLayer(i, list->hwLayers);
     92         }
     93     }
     94 }
     95 
     96 bool HwcDebug::needToDumpLayers()
     97 {
     98     bool bDumpLayer = false;
     99     char dumpPropStr[PROPERTY_VALUE_MAX];
    100     // Enable primary dump and disable external dump by default.
    101     bool bDumpEnable = !mDpy;
    102     time_t timeNow;
    103     tm dumpTime;
    104 
    105     // Override the bDumpEnable based on the property value, if the property
    106     // is present in the build.prop file.
    107     if ((property_get(mDumpPropKeyDisplayType, dumpPropStr, NULL) > 0)) {
    108         if(!strncmp(dumpPropStr, "true", strlen("true")))
    109             bDumpEnable = true;
    110         else
    111             bDumpEnable = false;
    112     }
    113 
    114     if (false == bDumpEnable)
    115         return false;
    116 
    117     time(&timeNow);
    118     localtime_r(&timeNow, &dumpTime);
    119 
    120     if ((property_get("debug.sf.dump.png", dumpPropStr, NULL) > 0) &&
    121             (strncmp(dumpPropStr, mDumpPropStrPng, PROPERTY_VALUE_MAX - 1))) {
    122         // Strings exist & not equal implies it has changed, so trigger a dump
    123         strlcpy(mDumpPropStrPng, dumpPropStr, sizeof(mDumpPropStrPng));
    124         mDumpCntLimPng = atoi(dumpPropStr);
    125         if (mDumpCntLimPng > MAX_ALLOWED_FRAMEDUMPS) {
    126             ALOGW("Warning: Using debug.sf.dump.png %d (= max)",
    127                 MAX_ALLOWED_FRAMEDUMPS);
    128             mDumpCntLimPng = MAX_ALLOWED_FRAMEDUMPS;
    129         }
    130         mDumpCntLimPng = (mDumpCntLimPng < 0) ? 0: mDumpCntLimPng;
    131         if (mDumpCntLimPng) {
    132             snprintf(mDumpDirPng, sizeof(mDumpDirPng),
    133                     "/data/sfdump.png.%04d.%02d.%02d.%02d.%02d.%02d",
    134                     dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
    135                     dumpTime.tm_mday, dumpTime.tm_hour,
    136                     dumpTime.tm_min, dumpTime.tm_sec);
    137             if (0 == mkdir(mDumpDirPng, 0777))
    138                 mDumpCntrPng = 0;
    139             else {
    140                 ALOGE("Error: %s. Failed to create sfdump directory: %s",
    141                     strerror(errno), mDumpDirPng);
    142                 mDumpCntrPng = mDumpCntLimPng + 1;
    143             }
    144         }
    145     }
    146 
    147     if (mDumpCntrPng <= mDumpCntLimPng)
    148         mDumpCntrPng++;
    149 
    150     if ((property_get("debug.sf.dump", dumpPropStr, NULL) > 0) &&
    151             (strncmp(dumpPropStr, mDumpPropStrRaw, PROPERTY_VALUE_MAX - 1))) {
    152         // Strings exist & not equal implies it has changed, so trigger a dump
    153         strlcpy(mDumpPropStrRaw, dumpPropStr, sizeof(mDumpPropStrRaw));
    154         mDumpCntLimRaw = atoi(dumpPropStr);
    155         if (mDumpCntLimRaw > MAX_ALLOWED_FRAMEDUMPS) {
    156             ALOGW("Warning: Using debug.sf.dump %d (= max)",
    157                 MAX_ALLOWED_FRAMEDUMPS);
    158             mDumpCntLimRaw = MAX_ALLOWED_FRAMEDUMPS;
    159         }
    160         mDumpCntLimRaw = (mDumpCntLimRaw < 0) ? 0: mDumpCntLimRaw;
    161         if (mDumpCntLimRaw) {
    162             snprintf(mDumpDirRaw, sizeof(mDumpDirRaw),
    163                     "/data/sfdump.raw.%04d.%02d.%02d.%02d.%02d.%02d",
    164                     dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
    165                     dumpTime.tm_mday, dumpTime.tm_hour,
    166                     dumpTime.tm_min, dumpTime.tm_sec);
    167             if (0 == mkdir(mDumpDirRaw, 0777))
    168                 mDumpCntrRaw = 0;
    169             else {
    170                 ALOGE("Error: %s. Failed to create sfdump directory: %s",
    171                     strerror(errno), mDumpDirRaw);
    172                 mDumpCntrRaw = mDumpCntLimRaw + 1;
    173             }
    174         }
    175     }
    176 
    177     if (mDumpCntrRaw <= mDumpCntLimRaw)
    178         mDumpCntrRaw++;
    179 
    180     bDumpLayer = (mDumpCntLimPng || mDumpCntLimRaw)? true : false;
    181     return bDumpLayer;
    182 }
    183 
    184 void HwcDebug::logHwcProps(uint32_t listFlags)
    185 {
    186     static int hwcModuleCompType = -1;
    187     static int sMdpCompMaxLayers = 0;
    188     static String8 hwcModuleCompTypeLog("");
    189     if (-1 == hwcModuleCompType) {
    190         // One time stuff
    191         char mdpCompPropStr[PROPERTY_VALUE_MAX];
    192         if (property_get("debug.mdpcomp.maxlayer", mdpCompPropStr, NULL) > 0) {
    193             sMdpCompMaxLayers = atoi(mdpCompPropStr);
    194         }
    195         hwcModuleCompType =
    196             qdutils::QCCompositionType::getInstance().getCompositionType();
    197         hwcModuleCompTypeLog.appendFormat("%s%s%s%s%s%s",
    198             // Is hwc module composition type now a bit-field?!
    199             (hwcModuleCompType == qdutils::COMPOSITION_TYPE_GPU)?
    200                 "[GPU]": "",
    201             (hwcModuleCompType & qdutils::COMPOSITION_TYPE_MDP)?
    202                 "[MDP]": "",
    203             (hwcModuleCompType & qdutils::COMPOSITION_TYPE_C2D)?
    204                 "[C2D]": "",
    205             (hwcModuleCompType & qdutils::COMPOSITION_TYPE_CPU)?
    206                 "[CPU]": "",
    207             (hwcModuleCompType & qdutils::COMPOSITION_TYPE_DYN)?
    208                 "[DYN]": "",
    209             (hwcModuleCompType >= (qdutils::COMPOSITION_TYPE_DYN << 1))?
    210                 "[???]": "");
    211     }
    212     ALOGI("Display[%s] Layer[*] %s-HwcModuleCompType, %d-layer MdpComp %s",
    213          mDisplayName, hwcModuleCompTypeLog.string(), sMdpCompMaxLayers,
    214         (listFlags & HWC_GEOMETRY_CHANGED)? "[HwcList Geometry Changed]": "");
    215 }
    216 
    217 void HwcDebug::logLayer(size_t layerIndex, hwc_layer_1_t hwLayers[])
    218 {
    219     if (NULL == hwLayers) {
    220         ALOGE("Display[%s] Layer[%zu] Error. No hwc layers to log.",
    221             mDisplayName, layerIndex);
    222         return;
    223     }
    224 
    225     hwc_layer_1_t *layer = &hwLayers[layerIndex];
    226     hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
    227     hwc_rect_t displayFrame = layer->displayFrame;
    228     size_t numHwcRects = layer->visibleRegionScreen.numRects;
    229     hwc_rect_t const *hwcRects = layer->visibleRegionScreen.rects;
    230     private_handle_t *hnd = (private_handle_t *)layer->handle;
    231 
    232     char pixFormatStr[32] = "None";
    233     String8 hwcVisRegsScrLog("[None]");
    234 
    235     for (size_t i = 0 ; (hwcRects && (i < numHwcRects)); i++) {
    236         if (0 == i)
    237             hwcVisRegsScrLog.clear();
    238         hwcVisRegsScrLog.appendFormat("[%dl, %dt, %dr, %db]",
    239                                         hwcRects[i].left, hwcRects[i].top,
    240                                         hwcRects[i].right, hwcRects[i].bottom);
    241     }
    242 
    243     if (hnd)
    244         getHalPixelFormatStr(hnd->format, pixFormatStr);
    245 
    246     // Log Line 1
    247     ALOGI("Display[%s] Layer[%zu] SrcBuff[%dx%d] SrcCrop[%dl, %dt, %dr, %db] "
    248         "DispFrame[%dl, %dt, %dr, %db] VisRegsScr%s", mDisplayName, layerIndex,
    249         (hnd)? getWidth(hnd) : -1, (hnd)? getHeight(hnd) : -1,
    250         sourceCrop.left, sourceCrop.top,
    251         sourceCrop.right, sourceCrop.bottom,
    252         displayFrame.left, displayFrame.top,
    253         displayFrame.right, displayFrame.bottom,
    254         hwcVisRegsScrLog.string());
    255     // Log Line 2
    256     ALOGI("Display[%s] Layer[%zu] LayerCompType = %s, Format = %s, "
    257         "Orientation = %s, Flags = %s%s%s, Hints = %s%s%s, "
    258         "Blending = %s%s%s", mDisplayName, layerIndex,
    259         (layer->compositionType == HWC_FRAMEBUFFER)? "Framebuffer(GPU)":
    260             (layer->compositionType == HWC_OVERLAY)? "Overlay":
    261             (layer->compositionType == HWC_BACKGROUND)? "Background":"???",
    262          pixFormatStr,
    263          (layer->transform == 0)? "ROT_0":
    264              (layer->transform == HWC_TRANSFORM_FLIP_H)? "FLIP_H":
    265              (layer->transform == HWC_TRANSFORM_FLIP_V)? "FLIP_V":
    266              (layer->transform == HWC_TRANSFORM_ROT_90)? "ROT_90":
    267                                                         "ROT_INVALID",
    268          (layer->flags)? "": "[None]",
    269          (layer->flags & HWC_SKIP_LAYER)? "[Skip layer]":"",
    270          (layer->flags & qhwc::HWC_MDPCOMP)? "[MDP Comp]":"",
    271          (layer->hints)? "":"[None]",
    272          (layer->hints & HWC_HINT_TRIPLE_BUFFER)? "[Triple Buffer]":"",
    273          (layer->hints & HWC_HINT_CLEAR_FB)? "[Clear FB]":"",
    274          (layer->blending == HWC_BLENDING_NONE)? "[None]":"",
    275          (layer->blending == HWC_BLENDING_PREMULT)? "[PreMult]":"",
    276          (layer->blending == HWC_BLENDING_COVERAGE)? "[Coverage]":"");
    277 }
    278 
    279 void HwcDebug::dumpLayer(size_t layerIndex, hwc_layer_1_t hwLayers[])
    280 {
    281     char dumpLogStrPng[128] = "";
    282     char dumpLogStrRaw[128] = "";
    283     bool needDumpPng = (mDumpCntrPng <= mDumpCntLimPng)? true:false;
    284     bool needDumpRaw = (mDumpCntrRaw <= mDumpCntLimRaw)? true:false;
    285 
    286     if (needDumpPng) {
    287         snprintf(dumpLogStrPng, sizeof(dumpLogStrPng),
    288             "[png-dump-frame: %03d of %03d]", mDumpCntrPng,
    289             mDumpCntLimPng);
    290     }
    291     if (needDumpRaw) {
    292         snprintf(dumpLogStrRaw, sizeof(dumpLogStrRaw),
    293             "[raw-dump-frame: %03d of %03d]", mDumpCntrRaw,
    294             mDumpCntLimRaw);
    295     }
    296 
    297     if (!(needDumpPng || needDumpRaw))
    298         return;
    299 
    300     if (NULL == hwLayers) {
    301         ALOGE("Display[%s] Layer[%zu] %s%s Error: No hwc layers to dump.",
    302             mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
    303         return;
    304     }
    305 
    306     hwc_layer_1_t *layer = &hwLayers[layerIndex];
    307     private_handle_t *hnd = (private_handle_t *)layer->handle;
    308     char pixFormatStr[32] = "None";
    309 
    310     if (NULL == hnd) {
    311         ALOGI("Display[%s] Layer[%zu] %s%s Skipping dump: Bufferless layer.",
    312             mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
    313         return;
    314     }
    315 
    316     getHalPixelFormatStr(hnd->format, pixFormatStr);
    317 #ifdef QCOM_BSP
    318     if (needDumpPng && hnd->base) {
    319         bool bResult = false;
    320         char dumpFilename[PATH_MAX];
    321         SkColorType tempSkBmpColor = kUnknown_SkColorType;
    322         snprintf(dumpFilename, sizeof(dumpFilename),
    323             "%s/sfdump%03d.layer%zu.%s.png", mDumpDirPng,
    324             mDumpCntrPng, layerIndex, mDisplayName);
    325 
    326         switch (hnd->format) {
    327             case HAL_PIXEL_FORMAT_RGBA_8888:
    328             case HAL_PIXEL_FORMAT_RGBX_8888:
    329                 tempSkBmpColor = kRGBA_8888_SkColorType;
    330                 break;
    331             case HAL_PIXEL_FORMAT_BGRA_8888:
    332                 tempSkBmpColor = kBGRA_8888_SkColorType;
    333                 break;
    334             case HAL_PIXEL_FORMAT_RGB_565:
    335                 tempSkBmpColor = kRGB_565_SkColorType;
    336                 break;
    337             case HAL_PIXEL_FORMAT_RGBA_5551:
    338             case HAL_PIXEL_FORMAT_RGBA_4444:
    339             case HAL_PIXEL_FORMAT_RGB_888:
    340             default:
    341                 tempSkBmpColor = kUnknown_SkColorType;
    342                 break;
    343         }
    344         if (kUnknown_SkColorType != tempSkBmpColor) {
    345             SkImageInfo info = SkImageInfo::Make(getWidth(hnd), getHeight(hnd),
    346                                                  tempSkBmpColor, kIgnore_SkAlphaType);
    347             SkPixmap pixmap(info, (const void*)hnd->base, info.minRowBytes());
    348             SkFILEWStream file(dumpFilename);
    349             bResult = SkEncodeImage(&file, pixmap, SkEncodedImageFormat::kPNG, 100);
    350             ALOGI("Display[%s] Layer[%zu] %s Dump to %s: %s",
    351                 mDisplayName, layerIndex, dumpLogStrPng,
    352                 dumpFilename, bResult ? "Success" : "Fail");
    353         } else {
    354             ALOGI("Display[%s] Layer[%zu] %s Skipping dump: Unsupported layer"
    355                 " format %s for png encoder",
    356                 mDisplayName, layerIndex, dumpLogStrPng, pixFormatStr);
    357         }
    358     }
    359 #endif
    360     if (needDumpRaw && hnd->base) {
    361         char dumpFilename[PATH_MAX];
    362         bool bResult = false;
    363         snprintf(dumpFilename, sizeof(dumpFilename),
    364             "%s/sfdump%03d.layer%zu.%dx%d.%s.%s.raw",
    365             mDumpDirRaw, mDumpCntrRaw,
    366             layerIndex, getWidth(hnd), getHeight(hnd),
    367             pixFormatStr, mDisplayName);
    368         FILE* fp = fopen(dumpFilename, "w+");
    369         if (NULL != fp) {
    370             bResult = (bool) fwrite((void*)hnd->base, hnd->size, 1, fp);
    371             fclose(fp);
    372         }
    373         ALOGI("Display[%s] Layer[%zu] %s Dump to %s: %s",
    374             mDisplayName, layerIndex, dumpLogStrRaw,
    375             dumpFilename, bResult ? "Success" : "Fail");
    376     }
    377 }
    378 
    379 void HwcDebug::getHalPixelFormatStr(int format, char pixFormatStr[])
    380 {
    381     if (!pixFormatStr)
    382         return;
    383 
    384     switch(format) {
    385         case HAL_PIXEL_FORMAT_RGBA_8888:
    386             strlcpy(pixFormatStr, "RGBA_8888", sizeof(pixFormatStr));
    387             break;
    388         case HAL_PIXEL_FORMAT_RGBX_8888:
    389             strlcpy(pixFormatStr, "RGBX_8888", sizeof(pixFormatStr));
    390             break;
    391         case HAL_PIXEL_FORMAT_RGB_888:
    392             strlcpy(pixFormatStr, "RGB_888", sizeof(pixFormatStr));
    393             break;
    394         case HAL_PIXEL_FORMAT_RGB_565:
    395             strlcpy(pixFormatStr, "RGB_565", sizeof(pixFormatStr));
    396             break;
    397         case HAL_PIXEL_FORMAT_BGRA_8888:
    398             strlcpy(pixFormatStr, "BGRA_8888", sizeof(pixFormatStr));
    399             break;
    400         case HAL_PIXEL_FORMAT_RGBA_5551:
    401             strlcpy(pixFormatStr, "RGBA_5551", sizeof(pixFormatStr));
    402             break;
    403         case HAL_PIXEL_FORMAT_RGBA_4444:
    404             strlcpy(pixFormatStr, "RGBA_4444", sizeof(pixFormatStr));
    405             break;
    406         case HAL_PIXEL_FORMAT_YV12:
    407             strlcpy(pixFormatStr, "YV12", sizeof(pixFormatStr));
    408             break;
    409         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
    410             strlcpy(pixFormatStr, "YCbCr_422_SP_NV16", sizeof(pixFormatStr));
    411             break;
    412         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
    413             strlcpy(pixFormatStr, "YCrCb_420_SP_NV21", sizeof(pixFormatStr));
    414             break;
    415         case HAL_PIXEL_FORMAT_YCbCr_422_I:
    416             strlcpy(pixFormatStr, "YCbCr_422_I_YUY2", sizeof(pixFormatStr));
    417             break;
    418         case HAL_PIXEL_FORMAT_YCrCb_422_I:
    419             strlcpy(pixFormatStr, "YCrCb_422_I_YVYU", sizeof(pixFormatStr));
    420             break;
    421         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
    422             strlcpy(pixFormatStr, "NV12_ENCODEABLE", sizeof(pixFormatStr));
    423             break;
    424         case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
    425             strlcpy(pixFormatStr, "YCbCr_420_SP_TILED_TILE_4x2",
    426                    sizeof(pixFormatStr));
    427             break;
    428         case HAL_PIXEL_FORMAT_YCbCr_420_SP:
    429             strlcpy(pixFormatStr, "YCbCr_420_SP", sizeof(pixFormatStr));
    430             break;
    431         case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
    432             strlcpy(pixFormatStr, "YCrCb_420_SP_ADRENO", sizeof(pixFormatStr));
    433             break;
    434         case HAL_PIXEL_FORMAT_YCrCb_422_SP:
    435             strlcpy(pixFormatStr, "YCrCb_422_SP", sizeof(pixFormatStr));
    436             break;
    437         case HAL_PIXEL_FORMAT_R_8:
    438             strlcpy(pixFormatStr, "R_8", sizeof(pixFormatStr));
    439             break;
    440         case HAL_PIXEL_FORMAT_RG_88:
    441             strlcpy(pixFormatStr, "RG_88", sizeof(pixFormatStr));
    442             break;
    443         case HAL_PIXEL_FORMAT_INTERLACE:
    444             strlcpy(pixFormatStr, "INTERLACE", sizeof(pixFormatStr));
    445             break;
    446         case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
    447             strlcpy(pixFormatStr, "YCbCr_420_SP_VENUS", sizeof(pixFormatStr));
    448             break;
    449         default:
    450             size_t len = sizeof(pixFormatStr);
    451             snprintf(pixFormatStr, len, "Unknown0x%X", format);
    452             break;
    453     }
    454 }
    455 
    456 } // namespace qhwc
    457 
    458