Example #1
0
/*
 * The poll function. Checks if more data is needed, and decodes/plays if
 * needed.
 */
int _apeg_audio_poll(APEG_LAYER *layer)
{
#ifndef DISABLE_MPEG_AUDIO
	struct reader *rd = &(layer->audio.rd);
	struct frame *fr = &(layer->audio.fr);
	struct mpstr *mp = &(layer->audio.mp);
	int ret = APEG_OK;
#endif

	if(layer->multiple <= 0.0f)
		return APEG_OK;

	if(layer->stream.flags & APEG_VORBIS_AUDIO)
		return alvorbis_update(layer);

#ifdef DISABLE_MPEG_AUDIO
	return APEG_ERROR;
#else
	// Check if we actually need more data yet
	while(!rd->eof && layer->audio.pcm.point < layer->audio.bufsize)
	{
		// Make sure we're not still in the process of decoding the previous
		// frame
		if(mp->return_later)
		{
			decode_frame(layer, fr, mp);
			continue;
		}

		ret = read_frame(layer, fr);
		if(ret != ALMPA_OK)
		{
			// Stream ended, but check if there's still audio in the buffer
			if(!layer->audio.pcm.point)
				return ret;

			ret = APEG_OK;
			break;
		}

		/* TODO: for fast forwarding */
/*		if(stream->frame > layer->audio.frame)
		{
			if(fr->lay == 3)
				set_pointer(mp, fr->sideInfoSize, 512);
			goto do_again;
		}*/

		// Check for header change. This works, but it will introduce a jump
		// if the frequency/channel count changes.
		if(!layer->audio.inited)
		{
			int old_rate = layer->stream.audio.freq;
			int old_channels = layer->stream.audio.channels;

			int newrate = freqs[fr->sampling_frequency] >>
			              layer->stream.audio.down_sample;

			layer->stream.audio.channels = (layer->stream.audio.down_channel?1:
			                                fr->stereo);
			layer->stream.audio.freq = newrate;

			layer->stream.audio.layer = fr->lay;
			layer->stream.audio.kbps = tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index];
			fr->down_sample_sblimit = SBLIMIT>>layer->stream.audio.down_sample;

			if(layer->stream.audio.freq != old_rate ||
			   layer->stream.audio.channels != old_channels)
			{
				if(fr->lay == 3)
					init_layer3(layer->stream.audio.down_sample);

				if(_apeg_audio_reset_parameters(layer) != APEG_OK)
					return APEG_ERROR;
			}

			layer->audio.inited = TRUE;
		}

		++(layer->audio.frame);
		decode_frame(layer, fr, mp);
	}
Example #2
0
/* 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;
	}