void sdpPlayerExample::LoadData(void) { //PlayerDataInfo.DataStart() = 1297723451.415; //PlayerDataInfo.DataEnd() = 1297723900.022; PlayerDataInfo.DataStart() = 4; PlayerDataInfo.DataEnd() = 100; if (Time < PlayerDataInfo.DataStart()) { Time = PlayerDataInfo.DataStart(); } if (Time > PlayerDataInfo.DataEnd()) { Time = PlayerDataInfo.DataEnd(); } //This is the standard. PlayUntilTime = PlayerDataInfo.DataEnd(); UpdatePlayerInfo(PlayerDataInfo); UpdateLimits(); }
void CVideoPlayerAudio::Process() { CLog::Log(LOGNOTICE, "running thread: CVideoPlayerAudio::Process()"); DVDAudioFrame audioframe; m_audioStats.Start(); while (!m_bStop) { CDVDMsg* pMsg; int timeout = (int)(1000 * m_dvdAudio.GetCacheTime()) + 100; // read next packet and return -1 on error int priority = 1; //Do we want a new audio frame? if (m_syncState == IDVDStreamPlayer::SYNC_STARTING || /* when not started */ ALLOW_AUDIO(m_speed) || /* when playing normally */ m_speed < DVD_PLAYSPEED_PAUSE || /* when rewinding */ (m_speed > DVD_PLAYSPEED_NORMAL && m_audioClock < m_pClock->GetClock())) /* when behind clock in ff */ priority = 0; if (m_syncState == IDVDStreamPlayer::SYNC_WAITSYNC) priority = 1; // consider stream stalled if queue is empty // we can't sync audio to clock with an empty queue if (ALLOW_AUDIO(m_speed) && !m_stalled) { timeout = 0; } MsgQueueReturnCode ret = m_messageQueue.Get(&pMsg, timeout, priority); if (MSGQ_IS_ERROR(ret)) { CLog::Log(LOGERROR, "Got MSGQ_ABORT or MSGO_IS_ERROR return true"); break; } else if (ret == MSGQ_TIMEOUT) { // Flush as the audio output may keep looping if we don't if (ALLOW_AUDIO(m_speed) && !m_stalled && m_syncState == IDVDStreamPlayer::SYNC_INSYNC) { // while AE sync is active, we still have time to fill buffers if (m_syncTimer.IsTimePast()) { CLog::Log(LOGNOTICE, "CVideoPlayerAudio::Process - stream stalled"); m_stalled = true; } } if (timeout == 0) Sleep(10); continue; } // handle messages if (pMsg->IsType(CDVDMsg::GENERAL_SYNCHRONIZE)) { if(((CDVDMsgGeneralSynchronize*)pMsg)->Wait( 100, SYNCSOURCE_AUDIO )) CLog::Log(LOGDEBUG, "CVideoPlayerAudio - CDVDMsg::GENERAL_SYNCHRONIZE"); else m_messageQueue.Put(pMsg->Acquire(), 1); // push back as prio message, to process other prio messages } else if (pMsg->IsType(CDVDMsg::GENERAL_RESYNC)) { //player asked us to set internal clock double pts = static_cast<CDVDMsgDouble*>(pMsg)->m_value; CLog::Log(LOGDEBUG, "CVideoPlayerAudio - CDVDMsg::GENERAL_RESYNC(%f)", pts); m_audioClock = pts + m_dvdAudio.GetDelay(); if (m_speed != DVD_PLAYSPEED_PAUSE) m_dvdAudio.Resume(); m_syncState = IDVDStreamPlayer::SYNC_INSYNC; m_syncTimer.Set(3000); } else if (pMsg->IsType(CDVDMsg::GENERAL_RESET)) { if (m_pAudioCodec) m_pAudioCodec->Reset(); m_syncState = IDVDStreamPlayer::SYNC_STARTING; } else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) { bool sync = static_cast<CDVDMsgBool*>(pMsg)->m_value; m_dvdAudio.Flush(); m_stalled = true; m_audioClock = 0; if (sync) { m_syncState = IDVDStreamPlayer::SYNC_STARTING; m_dvdAudio.Pause(); } if (m_pAudioCodec) m_pAudioCodec->Reset(); } else if (pMsg->IsType(CDVDMsg::GENERAL_EOF)) { CLog::Log(LOGDEBUG, "CVideoPlayerAudio - CDVDMsg::GENERAL_EOF"); } else if (pMsg->IsType(CDVDMsg::PLAYER_SETSPEED)) { double speed = static_cast<CDVDMsgInt*>(pMsg)->m_value; if (ALLOW_AUDIO(speed)) { if (speed != m_speed) { if (m_syncState == IDVDStreamPlayer::SYNC_INSYNC) m_dvdAudio.Resume(); } } else { m_dvdAudio.Pause(); } m_speed = speed; } else if (pMsg->IsType(CDVDMsg::AUDIO_SILENCE)) { m_silence = static_cast<CDVDMsgBool*>(pMsg)->m_value; CLog::Log(LOGDEBUG, "CVideoPlayerAudio - CDVDMsg::AUDIO_SILENCE(%f, %d)" , m_audioClock, m_silence); } else if (pMsg->IsType(CDVDMsg::GENERAL_STREAMCHANGE)) { CDVDMsgAudioCodecChange* msg(static_cast<CDVDMsgAudioCodecChange*>(pMsg)); OpenStream(msg->m_hints, msg->m_codec); msg->m_codec = NULL; } else if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET)) { DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket(); bool bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop(); int consumed = m_pAudioCodec->Decode(pPacket->pData, pPacket->iSize, pPacket->dts, pPacket->pts); if (consumed < 0) { CLog::Log(LOGERROR, "CVideoPlayerAudio::DecodeFrame - Decode Error. Skipping audio packet (%d)", consumed); m_pAudioCodec->Reset(); pMsg->Release(); continue; } m_audioStats.AddSampleBytes(pPacket->iSize); UpdatePlayerInfo(); // loop while no error and decoder produces output while (!m_bStop) { // get decoded data and the size of it m_pAudioCodec->GetData(audioframe); if (audioframe.nb_frames == 0) { if (consumed >= pPacket->iSize) break; int ret = m_pAudioCodec->Decode(pPacket->pData+consumed, pPacket->iSize-consumed, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE); if (ret < 0) { CLog::Log(LOGERROR, "CVideoPlayerAudio::DecodeFrame - Decode Error. Skipping audio packet (%d)", ret); m_pAudioCodec->Reset(); break; } consumed += ret; continue; } audioframe.hasTimestamp = true; if (audioframe.pts == DVD_NOPTS_VALUE) { audioframe.pts = m_audioClock; audioframe.hasTimestamp = false; } else { m_audioClock = audioframe.pts; } //Drop when not playing normally if (!ALLOW_AUDIO(m_speed) && m_syncState == IDVDStreamPlayer::SYNC_INSYNC) { break; } if (audioframe.format.m_sampleRate && m_streaminfo.samplerate != (int) audioframe.format.m_sampleRate) { // The sample rate has changed or we just got it for the first time // for this stream. See if we should enable/disable passthrough due // to it. m_streaminfo.samplerate = audioframe.format.m_sampleRate; if (SwitchCodecIfNeeded()) { break; } } // demuxer reads metatags that influence channel layout if (m_streaminfo.codec == AV_CODEC_ID_FLAC && m_streaminfo.channellayout) audioframe.format.m_channelLayout = CAEUtil::GetAEChannelLayout(m_streaminfo.channellayout); // 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_dvdAudio.Create(audioframe, m_streaminfo.codec, m_setsynctype == SYNC_RESAMPLE)) CLog::Log(LOGERROR, "%s - failed to create audio renderer", __FUNCTION__); if (m_syncState == IDVDStreamPlayer::SYNC_INSYNC) m_dvdAudio.Resume(); m_streaminfo.channels = audioframe.format.m_channelLayout.Count(); m_messageParent.Put(new CDVDMsg(CDVDMsg::PLAYER_AVCHANGE)); } // Zero out the frame data if we are supposed to silence the audio if (m_silence) { int size = audioframe.nb_frames * audioframe.framesize / audioframe.planes; for (unsigned int i=0; i<audioframe.planes; i++) memset(audioframe.data[i], 0, size); } SetSyncType(audioframe.passthrough); if (!bPacketDrop) { OutputPacket(audioframe); // signal to our parent that we have initialized if(m_syncState == IDVDStreamPlayer::SYNC_STARTING) { double cachetotal = DVD_SEC_TO_TIME(m_dvdAudio.GetCacheTotal()); double cachetime = m_dvdAudio.GetDelay(); if (cachetime >= cachetotal * 0.5) { m_syncState = IDVDStreamPlayer::SYNC_WAITSYNC; m_stalled = false; SStartMsg msg; msg.player = VideoPlayer_AUDIO; msg.cachetotal = cachetotal; msg.cachetime = cachetime; msg.timestamp = audioframe.hasTimestamp ? audioframe.pts : DVD_NOPTS_VALUE; m_messageParent.Put(new CDVDMsgType<SStartMsg>(CDVDMsg::PLAYER_STARTED, msg)); } } } // guess next pts m_audioClock += audioframe.duration; int ret = m_pAudioCodec->Decode(nullptr, 0, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE); if (ret < 0) { CLog::Log(LOGERROR, "CVideoPlayerAudio::DecodeFrame - Decode Error. Skipping audio packet (%d)", ret); m_pAudioCodec->Reset(); break; } } // while decoder produces output } // demuxer packet pMsg->Release(); } }
void CVideoPlayerAudio::Process() { CLog::Log(LOGNOTICE, "running thread: CVideoPlayerAudio::Process()"); DVDAudioFrame audioframe; audioframe.nb_frames = 0; audioframe.framesOut = 0; m_audioStats.Start(); bool onlyPrioMsgs = false; while (!m_bStop) { CDVDMsg* pMsg; int timeout = (int)(1000 * m_audioSink.GetCacheTime()); // read next packet and return -1 on error int priority = 1; //Do we want a new audio frame? if (m_syncState == IDVDStreamPlayer::SYNC_STARTING || /* when not started */ m_processInfo.IsTempoAllowed(static_cast<float>(m_speed)/DVD_PLAYSPEED_NORMAL) || m_speed < DVD_PLAYSPEED_PAUSE || /* when rewinding */ (m_speed > DVD_PLAYSPEED_NORMAL && m_audioClock < m_pClock->GetClock())) /* when behind clock in ff */ priority = 0; if (m_syncState == IDVDStreamPlayer::SYNC_WAITSYNC) priority = 1; if (m_paused) priority = 1; if (onlyPrioMsgs) { priority = 1; timeout = 0; } MsgQueueReturnCode ret = m_messageQueue.Get(&pMsg, timeout, priority); onlyPrioMsgs = false; if (MSGQ_IS_ERROR(ret)) { CLog::Log(LOGERROR, "Got MSGQ_ABORT or MSGO_IS_ERROR return true"); break; } else if (ret == MSGQ_TIMEOUT) { if (ProcessDecoderOutput(audioframe)) { onlyPrioMsgs = true; continue; } // if we only wanted priority messages, this isn't a stall if (priority) continue; if (m_processInfo.IsTempoAllowed(static_cast<float>(m_speed)/DVD_PLAYSPEED_NORMAL) && !m_stalled && m_syncState == IDVDStreamPlayer::SYNC_INSYNC) { // while AE sync is active, we still have time to fill buffers if (m_syncTimer.IsTimePast()) { CLog::Log(LOGNOTICE, "CVideoPlayerAudio::Process - stream stalled"); m_stalled = true; } } if (timeout == 0) Sleep(10); continue; } // handle messages if (pMsg->IsType(CDVDMsg::GENERAL_SYNCHRONIZE)) { if (static_cast<CDVDMsgGeneralSynchronize*>(pMsg)->Wait(100, SYNCSOURCE_AUDIO)) CLog::Log(LOGDEBUG, "CVideoPlayerAudio - CDVDMsg::GENERAL_SYNCHRONIZE"); else m_messageQueue.Put(pMsg->Acquire(), 1); // push back as prio message, to process other prio messages } else if (pMsg->IsType(CDVDMsg::GENERAL_RESYNC)) { //player asked us to set internal clock double pts = static_cast<CDVDMsgDouble*>(pMsg)->m_value; CLog::Log(LOGDEBUG, "CVideoPlayerAudio - CDVDMsg::GENERAL_RESYNC(%f), level: %d, cache: %f", pts, m_messageQueue.GetLevel(), m_audioSink.GetDelay()); double delay = m_audioSink.GetDelay(); if (pts > m_audioClock - delay + 0.5 * DVD_TIME_BASE) { m_audioSink.Flush(); } m_audioClock = pts + delay; if (m_speed != DVD_PLAYSPEED_PAUSE) m_audioSink.Resume(); m_syncState = IDVDStreamPlayer::SYNC_INSYNC; m_syncTimer.Set(3000); } else if (pMsg->IsType(CDVDMsg::GENERAL_RESET)) { if (m_pAudioCodec) m_pAudioCodec->Reset(); m_audioSink.Flush(); m_stalled = true; m_audioClock = 0; audioframe.nb_frames = 0; m_syncState = IDVDStreamPlayer::SYNC_STARTING; } else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) { bool sync = static_cast<CDVDMsgBool*>(pMsg)->m_value; m_audioSink.Flush(); m_stalled = true; m_audioClock = 0; audioframe.nb_frames = 0; if (sync) { m_syncState = IDVDStreamPlayer::SYNC_STARTING; m_audioSink.Pause(); } if (m_pAudioCodec) m_pAudioCodec->Reset(); } else if (pMsg->IsType(CDVDMsg::GENERAL_EOF)) { CLog::Log(LOGDEBUG, "CVideoPlayerAudio - CDVDMsg::GENERAL_EOF"); } else if (pMsg->IsType(CDVDMsg::PLAYER_SETSPEED)) { double speed = static_cast<CDVDMsgInt*>(pMsg)->m_value; if (m_processInfo.IsTempoAllowed(static_cast<float>(speed)/DVD_PLAYSPEED_NORMAL)) { if (speed != m_speed) { if (m_syncState == IDVDStreamPlayer::SYNC_INSYNC) { m_audioSink.Resume(); m_stalled = false; } } } else { m_audioSink.Pause(); } m_speed = (int)speed; } else if (pMsg->IsType(CDVDMsg::GENERAL_STREAMCHANGE)) { CDVDMsgAudioCodecChange* msg(static_cast<CDVDMsgAudioCodecChange*>(pMsg)); OpenStream(msg->m_hints, msg->m_codec); msg->m_codec = NULL; } else if (pMsg->IsType(CDVDMsg::GENERAL_PAUSE)) { m_paused = static_cast<CDVDMsgBool*>(pMsg)->m_value; CLog::Log(LOGDEBUG, "CVideoPlayerAudio - CDVDMsg::GENERAL_PAUSE: %d", m_paused); } else if (pMsg->IsType(CDVDMsg::PLAYER_REQUEST_STATE)) { SStateMsg msg; msg.player = VideoPlayer_AUDIO; msg.syncState = m_syncState; m_messageParent.Put(new CDVDMsgType<SStateMsg>(CDVDMsg::PLAYER_REPORT_STATE, msg)); } else if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET)) { DemuxPacket* pPacket = static_cast<CDVDMsgDemuxerPacket*>(pMsg)->GetPacket(); bool bPacketDrop = static_cast<CDVDMsgDemuxerPacket*>(pMsg)->GetPacketDrop(); if (bPacketDrop || (!m_processInfo.IsTempoAllowed(static_cast<float>(m_speed)/DVD_PLAYSPEED_NORMAL) && m_syncState == IDVDStreamPlayer::SYNC_INSYNC)) { pMsg->Release(); continue; } if (!m_pAudioCodec->AddData(*pPacket)) { m_messageQueue.PutBack(pMsg->Acquire()); onlyPrioMsgs = true; pMsg->Release(); continue; } m_audioStats.AddSampleBytes(pPacket->iSize); UpdatePlayerInfo(); if (ProcessDecoderOutput(audioframe)) { onlyPrioMsgs = true; } } // demuxer packet pMsg->Release(); } }
void CVideoPlayerAudio::Process() { CLog::Log(LOGNOTICE, "running thread: CVideoPlayerAudio::Process()"); DVDAudioFrame audioframe; m_audioStats.Start(); while (!m_bStop) { int result = DecodeFrame(audioframe); //Drop when not playing normally if (!ALLOW_AUDIO(m_speed) && m_syncState == IDVDStreamPlayer::SYNC_INSYNC) { result |= DECODE_FLAG_DROP; } UpdatePlayerInfo(); if (result & DECODE_FLAG_ERROR) { CLog::Log(LOGDEBUG, "CVideoPlayerAudio::Process - Decode Error"); continue; } if (result & DECODE_FLAG_TIMEOUT) { // Flush as the audio output may keep looping if we don't if (ALLOW_AUDIO(m_speed) && !m_stalled && m_syncState == IDVDStreamPlayer::SYNC_INSYNC) { m_stalled = true; } continue; } if (result & DECODE_FLAG_ABORT) { CLog::Log(LOGDEBUG, "CVideoPlayerAudio::Process - Abort received, exiting thread"); break; } if (audioframe.nb_frames == 0) continue; // demuxer reads metatags that influence channel layout if (m_streaminfo.codec == AV_CODEC_ID_FLAC && m_streaminfo.channellayout) audioframe.format.m_channelLayout = CAEUtil::GetAEChannelLayout(m_streaminfo.channellayout); // 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_dvdAudio.Create(audioframe, m_streaminfo.codec, m_setsynctype == SYNC_RESAMPLE)) CLog::Log(LOGERROR, "%s - failed to create audio renderer", __FUNCTION__); if (m_syncState == IDVDStreamPlayer::SYNC_INSYNC) m_dvdAudio.Resume(); m_streaminfo.channels = audioframe.format.m_channelLayout.Count(); g_dataCacheCore.SignalAudioInfoChange(); } // Zero out the frame data if we are supposed to silence the audio if (m_silence) { 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)) { SetSyncType(audioframe.passthrough); OutputPacket(audioframe); } // signal to our parent that we have initialized if(m_syncState == IDVDStreamPlayer::SYNC_STARTING && !(result & DECODE_FLAG_DROP)) { double cachetotal = DVD_SEC_TO_TIME(m_dvdAudio.GetCacheTotal()); double cachetime = m_dvdAudio.GetDelay(); if (cachetime >= cachetotal * 0.5) { m_syncState = IDVDStreamPlayer::SYNC_WAITSYNC; m_stalled = false; SStartMsg msg; msg.player = VideoPlayer_AUDIO; msg.cachetotal = cachetotal; msg.cachetime = cachetime; msg.timestamp = m_audioClock; m_messageParent.Put(new CDVDMsgType<SStartMsg>(CDVDMsg::PLAYER_STARTED, msg)); } } } }
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); } }