Ejemplo n.º 1
0
/*Unpacks a series of octets from a given byte array into the pack buffer.
  No checking is done to ensure the buffer contains enough data.
  _opb: The pack buffer to read the octets from.
  _buf: The byte array to store the unpacked bytes in.
  _len: The number of octets to unpack.*/
static void oc_unpack_octets(oc_pack_buf *_opb,char *_buf,size_t _len){
  while(_len-->0){
	long val;
	val=oc_pack_read(_opb,8);
	*_buf++=(char)val;
  }
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
static int oc_info_unpack(oc_pack_buf *_opb,th_info *_info){
  long val;
  /*Check the codec bitstream version.*/
  val=oc_pack_read(_opb,8);
  _info->version_major=(unsigned char)val;
  val=oc_pack_read(_opb,8);
  _info->version_minor=(unsigned char)val;
  val=oc_pack_read(_opb,8);
  _info->version_subminor=(unsigned char)val;
  /*verify we can parse this bitstream version.
	 We accept earlier minors and all subminors, by spec*/
  if(_info->version_major>TH_VERSION_MAJOR||
   _info->version_major==TH_VERSION_MAJOR&&
   _info->version_minor>TH_VERSION_MINOR){
	return TH_EVERSION;
  }
  /*Read the encoded frame description.*/
  val=oc_pack_read(_opb,16);
  _info->frame_width=(ogg_uint32_t)val<<4;
  val=oc_pack_read(_opb,16);
  _info->frame_height=(ogg_uint32_t)val<<4;
  val=oc_pack_read(_opb,24);
  _info->pic_width=(ogg_uint32_t)val;
  val=oc_pack_read(_opb,24);
  _info->pic_height=(ogg_uint32_t)val;
  val=oc_pack_read(_opb,8);
  _info->pic_x=(ogg_uint32_t)val;
  val=oc_pack_read(_opb,8);
  _info->pic_y=(ogg_uint32_t)val;
  val=oc_pack_read(_opb,32);
  _info->fps_numerator=(ogg_uint32_t)val;
  val=oc_pack_read(_opb,32);
  _info->fps_denominator=(ogg_uint32_t)val;
  if(_info->frame_width==0||_info->frame_height==0||
   _info->pic_width+_info->pic_x>_info->frame_width||
   _info->pic_height+_info->pic_y>_info->frame_height||
   _info->fps_numerator==0||_info->fps_denominator==0){
	return TH_EBADHEADER;
  }
  /*Note: The sense of pic_y is inverted in what we pass back to the
	 application compared to how it is stored in the bitstream.
	This is because the bitstream uses a right-handed coordinate system, while
	 applications expect a left-handed one.*/
  _info->pic_y=_info->frame_height-_info->pic_height-_info->pic_y;
  val=oc_pack_read(_opb,24);
  _info->aspect_numerator=(ogg_uint32_t)val;
  val=oc_pack_read(_opb,24);
  _info->aspect_denominator=(ogg_uint32_t)val;
  val=oc_pack_read(_opb,8);
  _info->colorspace=(th_colorspace)val;
  val=oc_pack_read(_opb,24);
  _info->target_bitrate=(int)val;
  val=oc_pack_read(_opb,6);
  _info->quality=(int)val;
  val=oc_pack_read(_opb,5);
  _info->keyframe_granule_shift=(int)val;
  val=oc_pack_read(_opb,2);
  _info->pixel_fmt=(th_pixel_fmt)val;
  if(_info->pixel_fmt==TH_PF_RSVD)return TH_EBADHEADER;
  val=oc_pack_read(_opb,3);
  if(val!=0||oc_pack_bytes_left(_opb)<0)return TH_EBADHEADER;
  return 0;
}
Ejemplo n.º 7
0
/*Unpacks a 32-bit integer encoded by octets in little-endian form.*/
static long oc_unpack_length(oc_pack_buf *_opb){
  long ret[4];
  int  i;
  for(i=0;i<4;i++)ret[i]=oc_pack_read(_opb,8);
  return ret[0]|ret[1]<<8|ret[2]<<16|ret[3]<<24;
}
Ejemplo n.º 8
0
static int oc_dec_headerin(oc_pack_buf *_opb,th_info *_info,
 th_comment *_tc,th_setup_info **_setup,ogg_packet *_op){
  char buffer[6];
  long val;
  int  packtype;
  int  ret;
  val=oc_pack_read(_opb,8);
  packtype=(int)val;
  /*If we're at a data packet and we have received all three headers, we're
	 done.*/
  if(!(packtype&0x80)&&_info->frame_width>0&&_tc->vendor!=NULL&&*_setup!=NULL){
	return 0;
  }
  /*Check the codec string.*/
  oc_unpack_octets(_opb,buffer,6);
  if(memcmp(buffer,"theora",6)!=0)return TH_ENOTFORMAT;
  switch(packtype){
	/*Codec info header.*/
	case 0x80:{
	  /*This should be the first packet, and we should not already be
		 initialized.*/
	  if(!_op->b_o_s||_info->frame_width>0)return TH_EBADHEADER;
	  ret=oc_info_unpack(_opb,_info);
	  if(ret<0)th_info_clear(_info);
	  else ret=3;
	}break;
	/*Comment header.*/
	case 0x81:{
	  if(_tc==NULL)return TH_EFAULT;
	  /*We shoud have already decoded the info header, and should not yet have
		 decoded the comment header.*/
	  if(_info->frame_width==0||_tc->vendor!=NULL)return TH_EBADHEADER;
	  ret=oc_comment_unpack(_opb,_tc);
	  if(ret<0)th_comment_clear(_tc);
	  else ret=2;
	}break;
	/*Codec setup header.*/
	case 0x82:{
	  oc_setup_info *setup;
	  if(_tc==NULL||_setup==NULL)return TH_EFAULT;
	  /*We should have already decoded the info header and the comment header,
		 and should not yet have decoded the setup header.*/
	  if(_info->frame_width==0||_tc->vendor==NULL||*_setup!=NULL){
		return TH_EBADHEADER;
	  }
	  setup=(oc_setup_info *)_ogg_calloc(1,sizeof(*setup));
	  if(setup==NULL)return TH_EFAULT;
	  ret=oc_setup_unpack(_opb,setup);
	  if(ret<0){
		oc_setup_clear(setup);
		_ogg_free(setup);
	  }
	  else{
		*_setup=setup;
		ret=1;
	  }
	}break;
	default:{
	  /*We don't know what this header is.*/
	  return TH_EBADHEADER;
	}break;
  }
  return ret;
}