Skip to content

HapGetFrameChunkCount  #15

@Qlex42

Description

@Qlex42

Hi Hap team !
Thanks you very much for sharing this wonderful codec library.

I think it could be nice having a HapGetFrameChunkCount function like HapGetFrameTextureFormat, allowing the client application to get the hap chunk's count of a file without decoding it.

This can be useful during the workflow to check if the graphists correctly encode their video files for quick decoding.

This can also help client application to fit the number of thread to decode hap files.

I wrote a version of this function who seems to work very well.
It's greatly copy pasted from hap_decode_single_texture function.
So a refactoring should be certainly needed.

Here my little contribution:

unsigned int HapGetFrameChunkCount(const void *inputBuffer, unsigned long inputBufferBytes, unsigned int index, unsigned int *chunkCount)
{
  unsigned int result = HapResult_No_Error;
  const void *texture_section;
  uint32_t texture_section_length;
  unsigned int texture_section_type;
  unsigned int compressor;

  /*
  Check arguments
  */
  if (inputBuffer == NULL
    || index > 1
    || chunkCount == NULL
    )
  {
    return HapResult_Bad_Arguments;
  }

  *chunkCount = 0;

  /*
  Locate the section at the given index, which will either be the top-level section in a single texture image, or one of the
  sections inside a multi-image top-level section.
  */
  result = hap_get_section_at_index(inputBuffer, inputBufferBytes, index, &texture_section, &texture_section_length, &texture_section_type);

  if (result == HapResult_No_Error)
  {
    // copy past from hap_decode_single_texture
    compressor = hap_top_4_bits(texture_section_type);
    if (compressor == kHapCompressorComplex)
    {
      const void *section_start;
      uint32_t section_header_length;
      uint32_t section_length;
      unsigned int section_type;
      size_t bytes_remaining = 0;

      const void *compressors = NULL;
      const void *chunk_sizes = NULL;
      const void *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;
      }

      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 (*chunkCount != 0 && section_chunk_count != *chunkCount)
          {
            return HapResult_Bad_Frame;
          }
          *chunkCount = section_chunk_count;
        }

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

    }
    else if (compressor == kHapCompressorSnappy)
    {
      // no chunk ?
    }
    else if (compressor == kHapCompressorNone)
    {
      // no chunk.
    }
    else
    {
      return HapResult_Bad_Frame;
    }
  }
  return result;
}

Hoping this can help
Best regards,

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions