Пример #1
0
static GstFlowReturn
vorbis_parse_queue_buffer (GstVorbisParse * parse, GstBuffer * buf)
{
    GstFlowReturn ret = GST_FLOW_OK;
    long blocksize;
    ogg_packet packet;

    buf = gst_buffer_make_metadata_writable (buf);

    packet.packet = GST_BUFFER_DATA (buf);
    packet.bytes = GST_BUFFER_SIZE (buf);
    packet.granulepos = GST_BUFFER_OFFSET_END (buf);
    packet.packetno = parse->packetno + parse->buffer_queue->length;
    packet.e_o_s = 0;

    blocksize = vorbis_packet_blocksize (&parse->vi, &packet);

    /* temporarily store the sample count in OFFSET -- we overwrite this later */

    if (parse->prev_blocksize < 0)
        GST_BUFFER_OFFSET (buf) = 0;
    else
        GST_BUFFER_OFFSET (buf) = (blocksize + parse->prev_blocksize) / 4;

    parse->prev_blocksize = blocksize;

    g_queue_push_tail (parse->buffer_queue, buf);

    if (GST_BUFFER_OFFSET_END_IS_VALID (buf))
        ret = vorbis_parse_drain_queue (parse, GST_BUFFER_OFFSET_END (buf));

    return ret;
}
Пример #2
0
/***********************************************************************
 * Flush
 ***********************************************************************
 *
 **********************************************************************/
static hb_buffer_t * Flush( hb_work_object_t * w )
{
    hb_work_private_t * pv = w->private_data;
    hb_buffer_t * buf;
    int64_t     blocksize = 0;

    if( vorbis_analysis_blockout( &pv->vd, &pv->vb ) == 1 )
    {
        ogg_packet op;

        vorbis_analysis( &pv->vb, NULL );
        vorbis_bitrate_addblock( &pv->vb );

        if( vorbis_bitrate_flushpacket( &pv->vd, &op ) )
        {
            buf = hb_buffer_init( sizeof( ogg_packet ) + op.bytes );
            memcpy( buf->data, &op, sizeof( ogg_packet ) );
            memcpy( buf->data + sizeof( ogg_packet ), op.packet,
                    op.bytes );
            blocksize = vorbis_packet_blocksize(&pv->vi, &op);
            buf->frametype   = HB_FRAME_AUDIO;
            buf->start = (int64_t)(vorbis_granule_time(&pv->vd, op.granulepos) * 90000);
            buf->stop  = (int64_t)(vorbis_granule_time(&pv->vd, (pv->prev_blocksize + blocksize)/4 + op.granulepos) * 90000);
            /* The stop time isn't accurate for the first ~3 packets, as the actual blocksize depends on the previous _and_ current packets. */
            pv->prev_blocksize = blocksize;
            return buf;
        }
    }

    return NULL;
}
Пример #3
0
void
xtr_oggvorbis_c::handle_frame(memory_cptr &frame,
                              KaxBlockAdditions *,
                              int64_t,
                              int64_t,
                              int64_t,
                              int64_t,
                              bool,
                              bool,
                              bool) {
  m_content_decoder.reverse(frame, CONTENT_ENCODING_SCOPE_BLOCK);

  ogg_packet op;
  op.packet               = frame->get_buffer();
  op.bytes                = frame->get_size();
  int64_t this_block_size = vorbis_packet_blocksize(&m_vorbis_info, &op);

  if (-1 != m_previous_block_size) {
    m_queued_granulepos   = m_samples;
    m_samples            += (this_block_size + m_previous_block_size) / 4;
  }

  m_previous_end        = m_samples * 1000000000 / m_sfreq;
  m_previous_block_size = this_block_size;

  queue_frame(frame, 0);
}
Пример #4
0
/* process the vorbis audio packets. Here we just take each packet out 
 * and add them into the new stream, flushing after so many samples. We
 * also check if an new headers are requested after each processed page
 */
