示例#1
0
/* The following function is basically a hacked version of the code in
 * examples/decoder_example.c */
void
read_vorbis_data_or_die (const char *filename, int srate, float * data, int count)
{
  ogg_sync_state   oy;
  ogg_stream_state os;
  ogg_page         og;
  ogg_packet       op;

  vorbis_info      vi;
  vorbis_comment   vc;
  vorbis_dsp_state vd;
  vorbis_block     vb;

  FILE *file;
  char *buffer;
  int  bytes;
  int eos = 0;
  int i;
  int read_total = 0 ;

  if ((file = fopen (filename, "rb")) == NULL) {
    printf("\n\nError : fopen failed : %s\n", strerror (errno)) ;
    exit (1) ;
  }

  ogg_sync_init (&oy);

  {
    /* fragile!  Assumes all of our headers will fit in the first 8kB,
       which currently they will */
    buffer = ogg_sync_buffer (&oy,8192);
    bytes = fread (buffer,1,8192,file);
    ogg_sync_wrote (&oy,bytes);

    if(ogg_sync_pageout (&oy,&og) != 1) {
      if(bytes < 8192) {
        printf ("Out of data.\n") ;
          goto done_decode ;
      }

      fprintf (stderr,"Input does not appear to be an Ogg bitstream.\n");
      exit (1);
    }

    ogg_stream_init (&os,ogg_page_serialno(&og));

    vorbis_info_init (&vi);
    vorbis_comment_init (&vc);
    if (ogg_stream_pagein (&os,&og) < 0) {
      fprintf (stderr,"Error reading first page of Ogg bitstream data.\n");
      exit (1);
    }

    if (ogg_stream_packetout(&os,&op) != 1) {
      fprintf (stderr,"Error reading initial header packet.\n");
      exit (1);
    }

    if (vorbis_synthesis_headerin (&vi,&vc,&op) < 0) {
      fprintf (stderr,"This Ogg bitstream does not contain Vorbis "
          "audio data.\n");
      exit (1);
    }

    i = 0;
    while ( i < 2) {
      while (i < 2) {

        int result = ogg_sync_pageout (&oy,&og);
        if(result == 0)
          break;
        if(result==1) {
          ogg_stream_pagein(&os,&og);

          while (i < 2) {
            result = ogg_stream_packetout (&os,&op);
            if (result == 0) break;
            if (result < 0) {
              fprintf (stderr,"Corrupt secondary header.  Exiting.\n");
              exit(1);
            }
            vorbis_synthesis_headerin (&vi,&vc,&op);
            i++;
          }
        }
      }

      buffer = ogg_sync_buffer (&oy,4096);
      bytes = fread (buffer,1,4096,file);
      if (bytes == 0 && i < 2) {
        fprintf (stderr,"End of file before finding all Vorbis headers!\n");
        exit (1);
      }

      ogg_sync_wrote (&oy,bytes);
    }

    if (vi.rate != srate) {
      printf ("\n\nError : File '%s' has sample rate of %ld when it should be %d.\n\n", filename, vi.rate, srate);
      exit (1) ;
    }

    vorbis_synthesis_init (&vd,&vi);
    vorbis_block_init (&vd,&vb);

    while(!eos) {
      while (!eos) {
        int result = ogg_sync_pageout (&oy,&og);
        if (result == 0)
          break;
        if (result < 0) {
          fprintf (stderr,"Corrupt or missing data in bitstream; "
                   "continuing...\n");
        } else {
          ogg_stream_pagein (&os,&og);
          while (1) {
            result = ogg_stream_packetout (&os,&op);

            if (result == 0)
              break;
            if (result < 0) {
              /* no reason to complain; already complained above */
            } else {
              float **pcm;
              int samples;

              if (vorbis_synthesis (&vb,&op) == 0)
                vorbis_synthesis_blockin(&vd,&vb);
              while ((samples = vorbis_synthesis_pcmout (&vd,&pcm)) > 0 && read_total < count) {
                int bout = samples < count ? samples : count;
                bout = read_total + bout > count ? count - read_total : bout;

                memcpy (data + read_total, pcm[0], bout * sizeof (float)) ;

                vorbis_synthesis_read (&vd,bout);
                read_total += bout ;
              }
            }
          }

          if (ogg_page_eos (&og)) eos = 1;
        }
      }

      if (!eos) {
        buffer = ogg_sync_buffer (&oy,4096);
        bytes = fread (buffer,1,4096,file);
        ogg_sync_wrote (&oy,bytes);
        if (bytes == 0) eos = 1;
      }
    }

    ogg_stream_clear (&os);

    vorbis_block_clear (&vb);
    vorbis_dsp_clear (&vd);
    vorbis_comment_clear (&vc);
    vorbis_info_clear (&vi);
  }
done_decode:

  /* OK, clean up the framer */
  ogg_sync_clear (&oy);

  fclose (file) ;
}
示例#2
0
/*!
 * \brief Create a new OGG/Vorbis filestream and set it up for reading.
 * \param s File that points to on disk storage of the OGG/Vorbis data.
 * \return The new filestream.
 */
static int ogg_vorbis_open(struct ast_filestream *s)
{
    int i;
    int bytes;
    int result;
    char **ptr;
    char *buffer;
    struct vorbis_desc *tmp = (struct vorbis_desc *)s->_private;

    tmp->writing = 0;

    ogg_sync_init(&tmp->oy);

    buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
    bytes = fread(buffer, 1, BLOCK_SIZE, s->f);
    ogg_sync_wrote(&tmp->oy, bytes);

    result = ogg_sync_pageout(&tmp->oy, &tmp->og);
    if (result != 1) {
        if(bytes < BLOCK_SIZE) {
            ast_log(LOG_ERROR, "Run out of data...\n");
        } else {
            ast_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n");
        }
        ogg_sync_clear(&tmp->oy);
        return -1;
    }

    ogg_stream_init(&tmp->os, ogg_page_serialno(&tmp->og));
    vorbis_info_init(&tmp->vi);
    vorbis_comment_init(&tmp->vc);

    if (ogg_stream_pagein(&tmp->os, &tmp->og) < 0) {
        ast_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n");
error:
        ogg_stream_clear(&tmp->os);
        vorbis_comment_clear(&tmp->vc);
        vorbis_info_clear(&tmp->vi);
        ogg_sync_clear(&tmp->oy);
        return -1;
    }

    if (ogg_stream_packetout(&tmp->os, &tmp->op) != 1) {
        ast_log(LOG_ERROR, "Error reading initial header packet.\n");
        goto error;
    }

    if (vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op) < 0) {
        ast_log(LOG_ERROR, "This Ogg bitstream does not contain Vorbis audio data.\n");
        goto error;
    }

    for (i = 0; i < 2 ; ) {
        while (i < 2) {
            result = ogg_sync_pageout(&tmp->oy, &tmp->og);
            if (result == 0)
                break;
            if (result == 1) {
                ogg_stream_pagein(&tmp->os, &tmp->og);
                while(i < 2) {
                    result = ogg_stream_packetout(&tmp->os,&tmp->op);
                    if(result == 0)
                        break;
                    if(result < 0) {
                        ast_log(LOG_ERROR, "Corrupt secondary header.  Exiting.\n");
                        goto error;
                    }
                    vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op);
                    i++;
                }
            }
        }

        buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
        bytes = fread(buffer, 1, BLOCK_SIZE, s->f);
        if (bytes == 0 && i < 2) {
            ast_log(LOG_ERROR, "End of file before finding all Vorbis headers!\n");
            goto error;
        }
        ogg_sync_wrote(&tmp->oy, bytes);
    }

    for (ptr = tmp->vc.user_comments; *ptr; ptr++)
        ast_debug(1, "OGG/Vorbis comment: %s\n", *ptr);
    ast_debug(1, "OGG/Vorbis bitstream is %d channel, %ldHz\n", tmp->vi.channels, tmp->vi.rate);
    ast_debug(1, "OGG/Vorbis file encoded by: %s\n", tmp->vc.vendor);

    if (tmp->vi.channels != 1) {
        ast_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n");
        goto error;
    }

    if (tmp->vi.rate != DEFAULT_SAMPLE_RATE) {
        ast_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n");
        vorbis_block_clear(&tmp->vb);
        vorbis_dsp_clear(&tmp->vd);
        goto error;
    }

    vorbis_synthesis_init(&tmp->vd, &tmp->vi);
    vorbis_block_init(&tmp->vd, &tmp->vb);

    return 0;
}
示例#3
0
/**
 * Handle inward rtp packet
 */
int vrtp_rtp_in(profile_handler_t *h, xrtp_rtp_packet_t *rtp)
{
   vrtp_handler_t *vh = (vrtp_handler_t *)h;
   
   uint16 seqno;
   uint32 src;

   uint32 rtpts_payload;
   uint32 rtpts_arrival;
   uint32 rtpts_toplay;
   uint32 rtpts_playing;
   uint32 rtpts_sync;
   
   member_state_t * sender = NULL;
   session_connect_t *rtp_conn = NULL;
   session_connect_t *rtcp_conn = NULL;

   rtime_t ms_arrival,us_arrival,ns_arrival;
   rtime_t ms_playing, us_playing, ns_playing;
   rtime_t ms_sync, us_sync, ns_sync;
   rtime_t us_since_sync;

   xrtp_media_t *rtp_media;

   uint32 rate;

   rtp_unpack(rtp);

   seqno = rtp_packet_seqno(rtp);
   src = rtp_packet_ssrc(rtp);

   rtpts_payload = rtp_packet_timestamp(rtp);
   vrtp_log(("audio/vorbis.vrtp_rtp_in: packet ssrc=%u, seqno=%u, timestamp=%u, rtp->connect=%d\n", src, seqno, rtpts_payload, (int)rtp->connect));

   sender = session_member_state(rtp->session, src);

   if(sender && sender->valid && !connect_match(rtp->connect, sender->rtp_connect))
   {
      /* this could be true if sender behind the firewall */
	  vrtp_debug(("audio/vorbis.vrtp_rtp_in: put NAT in mind\n"));
	  session_solve_collision(sender, src);

      rtp_packet_done(rtp);

      return XRTP_CONSUMED;
   }

   if(!sender)
   {
      /* The rtp packet is recieved before rtcp arrived, so the participant is not identified yet */
      if(!vh->session->$state.receive_from_anonymous)
	  {
         vrtp_log(("audio/vorbis.vrtp_rtp_in: participant waiting for identifed before receiving media\n"));
         rtp_packet_done(rtp);
         return XRTP_CONSUMED;
      }

      /* Get connect of the participant */
      rtp_conn = rtp->connect;
      rtcp_conn = NULL;

      rtp->connect = NULL; /* Dump the connect from rtcp packet */

      sender = session_new_member(vh->session, src, NULL);
      if(!sender)
	  {
         /* Something WRONG!!! packet disposed */
         rtp_packet_done(rtp);

         return XRTP_CONSUMED;
      }

      if(vh->session->$callbacks.member_connects)
	  {
         vh->session->$callbacks.member_connects(vh->session->$callbacks.member_connects_user, src, &rtp_conn, &rtcp_conn);
         session_member_set_connects(sender, rtp_conn, rtcp_conn);
      }
	  else
	  {
         rtcp_conn = connect_rtp_to_rtcp(rtp->connect); /* For RFC1889 static port allocation: rtcp port = rtp port + 1 */
         session_member_set_connects(sender, rtp->connect, rtcp_conn);
      }

      if(vh->session->join_to_rtp_port && connect_from_teleport(rtp->connect, vh->session->join_to_rtp_port))
	  {
         /* participant joined, clear the join desire */
         teleport_done(vh->session->join_to_rtp_port);
         vh->session->join_to_rtp_port = NULL;
         teleport_done(vh->session->join_to_rtcp_port);
         vh->session->join_to_rtcp_port = NULL;
      }
   }

   if(!sender->valid)
   {
      /* The rtp packet is recieved before rtcp arrived, so the participant is not identified yet */
      if(!vh->session->$state.receive_from_anonymous)
	  {
         vrtp_log(("audio/vorbis.vrtp_rtp_in: participant waiting for validated before receiving media\n"));
         rtp_packet_done(rtp);
         return XRTP_CONSUMED;
      }

      if(!session_update_seqno(sender, seqno))
	  {
         rtp_packet_done(rtp);
         return XRTP_CONSUMED;
      }
	  else
	  {
         if(!sender->rtp_connect)
		 {
            /* Get connect of the participant */
            rtp_conn = rtp->connect;
            rtcp_conn = NULL;

            rtp->connect = NULL; /* Dump the connect from rtcp packet */

            if(vh->session->$callbacks.member_connects)
			{
               vh->session->$callbacks.member_connects(vh->session->$callbacks.member_connects_user, src, &rtp_conn, &rtcp_conn);
               session_member_set_connects(sender, rtp_conn, rtcp_conn);
            }
			else
			{
               rtcp_conn = connect_rtp_to_rtcp(rtp->connect); /* For RFC1889 static port allocation: rtcp port = rtp port + 1 */
               session_member_set_connects(sender, rtp->connect, rtcp_conn);
            }
         }

         sender->valid = 1;
      }
   }

   if(session_member_update_by_rtp(sender, rtp) < XRTP_OK)
   {
	   vrtp_log(("text/rtp-test.tm_rtp_in: bad packet\n"));
	   rtp_packet_done(rtp);
	   return XRTP_CONSUMED;
   }

   if(session_member_seqno_stall(sender, seqno))
   {
	   vrtp_log(("audio/vorbis.vrtp_rtp_in: seqno[%u] is stall, discard\n", seqno));
	   rtp_packet_done(rtp);
	   return XRTP_CONSUMED;

   }

   /* calculate play timestamp */
   rtp_packet_arrival_time(rtp, &ms_arrival, &us_arrival, &ns_arrival);
   session_member_media_playing(sender, &rtpts_playing, &ms_playing, &us_playing, &ns_playing);

   rtp_media = (xrtp_media_t*)vh->vorbis_media;

   rate = rtp_media->clockrate;
   rtpts_arrival = rtpts_playing - (uint32)((us_playing - us_arrival)/1000000.0 * rate);

   rtpts_toplay = session_member_mapto_local_time(sender, rtpts_payload, rtpts_arrival, JITTER_ADJUSTMENT_LEVEL);

   if(!sender->media_playable && sender->media_playable != -1)
   {
	   uint32 rtpts_mi;
	   int signum;

	   int32 rtpts_pass;

	   vorbis_info_t *vinfo = (vorbis_info_t*)session_member_mediainfo(sender, &rtpts_mi, &signum);
	   
	   if(!vinfo || vinfo->head_packets != 3)
	   {
			vrtp_log(("audio/vorbis.vrtp_rtp_in: invalid media info\n"));
			rtp_packet_done(rtp);
			return XRTP_CONSUMED;
	   }

	   rtpts_pass = rtpts_toplay - rtpts_mi;
	   if(rtpts_pass >= 0)
	   {
		   int ret;
		   ogg_packet pack;
		   media_player_t *player, *explayer = NULL;
		   media_control_t *ctrl;

		   pack.granulepos = -1;

		   pack.packet = vinfo->header_identification;
		   pack.bytes = vinfo->header_identification_len;
		   pack.packetno = 0;
		   vorbis_synthesis_headerin(&vinfo->vi, &vinfo->vc, &pack);

		   pack.packet = vinfo->header_comment;
		   pack.bytes = vinfo->header_comment_len;
		   pack.packetno = 1;
		   vorbis_synthesis_headerin(&vinfo->vi, &vinfo->vc, &pack);

		   pack.packet = vinfo->header_setup;
		   pack.bytes = vinfo->header_setup_len;
		   pack.packetno = 2;
		   vorbis_synthesis_headerin(&vinfo->vi, &vinfo->vc, &pack);

		   sender->media_playable = 1;

		   ctrl = (media_control_t*)session_media_control(vh->session);
		   player = ctrl->find_player(ctrl, "playback", VORBIS_MIME, "", NULL);

		   ret = player->open_stream(player, (media_info_t*)vinfo);
		   if( ret < MP_OK)
		   {
				sender->media_playable = -1;
				player->done(player);
			
				vrtp_log(("audio/vorbis.vrtp_rtp_in: media is not playable\n"));
				rtp_packet_done(rtp);
			
				return XRTP_CONSUMED;
		   }         

		   explayer = (media_player_t*)session_member_set_player(sender, player);
		   if(explayer)
			   explayer->done(explayer);

		   /* start media delivery */
		   session_member_deliver(sender, seqno, 3);
	   }
   }

   /* convert rtp timestamp to usec */
   session_member_sync_point(sender, &rtpts_sync, &ms_sync, &us_sync, &ns_sync);
   us_since_sync = (uint32)((rtpts_toplay - rtpts_sync)/1000000.0 * rate);
   
   /* convert rtp packet to ogg packet */
   {   
	   char *payload;
	   int payload_bytes;
	   int cont,comp,count;
	   ogg_packet *oggpack;

	   payload_bytes = rtp_packet_payload(rtp, &payload);
	   cont = vorbis_rtp_is_continue((uint8)payload[0]);
	   comp = vorbis_rtp_is_complete((uint8)payload[0]);
	   count = vorbis_rtp_counter((uint8)payload[0]);

	   if(cont || !comp)
	   {
		   /*  handling fragments is NOT implemented currently */
		   vrtp_log(("audio/vorbis.vrtp_rtp_in: simply discard an ogg fragment\n"));
	   }
	   else if(count==1)
	   {
		   int last = 1;
		   /* single complete ogg packet */
		   oggpack = xmalloc(sizeof(ogg_packet));

		   payload_bytes = rtp_packet_dump_payload(rtp, &payload);

		   oggpack->packet = &payload[1];
		   oggpack->bytes = payload_bytes - 1;

		   /* convert rtp timestamp to granulepos */
		   oggpack->granulepos = session_member_samples(sender, rtpts_payload); 

		   session_member_hold_media(sender, (void*)oggpack, oggpack->bytes, seqno, rtpts_toplay, us_sync, us_since_sync, last, payload);
	   }
	   else if(count>1)
	   {
		   /* multi ogg packet bundle */
		   char *ogg = &payload[1];
		   int last = 0;
		   int i;

		   oggpack = xmalloc(sizeof(ogg_packet));

		   payload_bytes = rtp_packet_dump_payload(rtp, &payload);

		   for(i=0; i<count; i++)
		   {
			   oggpack->bytes = (int)ogg[0];
			   oggpack->packet = &ogg[1];

			   if(i==count-1)
			   {
				   oggpack->granulepos = session_member_samples(sender, rtpts_payload); 
				   last = 1;
			   }
			   else
			   {
				   oggpack->granulepos = -1;
			   }

			   session_member_hold_media(sender, (void*)oggpack, oggpack->bytes, seqno, rtpts_toplay, us_sync, us_since_sync, last, payload);
			   
			   ogg = ogg + oggpack->bytes + 1;
		   }
	   }
   }

   rtp_packet_done(rtp);

   return XRTP_CONSUMED;
}
示例#4
0
/*****************************************************************************
 * ProcessHeaders: process Vorbis headers.
 *****************************************************************************/
