From 7cd8f51eb42432a9581e81712cc66f1cd25852c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Mei=C3=9Fner?= Date: Sun, 26 Oct 2014 22:54:37 +0100 Subject: [PATCH] Make audio work Includes some reorganization and cleanup --- CMakeLists.txt | 5 + Sources/Plasma/Apps/plClient/CMakeLists.txt | 11 +- Sources/Plasma/Apps/plClient/plClient.cpp | 21 +- Sources/Plasma/Apps/plClient/plClient.h | 2 +- .../FeatureLib/pfMoviePlayer/CMakeLists.txt | 4 +- .../pfMoviePlayer/plMoviePlayer.cpp | 264 +++++++----------- .../FeatureLib/pfMoviePlayer/plMoviePlayer.h | 19 +- .../PubUtilLib/plAudio/plWin32VideoSound.cpp | 89 ++++-- .../PubUtilLib/plAudio/plWin32VideoSound.h | 13 +- cmake/FindOpus.cmake | 11 +- cmake/FindVPX.cmake | 8 +- 11 files changed, 213 insertions(+), 234 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b3028e18..19fcc063 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,11 @@ if(WIN32) find_package(DirectX REQUIRED) endif(WIN32) +if (VPX_FOUND AND Opus_FOUND) + set(VIDEO_AVAILABLE TRUE) + add_definitions(-DVIDEO_AVAILABLE) +endif() + include(PrecompiledHeader) #Precompiled Header helper macros # libCurl isn't smart enough to detect this for us, so we have to configure it ourselves diff --git a/Sources/Plasma/Apps/plClient/CMakeLists.txt b/Sources/Plasma/Apps/plClient/CMakeLists.txt index 11d44a82..68baa7be 100644 --- a/Sources/Plasma/Apps/plClient/CMakeLists.txt +++ b/Sources/Plasma/Apps/plClient/CMakeLists.txt @@ -12,6 +12,11 @@ include_directories(${OPENSSL_INCLUDE_DIR}) include_directories(${PYTHON_INCLUDE_DIR}) include_directories(${CURL_INCLUDE_DIR}) +if (VIDEO_AVAILABLE) + include_directories(${VPX_INCLUDE_DIR}) + include_directories(${Opus_INCLUDE_DIR}) +endif (VIDEO_AVAILABLE) + # Test for Python Interpreter, which will be used for extra build scripts if available find_package(PythonInterp) if(PYTHONINTERP_FOUND) @@ -161,15 +166,15 @@ target_link_libraries(plClient ${Ogg_LIBRARIES}) target_link_libraries(plClient ${Vorbis_LIBRARIES}) target_link_libraries(plClient ${DirectX_LIBRARIES}) target_link_libraries(plClient ${CURL_LIBRARY}) -target_link_libraries(plClient ${Opus_LIBRARIES}) if(USE_VLD) target_link_libraries(plClient ${VLD_LIBRARY}) endif() -if (VPX_AVAILABLE) +if (VIDEO_AVAILABLE) target_link_libraries(plClient ${VPX_LIBRARY}) -endif (VPX_AVAILABLE) + target_link_libraries(plClient ${Opus_LIBRARIES}) +endif (VIDEO_AVAILABLE) if (WIN32) target_link_libraries(plClient rpcrt4) diff --git a/Sources/Plasma/Apps/plClient/plClient.cpp b/Sources/Plasma/Apps/plClient/plClient.cpp index 8db1ff5a..f8ab1b12 100644 --- a/Sources/Plasma/Apps/plClient/plClient.cpp +++ b/Sources/Plasma/Apps/plClient/plClient.cpp @@ -825,18 +825,18 @@ bool plClient::IHandleMovieMsg(plMovieMsg* mov) if (mov->GetFileName().IsEmpty()) return true; - int i = fMovies.GetCount(); + size_t i = fMovies.size(); if (!(mov->GetCmd() & plMovieMsg::kMake)) { - for (i = 0; i < fMovies.GetCount(); i++) + for (i = 0; i < fMovies.size(); i++) { if (mov->GetFileName().CompareI(fMovies[i]->GetFileName().AsString()) == 0) break; } } - if (i == fMovies.GetCount()) + if (i == fMovies.size()) { - fMovies.Append(new plMoviePlayer); + fMovies.push_back(new plMoviePlayer()); fMovies[i]->SetFileName(mov->GetFileName()); } @@ -892,7 +892,8 @@ bool plClient::IHandleMovieMsg(plMovieMsg* mov) if (!fMovies[i]->GetFileName().IsValid()) { delete fMovies[i]; - fMovies.Remove(i); + fMovies[i] = fMovies.back(); + fMovies.pop_back(); } return true; } @@ -1827,13 +1828,13 @@ bool plClient::IDraw() void plClient::IServiceMovies() { - int i; - for (i = 0; i < fMovies.GetCount(); i++) + for (size_t i = 0; i < fMovies.size(); i++) { if (!fMovies[i]->NextFrame()) { delete fMovies[i]; - fMovies.Remove(i); + fMovies[i] = fMovies.back(); + fMovies.pop_back(); i--; } } @@ -1841,9 +1842,9 @@ void plClient::IServiceMovies() void plClient::IKillMovies() { - for (int i = 0; i < fMovies.GetCount(); i++) + for (size_t i = 0; i < fMovies.size(); i++) delete fMovies[i]; - fMovies.Reset(); + fMovies.clear(); } bool plClient::IPlayIntroMovie(const char* movieName, float endDelay, float posX, float posY, float scaleX, float scaleY, float volume /* = 1.0 */) diff --git a/Sources/Plasma/Apps/plClient/plClient.h b/Sources/Plasma/Apps/plClient/plClient.h index 77c9a357..c81fa37b 100644 --- a/Sources/Plasma/Apps/plClient/plClient.h +++ b/Sources/Plasma/Apps/plClient/plClient.h @@ -147,7 +147,7 @@ protected: int fQuality; bool fQuitIntro; - hsTArray fMovies; + std::vector fMovies; plMessagePumpProc fMessagePumpProc; diff --git a/Sources/Plasma/FeatureLib/pfMoviePlayer/CMakeLists.txt b/Sources/Plasma/FeatureLib/pfMoviePlayer/CMakeLists.txt index 9e0e2f34..f50904eb 100644 --- a/Sources/Plasma/FeatureLib/pfMoviePlayer/CMakeLists.txt +++ b/Sources/Plasma/FeatureLib/pfMoviePlayer/CMakeLists.txt @@ -3,10 +3,10 @@ include_directories(../../NucleusLib) include_directories(../../NucleusLib/inc) include_directories(../../PubUtilLib) -if (VPX_AVAILABLE) +if (VIDEO_AVAILABLE) include_directories(${VPX_INCLUDE_DIR}) include_directories(${Opus_INCLUDE_DIR}) -endif (VPX_AVAILABLE) +endif (VIDEO_AVAILABLE) set(pfMoviePlayer_SOURCES plMoviePlayer.cpp diff --git a/Sources/Plasma/FeatureLib/pfMoviePlayer/plMoviePlayer.cpp b/Sources/Plasma/FeatureLib/pfMoviePlayer/plMoviePlayer.cpp index f0efa687..59cd6eb8 100644 --- a/Sources/Plasma/FeatureLib/pfMoviePlayer/plMoviePlayer.cpp +++ b/Sources/Plasma/FeatureLib/pfMoviePlayer/plMoviePlayer.cpp @@ -41,18 +41,15 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com *==LICENSE==*/ #include "plMoviePlayer.h" -#include -#include -#ifdef VPX_AVAILABLE +#ifdef VIDEO_AVAILABLE # define VPX_CODEC_DISABLE_COMPAT 1 # include # include # define iface (vpx_codec_vp9_dx()) +# include #endif -#include - #include "plGImage/plMipmap.h" #include "pnKeyedObject/plUoid.h" #include "plPipeline/hsGDeviceRef.h" @@ -61,12 +58,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "hsResMgr.h" #include "hsTimer.h" #include "plAudio/plWin32VideoSound.h" -#include "../Apps/plClient/plClient.h" -#include "plScene/plSceneNode.h" -#include "pnSceneObject/plSceneObject.h" -#include "pnSceneObject/plAudioInterface.h" -#include "pnMessage/plSoundMsg.h" -#include "plgDispatch.h" #include "webm/mkvreader.hpp" #include "webm/mkvparser.hpp" @@ -88,6 +79,7 @@ class VPX { VPX() { } +#ifdef VIDEO_AVAILABLE public: vpx_codec_ctx_t codec; @@ -121,6 +113,7 @@ public: // if this proves false, move decoder function into IProcessVideoFrame return vpx_codec_get_frame(&codec, &iter); } +#endif }; // ===================================================== @@ -133,57 +126,46 @@ class TrackMgr bool PeekNextBlockEntry(const std::unique_ptr& segment) { // Assume that if blk_entry == nullptr, we need to start from the beginning + // Load the current cluster const mkvparser::Cluster* cluster; if (blk_entry) cluster = blk_entry->GetCluster(); else cluster = segment->GetFirst(); - while (true) - { - if (cluster->EOS() && cluster != NULL) - { - cluster = segment->GetNext(cluster); - blk_entry = nullptr; - if (!cluster) - return false; - } - if (blk_entry) - { - SAFE_OP(cluster->GetNext(blk_entry, blk_entry), "get next block"); - } - else if (cluster->m_pSegment != NULL) + // As long as we have clusters, they contain blocks that we have to process + while (cluster && !cluster->EOS()) { + // If we have no block yet, get the first one, otherwise the next one + if (!blk_entry) { SAFE_OP(cluster->GetFirst(blk_entry), "get first block"); } else { - blk_entry = nullptr; - return false; //reached end of movie. I hope. + SAFE_OP(cluster->GetNext(blk_entry, blk_entry), "get next block"); } - if (blk_entry) - { - if (blk_entry->EOS()) - continue; + // Are there any blocks left? + while (blk_entry && !blk_entry->EOS()) { + // Is this the next block we want for our track? Awesome, we're done! if (blk_entry->GetBlock()->GetTrackNumber() == number) return true; + SAFE_OP(cluster->GetNext(blk_entry, blk_entry), "get next block"); } - else - { - cluster = segment->GetNext(cluster); - blk_entry = nullptr; - if (!cluster) - return false; - } + + // No blocks left, go to next cluster + blk_entry = nullptr; + cluster = segment->GetNext(cluster); } - return false; // if this happens, boom. + + // That's it, nothing left... + return false; } public: - uint32_t number; + int32_t number; - TrackMgr(uint32_t num) : blk_entry(nullptr), valid(true), number(num) { } + TrackMgr(int32_t num) : blk_entry(nullptr), valid(true), number(num) { } bool GetFrames(plMoviePlayer* p, int64_t movieTime, std::vector& frames) { @@ -204,7 +186,8 @@ public: data.Read(p->fReader, buf); frames.push_back(std::make_tuple(std::unique_ptr(buf), static_cast(data.len))); } - } else + } + else { blk_entry = prev; return true; @@ -213,42 +196,6 @@ public: } return true; } - -#if 0 - bool Advance(plMoviePlayer* p, int64_t movieTime=0) - { - if (!valid) - return false; - - // This keeps us from getting behind due to freezes - // Assumption: Audio will not skip ahead in time. FIXME? - while ((valid = PeekNextBlockEntry(p->fSegment))) - { - const mkvparser::Block* blk = blk_entry->GetBlock(); - if (blk->GetTime(blk_entry->GetCluster()) < movieTime) - continue; - else - return true; - } - return false; // ran out of blocks - } - - int32_t GetBlockData(plMoviePlayer* p, std::vector& frames) const - { - const mkvparser::Block* block = blk_entry->GetBlock(); - - // Return the frames - frames.reserve(block->GetFrameCount()); - for (int32_t i = 0; i < block->GetFrameCount(); ++i) - { - const mkvparser::Block::Frame frame = block->GetFrame(i); - std::shared_ptr data(new uint8_t[frame.len]); - frame.Read(p->fReader, data.get()); - frames.push_back(std::make_tuple(data, frame.len)); - } - return block->GetFrameCount(); - } -#endif 0 }; // ===================================================== @@ -257,44 +204,27 @@ plMoviePlayer::plMoviePlayer() : fPlate(nullptr), fTexture(nullptr), fReader(nullptr), - fTimeScale(0), fStartTime(0), - fAudioPlayer(), fPosition(hsPoint2()), - fAudioInterface(), - fPlaying(true), - fOpusDecoder(nil) + fPlaying(false), + fOpusDecoder(nullptr) { fScale.Set(1.0f, 1.0f); - - - fAudioSound = std::shared_ptr(new plWin32VideoSound()); - fAudioPlayer.SetSound(fAudioSound); - plSceneNode* sceneNode = plClient::GetInstance()->GetCurrentScene(); - if (sceneNode != nullptr) - { - hsTArray& sceneObjects = sceneNode->GetSceneObjects(); - for (int i = 0; i < sceneObjects.GetCount(); ++i) - { - if (sceneObjects[i]->GetAudioInterface() == nullptr) - { - fAudioInterface.ISetAudible(&fAudioPlayer); - sceneObjects[i]->SetAudioInterface(&fAudioInterface); - break; - } - } - } } plMoviePlayer::~plMoviePlayer() { - opus_decoder_destroy(fOpusDecoder); if (fPlate) // The plPlate owns the Mipmap Texture, so it destroys it for us plPlateManager::Instance().DestroyPlate(fPlate); -#ifdef VPX_AVAILABLE +#ifdef VIDEO_AVAILABLE + if (fOpusDecoder) + opus_decoder_destroy(fOpusDecoder); if (fReader) + { fReader->Close(); + delete fReader; + } #endif } @@ -305,7 +235,7 @@ int64_t plMoviePlayer::GetMovieTime() const bool plMoviePlayer::IOpenMovie() { -#ifdef VPX_AVAILABLE +#ifdef VIDEO_AVAILABLE if (!plFileInfo(fMoviePath).Exists()) { hsAssert(false, "Tried to play a movie that doesn't exist"); @@ -326,9 +256,6 @@ bool plMoviePlayer::IOpenMovie() SAFE_OP(seg->Load(), "load segment from webm"); fSegment.reset(seg); - // Just in case someone gives us a weird file, find out the timecode offset - fTimeScale = fSegment->GetInfo()->GetTimeCodeScale(); - // TODO: Figure out video and audio based on current language // For now... just take the first one. const mkvparser::Tracks* tracks = fSegment->GetTracks(); @@ -360,8 +287,9 @@ bool plMoviePlayer::IOpenMovie() #endif } -bool plMoviePlayer::IProcessVideoFrame(const std::vector& frames) +void plMoviePlayer::IProcessVideoFrame(const std::vector& frames) { +#ifdef VIDEO_AVAILABLE vpx_image_t* img = nullptr; // We have to decode all the frames, but we only want to display the most recent one to the user. @@ -390,34 +318,45 @@ bool plMoviePlayer::IProcessVideoFrame(const std::vector& frames) // Flush new data to the device if (fTexture->GetDeviceRef()) fTexture->GetDeviceRef()->SetDirty(true); - return true; } - return false; +#endif } -bool plMoviePlayer::Start() +void plMoviePlayer::IProcessAudioFrame(const std::vector& frames) { - plSceneNode* sceneNode = plClient::GetInstance()->GetCurrentScene(); - if (sceneNode != nullptr) - sceneNode->GetKey(); +#ifdef VIDEO_AVAILABLE + const unsigned char* data = nullptr; + int32_t size = 0; + for (auto it = frames.begin(); it != frames.end(); ++it) + { + const std::unique_ptr& buf = std::get<0>(*it); + data = buf.get(); + size = std::get<1>(*it); -#ifdef VPX_AVAILABLE + static const int frameSize = 5760; //max packet duration at 48kHz + const mkvparser::AudioTrack* audio = static_cast(fSegment->GetTracks()->GetTrackByNumber(fAudioTrack->number)); + int16_t* pcm = new int16_t[frameSize * audio->GetChannels() * sizeof(int16_t)]; + int samples = opus_decode(fOpusDecoder, data, size, pcm, frameSize, 0); + if (samples < 0) + hsAssert(false, "opus error"); + fAudioSound->UpdateSoundBuffer(reinterpret_cast(pcm), samples * audio->GetChannels() * sizeof(int16_t)); + } +#endif +} + +bool plMoviePlayer::Start() +{ +#ifdef VIDEO_AVAILABLE if (!IOpenMovie()) return false; hsAssert(fVideoTrack, "nil video track -- expect bad things to happen!"); - // Initialize VP8 + // Initialize VPX if (VPX* vpx = VPX::Create()) fVpx.reset(vpx); else return false; - //initialize opus - int error; - fOpusDecoder = opus_decoder_create(48000, 1, &error); - if (error != OPUS_OK) - hsAssert(false, "Error occured initalizing opus"); - // Need to figure out scaling based on pipe size. plPlateManager& plateMgr = plPlateManager::Instance(); const mkvparser::VideoTrack* video = static_cast(fSegment->GetTracks()->GetTrackByNumber(fVideoTrack->number)); @@ -428,19 +367,34 @@ bool plMoviePlayer::Start() fPlate->SetVisible(true); fTexture = fPlate->CreateMaterial(static_cast(video->GetWidth()), static_cast(video->GetHeight()), nullptr); + //initialize opus + const mkvparser::AudioTrack* audio = static_cast(fSegment->GetTracks()->GetTrackByNumber(fAudioTrack->number)); + plWAVHeader header; + header.fFormatTag = plWAVHeader::kPCMFormatTag; + header.fNumChannels = audio->GetChannels(); + header.fBitsPerSample = audio->GetBitDepth() == 8 ? 8 : 16; + header.fNumSamplesPerSec = 48000; // OPUS specs say we shall always decode at 48kHz + header.fBlockAlign = header.fNumChannels * header.fBitsPerSample / 2; + header.fAvgBytesPerSec = header.fNumSamplesPerSec * header.fBlockAlign; + fAudioSound.reset(new plWin32VideoSound(header)); + int error; + fOpusDecoder = opus_decoder_create(48000, audio->GetChannels(), &error); + if (error != OPUS_OK) + hsAssert(false, "Error occured initalizing opus"); + fPlaying = true; return true; #else return false; -#endif // VPX_AVAILABLE +#endif // VIDEO_AVAILABLE } bool plMoviePlayer::NextFrame() { if (fPlaying) { -#ifdef VPX_AVAILABLE +#ifdef VIDEO_AVAILABLE // Get our current timecode int64_t movieTime = 0; if (fStartTime == 0) @@ -450,23 +404,21 @@ bool plMoviePlayer::NextFrame() std::vector audio; std::vector video; + uint8_t tracksWithData = 0; + if (fAudioTrack) { - uint8_t tracksWithData = 0; - if (fAudioTrack) - { - if (fAudioTrack->GetFrames(this, movieTime, audio)) - tracksWithData++; - } - if (fVideoTrack) - { - if (fVideoTrack->GetFrames(this, movieTime, video)) - tracksWithData++; - } - if (tracksWithData == 0) - { - Stop(); - return false; - } + if (fAudioTrack->GetFrames(this, movieTime, audio)) + tracksWithData++; + } + if (fVideoTrack) + { + if (fVideoTrack->GetFrames(this, movieTime, video)) + tracksWithData++; + } + if (!tracksWithData) + { + Stop(); + return false; } // Show our mess @@ -476,7 +428,7 @@ bool plMoviePlayer::NextFrame() return true; #else return false; -#endif // VPX_AVAILABLE +#endif // VIDEO_AVAILABLE } return false; } @@ -484,36 +436,10 @@ bool plMoviePlayer::NextFrame() bool plMoviePlayer::Stop() { fPlaying = false; + if (fAudioSound) + fAudioSound->Stop(); for (int i = 0; i < fCallbacks.size(); i++) fCallbacks[i]->Send(); fCallbacks.clear(); - return false; -} - -bool plMoviePlayer::IProcessAudioFrame(const std::vector& frames) -{ - const unsigned char* data = NULL; - int32_t size = 0; - for (auto it = frames.begin(); it != frames.end(); ++it) - { - const std::unique_ptr& buf = std::get<0>(*it); - data = buf.get(); - size = std::get<1>(*it); - - int error; - const int frameSize = 5760; //max packet duration at 48kHz - opus_int16* pcm = new opus_int16[frameSize * 1 * sizeof(opus_int16)]; - error = opus_decode(fOpusDecoder, data, size, pcm, frameSize, 0); - if (error < 0) - hsAssert(false, "opus error"); - fAudioSound->UpdateSoundBuffer(reinterpret_cast(pcm), error); - if (plClient::GetInstance()->GetCurrentScene() != nullptr) - { - plSoundMsg* soundMsg = new plSoundMsg(); - soundMsg->SetCmd(plSoundMsg::kPlay); - soundMsg->SetBCastFlag(plMessage::kBCastByType); - fAudioInterface.MsgReceive(soundMsg); - } - } return true; } diff --git a/Sources/Plasma/FeatureLib/pfMoviePlayer/plMoviePlayer.h b/Sources/Plasma/FeatureLib/pfMoviePlayer/plMoviePlayer.h index e774c4f1..14401c21 100644 --- a/Sources/Plasma/FeatureLib/pfMoviePlayer/plMoviePlayer.h +++ b/Sources/Plasma/FeatureLib/pfMoviePlayer/plMoviePlayer.h @@ -48,16 +48,11 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "hsPoint2.h" #include "hsColorRGBA.h" #include "plMessage/plMovieMsg.h" -#include "plAudio/plWin32VideoSound.h" -#include "plAudible/plVideoAudible.h" -#include "pnSceneObject/plAudioInterface.h" #include #include #include -#include - namespace mkvparser { class BlockEntry; @@ -79,23 +74,21 @@ protected: mkvparser::MkvReader* fReader; std::unique_ptr fSegment; std::unique_ptr fAudioTrack, fVideoTrack; // TODO: vector of tracks? + std::unique_ptr fAudioSound; + std::unique_ptr fVpx; - int64_t fTimeScale, fStartTime; + class OpusDecoder* fOpusDecoder; + int64_t fStartTime; hsPoint2 fPosition, fScale; plFileName fMoviePath; - OpusDecoder* fOpusDecoder; - std::shared_ptr fAudioSound; - plVideoAudible fAudioPlayer; - plAudioInterface fAudioInterface; - bool fPlaying; int64_t GetMovieTime() const; bool IOpenMovie(); - bool IProcessVideoFrame(const std::vector& frames); - bool IProcessAudioFrame(const std::vector& frames); + void IProcessVideoFrame(const std::vector& frames); + void IProcessAudioFrame(const std::vector& frames); public: plMoviePlayer(); diff --git a/Sources/Plasma/PubUtilLib/plAudio/plWin32VideoSound.cpp b/Sources/Plasma/PubUtilLib/plAudio/plWin32VideoSound.cpp index 20ae005d..819136ed 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plWin32VideoSound.cpp +++ b/Sources/Plasma/PubUtilLib/plAudio/plWin32VideoSound.cpp @@ -1,47 +1,98 @@ -#include -#include +/*==LICENSE==* -#include "hsResMgr.h" -#include "plFormat.h" +CyanWorlds.com Engine - MMOG client, server and tools +Copyright (C) 2011 Cyan Worlds, Inc. -#include "plDSoundBuffer.h" +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +Additional permissions under GNU GPL version 3 section 7 + +If you modify this Program, or any covered work, by linking or +combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, +NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent +JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK +(or a modified version of those libraries), +containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, +PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG +JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the +licensors of this Program grant you additional +permission to convey the resulting work. Corresponding Source for a +non-source form of such a combination shall include the source code for +the parts of OpenSSL and IJG JPEG Library used as well as that of the covered +work. + +You can contact Cyan Worlds, Inc. by email legal@cyan.com + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 + +*==LICENSE==*/ #include "plWin32VideoSound.h" +#include "hsResMgr.h" +#include "plFormat.h" +#include "plDSoundBuffer.h" + static int uniqueID = 0; -plWin32VideoSound::plWin32VideoSound() : plWin32Sound() +plWin32VideoSound::plWin32VideoSound(plWAVHeader& header) : plWin32Sound() { - plWAVHeader header; - header.fFormatTag = 0x1; - header.fNumChannels = 1; - header.fBitsPerSample = 16; + fCurrVolume = 1.0f; + fDesiredVol = 1.0f; + fSoftVolume = 1.0f; + fType = kGUISound; + fDSoundBuffer = new plDSoundBuffer(0, header, false, false, false, true); fDSoundBuffer->SetupVoiceSource(); + fDSoundBuffer->SetScalarVolume(1.0f); + uniqueID++; hsgResMgr::ResMgr()->NewKey(plFormat("videosound#{}", uniqueID), this, plLocation::kGlobalFixedLoc); - fSoftVolume = 1.0f; } plWin32VideoSound::~plWin32VideoSound() { - delete fDSoundBuffer; + if (fDSoundBuffer) + delete fDSoundBuffer; } -void plWin32VideoSound::UpdateSoundBuffer(unsigned char* buffer, size_t size) +void plWin32VideoSound::UpdateSoundBuffer(void* buffer, size_t size) { - unsigned int bufferID = 0; + uint32_t bufferId; + uint32_t chunk; - if (fDSoundBuffer->GetAvailableBufferId(&bufferID)) + fDSoundBuffer->UnQueueVoiceBuffers(); + while (size > 0) { - fDSoundBuffer->VoiceFillBuffer(buffer, size, bufferID); - IActuallyPlay(); + chunk = size < STREAM_BUFFER_SIZE ? size : STREAM_BUFFER_SIZE; + if (!fDSoundBuffer->GetAvailableBufferId(&bufferId)) + break; + + fDSoundBuffer->VoiceFillBuffer(buffer, chunk, bufferId); + size -= chunk; } + IActuallyPlay(); } void plWin32VideoSound::IDerivedActuallyPlay() { - if (!fDSoundBuffer->IsPlaying()) + if (!fReallyPlaying) + { fDSoundBuffer->Play(); + fReallyPlaying = true; + } } bool plWin32VideoSound::LoadSound(bool is3D) @@ -66,4 +117,4 @@ float plWin32VideoSound::GetActualTimeSec() void plWin32VideoSound::ISetActualTime(double t) { hsAssert(false, "unimplemented cause unnecessary for this class"); -} \ No newline at end of file +} diff --git a/Sources/Plasma/PubUtilLib/plAudio/plWin32VideoSound.h b/Sources/Plasma/PubUtilLib/plAudio/plWin32VideoSound.h index 0884152d..bdddf7d8 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plWin32VideoSound.h +++ b/Sources/Plasma/PubUtilLib/plAudio/plWin32VideoSound.h @@ -33,12 +33,13 @@ the parts of OpenSSL and IJG JPEG Library used as well as that of the covered work. You can contact Cyan Worlds, Inc. by email legal@cyan.com -or by snail mail at: -Cyan Worlds, Inc. -14617 N Newport Hwy -Mead, WA 99021 + or by snail mail at: + Cyan Worlds, Inc. + 14617 N Newport Hwy + Mead, WA 99021 *==LICENSE==*/ + #ifndef plWin32VideoSound_h #define plWin32VideoSound_h @@ -47,10 +48,10 @@ Mead, WA 99021 class plWin32VideoSound : public plWin32Sound { public: - plWin32VideoSound(); + plWin32VideoSound(plWAVHeader& header); virtual ~plWin32VideoSound(); - void UpdateSoundBuffer(unsigned char* buffer, size_t size); + void UpdateSoundBuffer(void* buffer, size_t size); protected: void IDerivedActuallyPlay(void); diff --git a/cmake/FindOpus.cmake b/cmake/FindOpus.cmake index 6864a304..11b6c589 100644 --- a/cmake/FindOpus.cmake +++ b/cmake/FindOpus.cmake @@ -1,8 +1,7 @@ if(Opus_INCLUDE_DIR AND Opus_LIBRARY) - set(Opus_FIND_QUIETLY TRUE) + set(Opus_FIND_QUIETLY TRUE) endif() - find_path(Opus_INCLUDE_DIR opus.h /usr/local/include /usr/include @@ -20,11 +19,11 @@ find_library(Silk_LIBRARY NAMES silk_common set(Opus_LIBRARIES ${Opus_LIBRARY} ${Celt_LIBRARY} - ${Silk_LIBRARY}) - + ${Silk_LIBRARY} +) if(Opus_INCLUDE_DIR AND Opus_LIBRARY) - set(Opus_FOUND TRUE) + set(Opus_FOUND TRUE) endif() if (Opus_FOUND) @@ -35,4 +34,4 @@ else() if(Opus_FIND_REQUIRED) message(FATAL_ERROR "Could not find libopus") endif() -endif() \ No newline at end of file +endif() diff --git a/cmake/FindVPX.cmake b/cmake/FindVPX.cmake index 0a94da51..53dadac5 100644 --- a/cmake/FindVPX.cmake +++ b/cmake/FindVPX.cmake @@ -7,12 +7,10 @@ find_path(VPX_INCLUDE_DIR vpx/vp8.h /usr/include ) -find_library(VPX_LIBRARY NAMES vpxmt vpx +find_library(VPX_LIBRARY NAMES vpxmt vpxmd vpx PATHS /usr/local/lib /usr/lib ) -# If everything has been found, we have movie support! -if (VPX_INCLUDE_DIR AND VPX_LIBRARY) - set(VPX_AVAILABLE TRUE) - add_definitions(-DVPX_AVAILABLE) +if(VPX_INCLUDE_DIR AND VPX_LIBRARY) + set(VPX_FOUND TRUE) endif()