static int process_vorbis_audio (ogg_state_t *ogg_info, ogg_codec_t *codec)
{
    vorbis_codec_t *source_vorbis = codec->specific;

    while (1)
    {
        int window;
        ogg_packet packet;

        /* now, lets extract what packets we can */
        if (ogg_stream_packetout (&codec->os, &packet) <= 0)
            break;

        /* calculate granulepos for the packet */
        window = vorbis_packet_blocksize (&source_vorbis->vi, &packet) / 4;

        source_vorbis->granulepos += window;
        if (source_vorbis->prev_packet)
        {
            ogg_packet *prev_packet = source_vorbis->prev_packet;

            add_audio_packet (source_vorbis, prev_packet);
            free_ogg_packet (prev_packet);
            packet . granulepos = source_vorbis->granulepos;
        }
        else
        {
            packet . granulepos = 0;
        }

        /* store the current packet details */
        source_vorbis->prev_window = window;
        source_vorbis->prev_packet = copy_ogg_packet (&packet);
        if (packet.e_o_s)
        {
            initiate_flush (source_vorbis);
            free_ogg_packet (source_vorbis->prev_packet);
            source_vorbis->prev_packet = NULL;
            return 1;
        }

        /* allow for pages to be flushed if there's over a certain number of samples */
        if (source_vorbis->samples_in_page > source_vorbis->page_samples_trigger)
            return 1;
    }
    if (source_vorbis->stream_notify)
    {
        initiate_flush (source_vorbis);
        source_vorbis->stream_notify = 0;
        return 1;
    }
    return -1;
}
Пример #5
0
void
xtr_oggvorbis_c::handle_frame(xtr_frame_t &f) {
  ogg_packet op;
  op.packet               = f.frame->get_buffer();
  op.bytes                = f.frame->get_size();
  int64_t this_block_size = vorbis_packet_blocksize(&m_vorbis_info, &op);

  if (-1 != m_previous_block_size) {
    m_queued_granulepos   = m_samples;
    m_samples            += (this_block_size + m_previous_block_size) / 4;
  }

  m_previous_end        = m_samples * 1000000000 / m_sfreq;
  m_previous_block_size = this_block_size;

  queue_frame(f.frame, 0);
}
Пример #6
0
/*****************************************************************************
 * SendPacket: send an ogg dated packet to the stream output.
 *****************************************************************************/
static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
                            block_t *p_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    int i_block_size, i_samples;

    i_block_size = vorbis_packet_blocksize( &p_sys->vi, p_oggpacket );
    if( i_block_size < 0 ) i_block_size = 0; /* non audio packet */
    i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;
    p_sys->i_last_block_size = i_block_size;

    /* Date management */
    p_block->i_dts = p_block->i_pts = date_Get( &p_sys->end_date );

    p_block->i_length = date_Increment( &p_sys->end_date, i_samples ) - p_block->i_pts;

    return p_block;
}
Пример #7
0
FXbool VorbisDecoder::find_stream_position() {
  const FXuchar * data_ptr = get_packet_offset();
  FXint cb,lb=-1,tb=0;
  while(get_next_packet()) {
    if (is_vorbis_header()){
      reset_decoder();
      goto reset;
      }
    cb=vorbis_packet_blocksize(&info,&op);
    if (lb!=-1) tb+=(lb+cb)>>2;
    lb=cb;
    if (op.granulepos!=-1) {
      stream_position=op.granulepos-tb;
      set_packet_offset(data_ptr);
      return true;
      }
    }
reset:
  set_packet_offset(data_ptr);
  return false;
  }