static int ProcessHeaders( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    ogg_packet oggpacket;

    unsigned pi_size[XIPH_MAX_HEADER_COUNT];
    void *pp_data[XIPH_MAX_HEADER_COUNT];
    unsigned i_count;
    if( xiph_SplitHeaders( pi_size, pp_data, &i_count,
                           p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra) )
        return VLC_EGENERIC;
    if( i_count < 3 )
        return VLC_EGENERIC;

    oggpacket.granulepos = -1;
    oggpacket.e_o_s = 0;
    oggpacket.packetno = 0;

    /* Take care of the initial Vorbis header */
    oggpacket.b_o_s  = 1; /* yes this actually is a b_o_s packet :) */
    oggpacket.bytes  = pi_size[0];
    oggpacket.packet = pp_data[0];
    if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )
    {
        msg_Err( p_dec, "this bitstream does not contain Vorbis audio data");
        return VLC_EGENERIC;
    }

    /* Setup the format */
    p_dec->fmt_out.audio.i_rate     = p_sys->vi.rate;
    p_dec->fmt_out.audio.i_channels = p_sys->vi.channels;

    if( p_dec->fmt_out.audio.i_channels > ARRAY_SIZE(pi_channels_maps) )
    {
        msg_Err( p_dec, "invalid number of channels (not between 1 and %lu): %i",
                 ARRAY_SIZE(pi_channels_maps),
                 p_dec->fmt_out.audio.i_channels );
        return VLC_EGENERIC;
    }

    p_dec->fmt_out.audio.i_physical_channels =
        p_dec->fmt_out.audio.i_original_channels =
            pi_channels_maps[p_sys->vi.channels];
    p_dec->fmt_out.i_bitrate = __MAX( 0, (int32_t) p_sys->vi.bitrate_nominal );

    date_Init( &p_sys->end_date, p_sys->vi.rate, 1 );

    msg_Dbg( p_dec, "channels:%d samplerate:%ld bitrate:%ud",
             p_sys->vi.channels, p_sys->vi.rate, p_dec->fmt_out.i_bitrate );

    /* The next packet in order is the comments header */
    oggpacket.b_o_s  = 0;
    oggpacket.bytes  = pi_size[1];
    oggpacket.packet = pp_data[1];
    if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )
    {
        msg_Err( p_dec, "2nd Vorbis header is corrupted" );
        return VLC_EGENERIC;
    }
    ParseVorbisComments( p_dec );

    /* The next packet in order is the codebooks header
     * We need to watch out that this packet is not missing as a
     * missing or corrupted header is fatal. */
    oggpacket.b_o_s  = 0;
    oggpacket.bytes  = pi_size[2];
    oggpacket.packet = pp_data[2];
    if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )
    {
        msg_Err( p_dec, "3rd Vorbis header is corrupted" );
        return VLC_EGENERIC;
    }

    if( !p_sys->b_packetizer )
    {
        /* Initialize the Vorbis packet->PCM decoder */
        vorbis_synthesis_init( &p_sys->vd, &p_sys->vi );
        vorbis_block_init( &p_sys->vd, &p_sys->vb );
    }
    else
    {
        p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
        p_dec->fmt_out.p_extra = xrealloc( p_dec->fmt_out.p_extra,
                                           p_dec->fmt_out.i_extra );
        memcpy( p_dec->fmt_out.p_extra,
                p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
    }

    ConfigureChannelOrder(p_sys->pi_chan_table, p_sys->vi.channels,
            p_dec->fmt_out.audio.i_physical_channels, true);

    return VLC_SUCCESS;
}
示例#5
0
void VideoStreamPlaybackTheora::set_file(const String &p_file) {

	ERR_FAIL_COND(playing);
	ogg_packet op;
	th_setup_info *ts = NULL;

	file_name = p_file;
	if (file) {
		memdelete(file);
	}
	file = FileAccess::open(p_file, FileAccess::READ);
	ERR_FAIL_COND(!file);

#ifdef THEORA_USE_THREAD_STREAMING
	thread_exit = false;
	thread_eof = false;
	//pre-fill buffer
	int to_read = ring_buffer.space_left();
	int read = file->get_buffer(read_buffer.ptr(), to_read);
	ring_buffer.write(read_buffer.ptr(), read);

	thread = Thread::create(_streaming_thread, this);

#endif

	ogg_sync_init(&oy);

	/* init supporting Vorbis structures needed in header parsing */
	vorbis_info_init(&vi);
	vorbis_comment_init(&vc);

	/* init supporting Theora structures needed in header parsing */
	th_comment_init(&tc);
	th_info_init(&ti);

	theora_eos = false;
	vorbis_eos = false;

	/* Ogg file open; parse the headers */
	/* Only interested in Vorbis/Theora streams */
	int stateflag = 0;

	int audio_track_skip = audio_track;

	while (!stateflag) {
		int ret = buffer_data();
		if (ret == 0) break;
		while (ogg_sync_pageout(&oy, &og) > 0) {
			ogg_stream_state test;

			/* is this a mandated initial header? If not, stop parsing */
			if (!ogg_page_bos(&og)) {
				/* don't leak the page; get it into the appropriate stream */
				queue_page(&og);
				stateflag = 1;
				break;
			}

			ogg_stream_init(&test, ogg_page_serialno(&og));
			ogg_stream_pagein(&test, &og);
			ogg_stream_packetout(&test, &op);

			/* identify the codec: try theora */
			if (!theora_p && th_decode_headerin(&ti, &tc, &ts, &op) >= 0) {
				/* it is theora */
				copymem(&to, &test, sizeof(test));
				theora_p = 1;
			} else if (!vorbis_p && vorbis_synthesis_headerin(&vi, &vc, &op) >= 0) {

				/* it is vorbis */
				if (audio_track_skip) {
					vorbis_info_clear(&vi);
					vorbis_comment_clear(&vc);
					ogg_stream_clear(&test);
					vorbis_info_init(&vi);
					vorbis_comment_init(&vc);

					audio_track_skip--;
				} else {
					copymem(&vo, &test, sizeof(test));
					vorbis_p = 1;
				}
			} else {
				/* whatever it is, we don't care about it */
				ogg_stream_clear(&test);
			}
		}
		/* fall through to non-bos page parsing */
	}

	/* we're expecting more header packets. */
	while ((theora_p && theora_p < 3) || (vorbis_p && vorbis_p < 3)) {
		int ret;

		/* look for further theora headers */
		while (theora_p && (theora_p < 3) && (ret = ogg_stream_packetout(&to, &op))) {
			if (ret < 0) {
				fprintf(stderr, "Error parsing Theora stream headers; "
								"corrupt stream?\n");
				clear();
				return;
			}
			if (!th_decode_headerin(&ti, &tc, &ts, &op)) {
				fprintf(stderr, "Error parsing Theora stream headers; "
								"corrupt stream?\n");
				clear();
				return;
			}
			theora_p++;
		}

		/* look for more vorbis header packets */
		while (vorbis_p && (vorbis_p < 3) && (ret = ogg_stream_packetout(&vo, &op))) {
			if (ret < 0) {
				fprintf(stderr, "Error parsing Vorbis stream headers; corrupt stream?\n");
				clear();
				return;
			}
			ret = vorbis_synthesis_headerin(&vi, &vc, &op);
			if (ret) {
				fprintf(stderr, "Error parsing Vorbis stream headers; corrupt stream?\n");
				clear();
				return;
			}
			vorbis_p++;
			if (vorbis_p == 3) break;
		}

		/* The header pages/packets will arrive before anything else we
		care about, or the stream is not obeying spec */

		if (ogg_sync_pageout(&oy, &og) > 0) {
			queue_page(&og); /* demux into the appropriate stream */
		} else {
			int ret = buffer_data(); /* someone needs more data */
			if (ret == 0) {
				fprintf(stderr, "End of file while searching for codec headers.\n");
				clear();
				return;
			}
		}
	}

	/* and now we have it all.  initialize decoders */
	if (theora_p) {
		td = th_decode_alloc(&ti, ts);
		printf("Ogg logical stream %lx is Theora %dx%d %.02f fps",
				to.serialno, ti.pic_width, ti.pic_height,
				(double)ti.fps_numerator / ti.fps_denominator);
		px_fmt = ti.pixel_fmt;
		switch (ti.pixel_fmt) {
			case TH_PF_420: printf(" 4:2:0 video\n"); break;
			case TH_PF_422: printf(" 4:2:2 video\n"); break;
			case TH_PF_444: printf(" 4:4:4 video\n"); break;
			case TH_PF_RSVD:
			default:
				printf(" video\n  (UNKNOWN Chroma sampling!)\n");
				break;
		}
		if (ti.pic_width != ti.frame_width || ti.pic_height != ti.frame_height)
			printf("  Frame content is %dx%d with offset (%d,%d).\n",
					ti.frame_width, ti.frame_height, ti.pic_x, ti.pic_y);
		th_decode_ctl(td, TH_DECCTL_GET_PPLEVEL_MAX, &pp_level_max,
				sizeof(pp_level_max));
		pp_level = pp_level_max;
		pp_level = 0;
		th_decode_ctl(td, TH_DECCTL_SET_PPLEVEL, &pp_level, sizeof(pp_level));
		pp_inc = 0;

		/*{
		int arg = 0xffff;
		th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MBMODE,&arg,sizeof(arg));
		th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MV,&arg,sizeof(arg));
		th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_QI,&arg,sizeof(arg));
		arg=10;
		th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_BITS,&arg,sizeof(arg));
		}*/

		int w;
		int h;
		w = (ti.pic_x + ti.frame_width + 1 & ~1) - (ti.pic_x & ~1);
		h = (ti.pic_y + ti.frame_height + 1 & ~1) - (ti.pic_y & ~1);
		size.x = w;
		size.y = h;

		texture->create(w, h, Image::FORMAT_RGBA8, Texture::FLAG_FILTER | Texture::FLAG_VIDEO_SURFACE);

	} else {
		/* tear down the partial theora setup */
		th_info_clear(&ti);
		th_comment_clear(&tc);
	}

	th_setup_free(ts);

	if (vorbis_p) {
		vorbis_synthesis_init(&vd, &vi);
		vorbis_block_init(&vd, &vb);
		fprintf(stderr, "Ogg logical stream %lx is Vorbis %d channel %ld Hz audio.\n",
				vo.serialno, vi.channels, vi.rate);
		//_setup(vi.channels, vi.rate);

	} else {
		/* tear down the partial vorbis setup */
		vorbis_info_clear(&vi);
		vorbis_comment_clear(&vc);
	}

	playing = false;
	buffering = true;
	time = 0;
	audio_frames_wrote = 0;
};
示例#6
0
static int _fetch_headers(OggVorbis_File *vf,
			  vorbis_info *vi,
			  vorbis_comment *vc,
			  ogg_uint32_t *serialno,
			  ogg_page *og_ptr){
  ogg_page og={0,0,0,0};
  ogg_packet op={0,0,0,0,0,0};
  int i,ret;
  
  if(!og_ptr){
    ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
    if(llret==OV_EREAD)return(OV_EREAD);
    if(llret<0)return OV_ENOTVORBIS;
    og_ptr=&og;
  }

  ogg_stream_reset_serialno(vf->os,ogg_page_serialno(og_ptr));
  if(serialno)*serialno=vf->os->serialno;
  vf->ready_state=STREAMSET;
  
  /* extract the initial header from the first page and verify that the
     Ogg bitstream is in fact Vorbis data */
  
  vorbis_info_init(vi);
  vorbis_comment_init(vc);
  
  i=0;
  while(i<3){
    ogg_stream_pagein(vf->os,og_ptr);
    while(i<3){
      int result=ogg_stream_packetout(vf->os,&op);
      if(result==0)break;
      if(result==-1){
	ret=OV_EBADHEADER;
	goto bail_header;
      }
      if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
	goto bail_header;
      }
      i++;
    }
    if(i<3)
      if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
	ret=OV_EBADHEADER;
	goto bail_header;
      }
  }

  ogg_packet_release(&op);
  ogg_page_release(&og);
  return 0; 

 bail_header:
  ogg_packet_release(&op);
  ogg_page_release(&og);
  vorbis_info_clear(vi);
  vorbis_comment_clear(vc);
  vf->ready_state=OPENED;

  return ret;
}
示例#7
0
static sf_count_t
ogg_length_aux (SF_PRIVATE * psf)
{
    ogg_sync_state osync ;
    ogg_page page ;
    int gotpage = 0 ;
    sf_count_t len = 0 ;
    stream_set *processors ;

    processors = create_stream_set () ;
    if (processors == NULL)
        return 0 ;	// out of memory?

    ogg_sync_init (&osync) ;

    while (ogg_length_get_next_page (psf, &osync, &page))
    {
        stream_processor *p = find_stream_processor (processors, &page) ;
        gotpage = 1 ;

        if (!p)
        {   len = 0 ;
            break ;
        } ;

        if (p->isillegal && !p->shownillegal)
        {
            p->shownillegal = 1 ;
            /* If it's a new stream, we want to continue processing this page
            ** anyway to suppress additional spurious errors
            */
            if (!p->isnew) continue ;
        } ;

        if (!p->isillegal)
        {   ogg_packet packet ;
            int header = 0 ;

            ogg_stream_pagein (&p->os, &page) ;
            if (p->doneheaders < 3)
                header = 1 ;

            while (ogg_stream_packetout (&p->os, &packet) > 0)
            {
                if (p->doneheaders < 3)
                {   if (vorbis_synthesis_headerin (&p->vi, &p->vc, &packet) < 0)
                        continue ;
                    p->doneheaders ++ ;
                } ;
            } ;
            if (!header)
            {   sf_count_t gp = ogg_page_granulepos (&page) ;
                if (gp > 0) p->lastgranulepos = gp ;
            } ;
            if (p->end)
            {   vorbis_end (p, &len) ;
                p->isillegal = 1 ;
            } ;
        } ;
    } ;

    ogg_sync_clear (&osync) ;
    free_stream_set (processors, &len) ;

    return len ;
} /* ogg_length_aux */
/** central buffer management function 
  * @param openmaxStandComp the component handle
  * @param inputbuffer contains the input ogg file content
  * @param outputbuffer is returned along with its output pcm file content that is produced as a result of this function execution
  */
