From b0fa0a83f8a370e3661de3c06fce85e53973f189 Mon Sep 17 00:00:00 2001 From: smelenchuk Date: Fri, 11 Feb 2011 18:59:42 +0000 Subject: [PATCH] * Dump AVI output on every VI (fixes issue #4064). * Add audio dumping (fixes issue #1638). git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7131 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/AudioCommon/Src/AudioCommon.cpp | 20 ++++++------ .../AudioCommon/Src/AudioCommonConfig.cpp | 2 ++ .../Core/AudioCommon/Src/AudioCommonConfig.h | 1 + Source/Core/AudioCommon/Src/Mixer.cpp | 28 ++++++++++++---- Source/Core/AudioCommon/Src/Mixer.h | 29 +++++++++++++++++ Source/Core/Common/Src/CommonPaths.h | 1 + Source/Core/Common/Src/FileUtil.cpp | 4 +++ Source/Core/Common/Src/FileUtil.h | 1 + Source/Core/DolphinWX/Src/ConfigMain.cpp | 6 ++++ Source/Core/DolphinWX/Src/ConfigMain.h | 2 ++ Source/Core/VideoCommon/Src/AVIDump.cpp | 19 ++++++----- Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 17 ++++++++-- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 32 ++++++++++++++++--- 13 files changed, 132 insertions(+), 30 deletions(-) diff --git a/Source/Core/AudioCommon/Src/AudioCommon.cpp b/Source/Core/AudioCommon/Src/AudioCommon.cpp index 547c0a8fe6..043d07d151 100644 --- a/Source/Core/AudioCommon/Src/AudioCommon.cpp +++ b/Source/Core/AudioCommon/Src/AudioCommon.cpp @@ -16,6 +16,7 @@ // http://code.google.com/p/dolphin-emu/ #include "AudioCommon.h" +#include "FileUtil.h" #include "Mixer.h" #include "NullSoundStream.h" #include "DSoundStream.h" @@ -53,11 +54,13 @@ namespace AudioCommon ac_Config.Update(); if (soundStream->Start()) { -#if 0 - // Start the sound recording - if (ac_Config.record) - soundStream->StartLogAudio(FULL_DUMP_DIR g_Config.recordFile); -#endif + if (ac_Config.m_DumpAudio) { + char audio_file_name[255]; + snprintf(audio_file_name, 255, "%saudiodump.wav", File::GetUserPath(D_DUMPAUDIO_IDX)); + mixer->StartLogAudio(audio_file_name); + //soundStream->StartLogAudio(audio_file_name); + } + return soundStream; } PanicAlertT("Could not initialize backend %s.", backend.c_str()); @@ -76,10 +79,9 @@ namespace AudioCommon if (soundStream) { soundStream->Stop(); -#if 0 - if (ac_Config.record) - soundStream->StopLogAudio(); -#endif + if (ac_Config.m_DumpAudio) + soundStream->GetMixer()->StopLogAudio(); + //soundStream->StopLogAudio(); delete soundStream; soundStream = NULL; } diff --git a/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp b/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp index 6a8a22f5e5..6e22512c06 100644 --- a/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp +++ b/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp @@ -33,6 +33,7 @@ void AudioCommonConfig::Load() file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true); file.Get("Config", "EnableThrottle", &m_EnableThrottle, true); file.Get("Config", "EnableJIT", &m_EnableJIT, true); + file.Get("Config", "DumpAudio", &m_DumpAudio, false); #if defined __linux__ && HAVE_ALSA file.Get("Config", "Backend", &sBackend, BACKEND_ALSA); #elif defined __APPLE__ @@ -55,6 +56,7 @@ void AudioCommonConfig::SaveSettings() file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic); file.Set("Config", "EnableThrottle", m_EnableThrottle); file.Set("Config", "EnableJIT", m_EnableJIT); + file.Set("Config", "DumpAudio", m_DumpAudio); file.Set("Config", "Backend", sBackend); file.Set("Config", "Frequency", sFrequency); file.Set("Config", "Volume", m_Volume); diff --git a/Source/Core/AudioCommon/Src/AudioCommonConfig.h b/Source/Core/AudioCommon/Src/AudioCommonConfig.h index c5f2efe645..98cbf60500 100644 --- a/Source/Core/AudioCommon/Src/AudioCommonConfig.h +++ b/Source/Core/AudioCommon/Src/AudioCommonConfig.h @@ -36,6 +36,7 @@ struct AudioCommonConfig bool m_EnableDTKMusic; bool m_EnableThrottle; bool m_EnableJIT; + bool m_DumpAudio; int m_Volume; std::string sBackend; int sFrequency; diff --git a/Source/Core/AudioCommon/Src/Mixer.cpp b/Source/Core/AudioCommon/Src/Mixer.cpp index c8eece73c7..8dcc972535 100644 --- a/Source/Core/AudioCommon/Src/Mixer.cpp +++ b/Source/Core/AudioCommon/Src/Mixer.cpp @@ -125,15 +125,29 @@ unsigned int CMixer::Mix(short* samples, unsigned int numSamples) if (numSamples > numLeft) memset(&samples[numLeft * 2], 0, (numSamples - numLeft) * 4); - // Add the DSPHLE sound, re-sampling is done inside - Premix(samples, numSamples); + //when logging, also throttle HLE audio + if (m_logAudio) { + if (m_AIplaying) { + Premix(samples, numLeft); - // Add the DTK Music - if (m_EnableDTKMusic) - { - // Re-sampling is done inside - AudioInterface::Callback_GetStreaming(samples, numSamples, m_sampleRate); + if (m_EnableDTKMusic) + AudioInterface::Callback_GetStreaming(samples, numLeft, m_sampleRate); + + g_wave_writer.AddStereoSamples(samples, numLeft); + } } + else { //or mix as usual + // Add the DSPHLE sound, re-sampling is done inside + Premix(samples, numSamples); + + // Add the DTK Music + if (m_EnableDTKMusic) + { + // Re-sampling is done inside + AudioInterface::Callback_GetStreaming(samples, numSamples, m_sampleRate); + } + } + Common::AtomicAdd(m_numSamples, -(s32)numLeft); diff --git a/Source/Core/AudioCommon/Src/Mixer.h b/Source/Core/AudioCommon/Src/Mixer.h index 0ce68ed259..9d7459921f 100644 --- a/Source/Core/AudioCommon/Src/Mixer.h +++ b/Source/Core/AudioCommon/Src/Mixer.h @@ -18,6 +18,8 @@ #ifndef _MIXER_H_ #define _MIXER_H_ +#include "WaveFile.h" + // 16 bit Stereo #define MAX_SAMPLES (1024 * 8) #define INDEX_MASK (MAX_SAMPLES * 2 - 1) @@ -36,6 +38,7 @@ public: , m_indexW(0) , m_indexR(0) , m_AIplaying(true) + , m_logAudio(0) { // AyuanX: The internal (Core & DSP) sample rate is fixed at 32KHz // So when AI/DAC sample rate differs than 32KHz, we have to do re-sampling @@ -63,14 +66,40 @@ public: void SetHLEReady(bool ready) { m_HLEready = ready;} // --------------------- + + virtual void StartLogAudio(const char *filename) { + if (! m_logAudio) { + m_logAudio = true; + g_wave_writer.Start(filename); + g_wave_writer.SetSkipSilence(false); + NOTICE_LOG(DSPHLE, "Starting Audio logging"); + } else { + WARN_LOG(DSPHLE, "Audio logging already started"); + } + } + + virtual void StopLogAudio() { + if (m_logAudio) { + m_logAudio = false; + g_wave_writer.Stop(); + NOTICE_LOG(DSPHLE, "Stopping Audio logging"); + } else { + WARN_LOG(DSPHLE, "Audio logging already stopped"); + } + } + + protected: unsigned int m_sampleRate; unsigned int m_aiSampleRate; unsigned int m_dacSampleRate; int m_bits; int m_channels; + + WaveFileWriter g_wave_writer; bool m_HLEready; + bool m_logAudio; bool m_EnableDTKMusic; bool m_throttle; diff --git a/Source/Core/Common/Src/CommonPaths.h b/Source/Core/Common/Src/CommonPaths.h index 3d08c568a2..96ced5b7c6 100644 --- a/Source/Core/Common/Src/CommonPaths.h +++ b/Source/Core/Common/Src/CommonPaths.h @@ -83,6 +83,7 @@ #define DUMP_DIR "Dump" #define DUMP_TEXTURES_DIR DUMP_DIR DIR_SEP "Textures" #define DUMP_FRAMES_DIR DUMP_DIR DIR_SEP "Frames" +#define DUMP_AUDIO_DIR DUMP_DIR DIR_SEP "Audio" #define DUMP_DSP_DIR DUMP_DIR DIR_SEP "DSP" #define LOGS_DIR "Logs" #define MAIL_LOGS_DIR LOGS_DIR DIR_SEP "Mail" diff --git a/Source/Core/Common/Src/FileUtil.cpp b/Source/Core/Common/Src/FileUtil.cpp index 48f99d8c1a..45ae2e1c95 100644 --- a/Source/Core/Common/Src/FileUtil.cpp +++ b/Source/Core/Common/Src/FileUtil.cpp @@ -640,6 +640,7 @@ const char *GetUserPath(int DirIDX) static char HiresTexturesDir[MAX_PATH] = {0}; static char DumpDir[MAX_PATH] = {0}; static char DumpFramesDir[MAX_PATH] = {0}; + static char DumpAudioDir[MAX_PATH] = {0}; static char DumpTexturesDir[MAX_PATH] = {0}; static char DumpDSPDir[MAX_PATH] = {0}; static char LogsDir[MAX_PATH] = {0}; @@ -684,6 +685,7 @@ const char *GetUserPath(int DirIDX) snprintf(HiresTexturesDir, sizeof(HiresTexturesDir), "%s" HIRES_TEXTURES_DIR DIR_SEP, UserDir); snprintf(DumpDir, sizeof(DumpDir), "%s" DUMP_DIR DIR_SEP, UserDir); snprintf(DumpFramesDir, sizeof(DumpFramesDir), "%s" DUMP_FRAMES_DIR DIR_SEP, UserDir); + snprintf(DumpAudioDir, sizeof(DumpAudioDir), "%s" DUMP_AUDIO_DIR DIR_SEP, UserDir); snprintf(DumpTexturesDir, sizeof(DumpTexturesDir), "%s" DUMP_TEXTURES_DIR DIR_SEP, UserDir); snprintf(DumpDSPDir, sizeof(DumpDSPDir), "%s" DUMP_DSP_DIR DIR_SEP, UserDir); snprintf(LogsDir, sizeof(LogsDir), "%s" LOGS_DIR DIR_SEP, UserDir); @@ -733,6 +735,8 @@ const char *GetUserPath(int DirIDX) return DumpDir; case D_DUMPFRAMES_IDX: return DumpFramesDir; + case D_DUMPAUDIO_IDX: + return DumpAudioDir; case D_DUMPTEXTURES_IDX: return DumpTexturesDir; case D_DUMPDSP_IDX: diff --git a/Source/Core/Common/Src/FileUtil.h b/Source/Core/Common/Src/FileUtil.h index 75aa75547e..588e0550b7 100644 --- a/Source/Core/Common/Src/FileUtil.h +++ b/Source/Core/Common/Src/FileUtil.h @@ -42,6 +42,7 @@ enum { D_HIRESTEXTURES_IDX, D_DUMP_IDX, D_DUMPFRAMES_IDX, + D_DUMPAUDIO_IDX, D_DUMPTEXTURES_IDX, D_DUMPDSP_IDX, D_LOGS_IDX, diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index 74f469ac3a..ee588e6687 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -127,6 +127,7 @@ EVT_CHECKBOX(ID_DISPLAY_NTSCJ, CConfigMain::DisplaySettingsChanged) EVT_RADIOBOX(ID_DSPENGINE, CConfigMain::AudioSettingsChanged) EVT_CHECKBOX(ID_ENABLE_DTK_MUSIC, CConfigMain::AudioSettingsChanged) EVT_CHECKBOX(ID_ENABLE_THROTTLE, CConfigMain::AudioSettingsChanged) +EVT_CHECKBOX(ID_DUMP_AUDIO, CConfigMain::AudioSettingsChanged) EVT_CHOICE(ID_FREQUENCY, CConfigMain::AudioSettingsChanged) EVT_CHOICE(ID_BACKEND, CConfigMain::AudioSettingsChanged) EVT_SLIDER(ID_VOLUME, CConfigMain::AudioSettingsChanged) @@ -399,6 +400,7 @@ void CConfigMain::InitializeGUIValues() VolumeText->SetLabel(wxString::Format(wxT("%d %%"), ac_Config.m_Volume)); EnableDTKMusic->SetValue(ac_Config.m_EnableDTKMusic ? true : false); EnableThrottle->SetValue(ac_Config.m_EnableThrottle ? true : false); + DumpAudio->SetValue(ac_Config.m_DumpAudio ? true : false); FrequencySelection->SetSelection( FrequencySelection->FindString(wxString::Format(_("%d Hz"), ac_Config.sFrequency))); // add backends to the list @@ -713,6 +715,8 @@ void CConfigMain::CreateGUIControls() wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); EnableThrottle = new wxCheckBox(AudioPage, ID_ENABLE_THROTTLE, _("Enable Audio Throttle"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + DumpAudio = new wxCheckBox(AudioPage, ID_DUMP_AUDIO, _("Dump Audio"), + wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); VolumeSlider = new wxSlider(AudioPage, ID_VOLUME, 0, 1, 100, wxDefaultPosition, wxDefaultSize, wxSL_VERTICAL|wxSL_INVERSE); VolumeText = new wxStaticText(AudioPage, wxID_ANY, wxT(""), @@ -728,6 +732,7 @@ void CConfigMain::CreateGUIControls() sbAudioSettings->Add(DSPEngine, 0, wxALL | wxEXPAND, 5); sbAudioSettings->Add(EnableDTKMusic, 0, wxALL, 5); sbAudioSettings->Add(EnableThrottle, 0, wxALL, 5); + sbAudioSettings->Add(DumpAudio, 0, wxALL, 5); wxStaticBoxSizer *sbVolume = new wxStaticBoxSizer(wxVERTICAL, AudioPage, _("Volume")); sbVolume->Add(VolumeSlider, 1, wxLEFT|wxRIGHT, 13); @@ -1069,6 +1074,7 @@ void CConfigMain::AudioSettingsChanged(wxCommandEvent& event) default: ac_Config.m_EnableDTKMusic = EnableDTKMusic->GetValue(); ac_Config.m_EnableThrottle = EnableThrottle->GetValue(); + ac_Config.m_DumpAudio = DumpAudio->GetValue(); ac_Config.sBackend = BackendSelection->GetStringSelection().mb_str(); long int frequency; FrequencySelection->GetStringSelection().ToLong(&frequency); diff --git a/Source/Core/DolphinWX/Src/ConfigMain.h b/Source/Core/DolphinWX/Src/ConfigMain.h index c3eba6194a..7397f841b0 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.h +++ b/Source/Core/DolphinWX/Src/ConfigMain.h @@ -89,6 +89,7 @@ private: ID_ENABLE_HLE_AUDIO, ID_ENABLE_DTK_MUSIC, ID_ENABLE_THROTTLE, + ID_DUMP_AUDIO, ID_FREQUENCY, ID_BACKEND, ID_VOLUME, @@ -183,6 +184,7 @@ private: wxStaticText* VolumeText; wxCheckBox* EnableDTKMusic; wxCheckBox* EnableThrottle; + wxCheckBox* DumpAudio; wxArrayString wxArrayBackends; wxChoice* BackendSelection; wxChoice* FrequencySelection; diff --git a/Source/Core/VideoCommon/Src/AVIDump.cpp b/Source/Core/VideoCommon/Src/AVIDump.cpp index 296f8f9165..a8639158b9 100644 --- a/Source/Core/VideoCommon/Src/AVIDump.cpp +++ b/Source/Core/VideoCommon/Src/AVIDump.cpp @@ -30,6 +30,8 @@ #include "CommonPaths.h" #include "Log.h" +#include "HW/VideoInterface.h" //for TargetRefreshRate + HWND m_emuWnd; LONG m_byteBuffer; LONG m_frameCount; @@ -189,8 +191,7 @@ bool AVIDump::SetVideoFormat() memset(&m_header, 0, sizeof(m_header)); m_header.fccType = streamtypeVIDEO; m_header.dwScale = 1; - // TODO: Decect FPS using NTSC/PAL - m_header.dwRate = 60; + m_header.dwRate = VideoInterface::TargetRefreshRate; m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage; return SUCCEEDED(AVIFileCreateStream(m_file, &m_stream, &m_header)); @@ -202,6 +203,8 @@ bool AVIDump::SetVideoFormat() #include "StringUtil.h" #include "Log.h" +#include "HW/VideoInterface.h" //for TargetRefreshRate + extern "C" { #include #include @@ -253,14 +256,14 @@ bool AVIDump::CreateFile() return false; } - s_Stream->codec->codec_id = s_FormatContext->oformat->video_codec; + s_Stream->codec->codec_id = CODEC_ID_FFV1; //s_FormatContext->oformat->video_codec; s_Stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; s_Stream->codec->bit_rate = 400000; s_Stream->codec->width = s_width; s_Stream->codec->height = s_height; - s_Stream->codec->time_base = (AVRational){1, 30}; + s_Stream->codec->time_base = (AVRational){1, VideoInterface::TargetRefreshRate}; s_Stream->codec->gop_size = 12; - s_Stream->codec->pix_fmt = PIX_FMT_YUV420P; + s_Stream->codec->pix_fmt = PIX_FMT_BGRA; av_set_parameters(s_FormatContext, NULL); @@ -272,7 +275,7 @@ bool AVIDump::CreateFile() } if(!(s_SwsContext = sws_getContext(s_width, s_height, PIX_FMT_BGR24, s_width, s_height, - PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL))) + PIX_FMT_BGRA, SWS_BICUBIC, NULL, NULL, NULL))) { CloseFile(); return false; @@ -281,10 +284,10 @@ bool AVIDump::CreateFile() s_BGRFrame = avcodec_alloc_frame(); s_YUVFrame = avcodec_alloc_frame(); - s_size = avpicture_get_size(PIX_FMT_YUV420P, s_width, s_height); + s_size = avpicture_get_size(PIX_FMT_BGRA, s_width, s_height); s_YUVBuffer = new uint8_t[s_size]; - avpicture_fill((AVPicture *)s_YUVFrame, s_YUVBuffer, PIX_FMT_YUV420P, s_width, s_height); + avpicture_fill((AVPicture *)s_YUVFrame, s_YUVBuffer, PIX_FMT_BGRA, s_width, s_height); s_OutBuffer = new uint8_t[s_size]; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 02c0f2f1c2..571b08996a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -920,6 +920,8 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle // This function has the final picture. We adjust the aspect ratio here. void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma) { + static char* data = 0; + static int w = 0, h = 0; if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight) { Core::Callback_VideoCopiedToXFB(false); @@ -1120,10 +1122,15 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons D3DLOCKED_RECT rect; if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, dst_rect.AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY))) { - char* data = (char*)malloc(3 * s_recordWidth * s_recordHeight); + if (!data || w != s_recordWidth || h != s_recordHeight) + { + free(data); + data = (char*)malloc(3 * s_recordWidth * s_recordHeight); + w = s_recordWidth; + h = s_recordHeight; + } formatBufferDump((const char*)rect.pBits, data, s_recordWidth, s_recordHeight, rect.Pitch); AVIDump::AddFrame(data); - free(data); ScreenShootMEMSurface->UnlockRect(); } } @@ -1133,6 +1140,12 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons { if (s_bLastFrameDumped && s_bAVIDumping) { + if (data) + { + free(data); + data = 0; + w = h = 0; + } AVIDump::Stop(); s_bAVIDumping = false; OSD::AddMessage("Stop dumping frames to AVI", 2000); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index d2ab2e1440..7f4e0aa6ec 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -961,8 +961,16 @@ void Renderer::SetBlendMode(bool forceUpdate) // This function has the final picture. We adjust the aspect ratio here. void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma) { + static u8 *data = 0; + static int w = 0, h = 0; if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight) { + if (g_ActiveConfig.bDumpFrames && data) + #ifdef _WIN32 + AVIDump::AddFrame((char *) data); + #else + AVIDump::AddFrame(data); + #endif Core::Callback_VideoCopiedToXFB(false); return; } @@ -975,6 +983,12 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount); if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB) { + if (g_ActiveConfig.bDumpFrames && data) + #ifdef _WIN32 + AVIDump::AddFrame((char *) data); + #else + AVIDump::AddFrame(data); + #endif Core::Callback_VideoCopiedToXFB(false); return; } @@ -1134,9 +1148,14 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons if (g_ActiveConfig.bDumpFrames) { s_criticalScreenshot.Enter(); - int w = dst_rect.GetWidth(); - int h = dst_rect.GetHeight(); - u8 *data = new u8[3 * w * h]; + if (!data || w != dst_rect.GetWidth() || + h != dst_rect.GetHeight()) + { + if (data) delete[] data; + w = dst_rect.GetWidth(); + h = dst_rect.GetHeight(); + data = new u8[3 * w * h]; + } glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, data); if (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0) @@ -1172,13 +1191,18 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons else NOTICE_LOG(VIDEO, "Error reading framebuffer"); - delete[] data; s_criticalScreenshot.Leave(); } else { if (s_bLastFrameDumped && s_bAVIDumping) { + if (data) + { + delete[] data; + data = 0; + w = h = 0; + } AVIDump::Stop(); s_bAVIDumping = false; OSD::AddMessage("Stop dumping frames", 2000);