static GstFlowReturn
vorbis_parse_queue_buffer (GstVorbisParse * parse, GstBuffer * buf)
{
  GstFlowReturn ret = GST_FLOW_OK;
  long blocksize;
  ogg_packet packet;
  GstMapInfo map;

  buf = gst_buffer_make_writable (buf);

  gst_buffer_map (buf, &map, GST_MAP_READ);
  packet.packet = map.data;
  packet.bytes = map.size;
  GST_DEBUG ("%p, %" G_GSIZE_FORMAT, map.data, map.size);
  packet.granulepos = GST_BUFFER_OFFSET_END (buf);
  packet.packetno = parse->packetno + parse->buffer_queue->length;
  packet.e_o_s = 0;

  blocksize = vorbis_packet_blocksize (&parse->vi, &packet);
  gst_buffer_unmap (buf, &map);

  /* temporarily store the sample count in OFFSET -- we overwrite this later */

  if (parse->prev_blocksize < 0)
    GST_BUFFER_OFFSET (buf) = 0;
  else
    GST_BUFFER_OFFSET (buf) = (blocksize + parse->prev_blocksize) / 4;

  parse->prev_blocksize = blocksize;

  g_queue_push_tail (parse->buffer_queue, buf);

  if (GST_BUFFER_OFFSET_END_IS_VALID (buf))
    ret = vorbis_parse_drain_queue (parse, GST_BUFFER_OFFSET_END (buf));

  return ret;
}
Пример #9
0
int input_calculate_ogg_sleep(ogg_page *page)
{
    static ogg_stream_state os;
    ogg_packet op;
    static vorbis_info vi;
    static vorbis_comment vc;
    static input_type codec = ICES_INPUT_UNKNOWN;
    static int need_start_pos, need_headers, state_in_use = 0;
    static int serialno = 0;
    static uint64_t offset;
    static uint64_t first_granulepos;

    if (ogg_page_granulepos(page) == -1)
    {
        LOG_ERROR0("Timing control: corrupt timing information in vorbis file, cannot stream.");
        return -1;
    }
    if (ogg_page_bos (page))
    {
        control.oldsamples = 0;

        if (state_in_use)
            ogg_stream_clear (&os);
        ogg_stream_init (&os, ogg_page_serialno (page));
        serialno = ogg_page_serialno (page);
        state_in_use = 1;
        vorbis_info_init (&vi);
        vorbis_comment_init (&vc);
        need_start_pos = 1;
        need_headers = 3;
        codec = ICES_INPUT_UNKNOWN;
        offset = (uint64_t)0;
    }
    if (need_start_pos)
    {
        int found_first_granulepos = 0;

        ogg_stream_pagein (&os, page);
        while (ogg_stream_packetout (&os, &op) == 1)
        {
            if (need_headers)
            {
                /* check for Vorbis. For Vorbis the Magic is {0x01|0x03|0x05}"vorbis" */
                if (op.bytes > 7 && memcmp(op.packet+1, "vorbis", 6) == 0)
                {
                    if (vorbis_synthesis_headerin (&vi, &vc, &op) < 0)
                    {
                        LOG_ERROR0("Timing control: can't determine sample rate for input, not vorbis.");
                        control.samplerate = 0;
                        vorbis_info_clear (&vi);
                        ogg_stream_clear (&os);
                        return -1;
                    }
                    control.samplerate = vi.rate;
                    codec = ICES_INPUT_VORBIS;
                }
                /* check for Opus. For Opus the magic is "OpusHead" */
                else if (op.bytes == 19 && memcmp(op.packet, "OpusHead", 8) == 0)
                {
                    if (op.packet[8] != 1)
                    {
                        LOG_ERROR0("Timing control: can't determine sample rate for input, unsupported Opus version.");
                        control.samplerate = 0;
                        vorbis_info_clear (&vi);
                        ogg_stream_clear (&os);
                        return -1;
                    }
                    /* Sample rate is fixed for Opus: 48kHz */
                    control.samplerate = 48000;
                    codec = ICES_INPUT_OGG;
                    /* No more headers after this one needed */
                    need_headers = 1;
                }
                else if (op.bytes >= 80 && memcmp(op.packet, "Speex   ", 8) == 0)
                {
                    if (__read_int32_le(op.packet+28) != 1 || __read_int32_le(op.packet+32) != op.bytes)
                    {
                        LOG_ERROR0("Timing control: can't determine sample rate for input, bad or unsupported Speex header.");
                        control.samplerate = 0;
                        vorbis_info_clear (&vi);
                        ogg_stream_clear (&os);
                        return -1;
                    }

                    control.samplerate = __read_int32_le(op.packet+36);
                    codec = ICES_INPUT_OGG;
                    /* No more headers after this one needed */
                    need_headers = 1;
                }
                else if (op.bytes >= 51 && memcmp(op.packet, "\177FLAC\1\0", 7) == 0 && memcmp(op.packet+9, "fLaC\0", 5) == 0)
                {
                    control.samplerate = __read_int20_be(op.packet+27);
                    codec = ICES_INPUT_OGG;
                    /* No more headers after this one needed */
                    need_headers = 1;
                }
                else if (codec == ICES_INPUT_UNKNOWN)
                {
                    LOG_ERROR0("Timing control: can't determine sample rate for input, unsupported input format.");
                    control.samplerate = 0;
                    vorbis_info_clear (&vi);
                    ogg_stream_clear (&os);
                    return -1;
                }
                need_headers--;

                if (need_headers == 0)
                {
                    vorbis_comment_clear (&vc);
                    first_granulepos = (uint64_t)0;
                    return 0;
                }
                continue;
            }
            /* headers have been read */
            if (first_granulepos == 0 && op.granulepos > 0)
            {
                first_granulepos = op.granulepos;
                found_first_granulepos = 1;
            }
            if (codec == ICES_INPUT_VORBIS)
            {
                offset += vorbis_packet_blocksize (&vi, &op) / 4;
            }
        }
        if (!found_first_granulepos)
            return 0;

        need_start_pos = 0;
        control.oldsamples = first_granulepos - offset;
        vorbis_info_clear (&vi);
        ogg_stream_clear (&os);
        state_in_use = 0;
    }
    if (serialno != ogg_page_serialno (page))
    {
        LOG_ERROR0 ("Found page which does not belong to current logical stream");
        return -1;
    }
    control.samples = ogg_page_granulepos (page) - control.oldsamples;
    control.oldsamples = ogg_page_granulepos (page);

    control.senttime += ((uint64_t)control.samples * 1000000 /
            (uint64_t)control.samplerate);

    return 0;
}
Пример #10
0
/****************************************************************************
 * Encode: the whole thing
 ****************************************************************************
 * This function spits out ogg packets.
 ****************************************************************************/
