Пример #1
0
/*Unpacks a sub-tree from the given buffer.
  _opb:      The buffer to unpack from.
  _binodes:  The nodes to store the sub-tree in.
  _nbinodes: The number of nodes available for the sub-tree.
  Return: 0 on success, or a negative value on error.*/
static int oc_huff_tree_unpack(oc_pack_buf *_opb,
 oc_huff_node *_binodes,int _nbinodes){
  oc_huff_node *binode;
  long          bits;
  int           nused;
  if(_nbinodes<1)return TH_EBADHEADER;
  binode=_binodes;
  nused=0;
  bits=oc_pack_read1(_opb);
  if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
  /*Read an internal node:*/
  if(!bits){
    int ret;
    nused++;
    binode->nbits=1;
    binode->depth=1;
    binode->nodes[0]=_binodes+nused;
    ret=oc_huff_tree_unpack(_opb,_binodes+nused,_nbinodes-nused);
    if(ret>=0){
      nused+=ret;
      binode->nodes[1]=_binodes+nused;
      ret=oc_huff_tree_unpack(_opb,_binodes+nused,_nbinodes-nused);
    }
    if(ret<0)return ret;
    nused+=ret;
  }
  /*Read a leaf node:*/
  else{
    int ntokens;
    int token;
    int i;
    bits=oc_pack_read(_opb,OC_NDCT_TOKEN_BITS);
    if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
    /*Find out how many internal tokens we translate this external token into.*/
    ntokens=OC_DCT_TOKEN_MAP_ENTRIES[bits];
    if(_nbinodes<2*ntokens-1)return TH_EBADHEADER;
    /*Fill in a complete binary tree pointing to the internal tokens.*/
    for(i=1;i<ntokens;i<<=1){
      int j;
      binode=_binodes+nused;
      nused+=i;
      for(j=0;j<i;j++){
        binode[j].nbits=1;
        binode[j].depth=1;
        binode[j].nodes[0]=_binodes+nused+2*j;
        binode[j].nodes[1]=_binodes+nused+2*j+1;
      }
    }
    /*And now the leaf nodes with those tokens.*/
    token=OC_DCT_TOKEN_MAP[bits];
    for(i=0;i<ntokens;i++){
      binode=_binodes+nused++;
      binode->nbits=0;
      binode->depth=1;
      binode->token=token+i;
    }
  }
  return nused;
}
Пример #2
0
/*Unpacks a Huffman codebook.
  _opb:    The buffer to unpack from.
  _tokens: Stores a list of internal tokens, in the order they were found in
			the codebook, and the lengths of their corresponding codewords.
		   This is enough to completely define the codebook, while minimizing
			stack usage and avoiding temporary allocations (for platforms
			where free() is a no-op).
  Return: The number of internal tokens in the codebook, or a negative value
   on error.*/
int oc_huff_tree_unpack(oc_pack_buf* _opb, unsigned char _tokens[256][2])
{
	ogg_uint32_t code;
	int len;
	int ntokens;
	int nleaves;
	code = 0;
	len = ntokens = nleaves = 0;
	for (;;)
	{
		long bits;
		bits = oc_pack_read1(_opb);
		/*Only process nodes so long as there's more bits in the buffer.*/
		if (oc_pack_bytes_left(_opb) < 0)
			return TH_EBADHEADER;
		/*Read an internal node:*/
		if (!bits)
		{
			len++;
			/*Don't allow codewords longer than 32 bits.*/
			if (len > 32)
				return TH_EBADHEADER;
		}
		/*Read a leaf node:*/
		else
		{
			ogg_uint32_t code_bit;
			int neb;
			int nentries;
			int token;
			/*Don't allow more than 32 spec-tokens per codebook.*/
			if (++nleaves > 32)
				return TH_EBADHEADER;
			bits = oc_pack_read(_opb, OC_NDCT_TOKEN_BITS);
			neb = OC_DCT_TOKEN_MAP_LOG_NENTRIES[bits];
			token = OC_DCT_TOKEN_MAP[bits];
			nentries = 1 << neb;
			while (nentries-- > 0)
			{
				_tokens[ntokens][0] = (unsigned char)token++;
				_tokens[ntokens][1] = (unsigned char)(len + neb);
				ntokens++;
			}
			code_bit = 0x80000000U >> len - 1;
			while (len > 0 && (code & code_bit))
			{
				code ^= code_bit;
				code_bit <<= 1;
				len--;
			}
			if (len <= 0)
				break;
			code |= code_bit;
		}
	}
	return ntokens;
}
Пример #3
0
/*This is used to copy the configuration of an existing setup header for use by
   the encoder.
  The decoder uses a completely different data structure for the Huffman
   codebooks.*/
int oc_huff_codes_unpack(oc_pack_buf *_opb,
 th_huff_code _codes[TH_NHUFFMAN_TABLES][TH_NDCT_TOKENS]){
  int i;
  for(i=0;i<TH_NHUFFMAN_TABLES;i++){
    ogg_uint32_t code;
    int          len;
    int          nleaves;
    code=0;
    len=nleaves=0;
    memset(_codes[i],0,TH_NDCT_TOKENS*sizeof(*_codes[i]));
    for(;;){
      long bits;
      bits=oc_pack_read1(_opb);
      /*Only process nodes so long as there's more bits in the buffer.*/
      if(oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
      /*Read an internal node:*/
      if(!bits){
        len++;
        /*Don't allow codewords longer than 32 bits.*/
        if(len>32)return TH_EBADHEADER;
      }
      /*Read a leaf node:*/
      else{
        ogg_uint32_t code_bit;
        /*Don't allow more than 32 tokens per codebook.*/
        if(++nleaves>32)return TH_EBADHEADER;
        bits=oc_pack_read(_opb,OC_NDCT_TOKEN_BITS);
        /*The current encoder does not support codebooks that do not contain
           all of the tokens.*/
        if(_codes[i][bits].nbits>0)return TH_EINVAL;
        _codes[i][bits].pattern=code>>32-len;
        _codes[i][bits].nbits=len;
        code_bit=0x80000000U>>len-1;
        while(len>0&&(code&code_bit)){
          code^=code_bit;
          code_bit<<=1;
          len--;
        }
        if(len<=0)break;
        code|=code_bit;
      }
    }
    /*The current encoder does not support codebooks that do not contain all of
       the tokens.*/
    if(nleaves<32)return TH_EINVAL;
  }
  return 0;
}
Пример #4
0
int oc_quant_params_unpack(oc_pack_buf *_opb,th_quant_info *_qinfo){
  th_quant_base *base_mats;
  long           val;
  int            nbase_mats;
  int            sizes[64];
  int            indices[64];
  int            nbits;
  int            bmi;
  int            ci;
  int            qti;
  int            pli;
  int            qri;
  int            qi;
  int            i;
  val=oc_pack_read(_opb,3);
  nbits=(int)val;
  for(qi=0;qi<64;qi++){
    val=oc_pack_read(_opb,nbits);
    _qinfo->loop_filter_limits[qi]=(unsigned char)val;
  }
  val=oc_pack_read(_opb,4);
  nbits=(int)val+1;
  for(qi=0;qi<64;qi++){
    val=oc_pack_read(_opb,nbits);
    _qinfo->ac_scale[qi]=(ogg_uint16_t)val;
  }
  val=oc_pack_read(_opb,4);
  nbits=(int)val+1;
  for(qi=0;qi<64;qi++){
    val=oc_pack_read(_opb,nbits);
    _qinfo->dc_scale[qi]=(ogg_uint16_t)val;
  }
  val=oc_pack_read(_opb,9);
  nbase_mats=(int)val+1;
  base_mats=_ogg_malloc(nbase_mats*sizeof(base_mats[0]));
  if(base_mats==NULL)return TH_EFAULT;
  for(bmi=0;bmi<nbase_mats;bmi++){
    for(ci=0;ci<64;ci++){
      val=oc_pack_read(_opb,8);
      base_mats[bmi][ci]=(unsigned char)val;
    }
  }
  nbits=oc_ilog(nbase_mats-1);
  for(i=0;i<6;i++){
    th_quant_ranges *qranges;
    th_quant_base   *qrbms;
    int             *qrsizes;
    qti=i/3;
    pli=i%3;
    qranges=_qinfo->qi_ranges[qti]+pli;
    if(i>0){
      val=oc_pack_read1(_opb);
      if(!val){
        int qtj;
        int plj;
        if(qti>0){
          val=oc_pack_read1(_opb);
          if(val){
            qtj=qti-1;
            plj=pli;
          }
          else{
            qtj=(i-1)/3;
            plj=(i-1)%3;
          }
        }
        else{
          qtj=(i-1)/3;
          plj=(i-1)%3;
        }
        *qranges=*(_qinfo->qi_ranges[qtj]+plj);
        continue;
      }
    }
    val=oc_pack_read(_opb,nbits);
    indices[0]=(int)val;
    for(qi=qri=0;qi<63;){
      val=oc_pack_read(_opb,oc_ilog(62-qi));
      sizes[qri]=(int)val+1;
      qi+=(int)val+1;
      val=oc_pack_read(_opb,nbits);
      indices[++qri]=(int)val;
    }
    /*Note: The caller is responsible for cleaning up any partially
       constructed qinfo.*/
    if(qi>63){
      _ogg_free(base_mats);
      return TH_EBADHEADER;
    }
    qranges->nranges=qri;
    qranges->sizes=qrsizes=(int *)_ogg_malloc(qri*sizeof(qrsizes[0]));
    if(qranges->sizes==NULL){
      /*Note: The caller is responsible for cleaning up any partially
         constructed qinfo.*/
      _ogg_free(base_mats);
      return TH_EFAULT;
    }
    memcpy(qrsizes,sizes,qri*sizeof(qrsizes[0]));
    qrbms=(th_quant_base *)_ogg_malloc((qri+1)*sizeof(qrbms[0]));
    if(qrbms==NULL){
      /*Note: The caller is responsible for cleaning up any partially
         constructed qinfo.*/
      _ogg_free(base_mats);
      return TH_EFAULT;
    }
    qranges->base_matrices=(const th_quant_base *)qrbms;
    do{
      bmi=indices[qri];
      /*Note: The caller is responsible for cleaning up any partially
         constructed qinfo.*/
      if(bmi>=nbase_mats){
        _ogg_free(base_mats);
        return TH_EBADHEADER;
      }
      memcpy(qrbms[qri],base_mats[bmi],sizeof(qrbms[qri]));
    }
    while(qri-->0);
  }
  _ogg_free(base_mats);
  return 0;
}