⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ebcot_receive_bits.c

📁 JPEG2000实现的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
  elts = 0;
  next_rows = rows;
  next_cols = cols;
  do {
    new_elts = next_rows*next_cols;
    elts += new_elts;
    next_rows = (1+next_rows)>>1;
    next_cols = (1+next_cols)>>1;
  } while (new_elts > 1);
  result = node = (tag_tree_node_ptr)
    local_malloc(EBCOT_MEM_KEY,sizeof(tag_tree_node)*(size_t) elts);
  do {
    elts = rows*cols;
    parents = node + elts;
    if (elts == 1)
      parents = NULL;
    next_rows = (1+rows)>>1;
    next_cols = (1+cols)>>1;
    for (r=0; r < rows; r++)
      for (c=0; c < cols; c++, node++)
        {
          node->value = INT_MAX;
          node->lower_bound = 0;
          node->child = NULL;
          node->parent = NULL;
          if (parents != NULL)
            node->parent = parents + ((r>>1)*next_cols + (c>>1));
        }
    rows = next_rows;
    cols = next_cols;
  } while (elts > 1);
  return(result);
}

/*****************************************************************************/
/* EXTERN                    ebcot_destroy_tag_tree                          */
/*****************************************************************************/

void
  ebcot_destroy_tag_tree(tag_tree_node_ptr tree)
{
  if (tree != NULL)
    local_free(tree);
}

/*****************************************************************************/
/* EXTERN                ebcot_get_packet_head_and_body                      */
/*****************************************************************************/

void
  ebcot_get_packet_head_and_body(ebcot_decoder_ref self,
                                 ebcot_precinct_info_ptr precinct,
                                 block_master_ptr master,
                                 int layer_idx)

 /* Note: the function computes several properties of corrupted packets
    which are not currently used, but could come in handy later.  These
    are `trailing_useless_bytes' (the total number of bytes recovered from
    the packet, which cannot and will not be used by the decompressor
    due to corruption) and `min_packet_bytes' (the minimum number of bytes
    from the packet which will be useful to the decoder).  The sum of these
    two quantities is equal to the total number of bytes recovered from
    the packet; the actual packet size may be slightly larger due to the
    inclusion of error correction codes. */