void omx_vorbisdec_component_BufferMgmtCallbackVorbis(OMX_COMPONENTTYPE *openmaxStandComp, OMX_BUFFERHEADERTYPE* inputbuffer, OMX_BUFFERHEADERTYPE* outputbuffer) {

  omx_vorbisdec_component_PrivateType* omx_vorbisdec_component_Private = openmaxStandComp->pComponentPrivate;
  OMX_U8* outputCurrBuffer;
  OMX_U32 outputLength;
  OMX_S32 result;  
  float **pcm;
  OMX_S32 samples;
  OMX_S32 i, j;
  OMX_S32 bout;
  OMX_S32 clipflag=0;
  int val;
  float  *mono;
  int eos=0;
  char *vorbis_buffer;
  ogg_int16_t convbuffer[4096];

 
  DEBUG(DEB_LEV_FULL_SEQ, "input buf %x filled len : %d \n", (int)inputbuffer->pBuffer, (int)inputbuffer->nFilledLen);  
  /** Fill up the current input buffer when a new buffer has arrived */
  if(omx_vorbisdec_component_Private->isNewBuffer) {
    omx_vorbisdec_component_Private->inputCurrBuffer = inputbuffer->pBuffer;
    omx_vorbisdec_component_Private->inputCurrLength = inputbuffer->nFilledLen;
    omx_vorbisdec_component_Private->positionInOutBuf = 0;

    DEBUG(DEB_LEV_SIMPLE_SEQ, "new -- input buf %x filled len : %d \n", (int)inputbuffer->pBuffer, (int)inputbuffer->nFilledLen);  

    /** for each new input buffer --- copy buffer content into into ogg sync state structure data */
    vorbis_buffer = ogg_sync_buffer(&omx_vorbisdec_component_Private->oy, inputbuffer->nAllocLen);
    memcpy(vorbis_buffer, inputbuffer->pBuffer, inputbuffer->nFilledLen);
    ogg_sync_wrote(&omx_vorbisdec_component_Private->oy, inputbuffer->nFilledLen);
    DEBUG(DEB_LEV_FULL_SEQ,"***** bytes read to buffer (of first header): %d \n",(int)inputbuffer->nFilledLen);
  }
  outputCurrBuffer = outputbuffer->pBuffer;
  outputLength = outputbuffer->nAllocLen;
  outputbuffer->nFilledLen = 0;
  outputbuffer->nOffset = 0;
  
  if(omx_vorbisdec_component_Private->packetNumber < 3) {
    omx_vorbisdec_component_Private->isNewBuffer = 0;
    if(omx_vorbisdec_component_Private->packetNumber == 0) {
      DEBUG(DEB_LEV_SIMPLE_SEQ, "in processing the first header buffer\n");      
      if(ogg_sync_pageout(&omx_vorbisdec_component_Private->oy, &omx_vorbisdec_component_Private->og) != 1)  {
        DEBUG(DEB_LEV_ERR, "this input stream is not an Ogg stream\n");
        return;
      }  
      ogg_stream_init(&omx_vorbisdec_component_Private->os, ogg_page_serialno(&omx_vorbisdec_component_Private->og));    
      vorbis_info_init(&omx_vorbisdec_component_Private->vi);
      vorbis_comment_init(&omx_vorbisdec_component_Private->vc);

      if(ogg_stream_pagein(&omx_vorbisdec_component_Private->os, &omx_vorbisdec_component_Private->og) < 0)  {
        DEBUG(DEB_LEV_ERR, "Error reading first page of Ogg bitstream data.\n");
        return;
      }
      if(ogg_stream_packetout(&omx_vorbisdec_component_Private->os, &omx_vorbisdec_component_Private->op) != 1)  {
        DEBUG(DEB_LEV_ERR, "Error reading initial header packet.\n");
        return;
      }
      
      omx_vorbisdec_component_Private->packetNumber++;

      if(vorbis_synthesis_headerin(&omx_vorbisdec_component_Private->vi, &omx_vorbisdec_component_Private->vc, &omx_vorbisdec_component_Private->op) < 0)  {
        DEBUG(DEB_LEV_ERR, "This Ogg bitstream does not contain Vorbis audio data\n");
        return;
      }  
    }

    while(omx_vorbisdec_component_Private->packetNumber < 3)
    {
      int result=ogg_sync_pageout(&omx_vorbisdec_component_Private->oy,&omx_vorbisdec_component_Private->og);
      if(result==0) { //break; /* Need more data */
        omx_vorbisdec_component_Private->isNewBuffer = 1;
        inputbuffer->nFilledLen = 0;
        return;
      }
      /* Don't complain about missing or corrupt data yet.  We'll
      catch it at the packet output phase */
      if(result==1) 
      {
        ogg_stream_pagein(&omx_vorbisdec_component_Private->os,&omx_vorbisdec_component_Private->og);
        /* we can ignore any errors here as they'll also become apparent at packetout */
        while(omx_vorbisdec_component_Private->packetNumber < 3) {
          result=ogg_stream_packetout(&omx_vorbisdec_component_Private->os,&omx_vorbisdec_component_Private->op);
          if(result==0)break;
          if(result<0) {
          /* Uh oh; data at some point was corrupted or missing!
            We can't tolerate that in a header.  Die. */
            DEBUG(DEB_LEV_ERR,"Corrupt secondary header.  Exiting.\n");
            break;
          }//end if
          omx_vorbisdec_component_Private->packetNumber++;
          vorbis_synthesis_headerin(&omx_vorbisdec_component_Private->vi,&omx_vorbisdec_component_Private->vc,&omx_vorbisdec_component_Private->op);
        }//end while
      }//end if
    }//end while

    omx_vorbisdec_component_Private->isNewBuffer = 1;
    inputbuffer->nFilledLen = 0;
    return;

  }

  /* A Vorbis logical bitstream begins with 3 headers. Once the last of these has been processed,
   * we can report the metadata and set up the output audio port appropriately. */
  if(omx_vorbisdec_component_Private->packetNumber == 3) {
    /* Throw the comments plus a few lines about the bitstream we're decoding */
    {
      // ptr should be declared earlier//
      char **ptr=omx_vorbisdec_component_Private->vc.user_comments;
      while(*ptr){
        DEBUG(DEB_LEV_ERR,"%s\n",*ptr);
        ++ptr;
      }
      DEBUG(DEB_LEV_ERR,"Bitstream is %d channel, %ldHz\n",omx_vorbisdec_component_Private->vi.channels,omx_vorbisdec_component_Private->vi.rate);
      DEBUG(DEB_LEV_ERR,"Encoded by: %s\n\n",omx_vorbisdec_component_Private->vc.vendor);
    }

    /* Update pAudioVorbis settings */
    omx_vorbisdec_component_Private->pAudioVorbis.nSampleRate = omx_vorbisdec_component_Private->vi.rate;
    omx_vorbisdec_component_Private->pAudioVorbis.nChannels = omx_vorbisdec_component_Private->vi.channels;

    /* Update audio port settings for this Vorbis bitstream */
    if ((omx_vorbisdec_component_Private->pAudioPcmMode.nSamplingRate != omx_vorbisdec_component_Private->pAudioVorbis.nSampleRate) ||
        (omx_vorbisdec_component_Private->pAudioPcmMode.nChannels != omx_vorbisdec_component_Private->pAudioVorbis.nChannels)) {
      omx_vorbisdec_component_Private->pAudioPcmMode.nSamplingRate = omx_vorbisdec_component_Private->pAudioVorbis.nSampleRate;
      omx_vorbisdec_component_Private->pAudioPcmMode.nChannels = omx_vorbisdec_component_Private->pAudioVorbis.nChannels;

      /*Send Port Settings changed call back*/
      (*(omx_vorbisdec_component_Private->callbacks->EventHandler))
        (openmaxStandComp,
        omx_vorbisdec_component_Private->callbackData,
        OMX_EventPortSettingsChanged, /* The command was completed */
        0,
        1, /* This is the output port index */
        NULL);
    }

    omx_vorbisdec_component_Private->convsize=inputbuffer->nFilledLen/omx_vorbisdec_component_Private->vi.channels;
    /* OK, got and parsed all three headers. Initialize the Vorbis
    packet->PCM decoder. */
    vorbis_synthesis_init(&omx_vorbisdec_component_Private->vd,&omx_vorbisdec_component_Private->vi); /* central decode state */
    vorbis_block_init(&omx_vorbisdec_component_Private->vd,&omx_vorbisdec_component_Private->vb);/* local state for most of the decode
                               so multiple block decodes can
                               proceed in parallel.  We could init
                               multiple vorbis_block structures
                               for vd here */
  }
  DEBUG(DEB_LEV_FULL_SEQ,"***** now the decoding will start *****\n");

  if(omx_vorbisdec_component_Private->isNewBuffer)  {
    omx_vorbisdec_component_Private->isNewBuffer=0;
    int result=ogg_sync_pageout(&omx_vorbisdec_component_Private->oy,&omx_vorbisdec_component_Private->og);
    DEBUG(DEB_LEV_FULL_SEQ," --->  page (read in decoding) - header len :  %ld body len : %ld \n",omx_vorbisdec_component_Private->og.header_len,omx_vorbisdec_component_Private->og.body_len);
    if(result == 0)  {
      omx_vorbisdec_component_Private->isNewBuffer = 1;
      inputbuffer->nFilledLen = 0;
      return;
    }
    if(result<0)
    { 
      /* missing or corrupt data at this page position */
      DEBUG(DEB_LEV_ERR,"Corrupt or missing data in bitstream; continuing...\n");
    }
    else {
      ogg_stream_pagein(&omx_vorbisdec_component_Private->os,&omx_vorbisdec_component_Private->og); /* can safely ignore errors at */
    }
  }
  
  result=ogg_stream_packetout(&omx_vorbisdec_component_Private->os,&omx_vorbisdec_component_Private->op);
  DEBUG(DEB_LEV_FULL_SEQ," packet length (read in decoding a particular page): %ld \n",omx_vorbisdec_component_Private->op.bytes);
  if(result == 0)  {
    omx_vorbisdec_component_Private->isNewBuffer = 1;
    inputbuffer->nFilledLen = 0;
    return;
  }
  if(result<0)
  {
    /* missing or corrupt data at this page position */
    /* no reason to complain; already complained above */
    DEBUG(DEB_LEV_ERR,"Corrupt or missing data in bitstream; continuing...\n");
  } else {
    /* we have a packet.  Decode it */
    omx_vorbisdec_component_Private->packetNumber++;

    if(vorbis_synthesis(&omx_vorbisdec_component_Private->vb,&omx_vorbisdec_component_Private->op)==0) /* test for success! */
    vorbis_synthesis_blockin(&omx_vorbisdec_component_Private->vd,&omx_vorbisdec_component_Private->vb);
    /**pcm is a multichannel float vector.  In stereo, for
      example, pcm[0] is left, and pcm[1] is right.  samples is
      the size of each channel.  Convert the float values
      (-1.<=range<=1.) to whatever PCM format and write it out */

    while((samples=vorbis_synthesis_pcmout(&omx_vorbisdec_component_Private->vd,&pcm))>0)
    {
      bout=(samples<omx_vorbisdec_component_Private->convsize?samples:omx_vorbisdec_component_Private->convsize);

      /* convert floats to 16 bit signed ints (host order) and interleave */
      for(i=0;i<omx_vorbisdec_component_Private->vi.channels;i++)
      {
        ogg_int16_t *ptr=convbuffer+i;
        mono=pcm[i];
        for(j=0;j<bout;j++)
        {
#if 1
          val=mono[j]*32767.f;
#else     /* optional dither */
          val=mono[j]*32767.f+drand48()-0.5f;
#endif
          /* might as well guard against clipping */
          if(val>32767)
          {
            val=32767;
            clipflag=1;
          }
          if(val<-32768)
          {
            val=-32768;
            clipflag=1;
          }
          *ptr=val;
          ptr+=omx_vorbisdec_component_Private->vi.channels;
        }
      }

      outputbuffer->nFilledLen=2*omx_vorbisdec_component_Private->vi.channels*bout;
      memcpy(outputCurrBuffer,(char *)convbuffer,outputbuffer->nFilledLen);

      if(clipflag) {
        DEBUG(DEB_LEV_FULL_SEQ,"Clipping in frame %ld\n",(long)(omx_vorbisdec_component_Private->vd.sequence));
      }
      vorbis_synthesis_read(&omx_vorbisdec_component_Private->vd,bout); /* tell libvorbis how many samples we actually consumed */
    }
  }
  if(ogg_page_eos(&omx_vorbisdec_component_Private->og)) {
    DEBUG(DEB_LEV_FULL_SEQ, "In %s EOS Detected\n",__func__);
    eos=1;
  }
 
  DEBUG(DEB_LEV_FULL_SEQ, "One output buffer %x len=%d is full returning\n", (int)outputbuffer->pBuffer, (int)outputbuffer->nFilledLen);  
}
示例#9
0
static int oggvorbis_decode_init(AVCodecContext *avccontext) {
    OggVorbisDecContext *context = avccontext->priv_data ;
    uint8_t *p= avccontext->extradata;
    int i, hsizes[3];
    unsigned char *headers[3], *extradata = avccontext->extradata;

    vorbis_info_init(&context->vi) ;
    vorbis_comment_init(&context->vc) ;

    if(! avccontext->extradata_size || ! p) {
        av_log(avccontext, AV_LOG_ERROR, "vorbis extradata absent\n");
        return -1;
    }

    if(p[0] == 0 && p[1] == 30) {
        for(i = 0; i < 3; i++){
            hsizes[i] = bytestream_get_be16((const uint8_t **)&p);
            headers[i] = p;
            p += hsizes[i];
        }
    } else if(*p == 2) {
        unsigned int offset = 1;
        p++;
        for(i=0; i<2; i++) {
            hsizes[i] = 0;
            while((*p == 0xFF) && (offset < avccontext->extradata_size)) {
                hsizes[i] += 0xFF;
                offset++;
                p++;
            }
            if(offset >= avccontext->extradata_size - 1) {
                av_log(avccontext, AV_LOG_ERROR,
                       "vorbis header sizes damaged\n");
                return -1;
            }
            hsizes[i] += *p;
            offset++;
            p++;
        }
        hsizes[2] = avccontext->extradata_size - hsizes[0]-hsizes[1]-offset;
#if 0
        av_log(avccontext, AV_LOG_DEBUG,
               "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n",
               hsizes[0], hsizes[1], hsizes[2], avccontext->extradata_size);
#endif
        headers[0] = extradata + offset;
        headers[1] = extradata + offset + hsizes[0];
        headers[2] = extradata + offset + hsizes[0] + hsizes[1];
    } else {
        av_log(avccontext, AV_LOG_ERROR,
               "vorbis initial header len is wrong: %d\n", *p);
        return -1;
    }

    for(i=0; i<3; i++){
        context->op.b_o_s= i==0;
        context->op.bytes = hsizes[i];
        context->op.packet = headers[i];
        if(vorbis_synthesis_headerin(&context->vi, &context->vc, &context->op)<0){
            av_log(avccontext, AV_LOG_ERROR, "%d. vorbis header damaged\n", i+1);
            return -1;
        }
    }

    avccontext->channels = context->vi.channels;
    avccontext->sample_rate = context->vi.rate;
    avccontext->sample_fmt = AV_SAMPLE_FMT_S16;
    avccontext->time_base= (AVRational){1, avccontext->sample_rate};

    vorbis_synthesis_init(&context->vd, &context->vi);
    vorbis_block_init(&context->vd, &context->vb);

    return 0 ;
}
示例#10
0
static void
vorbis_parse_push_headers (GstVorbisParse * parse)
{
  /* mark and put on caps */
  GstCaps *caps;
  GstBuffer *outbuf, *outbuf1, *outbuf2, *outbuf3;
  ogg_packet packet;
  GstMapInfo map;

  outbuf = GST_BUFFER_CAST (parse->streamheader->data);
  gst_buffer_map (outbuf, &map, GST_MAP_READ);
  packet.packet = map.data;
  packet.bytes = map.size;
  packet.granulepos = GST_BUFFER_OFFSET_END (outbuf);
  packet.packetno = 1;
  packet.e_o_s = 0;
  packet.b_o_s = 1;
  vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet);
  gst_buffer_unmap (outbuf, &map);
  parse->sample_rate = parse->vi.rate;
  parse->channels = parse->vi.channels;
  outbuf1 = outbuf;

  outbuf = GST_BUFFER_CAST (parse->streamheader->next->data);
  gst_buffer_map (outbuf, &map, GST_MAP_READ);
  packet.packet = map.data;
  packet.bytes = map.size;
  packet.granulepos = GST_BUFFER_OFFSET_END (outbuf);
  packet.packetno = 2;
  packet.e_o_s = 0;
  packet.b_o_s = 0;
  vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet);
  gst_buffer_unmap (outbuf, &map);
  outbuf2 = outbuf;

  outbuf = GST_BUFFER_CAST (parse->streamheader->next->next->data);
  gst_buffer_map (outbuf, &map, GST_MAP_READ);
  packet.packet = map.data;
  packet.bytes = map.size;
  packet.granulepos = GST_BUFFER_OFFSET_END (outbuf);
  packet.packetno = 3;
  packet.e_o_s = 0;
  packet.b_o_s = 0;
  vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet);
  gst_buffer_unmap (outbuf, &map);
  outbuf3 = outbuf;

  /* get the headers into the caps, passing them to vorbis as we go */
  caps = gst_caps_new_simple ("audio/x-vorbis",
      "rate", G_TYPE_INT, parse->sample_rate,
      "channels", G_TYPE_INT, parse->channels, NULL);;
  vorbis_parse_set_header_on_caps (parse, caps);
  GST_DEBUG_OBJECT (parse, "here are the caps: %" GST_PTR_FORMAT, caps);
  gst_pad_set_caps (parse->srcpad, caps);
  gst_caps_unref (caps);

  /* first process queued events */
  vorbis_parse_drain_event_queue (parse);

  /* push out buffers, ignoring return value... */
  gst_pad_push (parse->srcpad, outbuf1);
  gst_pad_push (parse->srcpad, outbuf2);
  gst_pad_push (parse->srcpad, outbuf3);

  g_list_free (parse->streamheader);
  parse->streamheader = NULL;
}
//---------------------------Start readProperties----------------------------------//
IFACEMETHODIMP VorbisPropertyHandler::readProperties (IStream *pStream) {
   oLOG ("VorbisPropertyHandler::readProperties ()" << std::endl);

   ogg_page         page;
   ogg_sync_state   syncstate;
   ogg_stream_state streamstate;
   ogg_packet       packet;

   int            packetCount = 0;

   // Initialize OGG structures
   V_ASSERT_ (ogg_sync_init (&syncstate) );
   V_ASSERT_ (ogg_stream_init(&streamstate, 0) );

   while (packetCount < 3) {
      H_ASSERT_ (readOGGPacket (pStream, page, syncstate, streamstate, packet) );

      // Check if it is a Vorbis header
      if (packetCount == 0 && vorbis_synthesis_idheader (&packet) != 1)
         break;

      V_ASSERT_ (vorbis_synthesis_headerin (&m_oInfo, &m_oComment, &packet) );

      // A packet is available, this is what we pass to the vorbis or theora libraries to decode.
      packetCount++;
   }

   //vorbis_dsp_state dspstate;
   //vorbis_block block;

   //V_ASSERT_ (vorbis_synthesis_init (&dspstate, &m_oInfo) );
   //V_ASSERT_ (vorbis_block_init (&dspstate, &block) );

#ifdef DEFINE
   g_oLog << "VorbisPropertyHandler::readProperties: m_oInfo = "
      << "\n" << m_oInfo.bitrate_lower
      << "\n" << m_oInfo.bitrate_nominal
      << "\n" << m_oInfo.bitrate_upper
      << "\n" << m_oInfo.bitrate_window
      << "\n" << m_oInfo.channels
      << "\n" << (char*)m_oInfo.codec_setup
      << "\n" << m_oInfo.rate
      << "\n" << m_oInfo.version
      << "\n" << m_oComment.vendor
      << "\n" << m_oComment.comments;

   char buffer[4096];

   for (int i = 0; i < m_oComment.comments; ++i) {
      memcpy (buffer, m_oComment.user_comments[i], m_oComment.comment_lengths[i]);
      buffer[m_oComment.comment_lengths[i] ] = 0;
      g_oLog << "\n" << buffer;
   }

   g_oLog << std::endl;
#endif

   // Delete OGG structures
   V_ASSERT_ (ogg_stream_clear (&streamstate) );
   V_ASSERT_ (ogg_sync_clear (&syncstate) );

   return S_OK;
}//end Fct
示例#12
0
/*!
 * \brief Create a new OGG/Vorbis filestream and set it up for reading.
 * \param fd Descriptor that points to on disk storage of the OGG/Vorbis data.
 * \return The new filestream.
 */
static struct cw_filestream *ogg_vorbis_open(FILE *fp)
{
    int i;
    int bytes;
    int result;
    char **ptr;
    char *buffer;

    struct cw_filestream *tmp;

