Sample Code

Windows Driver Samples/ USBView sample application/ C++/ h264.c/

//*****************************************************************************
// I N C L U D E S
//*****************************************************************************

#include "uvcview.h"
#include "h264.h"

#ifdef H264_SUPPORT

//*****************************************************************************
// G L O B A L S    
//*****************************************************************************
// H.264 format
UCHAR g_expectedNumberOfH264FrameDescriptors = 0;
UCHAR g_numberOfH264FrameDescriptors = 0;

// MJPEG format
UCHAR g_expectedNumberOfMJPEGFrameDescriptors = 0;
UCHAR g_numberOfMJPEGFrameDescriptors = 0;

// Uncompressed frame format
UCHAR g_expectedNumberOfUncompressedFrameFrameDescriptors = 0;
UCHAR g_numberOfUncompressedFrameFrameDescriptors = 0;

//*****************************************************************************
//
// external function prototypes 
//
//*****************************************************************************
extern VOID VDisplayBytes (PUCHAR Data, USHORT Len ); 

//*****************************************************************************
//
// H.264 video format descriptor string tables
//
//*****************************************************************************
STRINGLIST slSliceModes[]=
{
    {1,         "Maximum number of Macroblocks per slice mode",    ""},
    {2,         "Target compressed size per slice mode",           ""},
    {4,         "Number of slices per frame mode",                 ""},
    {8,         "Number of Macroblock rows per slice mode",        ""},
    {0x10,      "Reserved",                                        ""},
    {0x20,      "Reserved",                                        ""},
    {0x40,      "Reserved",                                        ""},
    {0x80,      "Reserved",                                        ""},
};

   
STRINGLIST slSyncFrameTypes[]=
{
    {1,         "Reset"           ,                                                                      ""},
    {2,         "IDR frame with SPS and PPS",                                                            ""},
    {4,         "IDR frame (with SPS and PPS) that is a long-term reference frame",                      ""},
    {8,         "Non-IDR random-access I frame (with SPS and PPS)",                                      ""},
    {0x10,      "Non-IDR random-access I frame (with SPS and PPS) that is a long-term reference frame",  ""},
    {0x20,      "P frame that is a long-term reference frame",                                           ""},
    {0x40,      "Gradual Decoder Refresh frames",                                                        ""},
    {0x80,      "Reserved",                                                                              ""},
};


//*****************************************************************************
//
// H.264 video frame rate descriptor string tables
//
//*****************************************************************************
STRINGLIST slUsage[]=
{
    {0x00000001,    "Real-time/UCConfig mode 0",        ""},  // 0
    {0x00000002,    "Real-time/UCConfig mode 1",        ""},
    {0x00000004,    "Real-time/UCConfig mode 2Q"        ""},
    {0x00000008,    "Real-time/UCConfig mode 2S"        ""},
    {0x00000010,    "Real-time/UCConfig mode 3",        ""},
    {0x00000020,    "Reserved",                         ""},
    {0x00000040,    "Reserved",                         ""},
    {0x00000080,    "Reserved",                         ""},

    {0x00000100,    "Broadcast mode 0",                ""}, // 8
    {0x00000200,    "Broadcast mode 1",                ""},
    {0x00000400,    "Broadcast mode 2",                ""},
    {0x00000800,    "Broadcast mode 3",                ""},
    {0x00001000,    "Broadcast mode 4",                ""},
    {0x00002000,    "Broadcast mode 5",                ""},
    {0x00004000,    "Broadcast mode 6",                ""},
    {0x00008000,    "Broadcast mode 7",                ""},

    {0x00010000,    "File Storage mode with I and P slices (e.g. IPPP)",            ""}, // 16
    {0x00020000,    "File Storage mode with I, P, and B slices (e.g. IB...BP)",     ""}, // 17
    {0x00040000,    "File storage all I frame mode",    ""}, // 18
    {0x00080000,    "Reserved",                         ""}, // 19
    {0x00100000,    "Reserved",                         ""}, // 20
    {0x00200000,    "Reserved",                         ""}, // 21
    {0x00400000,    "Reserved",                         ""}, // 22
    {0x00800000,    "Reserved",                         ""}, // 23

    {0x01000000,    "MVC Stereo High Mode",             ""}, // 24
    {0x02000000,    "MVC Multiview Mode",               ""}, // 25
    {0x04000000,    "Reserved",                         ""}, // 26
    {0x08000000,    "Reserved",                         ""}, // 27
    {0x10000000,    "Reserved",                         ""}, // 28
    {0x20000000,    "Reserved",                         ""}, // 29
    {0x40000000,    "Reserved",                         ""}, // 30
    {0x80000000,    "Reserved",                         ""}, // 31

 };
