2019-02-13 23:02:43 -05:00
|
|
|
#include "stdafx.h"
|
|
|
|
#include "IRenderingDevice.h"
|
|
|
|
#include "VideoRenderer.h"
|
|
|
|
#include "VideoDecoder.h"
|
|
|
|
#include "Console.h"
|
2019-03-15 12:48:34 -04:00
|
|
|
#include "EmuSettings.h"
|
2020-02-05 18:57:20 -05:00
|
|
|
#include "MessageManager.h"
|
|
|
|
#include "../Utilities/IVideoRecorder.h"
|
|
|
|
#include "../Utilities/AviRecorder.h"
|
|
|
|
#include "../Utilities/GifRecorder.h"
|
2019-02-13 23:02:43 -05:00
|
|
|
|
|
|
|
VideoRenderer::VideoRenderer(shared_ptr<Console> console)
|
|
|
|
{
|
|
|
|
_console = console;
|
2021-03-10 11:13:28 -05:00
|
|
|
_stopFlag = false;
|
2019-02-13 23:02:43 -05:00
|
|
|
StartThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
VideoRenderer::~VideoRenderer()
|
|
|
|
{
|
|
|
|
_stopFlag = true;
|
|
|
|
StopThread();
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoRenderer::StartThread()
|
|
|
|
{
|
|
|
|
#ifndef LIBRETRO
|
2021-03-10 11:13:28 -05:00
|
|
|
if(!_renderThread) {
|
2019-02-13 23:02:43 -05:00
|
|
|
_stopFlag = false;
|
|
|
|
_waitForRender.Reset();
|
|
|
|
|
|
|
|
_renderThread.reset(new std::thread(&VideoRenderer::RenderThread, this));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoRenderer::StopThread()
|
|
|
|
{
|
|
|
|
#ifndef LIBRETRO
|
|
|
|
_stopFlag = true;
|
2021-03-10 11:13:28 -05:00
|
|
|
if(_renderThread) {
|
2019-02-13 23:02:43 -05:00
|
|
|
_renderThread->join();
|
|
|
|
_renderThread.reset();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoRenderer::RenderThread()
|
|
|
|
{
|
2021-03-10 11:13:28 -05:00
|
|
|
if(_renderer) {
|
2019-02-13 23:02:43 -05:00
|
|
|
_renderer->Reset();
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
while(!_stopFlag.load()) {
|
2019-02-13 23:02:43 -05:00
|
|
|
//Wait until a frame is ready, or until 16ms have passed (to allow UI to run at a minimum of 60fps)
|
|
|
|
_waitForRender.Wait(16);
|
2021-03-10 11:13:28 -05:00
|
|
|
if(_renderer) {
|
2019-02-13 23:02:43 -05:00
|
|
|
_renderer->Render();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-05 18:57:20 -05:00
|
|
|
void VideoRenderer::UpdateFrame(void* frameBuffer, uint32_t width, uint32_t height)
|
2019-02-13 23:02:43 -05:00
|
|
|
{
|
2020-02-05 18:57:20 -05:00
|
|
|
shared_ptr<IVideoRecorder> recorder = _recorder;
|
2021-03-10 11:13:28 -05:00
|
|
|
if(recorder) {
|
2020-02-05 18:57:20 -05:00
|
|
|
recorder->AddFrame(frameBuffer, width, height, _console->GetFps());
|
2019-03-15 12:48:34 -04:00
|
|
|
}
|
2020-02-05 18:57:20 -05:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(_renderer) {
|
2019-02-13 23:02:43 -05:00
|
|
|
_renderer->UpdateFrame(frameBuffer, width, height);
|
|
|
|
_waitForRender.Signal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
void VideoRenderer::RegisterRenderingDevice(IRenderingDevice *renderer)
|
2019-02-13 23:02:43 -05:00
|
|
|
{
|
|
|
|
_renderer = renderer;
|
|
|
|
StartThread();
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
void VideoRenderer::UnregisterRenderingDevice(IRenderingDevice *renderer)
|
2019-02-13 23:02:43 -05:00
|
|
|
{
|
2021-03-10 11:13:28 -05:00
|
|
|
if(_renderer == renderer) {
|
2019-02-13 23:02:43 -05:00
|
|
|
StopThread();
|
|
|
|
_renderer = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoRenderer::StartRecording(string filename, VideoCodec codec, uint32_t compressionLevel)
|
|
|
|
{
|
|
|
|
FrameInfo frameInfo = _console->GetVideoDecoder()->GetFrameInfo();
|
2020-02-05 18:57:20 -05:00
|
|
|
|
|
|
|
shared_ptr<IVideoRecorder> recorder;
|
2021-03-10 11:13:28 -05:00
|
|
|
if(codec == VideoCodec::GIF) {
|
2020-02-05 18:57:20 -05:00
|
|
|
recorder.reset(new GifRecorder());
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2020-02-05 18:57:20 -05:00
|
|
|
recorder.reset(new AviRecorder(codec, compressionLevel));
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(recorder->StartRecording(filename, frameInfo.Width, frameInfo.Height, 4, _console->GetSettings()->GetAudioConfig().SampleRate, _console->GetFps())) {
|
2020-02-05 18:57:20 -05:00
|
|
|
_recorder = recorder;
|
|
|
|
MessageManager::DisplayMessage("VideoRecorder", "VideoRecorderStarted", filename);
|
2019-02-13 23:02:43 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoRenderer::AddRecordingSound(int16_t* soundBuffer, uint32_t sampleCount, uint32_t sampleRate)
|
|
|
|
{
|
2020-02-05 18:57:20 -05:00
|
|
|
shared_ptr<IVideoRecorder> recorder = _recorder;
|
2021-03-10 11:13:28 -05:00
|
|
|
if(recorder) {
|
2020-02-05 18:57:20 -05:00
|
|
|
recorder->AddSound(soundBuffer, sampleCount, sampleRate);
|
2019-02-13 23:02:43 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoRenderer::StopRecording()
|
|
|
|
{
|
2020-02-05 18:57:20 -05:00
|
|
|
shared_ptr<IVideoRecorder> recorder = _recorder;
|
2021-03-10 11:13:28 -05:00
|
|
|
if(recorder) {
|
2020-02-05 18:57:20 -05:00
|
|
|
MessageManager::DisplayMessage("VideoRecorder", "VideoRecorderStopped", recorder->GetOutputFile());
|
|
|
|
}
|
|
|
|
_recorder.reset();
|
2019-02-13 23:02:43 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
bool VideoRenderer::IsRecording()
|
|
|
|
{
|
2020-02-05 18:57:20 -05:00
|
|
|
return _recorder != nullptr && _recorder->IsRecording();
|
2021-03-10 11:13:28 -05:00
|
|
|
}
|