    if ((tmp = malloc(sizeof(struct cw_filestream))))
    {
        memset(tmp, 0, sizeof(struct cw_filestream));

        tmp->writing = 0;
        tmp->fp = fp;

        ogg_sync_init(&tmp->oy);

        buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
        bytes = fread(buffer, 1, BLOCK_SIZE, tmp->fp);

        ogg_sync_wrote(&tmp->oy, bytes);

        result = ogg_sync_pageout(&tmp->oy, &tmp->og);
        if (result != 1)
        {
            if (bytes < BLOCK_SIZE)
                cw_log(LOG_ERROR, "Run out of data... %d %s\n", errno, strerror(errno));
            else
                cw_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n");
            fclose(fp);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        ogg_stream_init(&tmp->os, ogg_page_serialno(&tmp->og));
        vorbis_info_init(&tmp->vi);
        vorbis_comment_init(&tmp->vc);

        if (ogg_stream_pagein(&tmp->os, &tmp->og) < 0)
        {
            cw_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        if (ogg_stream_packetout(&tmp->os, &tmp->op) != 1)
        { 
            cw_log(LOG_ERROR, "Error reading initial header packet.\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        if (vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op) < 0)
        { 
            cw_log(LOG_ERROR, "This Ogg bitstream does not contain Vorbis audio data.\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        i = 0;
        while (i < 2)
        {
            while (i < 2)
            {
                result = ogg_sync_pageout(&tmp->oy, &tmp->og);
                if (result == 0)
                    break;
                if (result == 1)
                {
                    ogg_stream_pagein(&tmp->os, &tmp->og);
                    while (i < 2)
                    {
                        result = ogg_stream_packetout(&tmp->os,&tmp->op);
                        if (result == 0)
                            break;
                        if (result < 0)
                        {
                            cw_log(LOG_ERROR, "Corrupt secondary header.  Exiting.\n");
                            fclose(fp);
                            ogg_stream_clear(&tmp->os);
                            vorbis_comment_clear(&tmp->vc);
                            vorbis_info_clear(&tmp->vi);
                            ogg_sync_clear(&tmp->oy);
                            free(tmp);
                            return NULL;
                        }
                        vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op);
                        i++;
                    }
                }
            }

            buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
            bytes = fread(buffer, 1, BLOCK_SIZE, tmp->fp);
            if (bytes == 0  &&  i < 2)
            {
                cw_log(LOG_ERROR, "End of file before finding all Vorbis headers!\n");
                fclose(fp);
                ogg_stream_clear(&tmp->os);
                vorbis_comment_clear(&tmp->vc);
                vorbis_info_clear(&tmp->vi);
                ogg_sync_clear(&tmp->oy);
                free(tmp);
                return NULL;
            }
            ogg_sync_wrote(&tmp->oy, bytes);
        }
        
        ptr = tmp->vc.user_comments;
        while (*ptr)
        {
            cw_log(LOG_DEBUG, "OGG/Vorbis comment: %s\n", *ptr);
            ++ptr;
        }
        cw_log(LOG_DEBUG, "OGG/Vorbis bitstream is %d channel, %ldHz\n", tmp->vi.channels, tmp->vi.rate);
        cw_log(LOG_DEBUG, "OGG/Vorbis file encoded by: %s\n", tmp->vc.vendor);

        if (tmp->vi.channels != 1)
        {
            cw_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n");
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        

        if (tmp->vi.rate != 8000)
        {
            cw_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_block_clear(&tmp->vb);
            vorbis_dsp_clear(&tmp->vd);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        vorbis_synthesis_init(&tmp->vd, &tmp->vi);
        vorbis_block_init(&tmp->vd, &tmp->vb);

        if (cw_mutex_lock(&ogg_vorbis_lock))
        {
            cw_log(LOG_WARNING, "Unable to lock ogg_vorbis list\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_block_clear(&tmp->vb);
            vorbis_dsp_clear(&tmp->vd);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        glistcnt++;
        cw_mutex_unlock(&ogg_vorbis_lock);
        cw_update_use_count();
    }
    return tmp;
}
示例#13
0
int OggDec::DecodeOGG(char *inmemory,int inmemsize,
                char *outmemory,int outmemsize,int *done)
{
	char	*buffer;
	int		i;

	*done = 0;
	if(leakSize){
		if(outmemsize >= leakSize){
			memcpy(outmemory,leak_mem,leakSize);
			*done = leakSize;
			free(leak_mem);
			leak_mem = NULL;
			leakSize = 0;
			allocMemSize = 0;
		}else{
			memcpy(outmemory,leak_mem,outmemsize);
			*done = outmemsize;
			memmove(leak_mem,leak_mem+outmemsize,leakSize-outmemsize);
			leakSize -= outmemsize;
		}
		if(inmemsize==0) return (OGG_DEC_CONTINUE);
	}
	if(0==decStep){
		eos = 0;
		buffer=ogg_sync_buffer(&oy,4096);
		memcpy(buffer,inmemory,inmemsize);
		ogg_sync_wrote(&oy,inmemsize);
		if(ogg_sync_pageout(&oy,&og)!=1){
			if(inmemsize<4096){
				Clear_ogg();
				return(OGG_DEC_END);
			}
			return(OGG_DEC_ERR);
		}
		ogg_stream_init(&os,ogg_page_serialno(&og));
		vorbis_info_init(&vi);
		vorbis_comment_init(&vc);
		if(ogg_stream_pagein(&os,&og)<0){ 
			return(OGG_DEC_ERR);
		}
		if(ogg_stream_packetout(&os,&op)!=1){ 
			return(OGG_DEC_ERR);
		}
		if(vorbis_synthesis_headerin(&vi,&vc,&op)<0){ 
			return(OGG_DEC_ERR);
		}
		wfmt.wFormatTag = WAVE_FORMAT_PCM;
		wfmt.nChannels = vi.channels;
		wfmt.wBitsPerSample = 16;
		wfmt.nSamplesPerSec = vi.rate;
		wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample/8);
		wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
		wfmt.cbSize = 0;
		bWaveGet = TRUE;
		decStep = 1;
		d1loop=0;
		return (OGG_DEC_CONTINUE);
	}
	if(1==decStep){
		while(d1loop<2){
			while(d1loop<2){
				int result=ogg_sync_pageout(&oy,&og);
				if(result==0)break;
				if(result==1){
					ogg_stream_pagein(&os,&og);
					while(d1loop<2){
						result=ogg_stream_packetout(&os,&op);
						if(result==0)break;
						if(result<0){
							return(OGG_DEC_ERR);
						}
						vorbis_synthesis_headerin(&vi,&vc,&op);
						d1loop++;
					}
				}
			}
			buffer=ogg_sync_buffer(&oy,4096);
			memcpy(buffer,inmemory,inmemsize);
			if(inmemsize==0 && d1loop<2){
				return(OGG_DEC_ERR);
			}
			ogg_sync_wrote(&oy,inmemsize);
			if(d1loop<2)
				return (OGG_DEC_CONTINUE);
		}
		decStep = 2;
		convsize=4096/vi.channels;
		vorbis_synthesis_init(&vd,&vi);
		vorbis_block_init(&vd,&vb);
		return (OGG_DEC_CONTINUE);
	}
	while(!eos){
	  while(!eos){
		int result=ogg_sync_pageout(&oy,&og);
		if(result==0)break;
		if(result<0){
		}else{
			ogg_stream_pagein(&os,&og);
			while(1){
				result=ogg_stream_packetout(&os,&op);
				if(result==0)break;
				if(result<0){
				}else{
					float **pcm;
					int samples;
		  
					if(vorbis_synthesis(&vb,&op)==0)
						vorbis_synthesis_blockin(&vd,&vb);
					while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0){
						int j;
						int clipflag=0;
						int bout=(samples<convsize?samples:convsize);
		
						for(i=0;i<vi.channels;i++){
							ogg_int16_t *ptr=convbuffer+i;
							float  *mono=pcm[i];
							for(j=0;j<bout;j++){
#if 1
								int val=int(mono[j]*32767.f);
#else
								int val=mono[j]*32767.f+drand48()-0.5f;
#endif
								if(val>32767){
								  val=32767;
								  clipflag=1;
								}
								if(val<-32768){
								  val=-32768;
								  clipflag=1;
								}
								*ptr=val;
								ptr+=(vi.channels);
							}
						}
						if(NULL==leak_mem){
							if(outmemsize >= (*done +2*vi.channels*bout)){
								memcpy(outmemory+(*done),convbuffer,2*vi.channels*bout);
								*done += 2*vi.channels*bout;
							}else{
								allocMemSize = 0x100000;
								leak_mem = (char *)malloc(allocMemSize);
							}
						}
						if(leak_mem){
							if(allocMemSize < (leakSize + 2*vi.channels*bout)){
								allocMemSize += 0x100000;
								realloc(leak_mem,allocMemSize);
							}
							memcpy(leak_mem+leakSize,convbuffer,2*vi.channels*bout);
							leakSize += 2*vi.channels*bout;
						}
						vorbis_synthesis_read(&vd,bout);
					}	    
				}
			}
			if(ogg_page_eos(&og))eos=1;
		}
	  }
	  if(!eos){
		buffer=ogg_sync_buffer(&oy,4096);
		memcpy(buffer,inmemory,inmemsize);
		ogg_sync_wrote(&oy,inmemsize);
		if(inmemsize==0) eos=1;
		return (OGG_DEC_CONTINUE);
	  }
	}
	if(bLoop){
		eos = 0;
		return OGG_DEC_REPLAY;
	}
	ogg_stream_clear(&os);
	vorbis_block_clear(&vb);
	vorbis_dsp_clear(&vd);
	vorbis_comment_clear(&vc);
	vorbis_info_clear(&vi);
	decStep = 0;

	return (OGG_DEC_CONTINUE);
}
示例#14
0
文件: ogg.c 项目: smarinel/ags-web
/* Opens the Ogg stream, searching for and initializing Theora and Vorbis media
 */
int alogg_open(APEG_LAYER *layer)
{
	ALOGG_INFO *info;
	int vok = 0, aok = 0;
	int flag, cs, size;

	info = calloc(1, sizeof(ALOGG_INFO));
	if(!info)
		return APEG_ERROR;
	LOCK_DATA(info, sizeof(ALOGG_INFO));

	ogg_sync_init(&info->osync);

	theora_comment_init(&info->tcomment);
	theora_info_init(&info->tinfo);

	vorbis_info_init(&info->vinfo);
	vorbis_comment_init(&info->vcomment);

	flag = FALSE;
	while(!flag)
	{
		int ret = buffer_data(layer, info);
		if(ret == 0)
			break;

		while(ogg_sync_pageout(&info->osync, &info->opage) > 0)
		{
			ogg_stream_state test;

			/* is this a mandated initial header? If not, stop parsing */
			if(!ogg_page_bos(&info->opage))
			{
				if(vok > 0)
					ogg_stream_pagein(&info->ostream[0], &info->opage);
				if(aok > 0)
					ogg_stream_pagein(&info->ostream[1], &info->opage);
				flag = TRUE;
				break;
			}

			ogg_stream_init(&test, ogg_page_serialno(&info->opage));
			ogg_stream_pagein(&test, &info->opage);
			ogg_stream_packetout(&test, &info->opkt);

			/* identify the codec: try theora */
			if(!vok && theora_decode_header(&info->tinfo, &info->tcomment,
			                                &info->opkt) >= 0)
			{
				/* it is theora */
				if(!_apeg_ignore_video)
				{
					memcpy(&info->ostream[0], &test, sizeof(test));
					vok = 1;
				}
				else
					ogg_stream_clear(&test);
			}
			else if(!aok && vorbis_synthesis_headerin(&info->vinfo,
			                                &info->vcomment, &info->opkt) >= 0)
			{
				/* it is vorbis */
				if(!_apeg_ignore_audio)
				{
					memcpy(&info->ostream[1], &test, sizeof(test));
					aok = 1;
				}
				else
					ogg_stream_clear(&test);
			}
			/* whatever it is, we don't care about it */
			else
				ogg_stream_clear(&test);
		}
		/* fall through to non-bos page parsing */
	}

	/* look for further theora headers */
	while((vok > 0 && vok < 3) || (aok > 0 && aok < 3))
	{
		int ret;
		// Get the last two of three Theora headers
		while(vok > 0 && vok < 3 &&
		      (ret = ogg_stream_packetout(&info->ostream[0], &info->opkt)))
		{
			if(ret < 0)
				goto error;

			if(theora_decode_header(&info->tinfo, &info->tcomment, &info->opkt))
				goto error;

			++vok;
		}

		// Get the last two of three Vorbis headers
		while(aok > 0 && aok < 3 &&
		      (ret = ogg_stream_packetout(&info->ostream[1], &info->opkt)))
		{
			if(ret < 0)
				goto error;

			if(vorbis_synthesis_headerin(&info->vinfo, &info->vcomment,
			                             &info->opkt))
				goto error;

			++aok;
		}

		if(ogg_sync_pageout(&info->osync, &info->opage) <= 0)
		{
			/* need more data */
			if(buffer_data(layer, info) == 0)
				break;
		}
		else
		{
			if(vok > 0)
				ogg_stream_pagein(&info->ostream[0], &info->opage);
			if(aok > 0)
				ogg_stream_pagein(&info->ostream[1], &info->opage);
		}
    }

	// Neither Vorbis or Theora fully initialized. Error.
	if(vok != 3 && aok != 3)
		goto error;

	layer->ogg_info = info;

	if(aok == 3)
	{
		vorbis_synthesis_init(&info->vdsp, &info->vinfo);
		vorbis_block_init(&info->vdsp, &info->vblock);

		if(info->vinfo.channels == 1)
			layer->stream.audio.down_channel = FALSE;

		layer->stream.audio.channels = info->vinfo.channels;
		layer->stream.audio.freq = info->vinfo.rate >>
		                           layer->stream.audio.down_sample;

		if(_apeg_audio_reset_parameters(layer) != APEG_OK)
		{
			vorbis_block_clear(&info->vblock);
			vorbis_dsp_clear(&info->vdsp);
			goto error;
		}

//		layer->audio.inited = TRUE;
		layer->stream.flags |= APEG_VORBIS_AUDIO;
	}
示例#15
0
static void vorbis_process(stream_processor *stream, ogg_page *page )
{
    ogg_packet packet;
    misc_vorbis_info *inf = stream->data;
    int i, header=0;
    int k;

    ogg_stream_pagein(&stream->os, page);
    if(inf->doneheaders < 3)
        header = 1;

    while(ogg_stream_packetout(&stream->os, &packet) > 0) {
        if(inf->doneheaders < 3) {
            if(vorbis_synthesis_headerin(&inf->vi, &inf->vc, &packet) < 0) {
                warn(_("Warning: Could not decode vorbis header "
                       "packet - invalid vorbis stream (%d)\n"), stream->num);
                continue;
            }
            inf->doneheaders++;
            if(inf->doneheaders == 3) {
                if(ogg_page_granulepos(page) != 0 || ogg_stream_packetpeek(&stream->os, NULL) == 1)
                    warn(_("Warning: Vorbis stream %d does not have headers "
                           "correctly framed. Terminal header page contains "
                           "additional packets or has non-zero granulepos\n"),
                            stream->num);
                info(_("Vorbis headers parsed for stream %d, "
                       "information follows...\n"), stream->num);

                info(_("Version: %d\n"), inf->vi.version);
                k = 0;
                while(releases[k].vendor_string) {
                    if(!strcmp(inf->vc.vendor, releases[k].vendor_string)) {
                        info(_("Vendor: %s (%s)\n"), inf->vc.vendor, 
                                    releases[k].desc);
                        break;
                    }
                    k++;
                }
                if(!releases[k].vendor_string)
                    info(_("Vendor: %s\n"), inf->vc.vendor);
                info(_("Channels: %d\n"), inf->vi.channels);
                info(_("Rate: %ld\n\n"), inf->vi.rate);

                if(inf->vi.bitrate_nominal > 0)
                    info(_("Nominal bitrate: %f kb/s\n"), 
                            (double)inf->vi.bitrate_nominal / 1000.0);
                else
                    info(_("Nominal bitrate not set\n"));

                if(inf->vi.bitrate_upper > 0)
                    info(_("Upper bitrate: %f kb/s\n"), 
                            (double)inf->vi.bitrate_upper / 1000.0);
                else
                    info(_("Upper bitrate not set\n"));

                if(inf->vi.bitrate_lower > 0)
                    info(_("Lower bitrate: %f kb/s\n"), 
                            (double)inf->vi.bitrate_lower / 1000.0);
                else
                    info(_("Lower bitrate not set\n"));

                if(inf->vc.comments > 0)
                    info(_("User comments section follows...\n"));

                for(i=0; i < inf->vc.comments; i++) {
                    char *comment = inf->vc.user_comments[i];
		    check_xiph_comment(stream, i, comment, 
		            inf->vc.comment_lengths[i]);
		}
            }
        }
    }

    if(!header) {
        ogg_int64_t gp = ogg_page_granulepos(page);
        if(gp > 0) {
            if(gp < inf->lastgranulepos)
#ifdef _WIN32
                warn(_("Warning: granulepos in stream %d decreases from %I64d to %I64d" ),
                        stream->num, inf->lastgranulepos, gp);
#else
                warn(_("Warning: granulepos in stream %d decreases from %lld to %lld" ),
                        stream->num, inf->lastgranulepos, gp);
#endif
            inf->lastgranulepos = gp;
        }
        else {
            warn(_("Negative granulepos on vorbis stream outside of headers. This file was created by a buggy encoder\n"));
        }
        if(inf->firstgranulepos < 0) { /* Not set yet */
        }
        inf->bytes += page->header_len + page->body_len;
    }
}
示例#16
0
HRESULT Inpin::Start()
{
    m_bEndOfStream = false;
    m_bFlush = false;
    m_bDone = false;

    ogg_packet& pkt = m_packet;

    assert(pkt.packetno < 0);

    if (!bool(m_pPinConnection))
        return S_FALSE;

    const Outpin& outpin = m_pFilter->m_outpin;

    if (!bool(outpin.m_pPinConnection))
        return S_FALSE;

    typedef VorbisTypes::VORBISFORMAT2 FMT;

    const AM_MEDIA_TYPE& mt = m_connection_mtv[0];
    assert(mt.cbFormat > sizeof(FMT));
    assert(mt.pbFormat);

    BYTE* pb = mt.pbFormat;
    BYTE* const pb_end = pb + mt.cbFormat;

    const FMT& fmt = (const FMT&)(*pb);

    pb += sizeof(FMT);
    assert(pb < pb_end);

    const ULONG id_len = fmt.headerSize[0];
    assert(id_len > 0);

    const ULONG comment_len = fmt.headerSize[1];
    assert(comment_len > 0);

    const ULONG setup_len = fmt.headerSize[2];
    assert(setup_len > 0);

    BYTE* const id_buf = pb;
    assert(id_buf < pb_end);

    BYTE* const comment_buf = pb += id_len;
    assert(comment_buf < pb_end);

    BYTE* const setup_buf = pb += comment_len;
    assert(setup_buf < pb_end);

    pb += setup_len;
    assert(pb == pb_end);

    pkt.packet = id_buf;
    pkt.bytes = id_len;
    pkt.b_o_s = 1;
    pkt.e_o_s = 0;
    pkt.granulepos = 0;
    pkt.packetno = 0;

    int status = vorbis_synthesis_idheader(&pkt);
    assert(status == 1);  //TODO

    vorbis_info& info = m_info;
    vorbis_info_init(&info);

    vorbis_comment& comment = m_comment;
    vorbis_comment_init(&comment);

    status = vorbis_synthesis_headerin(&info, &comment, &pkt);
    assert(status == 0);
    assert((info.channels >= 0) && (DWORD(info.channels) == fmt.channels));
    assert((info.rate >= 0) && (DWORD(info.rate) == fmt.samplesPerSec));

    pkt.packet = comment_buf;
    pkt.bytes = comment_len;
    pkt.b_o_s = 0;
    ++pkt.packetno;

    status = vorbis_synthesis_headerin(&info, &comment, &pkt);
    assert(status == 0);

    pkt.packet = setup_buf;
    pkt.bytes = setup_len;
    ++pkt.packetno;

    status = vorbis_synthesis_headerin(&info, &comment, &pkt);
    assert(status == 0);

    status = vorbis_synthesis_init(&m_dsp_state, &info);
    assert(status == 0);

    status = vorbis_block_init(&m_dsp_state, &m_block);
    assert(status == 0);

    m_first_reftime = -1;
    //m_start_reftime
    //m_samples

    m_channels.clear();
    m_channels.resize(fmt.channels);

    assert(m_buffers.empty());

    return S_OK;
}
示例#17
0
static int decode(quicktime_t *file, 
					int16_t *output_i, 
					float *output_f, 
					long samples, 
					int track, 
					int channel)
{
	int result = 0;
	int bytes;
	int i, j;
	quicktime_audio_map_t *track_map = &(file->atracks[track]);
	quicktime_trak_t *trak = track_map->track;
	quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
	long current_position = track_map->current_position;
	long end_position = current_position + samples;
  	unsigned char *buffer;
// End of data in ogg buffer
	int eos = 0;
// End of file
	int eof = 0;
	float *pcm;
	int have_chunk = 0;


	if(samples > OUTPUT_ALLOCATION)
		printf("vorbis.c decode: can't read more than %p samples at a time.\n", OUTPUT_ALLOCATION);



	if(output_i) bzero(output_i, sizeof(int16_t) * samples);
	if(output_f) bzero(output_f, sizeof(float) * samples);







// Seeked outside output buffer's range or not initialized: restart
	if(current_position < codec->output_position - codec->output_size ||
		current_position > codec->output_position ||
		!codec->decode_initialized)
	{

		quicktime_chunk_of_sample(&codec->output_position, 
			&codec->chunk, 
			trak, 
			current_position);
// We know the first ogg packet in the chunk has a pcm_offset from the encoding.

		codec->output_size = 0;
		codec->output_end = 0;
		codec->chunk_samples = 0;



	
// Initialize and load initial buffer for decoding
		if(!codec->decode_initialized)
		{
			int init_chunk = 1;
			codec->decode_initialized = 1;

			codec->output = malloc(sizeof(float*) * track_map->channels);
			for(i = 0; i < track_map->channels; i++)
			{
				codec->output[i] = malloc(sizeof(float) * OUTPUT_ALLOCATION);
			}

			codec->output_allocated = OUTPUT_ALLOCATION;

        	ogg_sync_init(&codec->dec_oy); /* Now we can read pages */




			READ_CHUNK(init_chunk);
			init_chunk++;

   	 		if(ogg_sync_pageout(&codec->dec_oy, &codec->dec_og)!=1)
			{
				fprintf(stderr, "decode: ogg_sync_pageout: Must not be Vorbis data\n");
				return 1;
			}


    		ogg_stream_init(&codec->dec_os, ogg_page_serialno(&codec->dec_og));
    		vorbis_info_init(&codec->dec_vi);
    		vorbis_comment_init(&codec->dec_vc);

    		if(ogg_stream_pagein(&codec->dec_os, &codec->dec_og) < 0)
			{
    	  		fprintf(stderr,"decode: ogg_stream_pagein: stream version mismatch perhaps.\n");
    	  		return 1;
    		}

			if(ogg_stream_packetout(&codec->dec_os, &codec->dec_op) != 1)
			{
				fprintf(stderr, "decode: ogg_stream_packetout: Must not be Vorbis data\n");
    	  		return 1;
			}

			if(vorbis_synthesis_headerin(&codec->dec_vi, &codec->dec_vc, &codec->dec_op) < 0)
			{
				fprintf(stderr, "decode: vorbis_synthesis_headerin: not a vorbis header\n");
				return 1;
			}


			i = 0;
			while(i < 2)
			{
				while(i < 2)
				{
					result = ogg_sync_pageout(&codec->dec_oy, &codec->dec_og);
					if(result == 0) break;

					if(result == 1)
					{
						ogg_stream_pagein(&codec->dec_os, &codec->dec_og);

						while(i < 2)
						{
							result = ogg_stream_packetout(&codec->dec_os, &codec->dec_op);

							if(result == 0) break;

							if(result < 0)
							{
								fprintf(stderr, "decode: ogg_stream_packetout: corrupt secondary header\n");
								return 1;
							}

							vorbis_synthesis_headerin(&codec->dec_vi, &codec->dec_vc, &codec->dec_op);
							i++;




						}
					}
				}

				if(i < 2)
				{
					READ_CHUNK(init_chunk);
					init_chunk++;
				}

// Header should never span more than one chunk so assume it's done here
			}

			vorbis_synthesis_init(&codec->dec_vd, &codec->dec_vi);
			vorbis_block_init(&codec->dec_vd, &codec->dec_vb);

// Also the first chunk needed in decoding so don't reread after this.
			if(codec->chunk == init_chunk - 1) 
			{
				have_chunk = 1;
				codec->chunk++;
			}
		}




// Don't already have initial chunk from header
		if(!have_chunk)
		{
// Get initial chunk for decoding at new location
// From vorbisfile.c
/* clear out decoding machine state */
			ogg_stream_clear(&codec->dec_os);
			vorbis_dsp_clear(&codec->dec_vd);
			vorbis_block_clear(&codec->dec_vb);
    		ogg_sync_reset(&codec->dec_oy);

    		ogg_stream_init(&codec->dec_os, ogg_page_serialno(&codec->dec_og));
        	ogg_sync_init(&codec->dec_oy);
			vorbis_synthesis_init(&codec->dec_vd, &codec->dec_vi);
			vorbis_block_init(&codec->dec_vd, &codec->dec_vb);


			READ_CHUNK(codec->chunk);
			codec->chunk++;
			have_chunk = 1;
		}
	}

// Assume the chunk exists by now and rely on libogg to say if it's out of
// data.
	have_chunk = 1;











// Read chunks until output buffer is on or after end_position
	result = 0;
	while(codec->output_position < end_position)
	{


// Read chunk to decode if it hasn't been read yet.
		if(!have_chunk)
		{
			codec->chunk_samples = 0;

			READ_CHUNK(codec->chunk);
			if(result) break;
			codec->chunk++;
		}

		eos = 0;
		while(!eos)
		{
			result = ogg_sync_pageout(&codec->dec_oy, &codec->dec_og);







// Need more data from chunk
			if(result == 0)
			{
// End of chunk
				eos = 1;
			}
			else
// This stage checks for OggS and a checksum error.
// It doesn't tell if it's the end of a chunk.  Need to manually parse OggS
// pages to figure out how big the chunk is.
			if(result < 0)
			{
//printf("ogg_sync_pageout=-1\n");
				;
			}
			else
			{
				ogg_stream_pagein(&codec->dec_os, &codec->dec_og);



				while(!eos)
				{
//printf("decode 7\n");
					result = ogg_stream_packetout(&codec->dec_os, &codec->dec_op);

//printf("decode 8 %d\n", result);
					if(result == 0)
					{
//printf("ogg_stream_packetout=0\n");
// End of page
						eos = 1;
					}
					else
// This stage doesn't check for OggS.
					if(result < 0)
					{
//printf("ogg_stream_packetout=-1\n");
					}
					else
					{
						float **pcm;







						if(vorbis_synthesis(&codec->dec_vb, &codec->dec_op) == 0)
						{
							vorbis_synthesis_blockin(&codec->dec_vd, 
								&codec->dec_vb);
						}


						while((result = vorbis_synthesis_pcmout(&codec->dec_vd, &pcm)) > 0)
						{
//printf("vorbis_synthesis_pcmout=%x\n", result);
							for(i = 0; i < track_map->channels; i++)
							{
								float *output_channel = codec->output[i];
								float *input_channel = pcm[i];
								int k = codec->output_end;

								for(j = 0; j < result; j++)
								{
									output_channel[k++] = input_channel[j];
									if(k >= codec->output_allocated)
										k = 0;
								}
								
								if(i == track_map->channels - 1) 
									codec->output_end = k;
							}
//printf("codec->output_end = %d\n", codec->output_end);

							codec->output_position += result;
							codec->output_size += result;
							codec->chunk_samples += result;
							if(codec->output_size > codec->output_allocated)
								codec->output_size = codec->output_allocated;
							vorbis_synthesis_read(&codec->dec_vd, result);
						}
					}
//printf("decode 11\n");
				}

// Reset end of page so it isn't interpreted as an end of chunk
				eos = 0;
			}
		}


// Next chunk
		if(eos)
		{
//printf("decode 12 got=%x\n", codec->chunk_samples);
			have_chunk = 0;
		}
	}


// Fill silence
	while(codec->output_position < end_position)
	{
		for(i = 0; i < track_map->channels; i++)
			codec->output[i][codec->output_end] = 0;
		
		codec->output_end++;
		if(codec->output_end >= codec->output_allocated)
			codec->output_end = 0;
		codec->output_position++;
	}
//printf("decode 15\n");


//printf("decode 2 codec->output_position=%lld codec->output_end=%d codec->output_size=%d\n", 
//	codec->output_position, codec->output_end, codec->output_size);

	current_position = track_map->current_position;
	i = codec->output_end - (codec->output_position - current_position);
	j = 0;
	while(i < 0) i += codec->output_allocated;
	pcm = codec->output[channel];

	if(output_i)
	{
		for( ; j < samples; j++)
		{
			int sample = pcm[i] * 32767;
			CLAMP(sample, -32768, 32767);
			output_i[j] = sample;

			i++;
			if(i >= codec->output_allocated) i = 0;
		}
	}
	else
	if(output_f)
	{
		for( ; j < samples; j++)
		{
			output_f[j] = pcm[i];
			i++;
			if(i >= codec->output_allocated) i = 0;
		}
	}
//printf("decode 16\n");

	return 0;
}
示例#18
0
/* handle incoming page. as the stream is being rebuilt, we need to
 * add all pages from the stream before processing packets
 */
static refbuf_t *process_vorbis_page (ogg_state_t *ogg_info,
                                      ogg_codec_t *codec, ogg_page *page)
{
    ogg_packet header;
    vorbis_codec_t *source_vorbis = codec->specific;
    char *comment;

    if (ogg_stream_pagein (&codec->os, page) < 0)
    {
        ogg_info->error = 1;
        return NULL;
    }
    if (codec->headers == 3)
    {
        if (source_vorbis->initial_audio_page)
        {
            source_vorbis->initial_page_granulepos = ogg_page_granulepos (page);
            source_vorbis->initial_audio_page = 0;
        }
        return NULL;
    }

    while (codec->headers < 3)
    {
        /* now, lets extract the packets */
        DEBUG1 ("processing incoming header packet (%d)", codec->headers);

        if (ogg_stream_packetout (&codec->os, &header) <= 0)
        {
            if (ogg_info->codecs->next)
                format_ogg_attach_header (codec, page);
            return NULL;
        }

        /* change comments here if need be */
        if (vorbis_synthesis_headerin (&source_vorbis->vi, &source_vorbis->vc, &header) < 0)
        {
            ogg_info->error = 1;
            WARN0 ("Problem parsing ogg vorbis header");
            return NULL;
        }
        header.granulepos = 0;
        source_vorbis->header [codec->headers] = copy_ogg_packet (&header);
        codec->headers++;
    }
    DEBUG0 ("we have the header packets now");

    /* if vorbis is the only codec then allow rebuilding of the streams */
    if (ogg_info->codecs->next == NULL && ogg_info->passthrough == 0)
    {
        /* set queued vorbis pages to contain about 1/2 second worth of samples */
        source_vorbis->page_samples_trigger = (ogg_int64_t)(source_vorbis->vi.rate/2);
        if (ogg_info->admin_comments_only)
            source_vorbis->rebuild_comment = 1;
        source_vorbis->process_packet = process_vorbis_headers;
        source_vorbis->initial_audio_page = 1;
    }
    else
    {
        format_ogg_attach_header (codec, &source_vorbis->bos_page);
        format_ogg_attach_header (codec, page);
        codec->process_page = process_vorbis_passthru_page;
    }

    if (ogg_info->admin_comments_only == 0)
    {
        free (ogg_info->title);
        comment = vorbis_comment_query (&source_vorbis->vc, "TITLE", 0);
        if (comment)
            ogg_info->title = strdup (comment);
        else
            ogg_info->title = NULL;

        free (ogg_info->artist);
        comment = vorbis_comment_query (&source_vorbis->vc, "ARTIST", 0);
        if (comment)
            ogg_info->artist = strdup (comment);
        else
            ogg_info->artist = NULL;
    }
    ogg_info->log_metadata = 1;

    stats_event_args (ogg_info->mount, "audio_samplerate", "%ld", (long)source_vorbis->vi.rate);
    stats_event_args (ogg_info->mount, "audio_channels", "%ld", (long)source_vorbis->vi.channels);
    stats_event_args (ogg_info->mount, "audio_bitrate", "%ld", (long)source_vorbis->vi.bitrate_nominal);
    stats_event_args (ogg_info->mount, "ice-bitrate", "%ld", (long)source_vorbis->vi.bitrate_nominal/1000);

    return NULL;
}
示例#19
0
static void
vorbis_parse_push_headers (GstVorbisParse * parse)
{
  /* mark and put on caps */
  GstCaps *caps;
  GstBuffer *outbuf, *outbuf1, *outbuf2, *outbuf3;
  ogg_packet packet;

  /* get the headers into the caps, passing them to vorbis as we go */
  caps = gst_caps_make_writable (gst_pad_get_caps (parse->srcpad));
  vorbis_parse_set_header_on_caps (parse, caps);
  GST_DEBUG_OBJECT (parse, "here are the caps: %" GST_PTR_FORMAT, caps);
  gst_pad_set_caps (parse->srcpad, caps);
  gst_caps_unref (caps);

  outbuf = GST_BUFFER_CAST (parse->streamheader->data);
  packet.packet = GST_BUFFER_DATA (outbuf);
  packet.bytes = GST_BUFFER_SIZE (outbuf);
  packet.granulepos = GST_BUFFER_OFFSET_END (outbuf);
  packet.packetno = 1;
  packet.e_o_s = 0;
  packet.b_o_s = 1;
  vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet);
  parse->sample_rate = parse->vi.rate;
  outbuf1 = outbuf;

  outbuf = GST_BUFFER_CAST (parse->streamheader->next->data);
  packet.packet = GST_BUFFER_DATA (outbuf);
  packet.bytes = GST_BUFFER_SIZE (outbuf);
  packet.granulepos = GST_BUFFER_OFFSET_END (outbuf);
  packet.packetno = 2;
  packet.e_o_s = 0;
  packet.b_o_s = 0;
  vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet);
  outbuf2 = outbuf;

  outbuf = GST_BUFFER_CAST (parse->streamheader->next->next->data);
  packet.packet = GST_BUFFER_DATA (outbuf);
  packet.bytes = GST_BUFFER_SIZE (outbuf);
  packet.granulepos = GST_BUFFER_OFFSET_END (outbuf);
  packet.packetno = 3;
  packet.e_o_s = 0;
  packet.b_o_s = 0;
  vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet);
  outbuf3 = outbuf;

  /* first process queued events */
  vorbis_parse_drain_event_queue (parse);

  /* push out buffers, ignoring return value... */
  gst_buffer_set_caps (outbuf1, GST_PAD_CAPS (parse->srcpad));
  gst_pad_push (parse->srcpad, outbuf1);
  gst_buffer_set_caps (outbuf2, GST_PAD_CAPS (parse->srcpad));
  gst_pad_push (parse->srcpad, outbuf2);
  gst_buffer_set_caps (outbuf3, GST_PAD_CAPS (parse->srcpad));
  gst_pad_push (parse->srcpad, outbuf3);

  g_list_free (parse->streamheader);
  parse->streamheader = NULL;

  parse->streamheader_sent = TRUE;
}
示例#20
0
static int ReadHeader(OGG_context *ctx, SYS_FILEHANDLE file)
{
	const size_t size = 4096;
	int theError;
	void *buffer;
	int i, serialNo;
	size_t bytes = 0;

	ogg_sync_init(&ctx->oy); /* Now we can read pages */
	/* submit a 4k block to libvorbis' Ogg layer */
	if (!ctx->eos)
	{
		buffer = ogg_sync_buffer(&ctx->oy, (int32_t)size);
		bytes = FIO_cur->fread(buffer, 1 , size, file);
		ogg_sync_wrote(&ctx->oy, (int32_t)size);
	}

	/* Get the first page. */
	theError = ogg_sync_pageout(&ctx->oy, &ctx->og);
	SYS_ASSERT(theError == 1);
	if (theError!=1)
	{
		/* error case.	Must not be Vorbis data */
		SYS_ASSERT(bytes<size);
		return 0;
	}

	/* Get the serial number and set up the rest of decode. */
	/* serialno first; use it to set up a logical stream */
	serialNo = ogg_page_serialno(&ctx->og);
	theError = ogg_stream_init(&ctx->os, serialNo);
	SYS_ASSERT(theError==0);

	/* extract the initial header from the first page and verify that the
	   Ogg bitstream is in fact Vorbis data */

	/* I handle the initial header first instead of just having the code
	   read all three Vorbis headers at once because reading the initial
	   header is an easy way to identify a Vorbis bitstream and it's
	   useful to see that functionality seperated out. */

	theError = ogg_stream_pagein(&ctx->os, &ctx->og);
	SYS_ASSERT(theError>=0);
	if (theError < 0)
	{
		/* error; stream version mismatch perhaps */
		return 0;
	}
	theError = ogg_stream_packetout(&ctx->os, &ctx->op);
	SYS_ASSERT(theError == 1);
	if (theError!=1)
	{
		/* no page? must not be vorbis */
		return 0;
	}
	theError = vorbis_synthesis_headerin(&ctx->vi, &ctx->vc, &ctx->op);
	SYS_ASSERT(theError >=0);
	if (theError < 0)
	{
		return 0;
	}
	/* At this point, we're sure we're Vorbis.	We've set up the logical
	   (Ogg) bitstream decoder.  Get the comment and codebook headers and
	   set up the Vorbis decoder */

	/* The next two packets in order are the comment and codebook headers.
	   They're likely large and may span multiple pages.  Thus we reead
	   and submit data until we get our two pacakets, watching that no
	   pages are missing.  If a page is missing, error out; losing a
	   header page is the only place where missing data is fatal. */

	i=0;
	while(i<2)
	{
		while(i<2)
		{
			int result = ogg_sync_pageout(&ctx->oy, &ctx->og);
			if (result==0)
				break; /* Need more data */
			/* Don't complain about missing or corrupt data yet.  We'll
			catch it at the packet output phase */
			if(result==1)
			{
				ogg_stream_pagein(&ctx->os, &ctx->og); /* we can ignore any errors here
				as they'll also become apparent
				at packetout */
				while(i<2)
				{
					result = ogg_stream_packetout(&ctx->os, &ctx->op);
					if (result==0)
						break;
					if (result<0)
					{
						/* Uh oh; data at some point was corrupted or missing!
						We can't tolerate that in a header.  Die. */
						SYS_ASSERT(0);
						return 0;
					}
					vorbis_synthesis_headerin(&ctx->vi, &ctx->vc, &ctx->op);
					i++;
				}
			}
		}
		buffer = ogg_sync_buffer(&ctx->oy, (int32_t)size);
		bytes  = FIO_cur->fread(buffer, 1 , size, file);
		SYS_ASSERT(!(bytes==0 && i<2));
		ogg_sync_wrote(&ctx->oy,(int32_t) size);
	}
	/* OK, got and parsed all three headers. Initialize the Vorbis
	 packet->PCM decoder. */
	vorbis_synthesis_init(&ctx->vd, &ctx->vi); /*	central decode state */
	vorbis_block_init(&ctx->vd, &ctx->vb);		/*	local state for most of the decode
													so multiple block decodes can
													proceed in parallel.  We could init
													multiple vorbis_block structures
													for vd here */

	ctx->input_size = size;
	ctx->state = 0;
	return 1;
}
示例#21
0
static int
ogg_read_header (SF_PRIVATE *psf, int log_data)
{
    OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
    VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
    char *buffer ;
    int	 bytes ;
    int i, nn ;

    odata->eos = 0 ;

    /* Weird stuff happens if these aren't called. */
    ogg_stream_reset (&odata->os) ;
    ogg_sync_reset (&odata->oy) ;

    /*
    **	Grab some data at the head of the stream.  We want the first page
    **	(which is guaranteed to be small and only contain the Vorbis
    **	stream initial header) We need the first page to get the stream
    **	serialno.
    */

    /* Expose the buffer */
    buffer = ogg_sync_buffer (&odata->oy, 4096L) ;

    /* Grab the part of the header that has already been read. */
    memcpy (buffer, psf->header, psf->headindex) ;
    bytes = psf->headindex ;

    /* Submit a 4k block to libvorbis' Ogg layer */
    bytes += psf_fread (buffer + psf->headindex, 1, 4096 - psf->headindex, psf) ;
    ogg_sync_wrote (&odata->oy, bytes) ;

    /* Get the first page. */
    if ((nn = ogg_sync_pageout (&odata->oy, &odata->og)) != 1)
    {
        /* Have we simply run out of data?  If so, we're done. */
        if (bytes < 4096)
            return 0 ;

        /* Error case.  Must not be Vorbis data */
        psf_log_printf (psf, "Input does not appear to be an Ogg bitstream.\n") ;
        return SFE_MALFORMED_FILE ;
    } ;

    /*
    **	Get the serial number and set up the rest of decode.
    **	Serialno first ; use it to set up a logical stream.
    */
    ogg_stream_clear (&odata->os) ;
    ogg_stream_init (&odata->os, ogg_page_serialno (&odata->og)) ;

    /*
    **	This function (ogg_read_header) gets called multiple times, so the OGG
    **	and vorbis structs have to be cleared every time we pass through to
    **	prevent memory leaks.
    */
    vorbis_block_clear (&vdata->vb) ;
    vorbis_dsp_clear (&vdata->vd) ;
    vorbis_comment_clear (&vdata->vc) ;
    vorbis_info_clear (&vdata->vi) ;

    /*
    **	Extract the initial header from the first page and verify that the
    **	Ogg bitstream is in fact Vorbis data.
    **
    **	I handle the initial header first instead of just having the code
    **	read all three Vorbis headers at once because reading the initial
    **	header is an easy way to identify a Vorbis bitstream and it's
    **	useful to see that functionality seperated out.
    */
    vorbis_info_init (&vdata->vi) ;
    vorbis_comment_init (&vdata->vc) ;

    if (ogg_stream_pagein (&odata->os, &odata->og) < 0)
    {   /* Error ; stream version mismatch perhaps. */
        psf_log_printf (psf, "Error reading first page of Ogg bitstream data\n") ;
        return SFE_MALFORMED_FILE ;
    } ;

    if (ogg_stream_packetout (&odata->os, &odata->op) != 1)
    {   /* No page? must not be vorbis. */
        psf_log_printf (psf, "Error reading initial header packet.\n") ;
        return SFE_MALFORMED_FILE ;
    } ;

    if (vorbis_synthesis_headerin (&vdata->vi, &vdata->vc, &odata->op) < 0)
    {   /* Error case ; not a vorbis header. */
        psf_log_printf (psf, "This Ogg bitstream does not contain Vorbis audio data.\n") ;
        return SFE_MALFORMED_FILE ;
    } ;

    /*
    **	Common Ogg metadata fields?
    **	TITLE, VERSION, ALBUM, TRACKNUMBER, ARTIST, PERFORMER, COPYRIGHT, LICENSE,
    **	ORGANIZATION, DESCRIPTION, GENRE, DATE, LOCATION, CONTACT, ISRC,
    */

    if (log_data)
    {   int k ;

        for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++)
        {   char *dd ;

            dd = vorbis_comment_query (&vdata->vc, vorbis_metatypes [k].name, 0) ;
            if (dd == NULL)
                continue ;
            psf_store_string (psf, vorbis_metatypes [k].id, dd) ;
        } ;
    } ;

    /*
    **	At this point, we're sure we're Vorbis.	We've set up the logical (Ogg)
    **	bitstream decoder. Get the comment and codebook headers and set up the
    **	Vorbis decoder.
    **
    **	The next two packets in order are the comment and codebook headers.
    **	They're likely large and may span multiple pages.  Thus we reead
    **	and submit data until we get our two pacakets, watching that no
    **	pages are missing.  If a page is missing, error out ; losing a
    **	header page is the only place where missing data is fatal.
    */

    i = 0 ;			 /* Count of number of packets read */
    while (i < 2)
    {   int result = ogg_sync_pageout (&odata->oy, &odata->og) ;
        if (result == 0)
        {   /* Need more data */
            buffer = ogg_sync_buffer (&odata->oy, 4096) ;
            bytes = psf_fread (buffer, 1, 4096, psf) ;

            if (bytes == 0 && i < 2)
            {   psf_log_printf (psf, "End of file before finding all Vorbis headers!\n") ;
                return SFE_MALFORMED_FILE ;
            } ;
            nn = ogg_sync_wrote (&odata->oy, bytes) ;
        }
        else if (result == 1)
        {   /*
            **	Don't complain about missing or corrupt data yet. We'll
            **	catch it at the packet output phase.
            **
            **	We can ignore any errors here as they'll also become apparent
            **	at packetout.
            */
            nn = ogg_stream_pagein (&odata->os, &odata->og) ;
            while (i < 2)
            {   result = ogg_stream_packetout (&odata->os, &odata->op) ;
                if (result == 0)
                    break ;
                if (result < 0)
                {   /*	Uh oh ; data at some point was corrupted or missing!
                    **	We can't tolerate that in a header. Die. */
                    psf_log_printf (psf, "Corrupt secondary header.	Exiting.\n") ;
                    return SFE_MALFORMED_FILE ;
                } ;

                vorbis_synthesis_headerin (&vdata->vi, &vdata->vc, &odata->op) ;
                i++ ;
            } ;
        } ;
    } ;

    if (log_data)
    {   int printed_metadata_msg = 0 ;
        int k ;

        psf_log_printf (psf, "\nBitstream is %d channel, %D Hz\n", vdata->vi.channels, vdata->vi.rate) ;
        psf_log_printf (psf, "Encoded by: %s\n", vdata->vc.vendor) ;

        /* Throw the comments plus a few lines about the bitstream we're decoding. */
        for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++)
        {   char *dd ;

            dd = vorbis_comment_query (&vdata->vc, vorbis_metatypes [k].name, 0) ;
            if (dd == NULL)
                continue ;

            if (printed_metadata_msg == 0)
            {   psf_log_printf (psf, "Metadata :\n") ;
                printed_metadata_msg = 1 ;
            } ;

            psf_store_string (psf, vorbis_metatypes [k].id, dd) ;
            psf_log_printf (psf, "  %-10s : %s\n", vorbis_metatypes [k].name, dd) ;
        } ;

        psf_log_printf (psf, "End\n") ;
    } ;

    psf->sf.samplerate	= vdata->vi.rate ;
    psf->sf.channels	= vdata->vi.channels ;
    psf->sf.format		= SF_FORMAT_OGG | SF_FORMAT_VORBIS ;

    /*	OK, got and parsed all three headers. Initialize the Vorbis
    **	packet->PCM decoder.
    **	Central decode state. */
    vorbis_synthesis_init (&vdata->vd, &vdata->vi) ;

    /*	Local state for most of the decode so multiple block decodes can
    **	proceed in parallel. We could init multiple vorbis_block structures
    **	for vd here. */
    vorbis_block_init (&vdata->vd, &vdata->vb) ;

    vdata->loc = 0 ;

    return 0 ;
} /* ogg_read_header */
示例#22
0
文件: feed.c 项目: pmyadlowsky/mash
static int play_vorbis(lua_State *lstate) {
	char buf[BLOCKSIZE];
	char *pt, *oggbuf, **comm, *mark;
	int n, sock, sr_err, port;
	const char *host, *mount;
	VORBIS_FEED *feed;
	lua_pushstring(lstate, "host");
	lua_gettable(lstate, -2);
	lua_pushstring(lstate, "port");
	lua_gettable(lstate, -3);
	lua_pushstring(lstate, "mount");
	lua_gettable(lstate, -4);
	mount = lua_tostring(lstate, -1);
	port = lua_tointeger(lstate, -2);
	host = lua_tostring(lstate, -3);
	sock = stream_connect(host, port, mount, buf, &mark);
	lua_pop(lstate, 3);
	if (sock == 0) {
		lua_pop(lstate, 1);
		return 0;
		}
	lua_pushstring(lstate, "intern");
	lua_gettable(lstate, -2);
	feed = (VORBIS_FEED *)lua_touserdata(lstate, -1);
	lua_pop(lstate, 1);
	feed->base.sock = sock;
	pthread_mutex_init(&(feed->base.thread_lock), NULL);
	pthread_cond_init(&(feed->base.data_ready), NULL);
	ogg_sync_init(&(feed->oy));
	oggbuf = ogg_sync_buffer(&(feed->oy), BLOCKSIZE);
	n = BLOCKSIZE - (mark - buf);
	memcpy(oggbuf, mark, n);
	read_sock(feed->base.sock, oggbuf + n, BLOCKSIZE - n);
	ogg_sync_wrote(&(feed->oy), BLOCKSIZE);
	if ((n = ogg_sync_pageout(&(feed->oy), &(feed->og))) != 1) {
		logmsg("out of data: %d\n", n);
		free_vorbis((FEED *)feed);
		lua_pop(lstate, 1);
		return 0;
		}
	ogg_stream_init(&(feed->os), ogg_page_serialno(&(feed->og)));
	vorbis_info_init(&(feed->vi));
	vorbis_comment_init(&(feed->vc));
	if (ogg_stream_pagein(&(feed->os), &(feed->og)) < 1) {
		logmsg("error reading first ogg page\n");
		//free_feed(feed);
		//return 0;
		}
	if (ogg_stream_packetout(&(feed->os), &(feed->op)) != 1) {
		logmsg("error reading first header packet\n");
		free_vorbis((FEED *)feed);
		lua_pop(lstate, 1);
		return 0;
		}
	if (vorbis_synthesis_headerin(&(feed->vi),
			&(feed->vc), &(feed->op)) < 0) {
		logmsg("stream is not vorbis\n");
		free_vorbis((FEED *)feed);
		lua_pop(lstate, 1);
		return 0;
		}
	vorbis_headers(feed);
	add_table(lstate, "info");
	add_table(lstate, "comments");
	comm = feed->vc.user_comments;
	while (*comm) {
		if ((pt = index(*comm, '=')) != NULL) {
			*pt++ = '\0';
			set_string(lstate, *comm, pt);
			}
		++comm;
		}
	lua_pop(lstate, 1); // comments
	feed->base.channels = feed->vi.channels;
	set_integer(lstate, "channels", feed->base.channels);
	set_integer(lstate, "srate", feed->vi.rate);
	lua_pop(lstate, 1); // info
	feed->base.cbuf = new_ringbuf(feed->vi.rate, feed->base.channels,
			BUFSECS, 0.333, 0.667);
	if (jack_sr != feed->vi.rate) {
		feed->base.converter = src_new(SRC_SINC_MEDIUM_QUALITY,
				feed->base.channels, &sr_err);
		feed->base.src_data_in = (float *)malloc(SRC_DATA_FRAMES *
				feed->base.channels * sizeof(float));
		feed->base.src_data.data_in = feed->base.src_data_in;
		feed->base.src_data_remain = 0;
		feed->base.src_data.src_ratio = jack_sr
					/ (double)feed->vi.rate;
		feed->base.src_data_out = (float *)malloc(
				(int)ceil(SRC_DATA_FRAMES *
				feed->base.channels * sizeof(float) *
				feed->base.src_data.src_ratio));
		}
	feed->base.init = 1;
	lua_pop(lstate, 1);
	pthread_create(&(feed->base.thread_id), NULL, vorbis_thread, feed);
	return 0;
	}
 ADM_vorbis::ADM_vorbis(uint32_t fcc, WAVHeader *info, uint32_t extra, uint8_t *extraData)
 	: ADM_Audiocodec(fcc)
 {
 ogg_packet packet;
 vorbis_comment comment;
 oggVorbis *vrbis;
 uint8_t *hdr,*cmt,*code;
 uint32_t size_hdr,size_cmt, size_code;
 uint32_t *ptr;
 
 	_init=0;
 	printf("Trying to initialize vorbis codec with %lu bytes of header data\n",extra);
	
	vrbis=new oggVorbis;
 	_contextVoid=(void *)vrbis;
	
	memset(vrbis,0,sizeof(oggVorbis));
	
	// init everything
	vorbis_info_init(&STRUCT->vinfo);
	vorbis_comment_init(&STRUCT->vcomment);
	
	// split extradata as header/comment/code
	ptr=(uint32_t *)extraData;
	size_hdr=*ptr++;
	size_cmt=*ptr++;
	size_code=*ptr++;
	
	hdr=extraData+3*sizeof(uint32_t);
	cmt=hdr+size_hdr;
	code=cmt+size_cmt;
	
 	// Feed header passed as extraData
	packet.bytes=size_hdr;
	packet.packet=hdr;
	packet.b_o_s=1; // yes, it is a new stream	
	if(0>vorbis_synthesis_headerin(&STRUCT->vinfo,&comment,&packet))
	{
		printf("Mmm something bad happened , cannot init 1st packet\n");
		return;
	}
	// update some info in header this is the only place to get them
	// especially frequency.
/*
	info->channels=STRUCT->vinfo.channels;
	info->frequency=STRUCT->vinfo.rate;
*/
	info->byterate=STRUCT->vinfo.bitrate_nominal>>3;
	
	if(!info->byterate) 
	{
		printf("Mmm, no nominal bitrate...\n");
		info->byterate=16000;
	}
	// now unpack comment
	packet.bytes=size_cmt;
	packet.packet=cmt;
	packet.b_o_s=0; // Not new
	if(0>vorbis_synthesis_headerin(&STRUCT->vinfo,&comment,&packet))
	{
		printf("Mmm something bad happened , cannot init 2st packet\n");
		return;
	}
	// and codebook
	packet.bytes=size_code;
	packet.packet=code;
	packet.b_o_s=0; // Not new
	if(0>vorbis_synthesis_headerin(&STRUCT->vinfo,&comment,&packet))
	{
		printf("Mmm something bad happened , cannot init 3st packet\n");
		return;
	}
	vorbis_comment_clear(&comment);
	vorbis_synthesis_init(&STRUCT->vdsp,&STRUCT->vinfo);
	vorbis_block_init(&STRUCT->vdsp,&STRUCT->vblock);
	printf("Vorbis init successfull\n");
	STRUCT->ampscale=1;
	_init=1;

	ch_route.input_type[0] = CH_FRONT_LEFT;
	ch_route.input_type[1] = CH_FRONT_RIGHT;
	ch_route.input_type[2] = CH_REAR_LEFT;
	ch_route.input_type[3] = CH_REAR_RIGHT;
	ch_route.input_type[4] = CH_FRONT_CENTER;
	ch_route.input_type[5] = CH_LFE;
 }
示例#24
0
bool TheoraDecoder::loadStream(Common::SeekableReadStream *stream) {
	close();

	_fileStream = stream;

	// start up Ogg stream synchronization layer
	ogg_sync_init(&_oggSync);

	// init supporting Vorbis structures needed in header parsing
	vorbis_info_init(&_vorbisInfo);
	vorbis_comment vorbisComment;
	vorbis_comment_init(&vorbisComment);

	// init supporting Theora structures needed in header parsing
	th_info theoraInfo;
	th_info_init(&theoraInfo);
	th_comment theoraComment;
	th_comment_init(&theoraComment);
	th_setup_info *theoraSetup = 0;

	uint theoraPackets = 0, vorbisPackets = 0;

	// Ogg file open; parse the headers
	// Only interested in Vorbis/Theora streams
	bool foundHeader = false;
	while (!foundHeader) {
		int ret = bufferData();

		if (ret == 0)
			break; // FIXME: Shouldn't this error out?

		while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0) {
			ogg_stream_state test;

			// is this a mandated initial header? If not, stop parsing
			if (!ogg_page_bos(&_oggPage)) {
				// don't leak the page; get it into the appropriate stream
				queuePage(&_oggPage);
				foundHeader = true;
				break;
			}

			ogg_stream_init(&test, ogg_page_serialno(&_oggPage));
			ogg_stream_pagein(&test, &_oggPage);
			ogg_stream_packetout(&test, &_oggPacket);

			// identify the codec: try theora
			if (theoraPackets == 0 && th_decode_headerin(&theoraInfo, &theoraComment, &theoraSetup, &_oggPacket) >= 0) {
				// it is theora
				memcpy(&_theoraOut, &test, sizeof(test));
				theoraPackets = 1;
				_hasVideo = true;
			} else if (vorbisPackets == 0 && vorbis_synthesis_headerin(&_vorbisInfo, &vorbisComment, &_oggPacket) >= 0) {
				// it is vorbis
				memcpy(&_vorbisOut, &test, sizeof(test));
				vorbisPackets = 1;
				_hasAudio = true;
			} else {
				// whatever it is, we don't care about it
				ogg_stream_clear(&test);
			}
		}
		// fall through to non-bos page parsing
	}

	// we're expecting more header packets.
	while ((theoraPackets && theoraPackets < 3) || (vorbisPackets && vorbisPackets < 3)) {
		int ret;

		// look for further theora headers
		while (theoraPackets && (theoraPackets < 3) && (ret = ogg_stream_packetout(&_theoraOut, &_oggPacket))) {
			if (ret < 0)
				error("Error parsing Theora stream headers; corrupt stream?");

			if (!th_decode_headerin(&theoraInfo, &theoraComment, &theoraSetup, &_oggPacket))
				error("Error parsing Theora stream headers; corrupt stream?");

			theoraPackets++;
		}

		// look for more vorbis header packets
		while (vorbisPackets && (vorbisPackets < 3) && (ret = ogg_stream_packetout(&_vorbisOut, &_oggPacket))) {
			if (ret < 0)
				error("Error parsing Vorbis stream headers; corrupt stream?");

			if (vorbis_synthesis_headerin(&_vorbisInfo, &vorbisComment, &_oggPacket))
				error("Error parsing Vorbis stream headers; corrupt stream?");

			vorbisPackets++;

			if (vorbisPackets == 3)
				break;
		}

		// The header pages/packets will arrive before anything else we
		// care about, or the stream is not obeying spec

		if (ogg_sync_pageout(&_oggSync, &_oggPage) > 0) {
			queuePage(&_oggPage); // demux into the appropriate stream
		} else {
			ret = bufferData(); // someone needs more data

			if (ret == 0)
				error("End of file while searching for codec headers.");
		}
	}

	// And now we have it all. Initialize decoders next
	if (_hasVideo) {
		_videoTrack = new TheoraVideoTrack(getDefaultHighColorFormat(), theoraInfo, theoraSetup);
		addTrack(_videoTrack);
	}

	th_info_clear(&theoraInfo);
	th_comment_clear(&theoraComment);
	th_setup_free(theoraSetup);

	if (_hasAudio) {
		_audioTrack = new VorbisAudioTrack(_soundType, _vorbisInfo);

		// Get enough audio data to start us off
		while (!_audioTrack->hasAudio()) {
			// Queue more data
			bufferData();
			while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0)
				queuePage(&_oggPage);

			queueAudio();
		}

		addTrack(_audioTrack);
	}

	vorbis_comment_clear(&vorbisComment);

	return true;
}
示例#25
0
size_t OggStegoDecoder::startDecodeOgg(FILE *instream, FILE *outstream, bool getMes)
{
	ogg_int16_t convbuffer[4096]; /* take 8k out of the data segment, not the stack */
	int convsize=4096;

	ogg_sync_state   oy; /* sync and verify incoming physical bitstream */
	ogg_stream_state os; /* take physical pages, weld into a logical
						 stream of packets */
	ogg_page         og; /* one Ogg bitstream page. Vorbis packets are inside */
	ogg_packet       op; /* one raw packet of data for decode */

	vorbis_info      vi; /* struct that stores all the static vorbis bitstream
						 settings */
	vorbis_comment   vc; /* struct that stores all the bitstream user comments */
	vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
	vorbis_block     vb; /* local working space for packet->PCM decode */

	char *buffer;
	int  bytes;

	/*FILE *instream;
	FILE *outstream;
	char *inname = "01.ogg";
	char *outname = "esmith2000-09-28d1t15.raw";*/

	//#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
	//  /* Beware the evil ifdef. We avoid these where we can, but this one we
	//     cannot. Don't add any more, you'll probably go to hell if you do. */
	//  //_setmode( _fileno( stdin ), _O_BINARY );
	//  //_setmode( _fileno( stdout ), _O_BINARY );
	//#endif

#if defined(macintosh) && defined(__MWERKS__)
	{
		int argc;
		char **argv;
		argc=ccommand(&argv); /* get a "command line" from the Mac user */
		/* this also lets the user set stdin and stdout */
	}
#endif

	/********** Decode setup ************/

	//opening the file


	/*if( fopen_s( &instream, inname, "rb" ) != 0 )
	{
	fprintf(stderr,"Can not open file %s\n", inname);
	exit(1);
	};

	if( fopen_s( &outstream, outname, "wb" ) != 0 )
	{
	fprintf(stderr,"Can not open file %s\n", outname);
	exit(1);
	}*/


	ogg_sync_init(&oy); /* Now we can read pages */

	while(1){ /* we repeat if the bitstream is chained */
		int eos=0;
		int i;

		/* grab some data at the head of the stream. We want the first page
		(which is guaranteed to be small and only contain the Vorbis
		stream initial header) We need the first page to get the stream
		serialno. */

		/* submit a 4k block to libvorbis' Ogg layer */
		buffer=ogg_sync_buffer(&oy,4096);
		//bytes=fread(buffer,1,4096,stdin);
		bytes=fread(buffer,1,4096,instream);
		ogg_sync_wrote(&oy,bytes);

		/* Get the first page. */
		if(ogg_sync_pageout(&oy,&og)!=1){
			/* have we simply run out of data?  If so, we're done. */
			if(bytes<4096)break;

			/* error case.  Must not be Vorbis data */
			throw Exception("Input does not appear to be an Ogg bitstream.\n");			
		}

		/* Get the serial number and set up the rest of decode. */
		/* serialno first; use it to set up a logical stream */
		ogg_stream_init(&os,ogg_page_serialno(&og));

		/* extract the initial header from the first page and verify that the
		Ogg bitstream is in fact Vorbis data */

		/* I handle the initial header first instead of just having the code
		read all three Vorbis headers at once because reading the initial
		header is an easy way to identify a Vorbis bitstream and it's
		useful to see that functionality seperated out. */

		vorbis_info_init(&vi);
		vorbis_comment_init(&vc);
		if(ogg_stream_pagein(&os,&og)<0){
			/* error; stream version mismatch perhaps */
			throw Exception("Error reading first page of Ogg bitstream data.\n");			
		}

		if(ogg_stream_packetout(&os,&op)!=1){
			/* no page? must not be vorbis */
			throw Exception("Error reading initial header packet.\n");			
		}

		if(vorbis_synthesis_headerin(&vi,&vc,&op)<0){
			/* error case; not a vorbis header */
			throw Exception("This Ogg bitstream does not contain Vorbis "
				"audio data.\n");			
		}



		/* At this point, we're sure we're Vorbis. We've set up the logical
		(Ogg) bitstream decoder. Get the comment and codebook headers and
		set up the Vorbis decoder */

		/* The next two packets in order are the comment and codebook headers.
		They're likely large and may span multiple pages. Thus we read
		and submit data until we get our two packets, watching that no
		pages are missing. If a page is missing, error out; losing a
		header page is the only place where missing data is fatal. */

		i=0;
		while(i<2){
			while(i<2){
				int result=ogg_sync_pageout(&oy,&og);
				if(result==0)break; /* Need more data */
				/* Don't complain about missing or corrupt data yet. We'll
				catch it at the packet output phase */
				if(result==1){
					ogg_stream_pagein(&os,&og); /* we can ignore any errors here
												as they'll also become apparent
												at packetout */
					while(i<2){
						result=ogg_stream_packetout(&os,&op);
						if(result==0)break;
						if(result<0){
							/* Uh oh; data at some point was corrupted or missing!
							We can't tolerate that in a header.  Die. */
							throw Exception("Corrupt secondary header.  Exiting.\n");							
						}
						result=vorbis_synthesis_headerin(&vi,&vc,&op);
						if(result<0){
							throw Exception("Corrupt secondary header.  Exiting.\n");							
						}
						i++;
					}
				}
			}
			/* no harm in not checking before adding more */
			buffer=ogg_sync_buffer(&oy,4096);
			//bytes=fread(buffer,1,4096,stdin);
			bytes=fread(buffer,1,4096,instream);
			if(bytes==0 && i<2){
				throw Exception("End of file before finding all Vorbis headers!\n");				
			}
			ogg_sync_wrote(&oy,bytes);
		}


		/* Throw the comments plus a few lines about the bitstream we're
		decoding */
//!!!!!!!Info
		/*{
			char **ptr=vc.user_comments;
			while(*ptr){
				fprintf(stderr,"%s\n",*ptr);
				++ptr;
			}
			fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi.channels,vi.rate);
			fprintf(stderr,"Encoded by: %s\n\n",vc.vendor);
		}*/
//!!!!!!!!!

		convsize=4096/vi.channels;

		/* OK, got and parsed all three headers. Initialize the Vorbis
		packet->PCM decoder. */
		if(vorbis_synthesis_init(&vd,&vi)==0){ /* central decode state */
			vorbis_block_init(&vd,&vb);          /* local state for most of the decode
												 so multiple block decodes can
												 proceed in parallel. We could init
												 multiple vorbis_block structures
												 for vd here */
			/*****************************************************************/
			/*****************************************************************/
			/*!!!!!!!!! set callback function !!!!!!!!!!*/					//
			InitVorbisStego(&vb,getMes);
			/*****************************************************************/
			/*****************************************************************/

			/* The rest is just a straight decode loop until end of stream */
			while(!eos){
				while(!eos){
					int result=ogg_sync_pageout(&oy,&og);
					if(result==0)break; /* need more data */
					if(result<0){ /* missing or corrupt data at this page position */
						fprintf(stderr,"Corrupt or missing data in bitstream; "
							"continuing...\n");
					}else{
						ogg_stream_pagein(&os,&og); /* can safely ignore errors at
													this point */
						while(1){
							result=ogg_stream_packetout(&os,&op);

							if(result==0)
								break; /* need more data */
							if(result<0){ /* missing or corrupt data at this page position */
								/* no reason to complain; already complained above */
							}else{
								/* we have a packet.  Decode it */
								float **pcm;
								int samples;

								if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
									vorbis_synthesis_blockin(&vd,&vb);
								/*

								**pcm is a multichannel float vector.  In stereo, for
								example, pcm[0] is left, and pcm[1] is right.  samples is
								the size of each channel.  Convert the float values
								(-1.<=range<=1.) to whatever PCM format and write it out */

								while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0){
									int j;
									int clipflag=0;
									int bout=(samples<convsize?samples:convsize);

									/* convert floats to 16 bit signed ints (host order) and
									interleave */
									for(i=0;i<vi.channels;i++){
										ogg_int16_t *ptr=convbuffer+i;
										float  *mono=pcm[i];
										for(j=0;j<bout;j++){
#if 1
											int val=floor(mono[j]*32767.f+.5f);
#else /* optional dither */
											int val=mono[j]*32767.f+drand48()-0.5f;
#endif
											/* might as well guard against clipping */
											if(val>32767){
												val=32767;
												clipflag=1;
											}
											if(val<-32768){
												val=-32768;
												clipflag=1;
											}
											*ptr=val;
											ptr+=vi.channels;
										}
									}

									/*if(clipflag)
									fprintf(stderr,"Clipping in frame %ld\n",(long)(vd.sequence));*/


									//fwrite(convbuffer,2*vi.channels,bout,stdout);
									fwrite(convbuffer,2*vi.channels,bout,outstream);
									/**/

									vorbis_synthesis_read(&vd,bout); /* tell libvorbis how
																	 many samples we
																	 actually consumed */
								}
							}
						}
						if(ogg_page_eos(&og))
							eos=1;
					}
				}
				if(!eos){
					buffer=ogg_sync_buffer(&oy,4096);
					//bytes=fread(buffer,1,4096,stdin);
					bytes=fread(buffer,1,4096,instream);
					ogg_sync_wrote(&oy,bytes);
					if(bytes==0)eos=1;
				}
			}

			/* ogg_page and ogg_packet structs always point to storage in
			libvorbis.  They're never freed or manipulated directly */

			vorbis_block_clear(&vb);
			vorbis_dsp_clear(&vd);
		}else{
			fprintf(stderr,"Error: Corrupt header during playback initialization.\n");
		}

		/* clean up this logical bitstream; before exit we see if we're
		followed by another [chained] */

		ogg_stream_clear(&os);
		vorbis_comment_clear(&vc);
		vorbis_info_clear(&vi);  /* must be called last */
	}

