int WOggDecoder::GetBitrate(int fAverage) { if(fAverage) return c_isInfo.nFileBitrate; int bitrate = ov_bitrate_instant(&vf); if(bitrate != 0 && bitrate != c_LastBitrate) c_LastBitrate = bitrate; return c_LastBitrate; }
void VorbisLMC::DecodeWork() { void *pOutBuffer; Error Err; int32 iValue; int32 section, ret; OutputInfo *info; vorbis_info *vi; uint32 bytesCopied, bytesPerFrame; int bitrateLoops = 0; assert(m_pPmi); assert(m_pPmo); m_pSleepSem->Wait(); m_pPmi->Wake(); Err = CanDecode(); if (Err == kError_Interrupt) return; if (Err != kError_NoErr) { m_pContext->log->Error("CanDecode returned false.\n"); if (m_decodeInfo.sendInfo) { ReportStatus(szCannotDecode); m_pTarget->AcceptEvent(new Event(INFO_DoneOutputtingDueToError)); } else ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent()); return; } Err = ExtractMediaInfo(); if (Err == kError_Interrupt) return; if (IsError(Err)) { m_pContext->log->Error("ExtractMediaInfo failed: %d\n", Err); if (m_decodeInfo.sendInfo) { ReportStatus(szCannotDecode); m_pTarget->AcceptEvent(new Event(INFO_DoneOutputtingDueToError)); } else ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOErrorEvent()); return; } if (!m_bInit) { Err = InitDecoder(); if (Err == kError_Interrupt) return; if (IsError(Err)) { m_pContext->log->Error("Initializing the decoder failed: %d\n", Err); ReportError("Initializing the decoder failed."); return; } } m_pContext->prefs->GetPrefInt32(kDecoderThreadPriorityPref, &iValue); m_decoderThread->SetPriority(iValue); bytesCopied = 0; bytesPerFrame = 1; for (m_frameCounter = 0; !m_bExit;) { if (m_bPause) { m_pPauseSem->Wait(); if (m_bExit) break; } if (m_newPos >= 0) { ov_time_seek(&m_vf, (double)(m_newPos / iFramesPerSecond)); m_frameCounter = m_newPos - 1; m_newPos = -1; bytesCopied = bytesPerFrame; } if (bytesCopied >= bytesPerFrame) { m_frameCounter += bytesCopied / bytesPerFrame; bytesCopied %= bytesPerFrame; ((EventBuffer *)m_pOutputBuffer)->AcceptEvent( new PMOTimeInfoEvent(m_frameCounter)); bitrateLoops++; if (bitrateLoops == iBitrateLoopsPerUpdate && m_decodeInfo.sendInfo) { int b; b = ov_bitrate_instant(&m_vf), vi = ov_info(&m_vf, -1); VorbisInfoEvent *mie = new VorbisInfoEvent(b, vi->channels, vi->rate, 1. / (float)iFramesPerSecond); m_pTarget->AcceptEvent(mie); bitrateLoops = 0; } } Err = m_pOutputBuffer->BeginWrite(pOutBuffer, iDecodeBlockSize); if (Err == kError_Interrupt) { break; } if (Err == kError_BufferTooSmall) { if (Sleep()) break; continue; } if (Err != kError_NoErr) { ReportError(szFailWrite); m_pContext->log->Error("LMC: Cannot write to eventbuffer: %s (%d)\n", m_szError, Err); break; } section = -1; ret = ov_read(&m_vf, (char *)pOutBuffer, iDecodeBlockSize, 0, 2, 1, §ion); if (ret == 0) { m_pOutputBuffer->EndWrite(0); break; } if (section != m_section) { vi = ov_info(&m_vf, -1); info = new OutputInfo; info->bits_per_sample = 16; info->number_of_channels = m_channels = vi->channels; info->samples_per_second = m_rate = vi->rate; info->samples_per_frame = vi->rate / iFramesPerSecond; info->max_buffer_size = 16384; m_frameCounter = 0; bytesCopied = 0; bytesPerFrame = (vi->rate / iFramesPerSecond) * sizeof(ogg_int16_t) * vi->channels; m_section = section; m_pOutputBuffer->EndWrite(0); ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOInitEvent(info)); ((EventBuffer *)m_pOutputBuffer)->AcceptEvent( new PMOTimeInfoEvent(m_frameCounter)); Err = m_pOutputBuffer->BeginWrite(pOutBuffer, iDecodeBlockSize); if (Err != kError_NoErr) { assert(0); } vorbis_comment *comment; comment = ov_comment(&m_vf, -1); if (comment) { PlaylistItem *plItem = m_pContext->plm->GetCurrentItem(); if (plItem) { MetaData mdata = plItem->GetMetaData(); string iso; char *temp; temp = vorbis_comment_query(comment, "title", 0); if (temp) { iso = ConvertToISO(temp); mdata.SetTitle(iso); } temp = vorbis_comment_query(comment, "artist", 0); if (temp) { iso = ConvertToISO(temp); mdata.SetArtist(iso); } temp = vorbis_comment_query(comment, "album", 0); if (temp) { iso = ConvertToISO(temp); mdata.SetAlbum(iso); } temp = vorbis_comment_query(comment, "tracknumber", 0); if (temp) mdata.SetTrack(atoi(temp)); plItem->SetMetaData(&mdata); m_pContext->target->AcceptEvent( new PlaylistCurrentItemInfoEvent(plItem, m_pContext->plm)); } } } if(ret <0) ret=0; // hole/error in data - we can safely ignore this m_pOutputBuffer->EndWrite(ret); bytesCopied += ret; } ((EventBuffer *)m_pOutputBuffer)->AcceptEvent(new PMOQuitEvent()); ov_clear(&m_vf); return; }
/* public */ static void vorbis_stream_decode(struct decoder *decoder, struct input_stream *input_stream) { GError *error = NULL; OggVorbis_File vf; struct vorbis_input_stream vis; struct audio_format audio_format; float total_time; int current_section; int prev_section = -1; long ret; char chunk[OGG_CHUNK_SIZE]; long bitRate = 0; long test; const vorbis_info *vi; enum decoder_command cmd = DECODE_COMMAND_NONE; if (ogg_stream_type_detect(input_stream) != VORBIS) return; /* rewind the stream, because ogg_stream_type_detect() has moved it */ input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL); if (!vorbis_is_open(&vis, &vf, decoder, input_stream)) return; vi = ov_info(&vf, -1); if (vi == NULL) { g_warning("ov_info() has failed"); return; } if (!audio_format_init_checked(&audio_format, vi->rate, SAMPLE_FORMAT_S16, vi->channels, &error)) { g_warning("%s", error->message); g_error_free(error); return; } total_time = ov_time_total(&vf, -1); if (total_time < 0) total_time = 0; decoder_initialized(decoder, &audio_format, vis.seekable, total_time); do { if (cmd == DECODE_COMMAND_SEEK) { double seek_where = decoder_seek_where(decoder); if (0 == ov_time_seek_page(&vf, seek_where)) { decoder_command_finished(decoder); } else decoder_seek_error(decoder); } ret = ov_read(&vf, chunk, sizeof(chunk), OGG_DECODE_USE_BIGENDIAN, 2, 1, ¤t_section); if (ret == OV_HOLE) /* bad packet */ ret = 0; else if (ret <= 0) /* break on EOF or other error */ break; if (current_section != prev_section) { char **comments; vi = ov_info(&vf, -1); if (vi == NULL) { g_warning("ov_info() has failed"); break; } if (vi->rate != (long)audio_format.sample_rate || vi->channels != (int)audio_format.channels) { /* we don't support audio format change yet */ g_warning("audio format change, stopping here"); break; } comments = ov_comment(&vf, -1)->user_comments; vorbis_send_comments(decoder, input_stream, comments); struct replay_gain_info rgi; if (vorbis_comments_to_replay_gain(&rgi, comments)) decoder_replay_gain(decoder, &rgi); prev_section = current_section; } if ((test = ov_bitrate_instant(&vf)) > 0) bitRate = test / 1000; cmd = decoder_data(decoder, input_stream, chunk, ret, bitRate); } while (cmd != DECODE_COMMAND_STOP); ov_clear(&vf); }
///////////////////////////////////////////////////////////////////////////////////////// //Audio callback ///////////////////////////////////////////////////////////////////////////////////////// static void oggDecodeThread(void *_buf2, unsigned int numSamples, void *pdata){ short *_buf = (short *)_buf2; //static short OGG_mixBuffer[PSP_NUM_AUDIO_SAMPLES * 2 * 2]__attribute__ ((aligned(64))); //static unsigned long OGG_tempmixleft = 0; int current_section; if (OGG_isPlaying) { // Playing , so mix up a buffer outputInProgress = 1; while (OGG_tempmixleft < numSamples) { // Not enough in buffer, so we must mix more unsigned long bytesRequired = (numSamples - OGG_tempmixleft) * 4; // 2channels, 16bit = 4 bytes per sample unsigned long ret = ov_read(&OGG_VorbisFile, (char *) &OGG_mixBuffer[OGG_tempmixleft * 2], bytesRequired, ¤t_section); //libtremor //unsigned long ret = ov_read(&OGG_VorbisFile, (char *) &OGG_mixBuffer[OGG_tempmixleft * 2], bytesRequired, 0, 2, 1, ¤t_section); //ogg-vorbis if (!ret) { //EOF OGG_isPlaying = 0; OGG_eos = 1; outputInProgress = 0; return; } else if (ret < 0) { if (ret == OV_HOLE) continue; OGG_isPlaying = 0; OGG_eos = 1; outputInProgress = 0; return; } OGG_tempmixleft += ret / 4; // back down to sample num } OGG_info.instantBitrate = ov_bitrate_instant(&OGG_VorbisFile); OGG_milliSeconds = ov_time_tell(&OGG_VorbisFile); //Check for playing speed: if (OGG_playingSpeed){ if (ov_raw_seek(&OGG_VorbisFile, ov_raw_tell(&OGG_VorbisFile) + OGG_playingDelta) != 0) OGG_setPlayingSpeed(0); } if (OGG_tempmixleft >= numSamples) { // Buffer has enough, so copy across int count, count2; short *_buf2; for (count = 0; count < numSamples; count++) { count2 = count + count; _buf2 = _buf + count2; //Volume boost: if (OGG_volume_boost){ *(_buf2) = volume_boost(&OGG_mixBuffer[count2], &OGG_volume_boost); *(_buf2 + 1) = volume_boost(&OGG_mixBuffer[count2 + 1], &OGG_volume_boost); }else{ // Double up for stereo *(_buf2) = OGG_mixBuffer[count2]; *(_buf2 + 1) = OGG_mixBuffer[count2 + 1]; } } // Move the pointers OGG_tempmixleft -= numSamples; // Now shuffle the buffer along for (count = 0; count < OGG_tempmixleft * 2; count++) OGG_mixBuffer[count] = OGG_mixBuffer[numSamples * 2 + count]; } outputInProgress = 0; } else { // Not Playing , so clear buffer int count; for (count = 0; count < numSamples * 2; count++) *(_buf + count) = 0; } }
/* public */ static void vorbis_stream_decode(struct decoder *decoder, struct input_stream *input_stream) { GError *error = NULL; if (ogg_codec_detect(decoder, input_stream) != OGG_CODEC_VORBIS) return; /* rewind the stream, because ogg_codec_detect() has moved it */ input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL); struct vorbis_input_stream vis; OggVorbis_File vf; if (!vorbis_is_open(&vis, &vf, decoder, input_stream)) return; const vorbis_info *vi = ov_info(&vf, -1); if (vi == NULL) { g_warning("ov_info() has failed"); return; } struct audio_format audio_format; if (!audio_format_init_checked(&audio_format, vi->rate, #ifdef HAVE_TREMOR SAMPLE_FORMAT_S16, #else SAMPLE_FORMAT_FLOAT, #endif vi->channels, &error)) { g_warning("%s", error->message); g_error_free(error); return; } float total_time = ov_time_total(&vf, -1); if (total_time < 0) total_time = 0; decoder_initialized(decoder, &audio_format, vis.seekable, total_time); enum decoder_command cmd = decoder_get_command(decoder); #ifdef HAVE_TREMOR char buffer[4096]; #else float buffer[2048]; const int frames_per_buffer = G_N_ELEMENTS(buffer) / audio_format.channels; const unsigned frame_size = sizeof(buffer[0]) * audio_format.channels; #endif int prev_section = -1; unsigned kbit_rate = 0; do { if (cmd == DECODE_COMMAND_SEEK) { double seek_where = decoder_seek_where(decoder); if (0 == ov_time_seek_page(&vf, seek_where)) { decoder_command_finished(decoder); } else decoder_seek_error(decoder); } int current_section; #ifdef HAVE_TREMOR long nbytes = ov_read(&vf, buffer, sizeof(buffer), VORBIS_BIG_ENDIAN, 2, 1, ¤t_section); #else float **per_channel; long nframes = ov_read_float(&vf, &per_channel, frames_per_buffer, ¤t_section); long nbytes = nframes; if (nframes > 0) { vorbis_interleave(buffer, (const float*const*)per_channel, nframes, audio_format.channels); nbytes *= frame_size; } #endif if (nbytes == OV_HOLE) /* bad packet */ nbytes = 0; else if (nbytes <= 0) /* break on EOF or other error */ break; if (current_section != prev_section) { vi = ov_info(&vf, -1); if (vi == NULL) { g_warning("ov_info() has failed"); break; } if (vi->rate != (long)audio_format.sample_rate || vi->channels != (int)audio_format.channels) { /* we don't support audio format change yet */ g_warning("audio format change, stopping here"); break; } char **comments = ov_comment(&vf, -1)->user_comments; vorbis_send_comments(decoder, input_stream, comments); struct replay_gain_info rgi; if (vorbis_comments_to_replay_gain(&rgi, comments)) decoder_replay_gain(decoder, &rgi); prev_section = current_section; } long test = ov_bitrate_instant(&vf); if (test > 0) kbit_rate = test / 1000; cmd = decoder_data(decoder, input_stream, buffer, nbytes, kbit_rate); } while (cmd != DECODE_COMMAND_STOP); ov_clear(&vf); }