STRINGLIST slCapabilities[]=
{
    {0x0001,    "CAVLC only",                       ""},
    {0x0002,    "CABAC only",                       ""},
    {0x0004,    "Constant frame rate",              ""},
    {0x0008,    "Separate QP for luma/chroma",      ""},
    {0x0010,    "Separate QP for Cb/Cr",            ""},
    {0x0020,    "No picture reordering",            ""},
    {0x0040,    "Long-term reference frame",        ""},
    {0x0080,    "Reserved",                         ""},
    {0x0100,    "Reserved",                         ""},
    {0x0200,    "Reserved",                         ""},
    {0x0400,    "Reserved",                         ""},
    {0x0800,    "Reserved",                         ""},
    {0x1000,    "Reserved",                         ""},
    {0x2000,    "Reserved",                         ""},
    {0x4000,    "Reserved",                         ""},
    {0x8000,    "Reserved",                         ""},
 };



STRINGLIST slRateControlModes[]=
{
    {1,         "Variable Bit Rate (VBR) with underflow allowed (H.264 low_delay_hrd_flag = 1)",    ""},
    {2,         "Constant Bit Rate (CBR) (H.264 low_delay_hrd_flag = 0)",                           ""},
    {4,         "Constant QP",                                                                      ""},
    {8,         "Global VBR with underflow allowed (H.264 low_delay_hrd_flag = 1)",                 ""},
    {0x10,      "VBR without underflow (H.264 low_delay_hrd_flag = 0)",                             ""},
    {0x20,      "Global VBR without underflow (H.264 low_delay_hrd_flag = 0)",                      ""},
    {0x40,      "Reserved",                                                                         ""},
    {0x80,      "Reserved",                                                                         ""},
};


STRINGLIST slProfiles[]=
{
    {0x4200,    "Baseline Profile",                                 ""},
    {0x4240,    "Constrained Baseline Profile",                     ""},
    {0x4D00,    "Main Profile",                                     ""},
    {0x5300,    "Scalable Baseline Profile",                        ""},
    {0x5304,    "Scalable Constrained Baseline Profile",            ""},
    {0x5600,    "Scalable High Profile",                            ""},
    {0x5604,    "Scalable Constrained High Profile",                ""},
    {0x6400,    "High Profile",                                     ""},
    {0x640C,    "Constrained High Profile",                         ""},
    {0x7600,    "Multiview High Profile",                           ""},
    {0x8000,    "Stereo High Profile",                              ""},
 };

//*****************************************************************************
//
// H.264 video encoding unit descriptor string tables
//
//*****************************************************************************

STRINGLIST slEncodingUnitControls[]=
{
    {0x000001,    "Select Layer",                                     ""}, // D0
    {0x000002,    "Profile and Toolset",                              ""}, // D1
    {0x000004,    "Video Resolution",                                 ""}, // D2
    {0x000008,    "Minimum Frame Interval",                           ""}, // D3
    {0x000010,    "Slice Mode",                                       ""}, // D4
    {0x000020,    "Rate Control Mode",                                ""}, // D5
    {0x000040,    "Average Bit Rate",                                 ""}, // D6
    {0x000080,    "CPB Size        ",                                 ""}, // D7
    {0x000100,    "Peak Bit Rate",                                    ""}, // D8
    {0x000200,    "Quantization Parameter",                           ""}, // D9
    {0x000400,    "Synchronization and Long-Term Reference Frame",    ""}, // D10
    {0x000800,    "Long-Term Buffer Size",                            ""}, // D11
    {0x001000,    "Picture Long-Term Reference",                      ""}, // D12
    {0x002000,    "Valid LTR",                                        ""}, // D13
    {0x004000,    "Level IDC",                                        ""}, // D14
    {0x008000,    "SEI Message",                                      ""}, // D15
    {0x010000,    "QP Range",                                         ""}, // D16
    {0x020000,    "Priority ID",                                      ""}, // D17
    {0x040000,    "Start or Stop Layer/View",                         ""}, // D18
    {0x080000,    "Error Resiliency",                                 ""}, // D19
    {0x100000,    "Reserved",                                         ""}, // D20
    {0x200000,    "Reserved",                                         ""}, // D21
    {0x400000,    "Reserved",                                         ""}, // D22
    {0x800000,    "Reserved",                                         ""}, // D23
 };

//*****************************************************************************
//
// commaPrintNumber()
//
//*****************************************************************************
char * commaPrintNumber( ULONG number )
{
    static char comma = ',';
    static char retbuf[30];
    int digitCount = 0;

    // null-terminate the string
    char * pOutputString = &retbuf[ sizeof(retbuf)-1 ];
    *pOutputString = '\0';

    do 
    {
        // for every 3rd digit, add a comma to the output string
        if ( ( digitCount%3 ) == 0 && ( digitCount != 0 ) )
        {
            *--pOutputString = comma;
        }
        *--pOutputString = '0' + number % 10;
        number /= 10;
        digitCount++;
    } 
    while( number != 0 );

    return pOutputString;
}