	/* OK, clean up the framer */
	ogg_sync_clear(&oy);

	fprintf(stderr,"Done.\n");
	return(0);
}
示例#26
0
文件: sndogg.c 项目: nonakap/xkazoku
int sndogg_open(SMIXTRACK trk) {

	__OV	*ov;
	char	*buffer;
	UINT	r;
	int		bytes;
	int 	i;
	int		result;

	ov = (__OV *)_MALLOC(sizeof(__OV), "__OV");
	if (ov == NULL) {
		goto ovopn_next;
	}
	ZeroMemory(ov, sizeof(__OV));

	r = sndmix_dataload(trk, trk->maxdatas);
	if ((r == (UINT)-1) || (r == 0)) {
		goto ovopn_next2;
	}
	buffer = ogg_sync_buffer(&ov->oy, trk->maxdatas);
	CopyMemory(buffer, trk->data, r);
	ogg_sync_wrote(&ov->oy, (int)r);

	if (ogg_sync_pageout(&ov->oy, &ov->og) != 1) {
		TRACEOUT(("Input does not appear to be an Ogg bitstream."));
		goto ovopn_next2;
	}
	ogg_stream_init(&ov->os, ogg_page_serialno(&ov->og));
	sndmix_datatrash(trk, (UINT)-1);

	vorbis_info_init(&ov->vi);
	vorbis_comment_init(&ov->vc);
	if (ogg_stream_pagein(&ov->os, &ov->og) < 0) {
		TRACEOUT(("Error reading first page of Ogg bitstream data."));
		goto ovopn_err1;
	}

	if (ogg_stream_packetout(&ov->os, &ov->op) != 1) {
		TRACEOUT(("Error reading initial header packet."));
		goto ovopn_err1;
	}

	if (vorbis_synthesis_headerin(&ov->vi, &ov->vc, &ov->op) < 0) {
		TRACEOUT(("This Ogg bitstream does not contain Vorbis audio data."));
		goto ovopn_err1;
	}

	i = 0;
	while(i < 2) {
		while(i < 2) {
			result = ogg_sync_pageout(&ov->oy, &ov->og);
			if (result == 0) {
				break;
			}
			if (result == 1) {
				ogg_stream_pagein(&ov->os, &ov->og);
				while(i < 2) {
					result = ogg_stream_packetout(&ov->os, &ov->op);
					if (result == 0) {
						break;
					}
					if (result < 0) {
						TRACEOUT(("Corrupt secondary header. Exiting."));
						goto ovopn_err1;
					}
					vorbis_synthesis_headerin(&ov->vi, &ov->vc, &ov->op);
					i++;
				}
			}
		}
		buffer = ogg_sync_buffer(&ov->oy, 4096);
		bytes = sndmix_dataread(trk, buffer, 4096);
		if ((bytes == 0) && (i < 2)) {
			TRACEOUT(("End of file before finding all Vorbis headers!"));
			return(SNDMIX_FAILURE);
		}
		ogg_sync_wrote(&ov->oy, bytes);
	}

	trk->snd = ov;
	trk->dec = (DECFN)ogg_dec;
	trk->decend = ogg_decend;
	trk->samprate = ov->vi.rate;
	trk->channels = ov->vi.channels;
	trk->block = 4096;
	trk->blksamp = 4096 / ov->vi.channels;
	trk->bit = 16;
#if defined(SOUND_MOREINFO)
	trk->bps = 0;
	trk->fmt = WAVEFMT_OGG;
	CopyMemory(trk->info, "Ogg vorbis", 11);
#endif

	vorbis_synthesis_init(&ov->vd, &ov->vi);
	vorbis_block_init(&ov->vd, &ov->vb);
	return(SNDMIX_SUCCESS);

ovopn_err1:
	ogg_sync_clear(&ov->oy);
	_MFREE(ov);
	return(SNDMIX_FAILURE);

ovopn_next2:
	_MFREE(ov);

ovopn_next:
	return(SNDMIX_NOTSUPPORT);
}
示例#27
0
文件: ogg.cpp 项目: AMDmi3/Wyrmgus
int OggInit(CFile *f, OggData *data)
{
	ogg_packet packet;
	int num_vorbis;
#ifdef USE_THEORA
	int num_theora;
#endif
	int stream_start;
	int ret;

	unsigned magic;
	f->read(&magic, sizeof(magic));
	if (SDL_SwapLE32(magic) != 0x5367674F) { // "OggS" in ASCII
		return -1;
	}
	f->seek(0, SEEK_SET);

	ogg_sync_init(&data->sync);

	vorbis_info_init(&data->vinfo);
	vorbis_comment_init(&data->vcomment);

#ifdef USE_THEORA
	theora_info_init(&data->tinfo);
	theora_comment_init(&data->tcomment);
#endif

#ifdef USE_THEORA
	num_theora = 0;
#endif
	num_vorbis = 0;
	stream_start = 0;
	while (!stream_start) {
		ogg_stream_state test;

		if (OggGetNextPage(&data->page, &data->sync, f)) {
			return -1;
		}

		if (!ogg_page_bos(&data->page)) {
			if (num_vorbis) {
				ogg_stream_pagein(&data->astream, &data->page);
			}
#ifdef USE_THEORA
			if (num_theora) {
				ogg_stream_pagein(&data->vstream, &data->page);
			}
#endif
			stream_start = 1;
			break;
		}

		ogg_stream_init(&test, ogg_page_serialno(&data->page));
		ogg_stream_pagein(&test, &data->page);

		// initial codec headers
		while (ogg_stream_packetout(&test, &packet) == 1) {
#ifdef USE_THEORA
			if (theora_decode_header(&data->tinfo, &data->tcomment, &packet) >= 0) {
				memcpy(&data->vstream, &test, sizeof(test));
				++num_theora;
			} else
#endif
				if (!vorbis_synthesis_headerin(&data->vinfo, &data->vcomment, &packet)) {
					memcpy(&data->astream, &test, sizeof(test));
					++num_vorbis;
				} else {
					ogg_stream_clear(&test);
				}
		}
	}

	data->audio = num_vorbis;
#ifdef USE_THEORA
	data->video = num_theora;
#endif

	// remainint codec headers
	while ((num_vorbis && num_vorbis < 3)
#ifdef USE_THEORA
		   || (num_theora && num_theora < 3)) {
		// are we in the theora page ?
		while (num_theora && num_theora < 3 &&
			   (ret = ogg_stream_packetout(&data->vstream, &packet))) {
			if (ret < 0) {
				return -1;
			}
			if (theora_decode_header(&data->tinfo, &data->tcomment, &packet)) {
				return -1;
			}
			++num_theora;
		}
#else
		  ) {
#endif

		// are we in the vorbis page ?
		while (num_vorbis && num_vorbis < 3 &&
			   (ret = ogg_stream_packetout(&data->astream, &packet))) {
			if (ret < 0) {
				return -1;
			}
			if (vorbis_synthesis_headerin(&data->vinfo, &data->vcomment, &packet)) {
				return -1;

			}
			++num_vorbis;
		}

		if (OggGetNextPage(&data->page, &data->sync, f)) {
			break;
		}

		if (num_vorbis) {
			ogg_stream_pagein(&data->astream, &data->page);
		}
#ifdef USE_THEORA
		if (num_theora) {
			ogg_stream_pagein(&data->vstream, &data->page);
		}
#endif
	}

	if (num_vorbis) {
		vorbis_synthesis_init(&data->vdsp, &data->vinfo);
		vorbis_block_init(&data->vdsp, &data->vblock);
	} else {
		vorbis_info_clear(&data->vinfo);
		vorbis_comment_clear(&data->vcomment);
	}

#ifdef USE_THEORA
	if (num_theora) {
		theora_decode_init(&data->tstate, &data->tinfo);
		data->tstate.internal_encode = NULL;  // needed for a bug in libtheora (fixed in next release)
	} else {
		theora_info_clear(&data->tinfo);
		theora_comment_clear(&data->tcomment);
	}

	return !(num_vorbis || num_theora);
#else
	return !num_vorbis;
#endif
}
示例#28
0
BOOL getogg_open(GETSND snd, UINT8 *ptr, UINT size) {

	__OV	*ov;
	char	*buffer;
	int		bytes;
	int 	i;
	int		result;

	snd->datptr = ptr;
	snd->datsize = size;

	ov = (__OV *)_MALLOC(sizeof(__OV), "__OV");
	if (ov == NULL) {
		goto ovopn_err0;
	}
	ZeroMemory(ov, sizeof(__OV));

	buffer = ogg_sync_buffer(&ov->oy, 4096);
	bytes = snd_read(snd, buffer, 4096);
	ogg_sync_wrote(&ov->oy, bytes);

	if (ogg_sync_pageout(&ov->oy, &ov->og) != 1) {
		TRACEOUT(("Input does not appear to be an Ogg bitstream."));
		goto ovopn_err1;
	}
	ogg_stream_init(&ov->os, ogg_page_serialno(&ov->og));

	vorbis_info_init(&ov->vi);
	vorbis_comment_init(&ov->vc);
	if (ogg_stream_pagein(&ov->os, &ov->og) < 0) {
		TRACEOUT(("Error reading first page of Ogg bitstream data."));
		goto ovopn_err1;
	}

	if (ogg_stream_packetout(&ov->os, &ov->op) != 1) {
		TRACEOUT(("Error reading initial header packet."));
		goto ovopn_err1;
	}

	if (vorbis_synthesis_headerin(&ov->vi, &ov->vc, &ov->op) < 0) {
		TRACEOUT(("This Ogg bitstream does not contain Vorbis audio data."));
		goto ovopn_err1;
	}

	i = 0;
	while(i < 2) {
		while(i < 2) {
			result = ogg_sync_pageout(&ov->oy, &ov->og);
			if (result == 0) {
				break;
			}
			if (result == 1) {
				ogg_stream_pagein(&ov->os, &ov->og);
				while(i < 2) {
					result = ogg_stream_packetout(&ov->os, &ov->op);
					if (result == 0) {
						break;
					}
					if (result < 0) {
						TRACEOUT(("Corrupt secondary header. Exiting."));
						goto ovopn_err1;
					}
					vorbis_synthesis_headerin(&ov->vi, &ov->vc, &ov->op);
					i++;
				}
			}
		}
		buffer = ogg_sync_buffer(&ov->oy, 4096);
		bytes = snd_read(snd, buffer, 4096);
		if ((bytes == 0) && (i < 2)) {
			TRACEOUT(("End of file before finding all Vorbis headers!"));
			return(-1);
		}
		ogg_sync_wrote(&ov->oy, bytes);
	}

	snd->snd = ov;
	snd->dec = (GSDEC)ogg_dec;
	snd->decend = ogg_decend;
	snd->samplingrate = ov->vi.rate;
	snd->channels = ov->vi.channels;
	snd->blocksize = 4096 * 2;
	snd->blocksamples = 4096 / ov->vi.channels;
	snd->bit = 16;

	vorbis_synthesis_init(&ov->vd, &ov->vi);
	vorbis_block_init(&ov->vd, &ov->vb);
	return(SUCCESS);

ovopn_err1:
	ogg_sync_clear(&ov->oy);
	_MFREE(ov);

ovopn_err0:
	return(FAILURE);
}
示例#29
0
static void vorbis_process(stream_processor *stream, ogg_page *page,
			   MP3FILE *pmp3)
{
    ogg_packet packet;
    misc_vorbis_info *inf = stream->data;
    int i, header=0;
    int k;

    ogg_stream_pagein(&stream->os, page);
    if(inf->doneheaders < 3)
        header = 1;

    while(ogg_stream_packetout(&stream->os, &packet) > 0) {
        if(inf->doneheaders < 3) {
            if(vorbis_synthesis_headerin(&inf->vi, &inf->vc, &packet) < 0) {
	        DPRINTF(E_WARN, L_SCAN, "Could not decode vorbis header "
                       "packet - invalid vorbis stream (%d)\n", stream->num);
                continue;
            }
            inf->doneheaders++;
            if(inf->doneheaders == 3) {
                if(ogg_page_granulepos(page) != 0 || ogg_stream_packetpeek(&stream->os, NULL) == 1)
		    DPRINTF(E_WARN, L_SCAN, "Vorbis stream %d does not have headers "
                           "correctly framed. Terminal header page contains "
                           "additional packets or has non-zero granulepos\n",
                            stream->num);
		DPRINTF(E_DBG, L_SCAN, "Vorbis headers parsed for stream %d, "
			"information follows...\n", stream->num);
                /*
                DPRINTF(E_INF, L_SCAN, "Version: %d\n", inf->vi.version);
                k = 0;
                while(releases[k].vendor_string) {
                    if(!strcmp(inf->vc.vendor, releases[k].vendor_string)) {
		      //PENDING:
		      DPRINTF(E_INF, L_SCAN, "Vendor: %s (%s)\n",
			      inf->vc.vendor, releases[k].desc);
                        break;
                    }
                    k++;
                    }

                if(!releases[k].vendor_string)
                DPRINTF(E_INF, L_SCAN, "Vendor: %s\n", inf->vc.vendor);*/

                DPRINTF(E_DBG, L_SCAN, "Channels: %d\n", inf->vi.channels);
                DPRINTF(E_DBG, L_SCAN, "Rate: %ld\n\n", inf->vi.rate);

		pmp3->samplerate = inf->vi.rate;

                if(inf->vi.bitrate_nominal > 0) {
                  DPRINTF(E_DBG, L_SCAN, "Nominal bitrate: %f kb/s\n",
                          (double)inf->vi.bitrate_nominal / 1000.0);
		    pmp3->bitrate = inf->vi.bitrate_nominal / 1000;
		}
                else {
                    int         upper_rate, lower_rate;

                    DPRINTF(E_DBG, L_SCAN, "Nominal bitrate not set\n");

                    /* Average the lower and upper bitrates if set */
                    
                    upper_rate = 0;
                    lower_rate = 0;

                    if(inf->vi.bitrate_upper > 0) {
                        DPRINTF(E_DBG, L_SCAN, "Upper bitrate: %f kb/s\n",
                                (double)inf->vi.bitrate_upper / 1000.0);
                        upper_rate = inf->vi.bitrate_upper;
                    } else {
                        DPRINTF(E_DBG, L_SCAN, "Upper bitrate not set\n");
                    }

                    if(inf->vi.bitrate_lower > 0) {
                        DPRINTF(E_DBG, L_SCAN,"Lower bitrate: %f kb/s\n",
                                (double)inf->vi.bitrate_lower / 1000.0);
                        lower_rate = inf->vi.bitrate_lower;;
                    } else {
                        DPRINTF(E_DBG, L_SCAN, "Lower bitrate not set\n");
                    }

                    if (upper_rate && lower_rate) {
                        pmp3->bitrate = (upper_rate + lower_rate) / 2;
                    } else {
                        pmp3->bitrate = upper_rate + lower_rate;
                    }
                }

                if(inf->vc.comments > 0)
                    DPRINTF(E_DBG, L_SCAN,
                            "User comments section follows...\n");

                for(i=0; i < inf->vc.comments; i++) {
                    char *sep = strchr(inf->vc.user_comments[i], '=');
                    char *decoded;
                    int j;
                    int broken = 0;
                    unsigned char *val;
                    int bytes;
                    int remaining;

                    if(sep == NULL) {
		        DPRINTF(E_WARN, L_SCAN,
				"Comment %d in stream %d is invalidly "
                               "formatted, does not contain '=': \"%s\"\n",
                               i, stream->num, inf->vc.user_comments[i]);
                        continue;
                    }

                    for(j=0; j < sep-inf->vc.user_comments[i]; j++) {
                        if(inf->vc.user_comments[i][j] < 0x20 ||
                           inf->vc.user_comments[i][j] > 0x7D) {
			    DPRINTF(E_WARN, L_SCAN,
				    "Warning: Invalid comment fieldname in "
                                   "comment %d (stream %d): \"%s\"\n",
                                    i, stream->num, inf->vc.user_comments[i]);
                            broken = 1;
                            break;
                        }
                    }

                    if(broken)
                        continue;

                    val = inf->vc.user_comments[i];

                    j = sep-inf->vc.user_comments[i]+1;
                    while(j < inf->vc.comment_lengths[i])
                    {
                        remaining = inf->vc.comment_lengths[i] - j;
                        if((val[j] & 0x80) == 0)
                            bytes = 1;
                        else if((val[j] & 0x40) == 0x40) {
                            if((val[j] & 0x20) == 0)
                                bytes = 2;
                            else if((val[j] & 0x10) == 0)
                                bytes = 3;
                            else if((val[j] & 0x08) == 0)
                                bytes = 4;
                            else if((val[j] & 0x04) == 0)
                                bytes = 5;
                            else if((val[j] & 0x02) == 0)
                                bytes = 6;
                            else {
                                DPRINTF(E_WARN, L_SCAN,
					"Illegal UTF-8 sequence in "
                                       "comment %d (stream %d): length "
                                       "marker wrong\n",
                                        i, stream->num);
                                broken = 1;
                                break;
                            }
                        }
                        else {
                            DPRINTF(E_WARN, L_SCAN,
				    "Illegal UTF-8 sequence in comment "
                                    "%d (stream %d): length marker wrong\n",
                                    i, stream->num);
                            broken = 1;
                            break;
                        }

                        if(bytes > remaining) {
                            DPRINTF(E_WARN, L_SCAN,
				    "Illegal UTF-8 sequence in comment "
				    "%d (stream %d): too few bytes\n",
				    i, stream->num);
                            broken = 1;
                            break;
                        }

                        switch(bytes) {
                            case 1:
                                /* No more checks needed */
                                break;
                            case 2:
                                if((val[j+1] & 0xC0) != 0x80)
                                    broken = 1;
                                if((val[j] & 0xFE) == 0xC0)
                                    broken = 1;
                                break;
                            case 3:
                                if(!((val[j] == 0xE0 && val[j+1] >= 0xA0 && 
                                        val[j+1] <= 0xBF && 
                                        (val[j+2] & 0xC0) == 0x80) ||
                                   (val[j] >= 0xE1 && val[j] <= 0xEC &&
                                        (val[j+1] & 0xC0) == 0x80 &&
                                        (val[j+2] & 0xC0) == 0x80) ||
                                   (val[j] == 0xED && val[j+1] >= 0x80 &&
                                        val[j+1] <= 0x9F &&
                                        (val[j+2] & 0xC0) == 0x80) ||
                                   (val[j] >= 0xEE && val[j] <= 0xEF &&
                                        (val[j+1] & 0xC0) == 0x80 &&
                                        (val[j+2] & 0xC0) == 0x80)))
                                    broken = 1;
                                if(val[j] == 0xE0 && (val[j+1] & 0xE0) == 0x80)
                                    broken = 1;
                                break;
                            case 4:
                                if(!((val[j] == 0xF0 && val[j+1] >= 0x90 &&
                                        val[j+1] <= 0xBF &&
                                        (val[j+2] & 0xC0) == 0x80 &&
                                        (val[j+3] & 0xC0) == 0x80) ||
                                     (val[j] >= 0xF1 && val[j] <= 0xF3 &&
                                        (val[j+1] & 0xC0) == 0x80 &&
                                        (val[j+2] & 0xC0) == 0x80 &&
                                        (val[j+3] & 0xC0) == 0x80) ||
                                     (val[j] == 0xF4 && val[j+1] >= 0x80 &&
                                        val[j+1] <= 0x8F &&
                                        (val[j+2] & 0xC0) == 0x80 &&
                                        (val[j+3] & 0xC0) == 0x80)))
                                    broken = 1;
                                if(val[j] == 0xF0 && (val[j+1] & 0xF0) == 0x80)
                                    broken = 1;
                                break;
                            /* 5 and 6 aren't actually allowed at this point*/  
                            case 5:
                                broken = 1;
                                break;
                            case 6:
                                broken = 1;
                                break;
                        }

                        if(broken) {
			    DPRINTF(E_WARN, L_SCAN,
				    "Illegal UTF-8 sequence in comment "
				    "%d (stream %d): invalid sequence\n",
                                    i, stream->num);
                            broken = 1;
                            break;
                        }

                        j += bytes;
                    }

                    if(!broken) {
		      /*                        if(utf8_decode(sep+1, &decoded) < 0) {
			    DPRINTF(E_WARN, L_SCAN,
				    "Failure in utf8 decoder. This "
				    "should be impossible\n");
                            continue;
			    }*/
                      
                      DPRINTF(E_DBG, L_SCAN,
                              "\t%s\n", inf->vc.user_comments[i]);

                        if (!strncasecmp(inf->vc.user_comments[i],"TITLE",5)) {
                            pmp3->title = strdup(sep + 1);
                            DPRINTF(E_DBG, L_SCAN, "Mapping %s to title.\n",
                                    sep + 1);
			} else if (!strncasecmp(inf->vc.user_comments[i], "ARTIST", 6)) {
                            pmp3->artist = strdup(sep + 1);
                            DPRINTF(E_DBG, L_SCAN, "Mapping %s to artist.\n",
                                    sep + 1);
			} else if (!strncasecmp(inf->vc.user_comments[i], "ALBUM", 5)) {
                            pmp3->album = strdup(sep + 1);
                            DPRINTF(E_DBG, L_SCAN, "Mapping %s to album.\n",
                                    sep + 1);
			} else if (!strncasecmp(inf->vc.user_comments[i],
					   "TRACKNUMBER", 11)) {
                            pmp3->track = atoi(sep + 1);
                            DPRINTF(E_INF, L_SCAN, "Mapping %s to track.\n",
                                    sep + 1);
			} else if (!strncasecmp(inf->vc.user_comments[i], "GENRE", 5)) {
                            pmp3->genre = strdup(sep + 1);
                            DPRINTF(E_INF, L_SCAN, "Mapping %s to genre.\n",
                                    sep + 1);
			} else if (!strncasecmp(inf->vc.user_comments[i], "DATE", 4)) {
			  //PENDING: Should only parse first 4 characters
                            pmp3->year = atoi(sep + 1);
                            DPRINTF(E_INF, L_SCAN, "Mapping %s to year.\n",
                                    sep + 1);
			} else if (!strncasecmp(inf->vc.user_comments[i], "COMMENT", 7)) {
                            pmp3->comment = strdup(sep + 1);
                            DPRINTF(E_INF, L_SCAN, "Mapping %s to comment.\n",
                                    sep + 1);
			}

                        *sep = 0;
			/*                        free(decoded);*/
                    }
                }
            }
        }
    }

    if(!header) {
        ogg_int64_t gp = ogg_page_granulepos(page);
        if(gp > 0) {
            if(gp < inf->lastgranulepos)
#ifdef _WIN32
                DPRINTF(E_WARN, L_SCAN, "granulepos in stream %d decreases from %I64d to %I64d",
                        stream->num, inf->lastgranulepos, gp);
#else
                DPRINTF(E_WARN, L_SCAN, "granulepos in stream %d decreases from %lld to %lld",
                        stream->num, inf->lastgranulepos, gp);
#endif
            inf->lastgranulepos = gp;
        }
        else {
            DPRINTF(E_WARN, L_SCAN, "Negative granulepos on vorbis stream outside of headers. This file was created by a buggy encoder\n");
        }
        if(inf->firstgranulepos < 0) { /* Not set yet */
        }
        inf->bytes += page->header_len + page->body_len;
    }
}
//TODO: vorbis/theora-header&init in sub-functions
//TODO: "clean" error-returns ...
int Cin_OGM_Init(const char* filename) {
	int status;
	ogg_page	og;
	ogg_packet	op;
	int i;

	if(g_ogm.ogmFile) {
		Com_Printf("WARNING: it seams there was already a ogm running, it will be killed to start %s\n", filename);
		Cin_OGM_Shutdown();
	}

	memset(&g_ogm,0,sizeof(cin_ogm_t));

	FS_FOpenFileRead(filename, &g_ogm.ogmFile, qtrue);
	if(!g_ogm.ogmFile) {
		Com_Printf("Can't open ogm-file for reading (%s)\n", filename);

		return -1;
	}

	ogg_sync_init(&g_ogm.oy); /* Now we can read pages */

	//FIXME? can serialno be 0 in ogg? (better way to check inited?)
	//TODO: support for more than one audio stream? / detect files with one stream(or without correct ones)
	while(!g_ogm.os_audio.serialno || !g_ogm.os_video.serialno) {
		if(ogg_sync_pageout(&g_ogm.oy,&og)==1) {
			if(strstr((char*)(og.body+1),"vorbis")) { //FIXME? better way to find audio stream
				if(g_ogm.os_audio.serialno) {
					Com_Printf("more than one audio stream, in ogm-file(%s) ... we will stay at the first one\n",filename);
				}
				else {
					ogg_stream_init(&g_ogm.os_audio, ogg_page_serialno(&og));
					ogg_stream_pagein(&g_ogm.os_audio,&og);
				}
			}
#ifdef USE_CIN_THEORA
			if(strstr((char*)(og.body+1),"theora")) {
				if(g_ogm.os_video.serialno) {
					Com_Printf("more than one video stream, in ogm-file(%s) ... we will stay at the first one\n",filename);
				}
				else{
					g_ogm.videoStreamIsTheora = qtrue;
					ogg_stream_init(&g_ogm.os_video, ogg_page_serialno(&og));
					ogg_stream_pagein(&g_ogm.os_video,&og);
				}
			}
#endif
#ifdef USE_CIN_XVID
			if(strstr((char*)(og.body+1),"video")) { //FIXME? better way to find video stream
				if(g_ogm.os_video.serialno) {
					Com_Printf("more than one video stream, in ogm-file(%s) ... we will stay at the first one\n",filename);
				}
				else{
					stream_header_t* sh;

					g_ogm.videoStreamIsXvid = qtrue;

					sh = (stream_header_t*)(og.body+1);
					//TODO: one solution for checking xvid and theora
					if(!isPowerOf2(sh->sh.stream_header_video.width)) {
						Com_Printf("VideoWidth of the ogm-file isn't a power of 2 value (%s)\n", filename);

						return -5;
					}
					if(!isPowerOf2(sh->sh.stream_header_video.height)) {
						Com_Printf("VideoHeight of the ogm-file isn't a power of 2 value (%s)\n", filename);

						return -6;
					}

					g_ogm.Vtime_unit = sh->time_unit;

					ogg_stream_init(&g_ogm.os_video, ogg_page_serialno(&og));
					ogg_stream_pagein(&g_ogm.os_video,&og);
				}
			}
#endif
		}
		else if(loadBlockToSync())
			break;
	}

	if(g_ogm.videoStreamIsXvid && g_ogm.videoStreamIsTheora) {
		Com_Printf("Found \"video\"- and \"theora\"-stream ,ogm-file (%s)\n", filename);

		return -2;
	}

	if(!g_ogm.os_audio.serialno) {
		Com_Printf("Haven't found a audio(vorbis) stream in ogm-file (%s)\n", filename);

		return -2;
	}
	if(!g_ogm.os_video.serialno) {
		Com_Printf("Haven't found a video stream in ogm-file (%s)\n", filename);

		return -3;
	}

	//load vorbis header
	vorbis_info_init(&g_ogm.vi);
	vorbis_comment_init(&g_ogm.vc);
	i=0;
	while(i<3) {
		status = ogg_stream_packetout(&g_ogm.os_audio,&op);
		if(status<0) {
			Com_Printf("Corrupt ogg packet while loading vorbis-headers, ogm-file(%s)\n", filename);

			return -8;
		}
		if(status>0) {
			status = vorbis_synthesis_headerin(&g_ogm.vi,&g_ogm.vc,&op);
			if(i==0 && status<0) {
				Com_Printf("This Ogg bitstream does not contain Vorbis audio data, ogm-file(%s)\n", filename);

				return -9;
			}
			++i;
		}
		else if(loadPagesToStreams()) {
			if(loadBlockToSync()) {
				Com_Printf("Couldn't find all vorbis headers before end of ogm-file (%s)\n", filename);

				return -10;
			}
		}
	}

	vorbis_synthesis_init(&g_ogm.vd,&g_ogm.vi);

#ifdef USE_CIN_XVID
	status = init_xvid();
	if (status) {
		Com_Printf("[Xvid]Decore INIT problem, return value %d(ogm-file: %s)\n", status, filename);

		return -4;
	}
#endif

#ifdef USE_CIN_THEORA
	if(g_ogm.videoStreamIsTheora) {
		ROQ_GenYUVTables();

		theora_info_init(&g_ogm.th_info);
		theora_comment_init(&g_ogm.th_comment);

		i=0;
		while(i<3) {
			status = ogg_stream_packetout(&g_ogm.os_video,&op);
			if(status<0) {
				Com_Printf("Corrupt ogg packet while loading theora-headers, ogm-file(%s)\n", filename);

				return -8;
			}
			if(status>0) {
				status = theora_decode_header(&g_ogm.th_info, &g_ogm.th_comment, &op);
				if(i==0 && status!=0) {
					Com_Printf("This Ogg bitstream does not contain theora data, ogm-file(%s)\n", filename);

					return -9;
				}
				++i;
			}
			else if(loadPagesToStreams()) {
				if(loadBlockToSync()) {
					Com_Printf("Couldn't find all theora headers before end of ogm-file (%s)\n", filename);

					return -10;
				}
			}
		}

		theora_decode_init(&g_ogm.th_state, &g_ogm.th_info);

		if(!isPowerOf2(g_ogm.th_info.width)) {
			Com_Printf("VideoWidth of the ogm-file isn't a power of 2 value (%s)\n", filename);

			return -5;
		}
		if(!isPowerOf2(g_ogm.th_info.height)) {
			Com_Printf("VideoHeight of the ogm-file isn't a power of 2 value (%s)\n", filename);

			return -6;
		}


		g_ogm.Vtime_unit = ((ogg_int64_t)g_ogm.th_info.fps_denominator *1000*10000 / g_ogm.th_info.fps_numerator);
	}
#endif

	Com_DPrintf("OGM-Init done (%s)\n",filename);

	return 0;
}