bool OMXPlayerAudio::Decode(OMXPacket *pkt) { if(!pkt) return false; /* last decoder reinit went wrong */ if(!m_decoder || !m_pAudioCodec) return true; if(!m_omx_reader->IsActive(OMXSTREAM_AUDIO, pkt->stream_index)) return true; int channels = pkt->hints.channels; unsigned int old_bitrate = m_hints.bitrate; unsigned int new_bitrate = pkt->hints.bitrate; /* only check bitrate changes on CODEC_ID_DTS, CODEC_ID_AC3, CODEC_ID_EAC3 */ if(m_hints.codec != CODEC_ID_DTS && m_hints.codec != CODEC_ID_AC3 && m_hints.codec != CODEC_ID_EAC3) { new_bitrate = old_bitrate = 0; } /* audio codec changed. reinit device and decoder */ if(m_hints.codec != pkt->hints.codec || m_hints.channels != channels || m_hints.samplerate != pkt->hints.samplerate || old_bitrate != new_bitrate || m_hints.bitspersample != pkt->hints.bitspersample) { printf("C : %d %d %d %d %d\n", m_hints.codec, m_hints.channels, m_hints.samplerate, m_hints.bitrate, m_hints.bitspersample); printf("N : %d %d %d %d %d\n", pkt->hints.codec, channels, pkt->hints.samplerate, pkt->hints.bitrate, pkt->hints.bitspersample); m_av_clock->OMXPause(); CloseDecoder(); CloseAudioCodec(); m_hints = pkt->hints; m_player_error = OpenAudioCodec(); if(!m_player_error) return false; m_player_error = OpenDecoder(); if(!m_player_error) return false; m_av_clock->OMXStateExecute(); m_av_clock->OMXReset(); m_av_clock->OMXResume(); } if(!((int)m_decoder->GetSpace() > pkt->size)) OMXClock::OMXSleep(10); if((int)m_decoder->GetSpace() > pkt->size) { if(pkt->dts != DVD_NOPTS_VALUE) m_iCurrentPts = pkt->dts; m_av_clock->SetPTS(m_iCurrentPts); const uint8_t *data_dec = pkt->data; int data_len = pkt->size; if(!m_passthrough && !m_hw_decode) { while(data_len > 0) { int len = m_pAudioCodec->Decode((BYTE *)data_dec, data_len); if( (len < 0) || (len > data_len) ) { m_pAudioCodec->Reset(); break; } data_dec+= len; data_len -= len; uint8_t *decoded; int decoded_size = m_pAudioCodec->GetData(&decoded); if(decoded_size <=0) continue; int ret = 0; if(m_bMpeg) ret = m_decoder->AddPackets(decoded, decoded_size, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE); else ret = m_decoder->AddPackets(decoded, decoded_size, m_iCurrentPts, m_iCurrentPts); if(ret != decoded_size) { printf("error ret %d decoded_size %d\n", ret, decoded_size); } int n = (m_hints.channels * 32 * m_hints.samplerate)>>3; if (n > 0 && m_iCurrentPts != DVD_NOPTS_VALUE) m_iCurrentPts += ((double)decoded_size * DVD_TIME_BASE) / n; HandleSyncError((((double)decoded_size * DVD_TIME_BASE) / n), m_iCurrentPts); } } else { if(m_bMpeg) m_decoder->AddPackets(pkt->data, pkt->size, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE); else m_decoder->AddPackets(pkt->data, pkt->size, m_iCurrentPts, m_iCurrentPts); HandleSyncError(0, m_iCurrentPts); } m_av_clock->SetAudioClock(m_iCurrentPts); return true; }
bool OMXPlayerAudio::Decode(DemuxPacket *pkt, bool bDropPacket) { if(!pkt || m_bad_state || !m_pAudioCodec) return false; if(pkt->dts != DVD_NOPTS_VALUE) m_audioClock = pkt->dts; const uint8_t *data_dec = pkt->pData; int data_len = pkt->iSize; if(!OMX_IS_RAW(m_format.m_dataFormat)) { while(!m_bStop && data_len > 0) { int len = m_pAudioCodec->Decode((BYTE *)data_dec, data_len); if( (len < 0) || (len > data_len) ) { m_pAudioCodec->Reset(); break; } data_dec+= len; data_len -= len; uint8_t *decoded; int decoded_size = m_pAudioCodec->GetData(&decoded); if(decoded_size <=0) continue; int ret = 0; m_audioStats.AddSampleBytes(decoded_size); if(CodecChange()) { m_DecoderOpen = OpenDecoder(); if(!m_DecoderOpen) return false; } while(!m_bStop) { HandlePlayspeed(bDropPacket); if(m_flush) { m_flush = false; break; } if(m_omxAudio.GetSpace() < (unsigned int)pkt->iSize) { Sleep(10); continue; } if(!bDropPacket) { // Zero out the frame data if we are supposed to silence the audio if(m_silence) memset(decoded, 0x0, decoded_size); ret = m_omxAudio.AddPackets(decoded, decoded_size, m_audioClock, m_audioClock); if(ret != decoded_size) { CLog::Log(LOGERROR, "error ret %d decoded_size %d\n", ret, decoded_size); } } int n = (m_nChannels * m_hints.bitspersample * m_hints.samplerate)>>3; if (n > 0) m_audioClock += ((double)decoded_size * DVD_TIME_BASE) / n; if(m_speed == DVD_PLAYSPEED_NORMAL) HandleSyncError((((double)decoded_size * DVD_TIME_BASE) / n)); break; } } } else { if(CodecChange())
void CDVDPlayerAudio::Process() { CLog::Log(LOGNOTICE, "running thread: CDVDPlayerAudio::Process()"); bool packetadded(false); DVDAudioFrame audioframe; m_audioStats.Start(); while (!m_bStop) { int result = DecodeFrame(audioframe); //Drop when not playing normally if(m_speed != DVD_PLAYSPEED_NORMAL && m_started == true) { result |= DECODE_FLAG_DROP; } UpdatePlayerInfo(); if( result & DECODE_FLAG_ERROR ) { CLog::Log(LOGDEBUG, "CDVDPlayerAudio::Process - Decode Error"); continue; } if( result & DECODE_FLAG_TIMEOUT ) { // Flush as the audio output may keep looping if we don't if(m_speed == DVD_PLAYSPEED_NORMAL && !m_stalled) { m_dvdAudio.Drain(); m_dvdAudio.Flush(); m_stalled = true; } continue; } if( result & DECODE_FLAG_ABORT ) { CLog::Log(LOGDEBUG, "CDVDPlayerAudio::Process - Abort received, exiting thread"); break; } if( audioframe.nb_frames == 0 ) continue; packetadded = false; // we have succesfully decoded an audio frame, setup renderer to match if (!m_dvdAudio.IsValidFormat(audioframe)) { if(m_speed) m_dvdAudio.Drain(); m_dvdAudio.Destroy(); if(m_speed) m_dvdAudio.Resume(); else m_dvdAudio.Pause(); if(!m_dvdAudio.Create(audioframe, m_streaminfo.codec, m_setsynctype == SYNC_RESAMPLE)) CLog::Log(LOGERROR, "%s - failed to create audio renderer", __FUNCTION__); m_streaminfo.channels = audioframe.passthrough ? audioframe.encoded_channel_count : audioframe.channel_count; g_dataCacheCore.SignalAudioInfoChange(); } // Zero out the frame data if we are supposed to silence the audio if (m_silence || (m_syncclock && !AE_IS_RAW_RAW(audioframe.data_format))) { int size = audioframe.nb_frames * audioframe.framesize / audioframe.planes; for (unsigned int i=0; i<audioframe.planes; i++) memset(audioframe.data[i], 0, size); } if(result & DECODE_FLAG_DROP) { // keep output times in sync m_dvdAudio.SetPlayingPts(m_audioClock); } else { SetSyncType(audioframe.passthrough); // add any packets play packetadded = OutputPacket(audioframe); // we are not running until something is cached in output device and // we still have a minimum level in the message queue if(m_stalled && m_dvdAudio.GetCacheTime() > 0.0 && m_messageQueue.GetLevel() > 5) m_stalled = false; } // signal to our parent that we have initialized if(m_started == false && !(result & DECODE_FLAG_DROP)) { m_started = true; m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_AUDIO)); m_errors.Flush(); } if( m_dvdAudio.GetPlayingPts() == DVD_NOPTS_VALUE ) continue; if( m_speed != DVD_PLAYSPEED_NORMAL ) continue; if (packetadded) HandleSyncError(audioframe.duration); } }