//*****************************************************************************
//
// DisplayBitmapData()
//
// Note that USB is always oriented Little Endian (least significant byte
// at the lowest address).
//
// Inputs: 
// PUCHAR pData - pointer to least significant byte of the data 
// UCHAR  byteCount - number of bytes to print in the pData data buffer
// char * stringLabel - string label to print for user's to identify the data type  
//
//*****************************************************************************
void DisplayBitmapData(_In_reads_(byteCount) PUCHAR pData, UCHAR byteCount,  _In_ char * stringLabel)
{
    UCHAR byteIndex;
    UCHAR data;
    UCHAR mask;
    UCHAR bitIndex;
    UCHAR checkBit = 0; // the bit we want to print

    // print the label and all the bytes on the first line
    AppendTextBuffer("%s : ", stringLabel);
    VDisplayBytes( pData, byteCount );

    for ( byteIndex = 0; byteIndex < byteCount; byteIndex++ )
    {
        data = pData[ byteIndex ];
        checkBit = 0; // the control bit value we are going to print
        for ( mask = 1, bitIndex = 0; bitIndex < 8; bitIndex++ )
        {
            checkBit =  data & mask;
            AppendTextBuffer("     D%02d = %d  %s\r\n",
                bitIndex + 8 * byteIndex,   // increment bit count
                checkBit ? 1 : 0,
                checkBit ? "yes" : " no");
            mask = mask << 1;
        }

    }
}

//*****************************************************************************
//
// DisplayBitmapDataWithStrings()
//
// Note that USB is always oriented Little Endian (least significant byte
// at the lowest address).
//
// This calls GetSTringFromList() to insert a string that corresonds to
// the bit value being print.
//
// Inputs: 
// PUCHAR pData - pointer to least significant byte of the data 
// UCHAR  byteCount - number of bytes to print in the pData data buffer
// char * stringLabel - string label to print for user's to identify the data type  
// STRINGLIST stringList - string table in which to look up bitmap strings
// ULONG numEntriesInTable - number of entrys (strings) in the table
//*****************************************************************************
void DisplayBitmapDataWithStrings( _In_reads_(byteCount) PUCHAR pData, UCHAR byteCount,
                                   _In_ char * stringLabel,  _In_ PSTRINGLIST stringList,
                                   ULONG numEntriesInTable)
{

    UCHAR byteIndex;
    UCHAR data;
    UCHAR byteMask;
    ULONGLONG stringMask;
    UCHAR bitIndex;
    UCHAR checkBit = 0; // the bit we want to print

    // print the label and all the bytes on the first line
    AppendTextBuffer("%s : ", stringLabel);
    VDisplayBytes( pData, byteCount );

    for ( stringMask = 1, byteIndex = 0; byteIndex < byteCount; byteIndex++ )
    {
        data = pData[ byteIndex ];
        checkBit = 0; // the control bit value we are going to print
        for ( byteMask = 1, bitIndex = 0; bitIndex < 8; bitIndex++ )
        {
            checkBit =  data & byteMask;
            AppendTextBuffer("     D%02d = %d  %s %s\r\n",
                bitIndex + 8 * byteIndex, // increment bit count
                checkBit ? 1 : 0,
                checkBit ? "yes - " : " no - ",
                   GetStringFromList(stringList, 
                        numEntriesInTable,
                        stringMask, 
                        "Reserved"));

            byteMask = byteMask << 1;
            stringMask = stringMask << 1;
        }

    }
}

//*****************************************************************************
//
// DisplayVCH264Format()
//
//*****************************************************************************
BOOL DisplayVCH264Format( _In_reads_(sizeof(VIDEO_FORMAT_H264)) PVIDEO_FORMAT_H264 H264FormatDesc )
{
    if ( H264FormatDesc->bSimulcastSupport == 0 )
    {
        AppendTextBuffer("\r\n          ===>Video Streaming H.264 Format Type Descriptor<===\r\n");
    }
    else
    {
        AppendTextBuffer("\r\n          ===>Video Streaming H.264 Simulcast Format Type Descriptor<===\r\n");
    }
    AppendTextBuffer("bLength:                           0x%02X = %d\r\n", H264FormatDesc->bLength,               H264FormatDesc->bLength);
    AppendTextBuffer("bDescriptorType:                   0x%02X \r\n",     H264FormatDesc->bDescriptorType);
    AppendTextBuffer("bDescriptorSubtype:                0x%02X \r\n",     H264FormatDesc->bDescriptorSubtype);
    AppendTextBuffer("bFormatIndex:                      0x%02X = %d\r\n", H264FormatDesc->bFormatIndex,          H264FormatDesc->bFormatIndex);
    AppendTextBuffer("bNumFrameDescriptors:              0x%02X = %d\r\n", H264FormatDesc->bNumFrameDescriptors,  H264FormatDesc->bNumFrameDescriptors);
    AppendTextBuffer("bDefaultFrameIndex:                0x%02X = %d\r\n", H264FormatDesc->bDefaultFrameIndex,    H264FormatDesc->bDefaultFrameIndex);
    AppendTextBuffer("bMaxCodecConfigDelay:              0x%02X = %d frames\r\n", H264FormatDesc->bMaxCodecConfigDelay,  H264FormatDesc->bMaxCodecConfigDelay);
    DisplayBitmapDataWithStrings( H264FormatDesc->bmSupportedSliceModes,     sizeof(H264FormatDesc->bmSupportedSliceModes),     "bmSupportedSliceModes",    slSliceModes,     sizeof(slSliceModes)/sizeof(STRINGLIST) );
    DisplayBitmapDataWithStrings( H264FormatDesc->bmSupportedSyncFrameTypes,  sizeof(H264FormatDesc->bmSupportedSyncFrameTypes),  "bmSupportedSyncFrameTypes", slSyncFrameTypes, sizeof(slSyncFrameTypes)/sizeof(STRINGLIST) );

    // handle bResolutionScaling
    if (  H264FormatDesc->bResolutionScaling == 0 )
    {
         AppendTextBuffer("bResolutionScaling:         0x%02X = %d, Not Supported\r\n", 
            H264FormatDesc->bResolutionScaling, 
            H264FormatDesc->bResolutionScaling );
    }
    else if ( H264FormatDesc->bResolutionScaling == 1 )
     {
         AppendTextBuffer("bResolutionScaling:         0x%02X = %d, Limited to 1.5 or 2.0 scaling in both directions, while maintaining the aspect ratio.\r\n", 
            H264FormatDesc->bResolutionScaling, 
            H264FormatDesc->bResolutionScaling );
    }
    else if ( H264FormatDesc->bResolutionScaling == 2 )
     {
         AppendTextBuffer("bResolutionScaling:         0x%02X = %d, Limited to 1.0, 1.5 or 2.0 scaling in either direction.\r\n", 
            H264FormatDesc->bResolutionScaling, 
            H264FormatDesc->bResolutionScaling );
    }
    else if ( H264FormatDesc->bResolutionScaling == 3 )
     {
         AppendTextBuffer("bResolutionScaling:         0x%02X = %d, Limited to resolutions reported by the associated Frame Descriptors\r\n", 
            H264FormatDesc->bResolutionScaling, 
            H264FormatDesc->bResolutionScaling );
    }
    else if ( H264FormatDesc->bResolutionScaling == 4 )
     {
         AppendTextBuffer("bResolutionScaling:         0x%02X = %d, Arbitrary scaling\r\n", 
            H264FormatDesc->bResolutionScaling, 
            H264FormatDesc->bResolutionScaling );
    }
    else // 5 ... 255
    {
         AppendTextBuffer("bResolutionScaling:         0x%02X = %d, Reserved \r\n", 
            H264FormatDesc->bResolutionScaling, 
            H264FormatDesc->bResolutionScaling );
    }
 
     // handle bSimulcastSupport 
    if ( H264FormatDesc->bSimulcastSupport == 0 )
    {
        AppendTextBuffer("bSimulcastSupport:                 0x%02X = %d, one stream\r\n",
            H264FormatDesc->bSimulcastSupport,
            H264FormatDesc->bSimulcastSupport );
    }
    else if ( H264FormatDesc->bSimulcastSupport == 1 )
    {
        AppendTextBuffer("bSimulcastSupport:                 0x%02X = %d, multiple streams\r\n",
            H264FormatDesc->bSimulcastSupport,
            H264FormatDesc->bSimulcastSupport );
    }
    else // ( H264FormatDesc->bSimulcastSupport > 1 )
    {
        AppendTextBuffer("bSimulcastSupport:                 0x%02X = %d *!*ERROR:  unknown bSimulcastSupport \r\n",
            H264FormatDesc->bSimulcastSupport,
            H264FormatDesc->bSimulcastSupport,
            H264FormatDesc->bSimulcastSupport );
    }

    
    DisplayBitmapDataWithStrings( &(H264FormatDesc->bmSupportedRateControlModes), sizeof(H264FormatDesc->bmSupportedRateControlModes), "bmSupportedRateControlModes",   slRateControlModes, sizeof(slRateControlModes)/sizeof(STRINGLIST) );
   
    // Note that USB is Little Endian according to the UVC 2.0 spec


    // Resolutions with no scalability
    AppendTextBuffer("wMaxMBperSecOneResolutionNoScalability:                 0x%04X (%s MB/sec)\r\n",
        H264FormatDesc->wMaxMBperSecOneResolutionNoScalability,
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionNoScalability) );

    AppendTextBuffer("wMaxMBperSecTwoResolutionsNoScalability:                0x%04X (%s MB/sec)\r\n", 
        H264FormatDesc->wMaxMBperSecTwoResolutionsNoScalability, 
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsNoScalability) );

    AppendTextBuffer("wMaxMBperSecThreeResolutionsNoScalability:              0x%04X (%s MB/sec)\r\n",
        H264FormatDesc->wMaxMBperSecThreeResolutionsNoScalability,
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsNoScalability) );

    AppendTextBuffer("wMaxMBperSecFourResolutionsNoScalability:               0x%04X (%s MB/sec)\r\n", 
        H264FormatDesc->wMaxMBperSecFourResolutionsNoScalability, 
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsNoScalability) );

    // Resolutions with temporal scalability
    AppendTextBuffer("wMaxMBperSecOneResolutionTemporalScalability:           0x%04X (%s MB/sec)\r\n",
        H264FormatDesc->wMaxMBperSecOneResolutionTemporalScalability,
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionTemporalScalability) );

    AppendTextBuffer("wMaxMBperSecTwoResolutionsTemporalScalability:          0x%04X (%s MB/sec)\r\n", 
        H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalScalability, 
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalScalability) );

    AppendTextBuffer("wMaxMBperSecThreeResolutionsTemporalScalability:        0x%04X (%s MB/sec)\r\n",
        H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalScalability,
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalScalability) );

    AppendTextBuffer("wMaxMBperSecFourResolutionsTemporalScalability:         0x%04X (%s MB/sec)\r\n", 
        H264FormatDesc->wMaxMBperSecFourResolutionsTemporalScalability, 
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsTemporalScalability) );

    // Resolutions with temporal and quality scalability
    AppendTextBuffer("wMaxMBperSecOneResolutionTemporalQualityScalability:    0x%04X (%s MB/sec)\r\n",
        H264FormatDesc->wMaxMBperSecOneResolutionTemporalQualityScalability,
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionTemporalQualityScalability) );

    AppendTextBuffer("wMaxMBperSecTwoResolutionsTemporalQualityScalability:   0x%04X (%s MB/sec)\r\n", 
        H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalQualityScalability, 
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalQualityScalability) );


    AppendTextBuffer("wMaxMBperSecThreeResolutionsTemporalQualityScalability: 0x%04X (%s MB/sec)\r\n",
        H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalQualityScalability,
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalQualityScalability) );

    AppendTextBuffer("wMaxMBperSecFourResolutionsTemporalQualityScalability:  0x%04X (%s MB/sec)\r\n", 
        H264FormatDesc->wMaxMBperSecFourResolutionsTemporalQualityScalability, 
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsTemporalQualityScalability) );

    // Resolutions with temporal and spatial scalability
    AppendTextBuffer("wMaxMBperSecOneResolutionTemporalSpatialScalability:    0x%04X (%s MB/sec)\r\n",
        H264FormatDesc->wMaxMBperSecOneResolutionTemporalSpatialScalability,
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionTemporalSpatialScalability) );

    AppendTextBuffer("wMaxMBperSecTwoResolutionsTemporalSpatialScalability:   0x%04X (%s MB/sec)\r\n", 
        H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalSpatialScalability, 
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalSpatialScalability) );


    AppendTextBuffer("wMaxMBperSecThreeResolutionsTemporalSpatialScalability: 0x%04X (%s MB/sec)\r\n",
        H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalSpatialScalability,
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalSpatialScalability) );

    AppendTextBuffer("wMaxMBperSecFourResolutionsTemporalSpatialScalability:  0x%04X (%s MB/sec)\r\n", 
        H264FormatDesc->wMaxMBperSecFourResolutionsTemporalSpatialScalability, 
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsTemporalSpatialScalability) );

   // Resolutions with full scalability
    AppendTextBuffer("wMaxMBperSecOneResolutionFullScalability:               0x%04X (%s MB/sec)\r\n",
        H264FormatDesc->wMaxMBperSecOneResolutionFullScalability,
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionFullScalability) );

    AppendTextBuffer("wMaxMBperSecTwoResolutionsFullScalability:              0x%04X (%s MB/sec)\r\n", 
        H264FormatDesc->wMaxMBperSecTwoResolutionsFullScalability, 
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsFullScalability) );

    AppendTextBuffer("wMaxMBperSecThreeResolutionsFullScalability:            0x%04X (%s MB/sec)\r\n",
        H264FormatDesc->wMaxMBperSecThreeResolutionsFullScalability,
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsFullScalability) );

    AppendTextBuffer("wMaxMBperSecFourResolutionsFullScalability:             0x%04X (%s MB/sec)\r\n", 
        H264FormatDesc->wMaxMBperSecFourResolutionsFullScalability, 
        commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsFullScalability) );


    return TRUE;
}