{
  dst_codeword_heap_ref code_mgr = self->code_heap_mgr;
  stream_in_ref stream = self->stream;
  tag_buffer_ptr tags;
  int useless_packet, packet_body_corrupted;
  int min_packet_bytes, trailing_useless_bytes;
  int packet_non_empty, new_passes;
  ebcot_precinct_band_info_ptr pband;
  ebcot_block_info_ptr bpp, block;
  int b, r, c, pos;

  assert(layer_idx == precinct->recovered_layers);
  if (layer_idx == 0)
    { /* Initialize various quantities. */
      for (b=precinct->min_band; b <= precinct->max_band; b++)
        {
          pband = precinct->bands + b;
          if (!pband->valid_band)
            continue;
          tag_tree__reset(pband->inclusion_tree);
          tag_tree__reset(pband->insignificant_msbs_tree);
          for (pos=0, bpp=pband->blocks,
               r=pband->blocks_high; r > 0; r--, bpp += pband->block_row_gap)
            for (block=bpp, c=pband->blocks_wide; c > 0; c--, block++, pos++)
              {
                block->num_passes = 0;
                block->num_signalled_passes = 0;
                block->total_bytes = 0;
                block->new_passes = 0;
                block->insignificant_msbs = 0;
                block->byte_count_bits = 3; /* Minimum number of bits for
                                               signalling byte counts. */
              }
          }
    }

  tags = create_tag_buffer();
  tag_buffer__reset(tags,stream);
  packet_non_empty = 0;
  if (tag_buffer__try(tags))
    {
      tag_buffer__pull_bit(tags,packet_non_empty);
      if (packet_non_empty)
        recover_packet_head(self,precinct,master,layer_idx,tags);
    }
  else
    precinct->packet_loss_encountered = 1;

  min_packet_bytes = tags->retrieved_bytes;
  if (precinct->packet_loss_encountered || !packet_non_empty)
    {
      tag_buffer__destroy(tags);
      trailing_useless_bytes = INT_MAX;
      useless_packet = 1;
      return;
    }

  /* If we get here then the packet appears to be uncorrupted so far
     and the `new_passes' fields of all code blocks identify the number
     of new passes which are being added.  We now try to read all the
     relevant block code bytes from the packet's body. */

  useless_packet = 0;
  packet_body_corrupted = 0;
  trailing_useless_bytes = 0;
  for (b=precinct->min_band; b <= precinct->max_band; b++)
    {
      pband = precinct->bands + b;
      if (!pband->valid_band)
        continue;
      for (pos=0, bpp=pband->blocks,
           r=pband->blocks_high; r > 0; r--, bpp += pband->block_row_gap)
        for (block=bpp, c=pband->blocks_wide; c > 0; c--, block++, pos++)
          {
            std_byte *wp;
            dst_heap_unit_ptr unit;
            int num_bytes, pulled_bytes, remaining_bytes, recovered_bytes;

            new_passes = block->new_passes;
            if (new_passes <= 0)
              continue;
            unit = block->first_unit;
            if (unit == NULL)
              { remaining_bytes = 0; wp = NULL; }
            else
              { remaining_bytes = DST_HEAP_BYTES;
                wp = (std_byte *)(unit->words); }
            num_bytes = block->total_signalled_bytes; /* Skip over these. */
            while (num_bytes > 0)
              {
                if (num_bytes > remaining_bytes)
                  {
                    unit = unit->next;
                    num_bytes -= remaining_bytes;
                    remaining_bytes = DST_HEAP_BYTES;
                    wp = (std_byte *)(unit->words);
                  }
                else
                  {
                    wp += num_bytes;
                    remaining_bytes -= num_bytes;
                    num_bytes = 0;
                  }
              }

            num_bytes = block->passes[block->num_signalled_passes].layer_bytes;
            recovered_bytes = 0;
            if (num_bytes == 0)
              { /* Length information for block must have been corrupted.
                   Cannot signal non-zero number of passes and a length of
                   zero! */
                packet_body_corrupted = 1;
              }
            while ((num_bytes > 0) && (!packet_body_corrupted))
              {
                if (remaining_bytes == 0)
                  { /* Allocate new unit. */
                    if (unit == NULL)
                      block->first_unit = unit = code_mgr->get_unit(code_mgr);
                    else
                      unit = unit->next = code_mgr->get_unit(code_mgr);
                    remaining_bytes = DST_HEAP_BYTES;
                    wp = (std_byte *)(unit->words);
                  }
                if (num_bytes > remaining_bytes)
                  {
                    pulled_bytes =
                      stream->pull_body_bytes(stream,wp,remaining_bytes);
                    recovered_bytes += pulled_bytes;
                    if (pulled_bytes < remaining_bytes)
                      { /* Corruption or truncation detected in the body at
                           least.  Assume for now that the head is OK so that
                           we will continue to update the signalled quantities
                           but not `num_passes' and `total_bytes'. */
                        packet_body_corrupted = 1;
                        break;
                      }
                    num_bytes -= remaining_bytes;
                    remaining_bytes = 0;
                    wp = NULL;
                  }
                else
                  {
                    pulled_bytes =
                      stream->pull_body_bytes(stream,wp,num_bytes);
                    recovered_bytes += pulled_bytes;
                    if (pulled_bytes < num_bytes)
                      { /* Corruption or truncation detected in the body at
                           least.  Assume for now that the head is OK so that
                           we will continue to update the signalled quantities
                           but not `num_passes' and `total_bytes'. */
                        packet_body_corrupted = 1;
                        break;
                      }
                    wp += num_bytes;
                    remaining_bytes -= num_bytes;
                    num_bytes = 0;
                  }
              }
            if (packet_body_corrupted)
              { /* There will be no more updating of the `num_passes' and
                   `total_bytes' fields from now on. */
                trailing_useless_bytes += recovered_bytes;
                if (min_packet_bytes == tags->retrieved_bytes)
                  useless_packet = 1;
              }
            else if (block->num_signalled_passes == block->num_passes)
              {
                assert(num_bytes == 0);
                block->num_passes += block->new_passes;
                block->total_bytes += recovered_bytes;
              }
            block->total_signalled_bytes += recovered_bytes;
            block->num_signalled_passes += block->new_passes;
            block->new_passes = 0;
            min_packet_bytes += recovered_bytes;
          }
    }
  tag_buffer__destroy(tags);
}

/*****************************************************************************/
/* EXTERN                      ebcot_parse_to_length                         */
/*****************************************************************************/

void
  ebcot_parse_to_length(ebcot_decoder_ref self, int max_bytes)
{
  int tnum, layer, max_layers, c, n, p;
  ebcot_tile_ptr tile;
  ebcot_component_info_ptr comp_info;
  ebcot_level_info_ptr lev;
  ebcot_precinct_info_ptr precinct;

  if (self->actual_bytes <= max_bytes)
    return;
  max_layers = 0;
  for (tnum=0; tnum < self->num_tiles; tnum++)
    {
      tile = self->tiles + tnum;
      if (tile->num_layers > max_layers)
        max_layers = tile->num_layers;
    }
  if (max_layers == 1)
    local_printf(0,76,"\nWarning: the bit-stream which is being parsed "
                       "down to satisfy the supplied bit-rate constraint "
                       "is not SNR scalable (i.e. no tile has more than one "
                       "quality layer)!!  This means "
                       "that whole blocks will be discarded , starting from "
                       "the high frequency subbands and working down.  This "
                       "is probably not what you want!");
  for (layer=max_layers-1; layer >= 0; layer--)
    {
      for (tnum=self->num_tiles-1; tnum >= 0; tnum--)
        {
          tile = self->tiles + tnum;
          if (tile->num_layers <= layer)
            continue; /* Nothing to remove from this tile. */
          for (c=tile->max_components-1; c >= 0; c--)
            {
              comp_info = tile->components + c;
              for (n=comp_info->num_levels; n >= 0; n--)
                {
                  lev = comp_info->levels + n;
                  for (p=lev->total_precincts-1; p >= 0; p--)
                    {
                      precinct = lev->precincts + p;
                      parse_packet(self,precinct,layer,max_bytes);
                      if (self->actual_bytes <= max_bytes)
                        return;
                    }
                }
            }
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -