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

📄 ebcot_receive_bits.c

📁 JPEG2000实现的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
        }
      passes[pass_idx].terminated = 0;
      if (terminate_each_pass ||
          ((full_effort_msbs <= 0) &&
           ((n==0) || (n==(PASSES_PER_BITPLANE-1)))))
        passes[pass_idx].terminated = 1;
    }
}

/*****************************************************************************/
/* STATIC                      recover_packet_head                           */
/*****************************************************************************/

static void
  recover_packet_head(ebcot_decoder_ref self,
                      ebcot_precinct_info_ptr precinct,
                      block_master_ptr master,
                      int layer_idx, tag_buffer_ptr tags)

 /* This function does quite a bit of the work of the function
    `ebcot_get_packet_head_and_body'.  It recovers the header information
    for the packet, filling in the `new_passes' field of each relevant block,
    as well as the relevant entries in the `passes' array for the
    corresponding blocks.  The caller should use this information to update
    the `num_passes', `num_signalled_passes' and `total_bytes' fields for all
    affected blocks and to recover the code bytes themselves.  Upon entry,
    the packet has been started and the initial bit of the header has already
    been read to determine whether or not the packet contains any information.
    If a problem is detected in the packet header, the function may not
    actually return, but this exception will be caught by the caller as a
    false return from `tag_buffer__try'. */

{
  ebcot_precinct_band_info_ptr pband;
  ebcot_block_info_ptr bpp, block;
  int new_passes, save_new_passes, tag_val;
  int b, r, c, k, pos;

  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++)
          {
            /* Recover inclusion information. */

            if (block->num_signalled_passes == 0)
              { /* Not previously included. */
                tag_val =
                  tag_tree__decode(pband->inclusion_tree+pos,layer_idx+1,tags);
              }
            else
              { /* Block has already been included in a previous layer. */
                tag_buffer__pull_bit(tags,tag_val);
              }
            if (!tag_val)
              continue;

            /* Recover `insignificant_msbs' information, if necessary. */

            if (block->num_signalled_passes == 0)
              {
                k = 1;
                while (!tag_tree__decode(pband->insignificant_msbs_tree+pos,k,
                                         tags))
                  k++;
                block->insignificant_msbs = k-1;
                /* Begin David T ER fix */
                if ((block->insignificant_msbs*PASSES_PER_BITPLANE) >=
                    block->max_passes)
                  { /* An error has occurred in the packet head; everything
                       from now on must be corrupt. */
                    precinct->packet_loss_encountered = 1;
                    return;
                  }
                /* End David T ER fix */
                mark_termination_points(block->passes,
                                        block->insignificant_msbs,
                                        block->max_passes,
                                        master->terminate_each_pass,
                                        master->full_effort_msbs);
              }

            /* Now recover information about the number of new passes. */
            
            if (block->num_signalled_passes == 0)
              new_passes =
                block->insignificant_msbs * PASSES_PER_BITPLANE + 1;
            else
              new_passes = 1;
            tag_buffer__pull_bit(tags,tag_val);
            if (tag_val)
              {
                new_passes++;
                tag_buffer__pull_bit(tags,tag_val);
                if (tag_val)
                  {
                    new_passes++;
                    tag_val = tag_buffer__pull_bits(tags,2);
                    new_passes += tag_val;
                    if (tag_val == 3)
                      {
                        tag_val = tag_buffer__pull_bits(tags,5);
                        new_passes += tag_val;
                        if (tag_val == 31)
                          {
                            tag_val = tag_buffer__pull_bits(tags,7);
                            new_passes += tag_val;
                          }
                      }
                  }
              }
            if ((block->num_signalled_passes + new_passes) > block->max_passes)
              { /* Must be due to corruption in bit-stream. */
                new_passes = block->max_passes - block->num_signalled_passes;
              }
            save_new_passes = new_passes;
            if (new_passes > 0)
              { /* Recover the number of bytes between successive termination
                   and/or truncation points within these new passes. */
                ebcot_pass_info_ptr layer_start_pass, seg_start_pass, scan;
                int bytes_from_layer_start, num_bits;
                    
                /* Now for comma code identifying any required increment
                   in `byte_count_bits'. */
                do {
                  tag_buffer__pull_bit(tags,tag_val);
#ifdef REPORT_LENGTH_SIGNALLING_COST
                  ebcot_total_length_signalling_bits++;
#endif /* REPORT_LENGTH_SIGNALLING_COST */
                  if (tag_val)
                    block->byte_count_bits++;
                  } while (tag_val);

                layer_start_pass = seg_start_pass =
                  block->passes + block->num_signalled_passes;
                if (block->num_signalled_passes == 0)
                  {
                    k = block->insignificant_msbs * PASSES_PER_BITPLANE;
                    seg_start_pass += k;
                    new_passes -= k;
                  }
                bytes_from_layer_start = 0;
                while (new_passes > 0)
                  {
                    scan = seg_start_pass;
                    for (k=0; k < (new_passes-1); k++, scan++)
                      if (scan->terminated)
                        break;
                    k++; /* Get number of new passes covered by length. */
                    new_passes -= k;
#ifdef REPORT_LENGTH_SIGNALLING_COST
                    ebcot_total_length_signalled_passes += k;
#endif /* REPORT_LENGTH_SIGNALLING_COST */
                    for (num_bits=block->byte_count_bits; k > 1; k>>=1)
                      num_bits++;
                    if (num_bits > 16)
                      { /* Packet is corrupt. */
                        precinct->packet_loss_encountered = 1;
                        return;
                      }
#ifdef REPORT_LENGTH_SIGNALLING_COST
                    ebcot_total_length_signalling_bits += num_bits;
#endif /* REPORT_LENGTH_SIGNALLING_COST */
                    tag_val = tag_buffer__pull_bits(tags,num_bits);
                    bytes_from_layer_start += tag_val;
                    if (scan->terminated)
                      scan->special_length =
                        (std_ushort) bytes_from_layer_start;
                    seg_start_pass = scan+1;
                  }
                scan = layer_start_pass;
                scan->layer_idx = (std_ushort) layer_idx;
                scan->layer_bytes = (std_ushort) bytes_from_layer_start;
                for (scan++; scan < seg_start_pass; scan++)
                  {
                    scan->layer_idx = (std_ushort) layer_idx;
                    scan->layer_bytes = 0;
                  }
              }
            block->new_passes = save_new_passes;
          }
      }
}

/*****************************************************************************/
/* STATIC                          parse_packet                              */
/*****************************************************************************/

static void
  parse_packet(ebcot_decoder_ref self, ebcot_precinct_info_ptr precinct,
               int layer_idx, int max_bytes)

 /* This function pares down the size of a packet in order to satisfy the
    constraint imposed by the `max_bytes' bound.  It should be
    invoked packet by packet, starting with the least interesting packets,
    until the constraint is satisfied.  The function always removes whole
    code bytes at a time, adjusting the `self->actual_bytes' count to
    reflect the number of bytes which should be saved if this task were
    performed by a separate bit-stream parsing tool.  The actual number of
    bytes which would be saved if the bit-stream were parsed correctly might
    actually be somewhat more than that which is estimated by this function,
    because we cannot correctly account for the saving in error detection
    and/or correction codes which might be incurred at the bit-stream level.
    If error resilience features are not utilized, then the simulation
    of real bit-stream parsing should be accurate. */

{
  ebcot_precinct_band_info_ptr pband;
  ebcot_block_info_ptr block;
  dst_heap_unit_ptr prev, scan;
  int stripped_bytes, min_stripped_bytes, keeping_partial_packet;
  int num_bytes, b, r, c, k;

  min_stripped_bytes = self->actual_bytes - max_bytes;
  assert(min_stripped_bytes > 0);
  if (layer_idx >= precinct->recovered_layers)
    return;

  keeping_partial_packet = 0;
  stripped_bytes = 0;
  for (b=precinct->max_band;
       (b >= precinct->min_band) && (!keeping_partial_packet);
       b--)
    {
      pband = precinct->bands + b;

      if (!pband->valid_band)
        continue;

      for (r=pband->blocks_high-1; (r >= 0) && (!keeping_partial_packet); r--)
        for (c=pband->blocks_wide-1; c >= 0; c--)
          {
            block = pband->blocks + (c + r*pband->block_row_gap);
            k = block->num_passes;
            if ((k <= 0) || (block->passes[k-1].layer_idx < layer_idx))
              continue;
            if (stripped_bytes >= min_stripped_bytes)
              {
                keeping_partial_packet = 1;
                break;
              }
            do {
              k--;
              assert(layer_idx == block->passes[k].layer_idx);
            } while ((num_bytes=block->passes[k].layer_bytes) == 0);
            block->num_passes = k;
            block->total_bytes -= num_bytes;
            assert(block->total_bytes >= 0);
            stripped_bytes += num_bytes;
            for (prev=NULL, scan=block->first_unit,
                 num_bytes=block->total_bytes; num_bytes > 0;
                 prev=scan, scan=scan->next)
              num_bytes -= DST_HEAP_BYTES;
            if (prev == NULL)
              {
                assert(block->total_bytes == 0);
                block->first_unit = NULL;
              }
            else
              prev->next = NULL;
            while ((prev=scan) != NULL)
              {
                scan=prev->next;
                self->code_heap_mgr->return_unit(self->code_heap_mgr,prev);
              }
          }
    }

  if (keeping_partial_packet)
    self->actual_bytes -= stripped_bytes;
  else
    { /* Remove entire packet. */
      precinct->recovered_layers--;
      assert(precinct->recovered_layers == layer_idx);
      assert(precinct->layer_bytes[layer_idx] >= stripped_bytes);
      self->actual_bytes -= precinct->layer_bytes[layer_idx];
    }
}

/* ========================================================================= */
/* ---------------------------- External Functions ------------------------- */
/* ========================================================================= */

/*****************************************************************************/
/* EXTERN                     ebcot_create_tag_tree                          */
/*****************************************************************************/

tag_tree_node_ptr
  ebcot_create_tag_tree(int rows, int cols)

 /* Creates a tag-tree with an array of `rows'*`cols' leaf nodes, returning
    a pointer to the top-left hand corner leaf node (the leaf nodes appear
    at the head of the returned array, in scan-line order). */

{
  tag_tree_node_ptr result, node, parents;
  int elts, new_elts, next_rows, next_cols, r, c;

  if ((rows == 0) || (cols == 0))
    return(NULL);

⌨️ 快捷键说明

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