示例#1
0
/* compute bitrate tracking setup, allocate circular packet size queue */
void BURGERCALL vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm){
  int i;
  codec_setup_info *ci=static_cast<codec_setup_info *>(vi->codec_setup);
  bitrate_manager_info *bi=&ci->bi;
  long maxlatency;

  FastMemSet(bm,0,sizeof(*bm));
  
  if(bi){
    
    bm->avg_sampledesired=(Word32)(bi->queue_avg_time*vi->rate);
    bm->avg_centerdesired=(Word32)(bi->queue_avg_time*vi->rate*bi->queue_avg_center);
    bm->minmax_sampledesired=(Word32)(bi->queue_minmax_time*vi->rate);
    
    /* first find the max possible needed queue size */
    maxlatency=bm->avg_sampledesired-bm->avg_centerdesired;
	if (maxlatency<(long)bm->minmax_sampledesired) {
		maxlatency=bm->minmax_sampledesired;
	}
    
	maxlatency += bm->avg_centerdesired;
    if(maxlatency>0 &&
       (bi->queue_avgmin>0 || bi->queue_avgmax>0 || bi->queue_hardmax>0 ||
	bi->queue_hardmin>0)){
      long maxpackets=maxlatency/(ci->blocksizes[0]>>1)+3;
      long bins=BITTRACK_DIVISOR*ci->passlimit[ci->coupling_passes-1];
      
      bm->queue_size=maxpackets;
      bm->queue_bins=bins;
      bm->queue_binned=static_cast<Word32 *>(AllocAPointer(maxpackets*bins*sizeof(*bm->queue_binned)));
      bm->queue_actual=static_cast<Word32 *>(AllocAPointer(maxpackets*sizeof(*bm->queue_actual)));
      
      if((bi->queue_avgmin>0 || bi->queue_avgmax>0) &&
	 bi->queue_avg_time>0){
	
	bm->avg_binacc=static_cast<long *>(AllocAPointer(bins*sizeof(*bm->avg_binacc)));
	bm->avgfloat=bi->avgfloat_initial;
	
	
      }else{
	bm->avg_tail= -1;
      }
      
      if((bi->queue_hardmin>0 || bi->queue_hardmax>0) &&
	 bi->queue_minmax_time>0){
	
	bm->minmax_binstack=static_cast<long *>(AllocAPointerClear((bins+1)*bins*2*sizeof(bm->minmax_binstack)));
	bm->minmax_posstack=static_cast<long *>(AllocAPointerClear((bins+1)*sizeof(bm->minmax_posstack)));
	bm->minmax_limitstack=static_cast<long *>(AllocAPointerClear((bins+1)*sizeof(bm->minmax_limitstack)));
      }else{
	bm->minmax_tail= -1;
      }
      
      /* space for the packet queueing */
      bm->queue_packet_buffers=static_cast<oggpack_buffer*>(AllocAPointerClear(maxpackets*sizeof(*bm->queue_packet_buffers)));
      bm->queue_packets=static_cast<ogg_packet *>(AllocAPointerClear(maxpackets*sizeof(*bm->queue_packets)));
      for(i=0;i<maxpackets;i++)
	oggpack_writeinit(bm->queue_packet_buffers+i);
      
    }else{
示例#2
0
TarkinError
_analysis_packetout (TarkinStream * s, uint32_t layer_id, uint32_t comp)
{
    ogg_packet op;
    oggpack_buffer opb;
    uint8_t *data;
    uint32_t data_len;
    int i;

    data = s->layer[layer_id].packet[comp].data;
    data_len = s->layer[layer_id].packet[comp].data_len;

    oggpack_writeinit (&opb);
    oggpack_write (&opb, 0, 8);   /* No feature flags for now */
    oggpack_write (&opb, layer_id, 12);
    oggpack_write (&opb, comp, 12);
    for (i = 0; i < data_len; i++)
        oggpack_write (&opb, *(data + i), 8);

    op.b_o_s = 0;
    op.e_o_s = data_len ? 0 : 1;
    op.granulepos = 0;
    op.bytes = oggpack_bytes (&opb) + 4;
    op.packet = opb.buffer;
#ifdef DBG_OGG
    printf ("dbg_ogg: writing packet layer %d, comp %d, data_len %d %s\n",
            layer_id, comp, data_len, op.e_o_s ? "eos" : "");
#endif
    s->layer[layer_id].packet[comp].data_len = 0; /* so direct call => eos */
    return (s->packet_out (s, &op));
}
示例#3
0
int vorbis_block_init( vorbis_dsp_state *v, vorbis_block *vb )
{
    int i;
    memset( vb, 0, sizeof( *vb ) );
    vb->vd = v;
    vb->localalloc = 0;
    vb->localstore = NULL;
    if ( v->analysisp )
    {
        vorbis_block_internal *vbi =
            vb->internal = _ogg_calloc( 1, sizeof( vorbis_block_internal ) );
        vbi->ampmax = -9999;

        for ( i = 0;i < PACKETBLOBS;i++ )
        {
            if ( i == PACKETBLOBS / 2 )
            {
                vbi->packetblob[i] = &vb->opb;
            }
            else
            {
                vbi->packetblob[i] =
                    _ogg_calloc( 1, sizeof( oggpack_buffer ) );
            }
            oggpack_writeinit( vbi->packetblob[i] );
        }
    }

    return( 0 );
}
示例#4
0
/* compute bitrate tracking setup, allocate circular packet size queue */
void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm){
  int i;
  codec_setup_info *ci=vi->codec_setup;
  bitrate_manager_info *bi=&ci->bi;
  long maxlatency;

  memset(bm,0,sizeof(*bm));
  
  if(bi){
    
    bm->avg_sampledesired=bi->queue_avg_time*vi->rate;
    bm->avg_centerdesired=bi->queue_avg_time*vi->rate*bi->queue_avg_center;
    bm->minmax_sampledesired=bi->queue_minmax_time*vi->rate;
    
    /* first find the max possible needed queue size */
    maxlatency=max(bm->avg_sampledesired-bm->avg_centerdesired,
		   bm->minmax_sampledesired)+bm->avg_centerdesired;
    
    if(maxlatency>0 &&
       (bi->queue_avgmin>0 || bi->queue_avgmax>0 || bi->queue_hardmax>0 ||
	bi->queue_hardmin>0)){
      long maxpackets=maxlatency/(ci->blocksizes[0]>>1)+3;
      long bins=PACKETBLOBS;
      
      bm->queue_size=maxpackets;
      bm->queue_bins=bins;
      bm->queue_binned=_ogg_calloc(maxpackets,bins*sizeof(*bm->queue_binned));
      bm->queue_actual=_ogg_calloc(maxpackets,sizeof(*bm->queue_actual));
      
      if((bi->queue_avgmin>0 || bi->queue_avgmax>0) &&
	 bi->queue_avg_time>0){
	
	bm->avg_binacc=_ogg_calloc(bins,sizeof(*bm->avg_binacc));
	bm->avgfloat=PACKETBLOBS/2;
	
      }else{
	bm->avg_tail= -1;
      }
      
      if((bi->queue_hardmin>0 || bi->queue_hardmax>0) &&
	 bi->queue_minmax_time>0){
	
	bm->minmax_binstack=_ogg_calloc((bins*2+1)*bins*2,
					sizeof(*bm->minmax_binstack));
	bm->minmax_posstack=_ogg_calloc((bins*2+1),
				      sizeof(*bm->minmax_posstack));
	bm->minmax_limitstack=_ogg_calloc((bins*2+1),
					  sizeof(*bm->minmax_limitstack));
      }else{
	bm->minmax_tail= -1;
      }
      
      /* space for the packet queueing */
      bm->packetbuffers=_ogg_calloc(maxpackets,sizeof(*bm->packetbuffers));
      bm->packets=_ogg_calloc(maxpackets,sizeof(*bm->packets));
      for(i=0;i<maxpackets;i++)
	oggpack_writeinit(bm->packetbuffers+i);
      
    }else{
示例#5
0
static PyObject * py_ogg_oggpack_writeinit(PyObject *self, PyObject *args) {
  int size;
  oggpack_buffer * b;
  PyArg_ParseTuple(args, "s#", &b, &size);
  oggpack_writeinit(b);
  Py_INCREF(Py_None);
  return Py_None;
};
/*
 * Class:     org_tritonus_lowlevel_ogg_Buffer
 * Method:    writeInit
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_org_tritonus_lowlevel_ogg_Buffer_writeInit
(JNIEnv* env, jobject obj)
{
	oggpack_buffer*	handle;

	if (debug_flag) { fprintf(debug_file, "Java_org_tritonus_lowlevel_ogg_Buffer_writeInit(): begin\n"); }
	handle = getHandle(env, obj);
	oggpack_writeinit(handle);
	if (debug_flag) { fprintf(debug_file, "Java_org_tritonus_lowlevel_ogg_Buffer_writeInit(): end\n"); }
}
示例#7
0
int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
  memset(vb,0,sizeof(vorbis_block));
  vb->vd=v;
  vb->localalloc=0;
  vb->localstore=NULL;
  if(v->analysisp){
    oggpack_writeinit(&vb->opb);
    vb->internal=_ogg_calloc(1,sizeof(vorbis_block_internal));
    ((vorbis_block_internal *)vb->internal)->ampmax=-9999;
  }
  
  return(0);
}
示例#8
0
static int _commentheader_out(vcedit_state *state, ogg_packet *op)
{
    vorbis_comment *vc = state->vc;
    char           *vendor = state->vendor;
    oggpack_buffer opb;

    oggpack_writeinit(&opb);

    if (state->oggtype == VCEDIT_IS_OGGVORBIS)
    {
        /* preamble */
        oggpack_write(&opb,0x03,8);
        _v_writestring(&opb,"vorbis", 6);
    }

    /* vendor */
    oggpack_write(&opb,strlen(vendor),32);
    _v_writestring(&opb,vendor, strlen(vendor));

    /* comments */
    oggpack_write(&opb,vc->comments,32);
    if(vc->comments){
        int i;
        for(i=0;i<vc->comments;i++){
            if(vc->user_comments[i]){
                oggpack_write(&opb,vc->comment_lengths[i],32);
                _v_writestring(&opb,vc->user_comments[i],
                               vc->comment_lengths[i]);
            }else{
                oggpack_write(&opb,0,32);
            }
        }
    }
    oggpack_write(&opb,1,1);

    op->packet = _ogg_malloc(oggpack_bytes(&opb));
    memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));

    op->bytes=oggpack_bytes(&opb);
    op->b_o_s=0;
    op->e_o_s=0;
    op->granulepos=0;
    if (state->oggtype == VCEDIT_IS_OGGVORBIS)
    {
        op->packetno = 1;
    }

    oggpack_writeclear(&opb);
    return 0;
}
示例#9
0
int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
  memset(vb,0,sizeof(*vb));
  vb->vd=v;
  vb->localalloc=0;
  vb->localstore=NULL;
  if(v->analysisp){
    vorbis_block_internal *vbi=
      vb->internal=_ogg_calloc(1,sizeof(vorbis_block_internal));
    oggpack_writeinit(&vb->opb);
    vbi->ampmax=-9999;
    vbi->packet_markers=_ogg_malloc(vorbis_bitrate_maxmarkers()*
			       sizeof(*vbi->packet_markers));
  }
  
  return(0);
}
示例#10
0
static bool
write_comments (vcedit_state *s, ogg_packet *packet)
{
	oggpack_buffer opb;
	size_t len;
	int i;

	ogg_packet_init (packet, NULL, 0);

	oggpack_writeinit (&opb);

	/* preamble */
	oggpack_write (&opb, 0x03, 8);
	_v_writestring (&opb, "vorbis", 6);

	/* vendor */
	len = strlen (s->vendor);
	oggpack_write (&opb, len, 32);
	_v_writestring (&opb, s->vendor, len);

	/* comments */
	oggpack_write (&opb, s->vc.comments, 32);

	for (i = 0; i < s->vc.comments; i++)
		if (!s->vc.user_comments[i])
			oggpack_write (&opb, 0, 32);
		else {
			oggpack_write (&opb, s->vc.comment_lengths[i], 32);
			_v_writestring (&opb, s->vc.user_comments[i],
			                s->vc.comment_lengths[i]);
		}

	oggpack_write (&opb, 1, 1);

	packet->bytes = oggpack_bytes (&opb);

	packet->packet = _ogg_malloc (packet->bytes);
	if (!packet->packet)
		return false;

	memcpy (packet->packet, opb.buffer, packet->bytes);

	oggpack_writeclear (&opb);

	return true;
}
示例#11
0
文件: info.c 项目: kazutomi/xiphqt
int tarkin_comment_header_out(TarkinComment *vc, ogg_packet *op)
{

  oggpack_buffer opb;

  oggpack_writeinit(&opb);
  if(_tarkin_pack_comment(&opb,vc)) return -TARKIN_NOT_IMPLEMENTED;

  op->packet = MALLOC(oggpack_bytes(&opb));
  memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));

  op->bytes=oggpack_bytes(&opb);
  op->b_o_s=0;
  op->e_o_s=0;
  op->granulepos=0;

  return 0;
}
示例#12
0
int BURGERCALL vorbis_commentheader_out(vorbis_comment *vc,
    				      ogg_packet *op){

  oggpack_buffer opb;

  oggpack_writeinit(&opb);
  if(_vorbis_pack_comment(&opb,vc)) return OV_EIMPL;

  op->packet = static_cast<Word8 *>(AllocAPointer(oggpack_bytes(&opb)));
  FastMemCpy(op->packet, opb.buffer, oggpack_bytes(&opb));

  op->bytes=oggpack_bytes(&opb);
  op->b_o_s=0;
  op->e_o_s=0;
  op->granulepos=0;

  return 0;
}
示例#13
0
int vorbis_commentheader_out(vorbis_comment *vc,
    				      ogg_packet *op){

  oggpack_buffer opb;

  oggpack_writeinit(&opb);
  if(_vorbis_pack_comment(&opb,vc)) return OV_EIMPL;

  op->packet = _ogg_malloc(oggpack_bytes(&opb));
  memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));

  op->bytes=oggpack_bytes(&opb);
  op->b_o_s=0;
  op->e_o_s=0;
  op->granulepos=0;

  return 0;
}
示例#14
0
static int
_commentheader_out(vorbis_comment * vc, char *vendor, ogg_packet * op)
{
    oggpack_buffer opb;

    oggpack_writeinit(&opb);

    /* preamble */
    oggpack_write(&opb, 0x03, 8);
    _v_writestring(&opb, "vorbis", 6);

    /* vendor */
    oggpack_write(&opb, strlen(vendor), 32);
    _v_writestring(&opb, vendor, strlen(vendor));

    /* comments */
    oggpack_write(&opb, vc->comments, 32);
    if (vc->comments) {
        int i;
        for (i = 0; i < vc->comments; i++) {
            if (vc->user_comments[i]) {
                oggpack_write(&opb, vc->comment_lengths[i], 32);
                _v_writestring(&opb, vc->user_comments[i],
                               vc->comment_lengths[i]);
            }
            else {
                oggpack_write(&opb, 0, 32);
            }
        }
    }
    oggpack_write(&opb, 1, 1);

    op->packet = _ogg_malloc(oggpack_bytes(&opb));
    memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));

    op->bytes = oggpack_bytes(&opb);
    op->b_o_s = 0;
    op->e_o_s = 0;
    op->granulepos = 0;

    return 0;
}
示例#15
0
文件: info.c 项目: srnsw/xena
int vorbis_analysis_headerout(vorbis_dsp_state *v,
							  ogg_packet *op_code)
{
  int ret=OV_EIMPL;
  vorbis_info *vi=v->vi;
  oggpack_buffer opb;
  private_state *b=v->backend_state;

  if(!b){
    ret=OV_EFAULT;
    goto err_out;
  }

  oggpack_writeinit(&opb);

  /* third header packet (modes/codebooks) ****************************/

  oggpack_reset(&opb);
  if(_vorbis_pack_books(&opb,vi))goto err_out;

  if(b->header2)_ogg_free(b->header2);
  b->header2=_ogg_malloc(oggpack_bytes(&opb));
  memcpy(b->header2,opb.buffer,oggpack_bytes(&opb));
  op_code->packet=b->header2;
  op_code->bytes=oggpack_bytes(&opb);
  op_code->b_o_s=0;
  op_code->e_o_s=0;
  op_code->granulepos=0;

  oggpack_writeclear(&opb);
  return(0);
 err_out:
  oggpack_writeclear(&opb);
  memset(op_code,0,sizeof(*op_code));

  if(b->header2)_ogg_free(b->header2);
  b->header2=NULL;
  return(ret);
}
示例#16
0
void rebuilder::rebuild_id_header(
  int channels, int rate, int blocksize_short, int blocksize_long, 
  ogg_packet_holder & packet) {
  
  // Identification header
  oggpack_buffer opb;
  oggpack_writeinit(&opb);

  // Preamble
  oggpack_write(&opb, 0x01, 8);
  oggpack_write_string(&opb, "vorbis");

  // Basic information about the stream.
  oggpack_write(&opb, 0x00, 32);
  oggpack_write(&opb, channels, 8);
  oggpack_write(&opb, rate, 32);

  // Bitrate upper, nominal and lower.
  // All are optional and we do not provide them.
  oggpack_write(&opb, 0, 32);
  oggpack_write(&opb, 0, 32);
  oggpack_write(&opb, 0, 32);

  oggpack_write(&opb, ilog2(blocksize_short), 4);
  oggpack_write(&opb, ilog2(blocksize_long), 4);
  oggpack_write(&opb, 1, 1);

  CHECK(oggpack_writecheck(&opb) == 0);
  
  packet.assign(opb.buffer, oggpack_bytes(&opb));
  packet->b_o_s = 1;
  packet->e_o_s = 0;
  packet->granulepos = 0;
  packet->packetno = 0;
  
  oggpack_writeclear(&opb);
}
示例#17
0
int BURGERCALL vorbis_analysis_headerout(vorbis_dsp_state *v,
			      vorbis_comment *vc,
			      ogg_packet *op,
			      ogg_packet *op_comm,
			      ogg_packet *op_code){
  int ret=OV_EIMPL;
  vorbis_info *vi=v->vi;
  oggpack_buffer opb;
  backend_lookup_state *b=static_cast<backend_lookup_state *>(v->backend_state);

  if(!b){
    ret=OV_EFAULT;
    goto err_out;
  }

  /* first header packet **********************************************/

  oggpack_writeinit(&opb);
  if(_vorbis_pack_info(&opb,vi))goto err_out;

  /* build the packet */
  if(b->header)DeallocAPointer(b->header);
  b->header=static_cast<Word8 *>(AllocAPointer(oggpack_bytes(&opb)));
  FastMemCpy(b->header,opb.buffer,oggpack_bytes(&opb));
  op->packet=b->header;
  op->bytes=oggpack_bytes(&opb);
  op->b_o_s=1;
  op->e_o_s=0;
  op->granulepos=0;

  /* second header packet (comments) **********************************/

  oggpack_reset(&opb);
  if(_vorbis_pack_comment(&opb,vc))goto err_out;

  if(b->header1)DeallocAPointer(b->header1);
  b->header1=static_cast<Word8 *>(AllocAPointer(oggpack_bytes(&opb)));
  FastMemCpy(b->header1,opb.buffer,oggpack_bytes(&opb));
  op_comm->packet=b->header1;
  op_comm->bytes=oggpack_bytes(&opb);
  op_comm->b_o_s=0;
  op_comm->e_o_s=0;
  op_comm->granulepos=0;

  /* third header packet (modes/codebooks) ****************************/

  oggpack_reset(&opb);
  if(_vorbis_pack_books(&opb,vi))goto err_out;

  if(b->header2)DeallocAPointer(b->header2);
  b->header2=static_cast<Word8 *>(AllocAPointer(oggpack_bytes(&opb)));
  FastMemCpy(b->header2,opb.buffer,oggpack_bytes(&opb));
  op_code->packet=b->header2;
  op_code->bytes=oggpack_bytes(&opb);
  op_code->b_o_s=0;
  op_code->e_o_s=0;
  op_code->granulepos=0;

  oggpack_writeclear(&opb);
  return(0);
 err_out:
  oggpack_writeclear(&opb);
  FastMemSet(op,0,sizeof(*op));
  FastMemSet(op_comm,0,sizeof(*op_comm));
  FastMemSet(op_code,0,sizeof(*op_code));

  if(b->header)DeallocAPointer(b->header);
  if(b->header1)DeallocAPointer(b->header1);
  if(b->header2)DeallocAPointer(b->header2);
  b->header=NULL;
  b->header1=NULL;
  b->header2=NULL;
  return(ret);
}
JNIEXPORT void JNICALL Java_org_echocat_jogg_OggPackBufferJNI_writetnit
    (JNIEnv *env, jclass thisClass, jlong handle) {

    oggpack_writeinit((oggpack_buffer*) handle);
}
示例#19
0
文件: info.c 项目: vvs-/OpenTomb
int vorbis_analysis_headerout(vorbis_dsp_state *v,
                              vorbis_comment *vc,
                              ogg_packet *op,
                              ogg_packet *op_comm,
                              ogg_packet *op_code){
  int ret=OV_EIMPL;
  vorbis_info *vi=v->vi;
  oggpack_buffer opb;
  private_state *b=v->backend_state;

  if(!b){
    ret=OV_EFAULT;
    goto err_out;
  }

  /* first header packet **********************************************/

  oggpack_writeinit(&opb);
  if(_vorbis_pack_info(&opb,vi))goto err_out;

  /* build the packet */
  if(b->header)_ogg_free(b->header);
  b->header=_ogg_malloc(oggpack_bytes(&opb));
  memcpy(b->header,opb.buffer,oggpack_bytes(&opb));
  op->packet=b->header;
  op->bytes=oggpack_bytes(&opb);
  op->b_o_s=1;
  op->e_o_s=0;
  op->granulepos=0;
  op->packetno=0;

  /* second header packet (comments) **********************************/

  oggpack_reset(&opb);
  if(_vorbis_pack_comment(&opb,vc))goto err_out;

  if(b->header1)_ogg_free(b->header1);
  b->header1=_ogg_malloc(oggpack_bytes(&opb));
  memcpy(b->header1,opb.buffer,oggpack_bytes(&opb));
  op_comm->packet=b->header1;
  op_comm->bytes=oggpack_bytes(&opb);
  op_comm->b_o_s=0;
  op_comm->e_o_s=0;
  op_comm->granulepos=0;
  op_comm->packetno=1;

  /* third header packet (modes/codebooks) ****************************/

  oggpack_reset(&opb);
  if(_vorbis_pack_books(&opb,vi))goto err_out;

  if(b->header2)_ogg_free(b->header2);
  b->header2=_ogg_malloc(oggpack_bytes(&opb));
  memcpy(b->header2,opb.buffer,oggpack_bytes(&opb));
  op_code->packet=b->header2;
  op_code->bytes=oggpack_bytes(&opb);
  op_code->b_o_s=0;
  op_code->e_o_s=0;
  op_code->granulepos=0;
  op_code->packetno=2;

  oggpack_writeclear(&opb);
  return(0);
 err_out:
  memset(op,0,sizeof(*op));
  memset(op_comm,0,sizeof(*op_comm));
  memset(op_code,0,sizeof(*op_code));

  if(b){
    oggpack_writeclear(&opb);
    if(b->header)_ogg_free(b->header);
    if(b->header1)_ogg_free(b->header1);
    if(b->header2)_ogg_free(b->header2);
    b->header=NULL;
    b->header1=NULL;
    b->header2=NULL;
  }
  return(ret);
}
示例#20
0
文件: bitwise.c 项目: Chocobo1/ogg
void oggpackB_writeinit(oggpack_buffer *b) {
    oggpack_writeinit(b);
}
示例#21
0
TarkinError
tarkin_analysis_headerout (TarkinStream * v,
    TarkinComment * vc,
    ogg_packet * op, ogg_packet * op_comm, ogg_packet * op_code)
{
  int ret = -TARKIN_NOT_IMPLEMENTED;
  TarkinInfo *vi;
  oggpack_buffer opb;
  tarkin_header_store *b = &v->headers;

  vi = v->ti;

  /* first header packet ********************************************* */

  oggpack_writeinit (&opb);
  if (_tarkin_pack_info (&opb, vi))
    goto err_out;

  /* build the packet */
  if (b->header)
    FREE (b->header);
  b->header = MALLOC (oggpack_bytes (&opb));
  memcpy (b->header, opb.buffer, oggpack_bytes (&opb));
  op->packet = b->header;
  op->bytes = oggpack_bytes (&opb);
  op->b_o_s = 1;
  op->e_o_s = 0;
  op->granulepos = 0;

  /* second header packet (comments) ********************************* */

  oggpack_reset (&opb);
  if (_tarkin_pack_comment (&opb, vc))
    goto err_out;

  if (b->header1)
    FREE (b->header1);
  b->header1 = MALLOC (oggpack_bytes (&opb));
  memcpy (b->header1, opb.buffer, oggpack_bytes (&opb));
  op_comm->packet = b->header1;
  op_comm->bytes = oggpack_bytes (&opb);
  op_comm->b_o_s = 0;
  op_comm->e_o_s = 0;
  op_comm->granulepos = 0;

  /* third header packet (modes/codebooks) *************************** */

  oggpack_reset (&opb);
  if (_tarkin_pack_layer_desc (&opb, vi))
    goto err_out;

  if (b->header2)
    FREE (b->header2);
  b->header2 = MALLOC (oggpack_bytes (&opb));
  memcpy (b->header2, opb.buffer, oggpack_bytes (&opb));
  op_code->packet = b->header2;
  op_code->bytes = oggpack_bytes (&opb);
  op_code->b_o_s = 0;
  op_code->e_o_s = 0;
  op_code->granulepos = 0;

  oggpack_writeclear (&opb);
  return (0);
err_out:
  oggpack_writeclear (&opb);
  memset (op, 0, sizeof (*op));
  memset (op_comm, 0, sizeof (*op_comm));
  memset (op_code, 0, sizeof (*op_code));

  if (b->header)
    FREE (b->header);
  if (b->header1)
    FREE (b->header1);
  if (b->header2)
    FREE (b->header2);
  b->header = NULL;
  b->header1 = NULL;
  b->header2 = NULL;
  return (ret);
}