static block_t *Encode( encoder_t *p_enc, block_t *p_aout_buf )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    ogg_packet oggpacket;
    block_t *p_block, *p_chain = NULL;
    float **buffer;

    /* FIXME: flush buffers in here */
    if( unlikely( !p_aout_buf ) ) return NULL;

    mtime_t i_pts = p_aout_buf->i_pts -
                    (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
                    (mtime_t)p_enc->fmt_in.audio.i_rate;

    p_sys->i_samples_delay += p_aout_buf->i_nb_samples;

    buffer = vorbis_analysis_buffer( &p_sys->vd, p_aout_buf->i_nb_samples );

    /* convert samples to float and uninterleave */
    for( unsigned int i = 0; i < p_sys->i_channels; i++ )
    {
        for( unsigned int j = 0 ; j < p_aout_buf->i_nb_samples ; j++ )
        {
            buffer[i][j]= ((float *)p_aout_buf->p_buffer)
                          [j * p_sys->i_channels + p_sys->pi_chan_table[i]];
        }
    }

    vorbis_analysis_wrote( &p_sys->vd, p_aout_buf->i_nb_samples );

    while( vorbis_analysis_blockout( &p_sys->vd, &p_sys->vb ) == 1 )
    {
        int i_samples;

        vorbis_analysis( &p_sys->vb, NULL );
        vorbis_bitrate_addblock( &p_sys->vb );

        while( vorbis_bitrate_flushpacket( &p_sys->vd, &oggpacket ) )
        {
            int i_block_size;
            p_block = block_Alloc( oggpacket.bytes );
            memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes );

            i_block_size = vorbis_packet_blocksize( &p_sys->vi, &oggpacket );

            if( i_block_size < 0 ) i_block_size = 0;
            i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;
            p_sys->i_last_block_size = i_block_size;

            p_block->i_length = (mtime_t)1000000 *
                                (mtime_t)i_samples / (mtime_t)p_enc->fmt_in.audio.i_rate;

            p_block->i_dts = p_block->i_pts = i_pts;

            p_sys->i_samples_delay -= i_samples;

            /* Update pts */
            i_pts += p_block->i_length;
            block_ChainAppend( &p_chain, p_block );
        }
    }

    return p_chain;
}
Пример #11
0
int input_calculate_ogg_sleep(ogg_page *page)
{
    static ogg_stream_state os;
    ogg_packet op;
    static vorbis_info vi;
    static vorbis_comment vc;
    static int need_start_pos, need_headers, state_in_use = 0;
    static int serialno = 0;
    static uint64_t offset;
    static uint64_t first_granulepos;

    if (ogg_page_granulepos(page) == -1)
    {
        LOG_ERROR0("Timing control: corrupt timing information in vorbis file, cannot stream.");
        return -1;
    }
    if (ogg_page_bos (page))
    {
        control.oldsamples = 0;

        if (state_in_use)
            ogg_stream_clear (&os);
        ogg_stream_init (&os, ogg_page_serialno (page));
        serialno = ogg_page_serialno (page);
        state_in_use = 1;
        vorbis_info_init (&vi);
        vorbis_comment_init (&vc);
        need_start_pos = 1;
        need_headers = 3;
        offset = (uint64_t)0;
    }
    if (need_start_pos)
    {
        int found_first_granulepos = 0;

        ogg_stream_pagein (&os, page);
        while (ogg_stream_packetout (&os, &op) == 1)
        {
            if (need_headers)
            {
                if (vorbis_synthesis_headerin (&vi, &vc, &op) < 0)
                {
                    LOG_ERROR0("Timing control: can't determine sample rate for input, not vorbis.");
                    control.samplerate = 0;
                    return -1;
                }
                need_headers--;
                control.samplerate = vi.rate;

                if (need_headers == 0)
                {
                    vorbis_comment_clear (&vc);
                    first_granulepos = (uint64_t)0;
                    return 0;
                }
                continue;
            }
            /* headers have been read */
            if (first_granulepos == 0 && op.granulepos > 0)
            {
                first_granulepos = op.granulepos;
                found_first_granulepos = 1;
            }
            offset += vorbis_packet_blocksize (&vi, &op) / 4;
        }
        if (!found_first_granulepos)
            return 0;

        need_start_pos = 0;
        control.oldsamples = first_granulepos - offset;
        vorbis_info_clear (&vi);
        ogg_stream_clear (&os);
        state_in_use = 0;
    }
    if (serialno != ogg_page_serialno (page))
    {
        LOG_ERROR0 ("Found page which does not belong to current logical stream");
        return -1;
    }
    control.samples = ogg_page_granulepos (page) - control.oldsamples;
    control.oldsamples = ogg_page_granulepos (page);

    control.senttime += ((uint64_t)control.samples * 1000000 /
            (uint64_t)control.samplerate);

    return 0;
}
Пример #12
0
/* this is void and does not propogate errors up because we want to be
   able to open and use damaged bitstreams as well as we can.  Just
   watch out for missing information for links in the OggVorbis_File
   struct */
