/* * 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); }
/* 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; }