示例#1
0
文件: hap.c 项目: Vidvox/hap
int hap_get_section_at_index(const void *input_buffer, uint32_t input_buffer_bytes,
                             unsigned int index,
                             const void **section, uint32_t *section_length, unsigned int *section_type)
{
    int result;
    uint32_t section_header_length;

    result = hap_read_section_header(input_buffer, input_buffer_bytes, &section_header_length, section_length, section_type);

    if (result != HapResult_No_Error)
    {
        return result;
    }

    if (*section_type == kHapSectionMultipleImages)
    {
        /*
         Step through until we find the section at index
         */
        size_t offset = 0;
        size_t top_section_length = *section_length;
        input_buffer = ((uint8_t *)input_buffer) + section_header_length;
        section_header_length = 0;
        *section_length = 0;
        for (int i = 0; i <= index; i++) {
            offset += section_header_length + *section_length;
            if (offset >= top_section_length)
            {
                return HapResult_Bad_Arguments;
            }
            result = hap_read_section_header(((uint8_t *)input_buffer) + offset,
                                             top_section_length - offset,
                                             &section_header_length,
                                             section_length,
                                             section_type);
            if (result != HapResult_No_Error)
            {
                return result;
            }
        }
        offset += section_header_length;
        *section = ((uint8_t *)input_buffer) + offset;
        return HapResult_No_Error;
    }
    else if (index == 0)
    {
        /*
         A single-texture frame with the texture as the top section.
         */
        *section = ((uint8_t *)input_buffer) + section_header_length;
        return HapResult_No_Error;
    }
    else
    {
        *section = NULL;
        *section_length = 0;
        *section_type = 0;
        return HapResult_Bad_Arguments;
    }
}
示例#2
0
文件: hap.c 项目: jossgray/hap
unsigned int HapGetFrameTextureFormat(const void *inputBuffer, unsigned long inputBufferBytes, unsigned int *outputBufferTextureFormat)
{
    unsigned int result = HapResult_No_Error;
    uint32_t sectionHeaderLength;
    uint32_t sectionLength;
    unsigned int sectionType;
    /*
     Check arguments
     */
    if (inputBuffer == NULL
        || outputBufferTextureFormat == NULL
        )
    {
        return HapResult_Bad_Arguments;
    }
    /*
    Read the frame's top-level section
     */
    result = hap_read_section_header(inputBuffer, (uint32_t)inputBufferBytes, &sectionHeaderLength, &sectionLength, &sectionType);
    if (result == HapResult_No_Error)
    {
        /*
         Pass the API enum value to match the constant out
         */
        *outputBufferTextureFormat = hap_texture_format_constant_for_format_identifier(hap_bottom_4_bits(sectionType));
        /*
         Check a valid format was present
         */
        if (*outputBufferTextureFormat == 0)
        {
            result = HapResult_Bad_Frame;
        }
    }
    return result;
}
示例#3
0
文件: hap.c 项目: Vidvox/hap
unsigned int HapGetFrameTextureCount(const void *inputBuffer, unsigned long inputBufferBytes, unsigned int *outputTextureCount)
{
    int result;
    uint32_t section_header_length;
    uint32_t section_length;
    unsigned int section_type;

    result = hap_read_section_header(inputBuffer, inputBufferBytes, &section_header_length, &section_length, &section_type);

    if (result != HapResult_No_Error)
    {
        return result;
    }

    if (section_type == kHapSectionMultipleImages)
    {
        /*
         Step through, counting sections
         */
        uint32_t offset = section_header_length;
        uint32_t top_section_length = section_length;
        *outputTextureCount = 0;
        while (offset < top_section_length) {
            result = hap_read_section_header(((uint8_t *)inputBuffer) + offset,
                                             inputBufferBytes - offset,
                                             &section_header_length,
                                             &section_length,
                                             &section_type);
            if (result != HapResult_No_Error)
            {
                return result;
            }
            offset += section_header_length + section_length;
            *outputTextureCount += 1;
        }
        return HapResult_No_Error;
    }
    else
    {
        /*
         A single-texture frame with the texture as the top section.
         */
        *outputTextureCount = 1;
        return HapResult_No_Error;
    }
}
示例#4
0
文件: hap.c 项目: jossgray/hap
unsigned int HapDecode(const void *inputBuffer, unsigned long inputBufferBytes,
                       HapDecodeCallback callback, void *info,
                       void *outputBuffer, unsigned long outputBufferBytes,
                       unsigned long *outputBufferBytesUsed,
                       unsigned int *outputBufferTextureFormat)
{
    int result = HapResult_No_Error;
    uint32_t sectionHeaderLength;
    uint32_t sectionLength;
    unsigned int sectionType;
    unsigned int textureFormat;
    unsigned int compressor;
    const void *sectionStart;
    size_t bytesUsed = 0;

    /*
     Check arguments
     */
    if (inputBuffer == NULL
        || outputBuffer == NULL
        || outputBufferTextureFormat == NULL
        )
    {
        return HapResult_Bad_Arguments;
    }

    /*
     One top-level section type describes texture-format and second-stage compression
     */
    result = hap_read_section_header(inputBuffer, (uint32_t)inputBufferBytes, &sectionHeaderLength, &sectionLength, &sectionType);

    if (result != HapResult_No_Error)
    {
        return result;
    }
    
    /*
     Hap compressor/format constants can be unpacked by reading the top and bottom four bits.
     */
    compressor = hap_top_4_bits(sectionType);
    textureFormat = hap_bottom_4_bits(sectionType);

    if (compressor == kHapCompressorComplex && callback == NULL)
    {
        return HapResult_Bad_Arguments;
    }

    /*
     Pass the texture format out
     */
    *outputBufferTextureFormat = hap_texture_format_constant_for_format_identifier(textureFormat);
    if (*outputBufferTextureFormat == 0)
    {
        return HapResult_Bad_Frame;
    }

    sectionStart = ((uint8_t *)inputBuffer) + sectionHeaderLength;
    
    if (compressor == kHapCompressorComplex)
    {
        /*
         The top-level section should contain a Decode Instructions Container followed by frame data
         */

        const char *frame_data = NULL;
        size_t bytes_remaining = 0;

        int chunk_count = 0;
        const void *compressors = NULL;
        const void *chunk_sizes = NULL;
        const void *chunk_offsets = NULL;

        result = hap_read_section_header(sectionStart, inputBufferBytes - sectionHeaderLength, &sectionHeaderLength, &sectionLength, &sectionType);

        if (result == HapResult_No_Error && sectionType != kHapSectionDecodeInstructionsContainer)
        {
            result = HapResult_Bad_Frame;
        }

        if (result != HapResult_No_Error)
        {
            return result;
        }

        /*
         Frame data follows immediately after the Decode Instructions Container
         */
        frame_data = ((const char *)sectionStart) + sectionHeaderLength + sectionLength;

        /*
         Step through the sections inside the Decode Instructions Container
         */
        sectionStart = ((uint8_t *)sectionStart) + sectionHeaderLength;
        bytes_remaining = sectionLength;

        while (bytes_remaining > 0) {
            unsigned int section_chunk_count = 0;
            result = hap_read_section_header(sectionStart, bytes_remaining, &sectionHeaderLength, &sectionLength, &sectionType);
            if (result != HapResult_No_Error)
            {
                return result;
            }
            sectionStart = ((uint8_t *)sectionStart) + sectionHeaderLength;
            switch (sectionType) {
                case kHapSectionChunkSecondStageCompressorTable:
                    compressors = sectionStart;
                    section_chunk_count = sectionLength;
                    break;
                case kHapSectionChunkSizeTable:
                    chunk_sizes = sectionStart;
                    section_chunk_count = sectionLength / 4;
                    break;
                case kHapSectionChunkOffsetTable:
                    chunk_offsets = sectionStart;
                    section_chunk_count = sectionLength / 4;
                    break;
                default:
                    // Ignore unrecognized sections
                    break;
            }

            /*
             If we calculated a chunk count and already have one, make sure they match
             */
            if (section_chunk_count != 0)
            {
                if (chunk_count != 0 && section_chunk_count != chunk_count)
                {
                    return HapResult_Bad_Frame;
                }
                chunk_count = section_chunk_count;
            }

            sectionStart = ((uint8_t *)sectionStart) + sectionLength;
            bytes_remaining -= sectionHeaderLength + sectionLength;
        }

        /*
         The Chunk Second-Stage Compressor Table and Chunk Size Table are required
         */
        if (compressors == NULL || chunk_sizes == NULL)
        {
            return HapResult_Bad_Frame;
        }

        if (chunk_count > 0)
        {
            /*
             Step through the chunks, storing information for their decompression
             */
            HapChunkDecodeInfo *chunk_info = (HapChunkDecodeInfo *)malloc(sizeof(HapChunkDecodeInfo) * chunk_count);

            size_t running_compressed_chunk_size = 0;
            size_t running_uncompressed_chunk_size = 0;
            int i;

            if (chunk_info == NULL)
            {
                return HapResult_Internal_Error;
            }

            for (i = 0; i < chunk_count; i++) {

                chunk_info[i].compressor = *(((uint8_t *)compressors) + i);

                chunk_info[i].compressed_chunk_size = hap_read_4_byte_uint(((uint8_t *)chunk_sizes) + (i * 4));

                if (chunk_offsets)
                {
                    chunk_info[i].compressed_chunk_data = frame_data + hap_read_4_byte_uint(((uint8_t *)chunk_offsets) + (i * 4));
                }
                else
                {
                    chunk_info[i].compressed_chunk_data = frame_data + running_compressed_chunk_size;
                }

                running_compressed_chunk_size += chunk_info[i].compressed_chunk_size;

                if (chunk_info[i].compressor == kHapCompressorSnappy)
                {
                    snappy_status snappy_result = snappy_uncompressed_length(chunk_info[i].compressed_chunk_data,
                        chunk_info[i].compressed_chunk_size,
                        &(chunk_info[i].uncompressed_chunk_size));

                    if (snappy_result != SNAPPY_OK)
                    {
                        switch (snappy_result)
                        {
                        case SNAPPY_INVALID_INPUT:
                            result = HapResult_Bad_Frame;
                            break;
                        default:
                            result = HapResult_Internal_Error;
                            break;
                        }
                        break;
                    }
                }
                else
                {
                    chunk_info[i].uncompressed_chunk_size = chunk_info[i].compressed_chunk_size;
                }

                chunk_info[i].uncompressed_chunk_data = (char *)(((uint8_t *)outputBuffer) + running_uncompressed_chunk_size);
                running_uncompressed_chunk_size += chunk_info[i].uncompressed_chunk_size;
            }

            if (result == HapResult_No_Error && running_uncompressed_chunk_size > outputBufferBytes)
            {
                result = HapResult_Buffer_Too_Small;
            }

            if (result == HapResult_No_Error)
            {
                /*
                 Perform decompression
                 */
                bytesUsed = running_uncompressed_chunk_size;

                callback((HapDecodeWorkFunction)hap_decode_chunk, chunk_info, chunk_count, info);

                /*
                 Check to see if we encountered any errors and report one of them
                 */
                for (i = 0; i < chunk_count; i++)
                {
                    if (chunk_info[i].result != HapResult_No_Error)
                    {
                        result = chunk_info[i].result;
                        break;
                    }
                }
            }

            free(chunk_info);

            if (result != HapResult_No_Error)
            {
                return result;
            }
        }
    }
    else if (compressor == kHapCompressorSnappy)
    {
        /*
         Only one section is present containing a single block of snappy-compressed S3 data
         */
        snappy_status snappy_result = snappy_uncompressed_length((const char *)sectionStart, sectionLength, &bytesUsed);
        if (snappy_result != SNAPPY_OK)
        {
            return HapResult_Internal_Error;
        }
        if (bytesUsed > outputBufferBytes)
        {
            return HapResult_Buffer_Too_Small;
        }
        snappy_result = snappy_uncompress((const char *)sectionStart, sectionLength, (char *)outputBuffer, &bytesUsed);
        if (snappy_result != SNAPPY_OK)
        {
            return HapResult_Internal_Error;
        }
    }
    else if (compressor == kHapCompressorNone)
    {
        /*
         Only one section is present containing a single block of uncompressed S3 data
         */
        bytesUsed = sectionLength;
        if (sectionLength > outputBufferBytes)
        {
            return HapResult_Buffer_Too_Small;
        }
        memcpy(outputBuffer, sectionStart, sectionLength);
    }
    else
    {
        return HapResult_Bad_Frame;
    }
    /*
     Fill out the remaining return value
     */
    if (outputBufferBytesUsed != NULL)
    {
        *outputBufferBytesUsed = bytesUsed;
    }
    
    return HapResult_No_Error;
}
示例#5
0
文件: hap.c 项目: Vidvox/hap
static unsigned int hap_decode_header_complex_instructions(const void *texture_section, uint32_t texture_section_length, int * chunk_count,
                                                   const void **compressors, const void **chunk_sizes, const void **chunk_offsets, const char **frame_data){
    int result = HapResult_No_Error;
    const void *section_start;
    uint32_t section_header_length;
    uint32_t section_length;
    unsigned int section_type;
    size_t bytes_remaining = 0;

    *compressors = NULL;
    *chunk_sizes = NULL;
    *chunk_offsets = NULL;

    result = hap_read_section_header(texture_section, texture_section_length, &section_header_length, &section_length, &section_type);

    if (result == HapResult_No_Error && section_type != kHapSectionDecodeInstructionsContainer)
    {
        result = HapResult_Bad_Frame;
    }

    if (result != HapResult_No_Error)
    {
        return result;
    }

    /*
     Frame data follows immediately after the Decode Instructions Container
     */
    *frame_data = ((const char *)texture_section) + section_header_length + section_length;

    /*
     Step through the sections inside the Decode Instructions Container
     */
    section_start = ((uint8_t *)texture_section) + section_header_length;
    bytes_remaining = section_length;

    while (bytes_remaining > 0) {
        unsigned int section_chunk_count = 0;
        result = hap_read_section_header(section_start, bytes_remaining, &section_header_length, &section_length, &section_type);
        if (result != HapResult_No_Error)
        {
            return result;
        }
        section_start = ((uint8_t *)section_start) + section_header_length;
        switch (section_type) {
            case kHapSectionChunkSecondStageCompressorTable:
                *compressors = section_start;
                section_chunk_count = section_length;
                break;
            case kHapSectionChunkSizeTable:
                *chunk_sizes = section_start;
                section_chunk_count = section_length / 4;
                break;
            case kHapSectionChunkOffsetTable:
                *chunk_offsets = section_start;
                section_chunk_count = section_length / 4;
                break;
            default:
                // Ignore unrecognized sections
                break;
        }

        /*
         If we calculated a chunk count and already have one, make sure they match
         */
        if (section_chunk_count != 0)
        {
            if ((*chunk_count) != 0 && section_chunk_count != (*chunk_count))
            {
                return HapResult_Bad_Frame;
            }
            *chunk_count = section_chunk_count;
        }

        section_start = ((uint8_t *)section_start) + section_length;
        bytes_remaining -= section_header_length + section_length;
    }

    /*
     The Chunk Second-Stage Compressor Table and Chunk Size Table are required
     */
    if (*compressors == NULL || *chunk_sizes == NULL)
    {
        return HapResult_Bad_Frame;
    }
    return result;
}