static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){
  ogg_page og={0,0,0,0};
  int i;
  ogg_int64_t ret;
  
  vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
  vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
  vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
  vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
  
  for(i=0;i<vf->links;i++){
    if(i==0){
      /* we already grabbed the initial header earlier.  Just set the offset */
      vf->dataoffsets[i]=dataoffset;
      _seek_helper(vf,dataoffset);

    }else{

      /* seek to the location of the initial header */

      _seek_helper(vf,vf->offsets[i]);
      if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL,NULL)<0){
    	vf->dataoffsets[i]=-1;
      }else{
	vf->dataoffsets[i]=vf->offset;
      }
    }

    /* fetch beginning PCM offset */

    if(vf->dataoffsets[i]!=-1){
      ogg_int64_t accumulated=0,pos;
      long        lastblock=-1;
      int         result;

      ogg_stream_reset_serialno(vf->os,vf->serialnos[i]);

      while(1){
	ogg_packet op={0,0,0,0,0,0};

	ret=_get_next_page(vf,&og,-1);
	if(ret<0)
	  /* this should not be possible unless the file is
             truncated/mangled */
	  break;
       
	if(ogg_page_serialno(&og)!=vf->serialnos[i])
	  break;
	
	pos=ogg_page_granulepos(&og);

	/* count blocksizes of all frames in the page */
	ogg_stream_pagein(vf->os,&og);
	while((result=ogg_stream_packetout(vf->os,&op))){
	  if(result>0){ /* ignore holes */
	    long thisblock=vorbis_packet_blocksize(vf->vi+i,&op);
	    if(lastblock!=-1)
	      accumulated+=(lastblock+thisblock)>>2;
	    lastblock=thisblock;
	  }
	}
	ogg_packet_release(&op);

	if(pos!=-1){
	  /* pcm offset of last packet on the first audio page */
	  accumulated= pos-accumulated;
	  break;
	}
      }

      /* less than zero?  This is a stream with samples trimmed off
         the beginning, a normal occurrence; set the offset to zero */
      if(accumulated<0)accumulated=0;

      vf->pcmlengths[i*2]=accumulated;
    }