//*****************************************************************************
//
// DisplayVCH264FrameType()
//
//*****************************************************************************
BOOL DisplayVCH264FrameType( _In_reads_(sizeof(VIDEO_FRAME_H264)) PVIDEO_FRAME_H264 H264FrameDesc )
{

    ULONG frameIntervalIndex;
    ULONG value;
    ULONG i;

    AppendTextBuffer("\r\n          ===>Video Streaming H.264 Frame Type Descriptor<===\r\n");
    AppendTextBuffer("bLength:                           0x%02X = %d\r\n", H264FrameDesc->bLength,            H264FrameDesc->bLength);
    AppendTextBuffer("bDescriptorType:                   0x%02X \r\n",     H264FrameDesc->bDescriptorType);
    AppendTextBuffer("bDescriptorSubtype:                0x%02X \r\n",     H264FrameDesc->bDescriptorSubtype);
    AppendTextBuffer("bFrameIndex:                       0x%02X = %d\r\n", H264FrameDesc->bFrameIndex,        H264FrameDesc->bFrameIndex);
    AppendTextBuffer("wWidth:                          0x%04X = %d\r\n", H264FrameDesc->wWidth,               H264FrameDesc->wWidth);
    AppendTextBuffer("wHeight:                         0x%04X = %d\r\n", H264FrameDesc->wHeight,              H264FrameDesc->wHeight);
    AppendTextBuffer("wSARwidth:                       0x%04X = %d\r\n", H264FrameDesc->wSARwidth,            H264FrameDesc->wSARwidth);
    AppendTextBuffer("wSARheight:                      0x%04X = %d\r\n", H264FrameDesc->wSARheight,           H264FrameDesc->wSARheight);
    AppendTextBuffer("wProfile:                        0x%04X - %s\r\n", H264FrameDesc->wProfile,
        GetStringFromList( slProfiles,                                  // string table                                    
                           sizeof(slProfiles)/sizeof(STRINGLIST),       // number of strings in the table
                           H264FrameDesc->wProfile,                     // index of string we want to look up in the string table
                           "Unknown profile" ) );                       // string to use if the lookup fails
   
    AppendTextBuffer("bLevelIDC:                       0x%02X = %d = Level %01.01lf \r\n", 
        H264FrameDesc->bLevelIDC, H264FrameDesc->bLevelIDC, H264FrameDesc->bLevelIDC/10.0 );
    
    AppendTextBuffer("wConstrainedToolset:             0x%04X %s\r\n", H264FrameDesc->wConstrainedToolset,
        ((H264FrameDesc->wConstrainedToolset == 0) ? "- Reserved" : "*!*ERROR: field is reserved and should be zero"));

    DisplayBitmapDataWithStrings( H264FrameDesc->bmSupportedUsages, sizeof(H264FrameDesc->bmSupportedUsages), "bmSupportedUsages", slUsage, sizeof(slUsage)/sizeof(STRINGLIST) );
    DisplayBitmapDataWithStrings( H264FrameDesc->bmCapabilities, sizeof(H264FrameDesc->bmCapabilities), "bmCapabilities",         slCapabilities, sizeof(slCapabilities)/sizeof(STRINGLIST) );
    

    // bmSVCCapabilities[4]      
    AppendTextBuffer("%s : ", "bmSVCCapabilities");
    VDisplayBytes( &(H264FrameDesc->bmSVCCapabilities[0]), sizeof(H264FrameDesc->bmSVCCapabilities)  );
    AppendTextBuffer("     D2..D0   = %d  Maximum number of temporal layers = %d\r\n", 
        H264FrameDesc->bmSVCCapabilities[0] & 0x7, 
        (H264FrameDesc->bmSVCCapabilities[0] & 0x7) + 1 );
    AppendTextBuffer("     D3       = %d %s - Rewrite Support\r\n", (H264FrameDesc->bmSVCCapabilities[0] & 0x8) >> 3,
        ((H264FrameDesc->bmSVCCapabilities[0] & 0x8) >> 3) ? "yes" : " no" );
    AppendTextBuffer("     D6..D4   = %d  Maximum number of CGS layers = %d\r\n", 
        (H264FrameDesc->bmSVCCapabilities[0] & 0x70) >> 4, 
        ((H264FrameDesc->bmSVCCapabilities[0] & 0x70) >> 4) + 1 );

    value = ( H264FrameDesc->bmSVCCapabilities[1] << 8 ) | H264FrameDesc->bmSVCCapabilities[0];
    value >>= 7;    // shift bit 7 right so that it ends up in the lsb of value
    value &= 0x7;
    AppendTextBuffer("     D9..D7   = %d  Number of MGS sublayers\r\n", value );

    AppendTextBuffer("     D10      = %d %s - Additional SNR scalability support in spatial enhancement layers\r\n",
        (H264FrameDesc->bmSVCCapabilities[1] & 0x4) >> 2,
        ((H264FrameDesc->bmSVCCapabilities[1] & 0x4) >> 2) ? "yes" : " no");
    AppendTextBuffer("     D13..D11 = %d  Maximum number of spatial layers = %d\r\n", 
        (H264FrameDesc->bmSVCCapabilities[1] & 0x38) >> 3, 
        ((H264FrameDesc->bmSVCCapabilities[1] & 0x38) >> 3) + 1 );

    value = ( H264FrameDesc->bmSVCCapabilities[3] << 16 ) | ( H264FrameDesc->bmSVCCapabilities[2] << 8 ) | H264FrameDesc->bmSVCCapabilities[1];
    value >>= 6; // get bit 14 at LSB
    for ( i = 0; i < 18; i++ )   // bits 31...14
    {    
        AppendTextBuffer("     D%02d      = %d %s - Reserved \r\n", 14 + i, value & 0x1, (value & 0x1) ? "yes" : " no"  );
        value >>= 1;
    }

    // bmMVCCapabilities[4]
    AppendTextBuffer("%s : ", "bmMVCCapabilities");
    VDisplayBytes( &(H264FrameDesc->bmMVCCapabilities[0]), sizeof(H264FrameDesc->bmMVCCapabilities)  );
    AppendTextBuffer("     D2..D0   = %d  Maximum number of temporal layers = %d\r\n", 
        H264FrameDesc->bmMVCCapabilities[0] & 0x7, 
        ((H264FrameDesc->bmMVCCapabilities[0] & 0x7) + 1) );

     value =  (H264FrameDesc->bmMVCCapabilities[1] << 8) |  H264FrameDesc->bmMVCCapabilities[0];
     value >>= 3;    // shift bit 3 right so that it ends up in the lsb of value
     value &= 0xff;
     AppendTextBuffer("     D10..D3  = %d  Maximum number of view components = %d\r\n", 
        value, value + 1);

     value = (  (H264FrameDesc->bmMVCCapabilities[3] << 16) | (H264FrameDesc->bmMVCCapabilities[2] << 8) |  H264FrameDesc->bmMVCCapabilities[1] );
     value >>= 3;    // shift bit 11 right so that it ends up in the lsb of value
     for ( i = 0; i < 21; i++ )   // bits 31...11
    {                    
        AppendTextBuffer("     D%02d      = %d %s - Reserved \r\n", 11 + i, value & 0x1, (value & 0x1) ? "yes" : " no" );
        value >>= 1;
    }


    AppendTextBuffer("dwMinBitRate:                    0x%08X  = %s bps\r\n", H264FrameDesc->dwMinBitRate, commaPrintNumber(H264FrameDesc->dwMinBitRate));
    AppendTextBuffer("dwMaxBitRate:                    0x%08X  = %s bps\r\n", H264FrameDesc->dwMaxBitRate, commaPrintNumber(H264FrameDesc->dwMaxBitRate));

    // To convert the default frame interval, which is in 100 ns units,  to  milliseconds, we divide by 10,000.
    // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds
    // = 1/10,000 milliseconds

    AppendTextBuffer("dwDefaultFrameInterval:          0x%08X  = %lf mSec (%4.2f Hz) \r\n",
        H264FrameDesc->dwDefaultFrameInterval, ((double)H264FrameDesc->dwDefaultFrameInterval)/10000.0, (10000000.0/((double)H264FrameDesc->dwDefaultFrameInterval)));
    AppendTextBuffer("bNumFrameIntervals:              0x%02X = %d\r\n", H264FrameDesc->bNumFrameIntervals, H264FrameDesc->bNumFrameIntervals);


    // frame interval 100 ns units.  
    
    //To convert the frame interval to seconds we would divide by 10,000,000.
    // 100 ns = 10^(-7) seconds = 1/10,000,000 

    // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse

    // To convert the frame interval to  milliseconds, we divide by 10,000.
    // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds
    // = 1/10,000 milliseconds

    for ( frameIntervalIndex = 0; frameIntervalIndex < H264FrameDesc->bNumFrameIntervals; frameIntervalIndex++ )
    {
        value = (ULONG)H264FrameDesc->dwFrameInterval[ frameIntervalIndex ];
        AppendTextBuffer("dwFrameInterval[%d]: 0x%08x = %lf mSec (%4.2f Hz)\r\n", frameIntervalIndex, value, ((double)value)/10000.0, (10000000.0/((double)value)) );

    }

    return TRUE;
}


//*****************************************************************************
//
// DisplayVCH264EncodingUnit()
//
//*****************************************************************************
BOOL DisplayVCH264EncodingUnit(
                        _In_reads_(sizeof(VIDEO_ENCODING_UNIT)) PVIDEO_ENCODING_UNIT VidEncodingDesc
        )
{

    PUCHAR pControlsRunTimeData = NULL;

    AppendTextBuffer("\r\n          ===>Video Control Encoding Unit Descriptor<===\r\n");
    AppendTextBuffer("bLength:                           0x%02X = %d\r\n", VidEncodingDesc->bLength,        VidEncodingDesc->bLength);
    AppendTextBuffer("bDescriptorType:                   0x%02X \r\n",     VidEncodingDesc->bDescriptorType );
    AppendTextBuffer("bDescriptorSubtype:                0x%02X \r\n",     VidEncodingDesc->bDescriptorSubtype );
    AppendTextBuffer("bUnitID:                           0x%02X = %d\r\n", VidEncodingDesc->bUnitID,        VidEncodingDesc->bUnitID);
    AppendTextBuffer("bSourceID:                         0x%02X = %d\r\n", VidEncodingDesc->bSourceID,      VidEncodingDesc->bSourceID);
    AppendTextBuffer("iEncoding:                         0x%02X = %d\r\n", VidEncodingDesc->iEncoding,      VidEncodingDesc->iEncoding);
    AppendTextBuffer("bControlSize:                      0x%02X = %d\r\n", VidEncodingDesc->bControlSize,   VidEncodingDesc->bControlSize);

    if ( VidEncodingDesc->bControlSize > 0)
    {
        // Encoding Unit Descriptor bmControls field
        DisplayBitmapDataWithStrings( VidEncodingDesc->bmControls, VidEncodingDesc->bControlSize /* print bControlSize bytes worth of bitmap info */,
            "bmControls", slEncodingUnitControls, sizeof(slEncodingUnitControls)/sizeof(STRINGLIST) );

        // Encoding Unit Descriptor bmControlsRuntime field
        pControlsRunTimeData = ((UCHAR *)(&VidEncodingDesc->bmControls)) + VidEncodingDesc->bControlSize;
        DisplayBitmapDataWithStrings( pControlsRunTimeData, VidEncodingDesc->bControlSize /* print bControlSize bytes worth of bitmap info */,
            "bmControlsRuntime", slEncodingUnitControls, sizeof(slEncodingUnitControls)/sizeof(STRINGLIST) );
    }
    return TRUE;
}