Пример #13
0
int ov_raw_seek(OggVorbis_File *vf,long pos){
  ogg_stream_state work_os;

  if(vf->ready_state<OPENED)return(OV_EINVAL);
  if(!vf->seekable)
    return(OV_ENOSEEK); /* don't dump machine if we can't seek */

  if(pos<0 || pos>vf->offsets[vf->links])return(OV_EINVAL);
  
  /* clear out decoding machine state */
  vf->pcm_offset=-1;
  _decode_clear(vf);
  
  _seek_helper(vf,pos);

  /* we need to make sure the pcm_offset is set, but we don't want to
     advance the raw cursor past good packets just to get to the first
     with a granulepos.  That's not equivalent behavior to beginning
     decoding as immediately after the seek position as possible.

     So, a hack.  We use two stream states; a local scratch state and
     a the shared vf->os stream state.  We use the local state to
     scan, and the shared state as a buffer for later decode. 

     Unfortuantely, on the last page we still advance to last packet
     because the granulepos on the last page is not necessarily on a
     packet boundary, and we need to make sure the granpos is
     correct. 
  */

  {
    ogg_page og;
    ogg_packet op;
    int lastblock=0;
    int accblock=0;
    int thisblock=-1;
    int eosflag=0;

    memset(&work_os,0,sizeof(work_os));/* so that it's safe to clear
					  it later even if we don't
					  init it */

    while(1){
      if(vf->ready_state==STREAMSET){
	/* snarf/scan a packet if we can */
	int result=ogg_stream_packetout(&work_os,&op);
      
	if(result>0){

	  if(vf->vi[vf->current_link].codec_setup)
	    thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
	  if(eosflag)
	    ogg_stream_packetout(&vf->os,NULL);
	  else
	    if(lastblock)accblock+=(lastblock+thisblock)>>2;

	  if(op.granulepos!=-1){
	    int i,link=vf->current_link;
	    ogg_int64_t granulepos=op.granulepos;
	    
	    for(i=0;i<link;i++)
	      granulepos+=vf->pcmlengths[i];
	    vf->pcm_offset=granulepos-accblock;
	    break;
	  }
	  lastblock=thisblock;
	  continue;
	}
      }
      
      if(!lastblock){
	if(_get_next_page(vf,&og,-1)<0){
	  vf->pcm_offset=ov_pcm_total(vf,-1);
	  break;
	}
      }else{
	/* huh?  Bogus stream with packets but no granulepos */
	vf->pcm_offset=-1;
	break;
      }
      
      /* has our decoding just traversed a bitstream boundary? */
      if(vf->ready_state==STREAMSET)
	if(vf->current_serialno!=ogg_page_serialno(&og)){
	_decode_clear(vf); /* clear out stream state */
	ogg_stream_clear(&work_os);
      }

      if(vf->ready_state<STREAMSET){
	int link;
	
	vf->current_serialno=ogg_page_serialno(&og);
	for(link=0;link<vf->links;link++)
	  if(vf->serialnos[link]==vf->current_serialno)break;
	if(link==vf->links)goto seek_error; /* sign of a bogus stream.
					       error out, leave
					       machine uninitialized */
	vf->current_link=link;
	
	ogg_stream_init(&vf->os,vf->current_serialno);
	ogg_stream_reset(&vf->os); 
	ogg_stream_init(&work_os,vf->current_serialno);
	ogg_stream_reset(&work_os); 
	vf->ready_state=STREAMSET;
	
      }
    
      ogg_stream_pagein(&vf->os,&og);
      ogg_stream_pagein(&work_os,&og);
      eosflag=ogg_page_eos(&og);
    }
  }
Пример #14
0
nsresult VorbisState::ReconstructVorbisGranulepos()
{
  // The number of samples in a Vorbis packet is:
  // window_blocksize(previous_packet)/4+window_blocksize(current_packet)/4
  // See: http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-230001.3.2
  // So we maintain mPrevVorbisBlockSize, the block size of the last packet
  // encountered. We also maintain mGranulepos, which is the granulepos of
  // the last encountered packet. This enables us to give granulepos to
  // packets when the last packet in mUnstamped doesn't have a granulepos
  // (for example if the stream was truncated).
  //
  // We validate our prediction of the number of samples decoded when
  // VALIDATE_VORBIS_SAMPLE_CALCULATION is defined by recording the predicted
  // number of samples, and verifing we extract that many when decoding
  // each packet.

  NS_ASSERTION(mUnstamped.Length() > 0, "Length must be > 0");
  ogg_packet* last = mUnstamped[mUnstamped.Length()-1];
  NS_ASSERTION(last->e_o_s || last->granulepos >= 0,
    "Must know last granulepos!");
  if (mUnstamped.Length() == 1) {
    ogg_packet* packet = mUnstamped[0];
    long blockSize = vorbis_packet_blocksize(&mInfo, packet);
    if (blockSize < 0) {
      // On failure vorbis_packet_blocksize returns < 0. If we've got
      // a bad packet, we just assume that decode will have to skip this
      // packet, i.e. assume 0 samples are decodable from this packet.
      blockSize = 0;
      mPrevVorbisBlockSize = 0;
    }
    long samples = mPrevVorbisBlockSize / 4 + blockSize / 4;
    mPrevVorbisBlockSize = blockSize;
    if (packet->granulepos == -1) {
      packet->granulepos = mGranulepos + samples;
    }

    // Account for a partial last frame
    if (packet->e_o_s && packet->granulepos >= mGranulepos) {
       samples = packet->granulepos - mGranulepos;
    }
 
    mGranulepos = packet->granulepos;
    RecordVorbisPacketSamples(packet, samples);
    return NS_OK;
  }

  bool unknownGranulepos = last->granulepos == -1;
  int totalSamples = 0;
  for (int32_t i = mUnstamped.Length() - 1; i > 0; i--) {
    ogg_packet* packet = mUnstamped[i];
    ogg_packet* prev = mUnstamped[i-1];
    ogg_int64_t granulepos = packet->granulepos;
    NS_ASSERTION(granulepos != -1, "Must know granulepos!");
    long prevBlockSize = vorbis_packet_blocksize(&mInfo, prev);
    long blockSize = vorbis_packet_blocksize(&mInfo, packet);

    if (blockSize < 0 || prevBlockSize < 0) {
      // On failure vorbis_packet_blocksize returns < 0. If we've got
      // a bad packet, we just assume that decode will have to skip this
      // packet, i.e. assume 0 samples are decodable from this packet.
      blockSize = 0;
      prevBlockSize = 0;
    }

    long samples = prevBlockSize / 4 + blockSize / 4;
    totalSamples += samples;
    prev->granulepos = granulepos - samples;
    RecordVorbisPacketSamples(packet, samples);
  }

  if (unknownGranulepos) {
    for (uint32_t i = 0; i < mUnstamped.Length(); i++) {
      ogg_packet* packet = mUnstamped[i];
      packet->granulepos += mGranulepos + totalSamples + 1;
    }
  }

  ogg_packet* first = mUnstamped[0];
  long blockSize = vorbis_packet_blocksize(&mInfo, first);
  if (blockSize < 0) {
    mPrevVorbisBlockSize = 0;
    blockSize = 0;
  }

  long samples = (mPrevVorbisBlockSize == 0) ? 0 :
                  mPrevVorbisBlockSize / 4 + blockSize / 4;
  int64_t start = first->granulepos - samples;
  RecordVorbisPacketSamples(first, samples);

  if (last->e_o_s && start < mGranulepos) {
    // We've calculated that there are more samples in this page than its
    // granulepos claims, and it's the last page in the stream. This is legal,
    // and we will need to prune the trailing samples when we come to decode it.
    // We must correct the timestamps so that they follow the last Vorbis page's
    // samples.
    int64_t pruned = mGranulepos - start;
    for (uint32_t i = 0; i < mUnstamped.Length() - 1; i++) {
      mUnstamped[i]->granulepos += pruned;
    }
#ifdef VALIDATE_VORBIS_SAMPLE_CALCULATION
    mVorbisPacketSamples[last] -= pruned;
#endif
  }

  mPrevVorbisBlockSize = vorbis_packet_blocksize(&mInfo, last);
  mPrevVorbisBlockSize = std::max(static_cast<long>(0), mPrevVorbisBlockSize);
  mGranulepos = last->granulepos;

  return NS_OK;
}