//*****************************************************************************
//
// DoAdditionalErrorChecks()
//
// Currently this function only checks to see that the number of frame
// descriptors actually found equals the number specified in the corresponding
// format descriptor.
//
// Because this potentially involves parsing multiple frame descriptors, we
// call this routine after the video descriptor has been parsed and displayed.
//
//*****************************************************************************
void DoAdditionalErrorChecks()
{
    if( g_expectedNumberOfH264FrameDescriptors > 0 || g_numberOfH264FrameDescriptors > 0
        || g_expectedNumberOfUncompressedFrameFrameDescriptors > 0 || g_numberOfUncompressedFrameFrameDescriptors > 0
        || g_expectedNumberOfMJPEGFrameDescriptors > 0 || g_numberOfMJPEGFrameDescriptors > 0)
    {
        AppendTextBuffer("\r\n          ===>Additional Error Checking<===\r\n");

        // H.264 frame descriptor
        if( g_expectedNumberOfH264FrameDescriptors > 0 || g_numberOfH264FrameDescriptors > 0)
        {
            if ( g_expectedNumberOfH264FrameDescriptors == g_numberOfH264FrameDescriptors )
            {
                AppendTextBuffer("PASS: number of H.264 frame descriptors (%d) == number of frame descriptors (%d) specified in H.264 format descriptor(s)\r\n",
                    g_expectedNumberOfH264FrameDescriptors, g_numberOfH264FrameDescriptors );
            }
            else
            {
                AppendTextBuffer("FAIL: number of H.264 frame descriptors (%d) != number of frame descriptors (%d) specified in H.264 format descriptor(s)\r\n",
                    g_expectedNumberOfH264FrameDescriptors, g_numberOfH264FrameDescriptors );
            }
        }

        // uncompressed frame descriptor
        if( g_expectedNumberOfUncompressedFrameFrameDescriptors > 0 || g_numberOfUncompressedFrameFrameDescriptors > 0)
        {

            if ( g_expectedNumberOfUncompressedFrameFrameDescriptors == g_numberOfUncompressedFrameFrameDescriptors )
            {
                AppendTextBuffer("PASS: number of uncompressed-frame frame descriptors (%d) == number of frame descriptors (%d) specified in uncompressed format descriptor(s)\r\n",
                    g_expectedNumberOfUncompressedFrameFrameDescriptors, g_numberOfUncompressedFrameFrameDescriptors );
            }
            else
            {
                AppendTextBuffer("FAIL: number of uncompressed-frame frame descriptors (%d) != number of frame descriptors (%d) specified in uncompressed format descriptor(s)\r\n",
                    g_expectedNumberOfUncompressedFrameFrameDescriptors, g_numberOfUncompressedFrameFrameDescriptors );
            }
        }

        // MJPEG frame descriptor
        if( g_expectedNumberOfMJPEGFrameDescriptors > 0 || g_numberOfMJPEGFrameDescriptors > 0)
        {
            if ( g_expectedNumberOfMJPEGFrameDescriptors == g_numberOfMJPEGFrameDescriptors )
            {
                AppendTextBuffer("PASS: number of MJPEG frame descriptors (%d) == number of frame descriptors (%d) specified in MJPEG format descriptor(s)\r\n",
                    g_expectedNumberOfMJPEGFrameDescriptors, g_numberOfMJPEGFrameDescriptors );
            }
            else
            {
                AppendTextBuffer("FAIL: number of MJPEG frame descriptors (%d) != number of frame descriptors (%d) specified in MJPEG format descriptor(s)\r\n",
                    g_expectedNumberOfMJPEGFrameDescriptors, g_numberOfMJPEGFrameDescriptors );
            }
        }
    }
}

//*****************************************************************************
//
// ResetErrorCounts()
//
//*****************************************************************************
void ResetErrorCounts()
{

    // H.264 format
    g_expectedNumberOfH264FrameDescriptors = 0;
    g_numberOfH264FrameDescriptors = 0;

    // MJPEG format
    g_expectedNumberOfMJPEGFrameDescriptors = 0;
    g_numberOfMJPEGFrameDescriptors = 0;

    // Uncompressed frame format
    g_expectedNumberOfUncompressedFrameFrameDescriptors = 0;
    g_numberOfUncompressedFrameFrameDescriptors = 0;
}

#endif //H264_SUPPORT

Our Services

  • What our customers say about us?

© 2011-2024 All Rights Reserved. Joya Systems. 4425 South Mopac Building II Suite 101 Austin, TX 78735 Tel: 800-DEV-KERNEL

Privacy Policy. Terms of use. Valid XHTML & CSS