Cocoa Port: Do a bunch of tweaks and fixes for an upcoming new feature. (Related to commit 932cdd6.)
This commit is contained in:
parent
bee3fd30ce
commit
232e3d6f51
|
@ -245,7 +245,11 @@ ClientAVCaptureObject::ClientAVCaptureObject(size_t videoFrameWidth, size_t vide
|
|||
{
|
||||
__InstanceInit(videoFrameWidth, videoFrameHeight);
|
||||
|
||||
_pendingVideoBuffer = (u8 *)malloc_alignedCacheLine(_videoFrameSize * _pendingBufferCount);
|
||||
if (_videoFrameSize > 0)
|
||||
{
|
||||
_pendingVideoBuffer = (u8 *)malloc_alignedCacheLine(_videoFrameSize * _pendingBufferCount);
|
||||
}
|
||||
|
||||
_pendingAudioBuffer = (u8 *)malloc_alignedCacheLine(_audioFrameSize * _pendingBufferCount);
|
||||
_pendingAudioWriteSize = (size_t *)calloc(_pendingBufferCount, sizeof(size_t));
|
||||
|
||||
|
@ -258,7 +262,7 @@ ClientAVCaptureObject::ClientAVCaptureObject(size_t videoFrameWidth, size_t vide
|
|||
_convertParam[i].firstLineIndex = 0;
|
||||
_convertParam[i].lastLineIndex = linesPerThread - 1;
|
||||
_convertParam[i].srcOffset = 0;
|
||||
_convertParam[i].dstOffset = (videoFrameWidth * (videoFrameHeight - 1) * 3);
|
||||
_convertParam[i].dstOffset = 0;
|
||||
_convertParam[i].frameWidth = videoFrameWidth;
|
||||
}
|
||||
}
|
||||
|
@ -283,7 +287,7 @@ ClientAVCaptureObject::ClientAVCaptureObject(size_t videoFrameWidth, size_t vide
|
|||
}
|
||||
|
||||
_convertParam[i].srcOffset = (videoFrameWidth * _convertParam[i].firstLineIndex);
|
||||
_convertParam[i].dstOffset = (videoFrameWidth * (videoFrameHeight - (_convertParam[i].firstLineIndex + 1)) * 3);
|
||||
_convertParam[i].dstOffset = (videoFrameWidth * _convertParam[i].firstLineIndex * 3);
|
||||
_convertParam[i].frameWidth = videoFrameWidth;
|
||||
}
|
||||
}
|
||||
|
@ -297,9 +301,20 @@ void ClientAVCaptureObject::__InstanceInit(size_t videoFrameWidth, size_t videoF
|
|||
|
||||
_mutexCaptureFlags = slock_new();
|
||||
|
||||
_videoFrameWidth = videoFrameWidth;
|
||||
_videoFrameHeight = videoFrameHeight;
|
||||
_videoFrameSize = videoFrameWidth * videoFrameHeight * 3; // The video frame will always be in the RGB888 colorspace.
|
||||
if ( (videoFrameWidth == 0) || (videoFrameHeight == 0) )
|
||||
{
|
||||
// Audio-only capture.
|
||||
_videoFrameWidth = 0;
|
||||
_videoFrameHeight = 0;
|
||||
_videoFrameSize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_videoFrameWidth = videoFrameWidth;
|
||||
_videoFrameHeight = videoFrameHeight;
|
||||
_videoFrameSize = videoFrameWidth * videoFrameHeight * 3; // The video frame will always be in the RGB888 colorspace.
|
||||
}
|
||||
|
||||
_audioBlockSize = sizeof(int16_t) * 2;
|
||||
_audioFrameSize = ((DESMUME_SAMPLE_RATE * _audioBlockSize) / 30);
|
||||
|
||||
|
@ -433,27 +448,24 @@ void ClientAVCaptureObject::StreamWriteStart()
|
|||
return;
|
||||
}
|
||||
|
||||
// Force video conversion to finish before putting the frame on the queue.
|
||||
if ( (this->_videoFrameSize > 0) && (this->_numThreads > 0) )
|
||||
{
|
||||
for (size_t i = 0; i < this->_numThreads; i++)
|
||||
{
|
||||
this->_convertThread[i]->finish();
|
||||
}
|
||||
}
|
||||
|
||||
const size_t bufferIndex = this->_currentBufferIndex;
|
||||
const size_t queueSize = this->_fs->GetQueueSize();
|
||||
const bool isQueueEmpty = (queueSize == 0);
|
||||
|
||||
// If there are no frames in the current write queue, then we know that the current
|
||||
// pending video frame will be written immediately. If this is the case, then we
|
||||
// need to force the video conversion to finish so that we can write out the frame.
|
||||
if (isQueueEmpty)
|
||||
{
|
||||
if (this->_videoFrameSize > 0)
|
||||
{
|
||||
for (size_t i = 0; i < this->_numThreads; i++)
|
||||
{
|
||||
this->_convertThread[i]->finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->_fs->QueueAdd(this->_pendingVideoBuffer + (this->_videoFrameSize * bufferIndex), this->_videoFrameSize,
|
||||
this->_pendingAudioBuffer + (AUDIO_STREAM_BUFFER_SIZE * bufferIndex), this->_pendingAudioWriteSize[bufferIndex]);
|
||||
|
||||
// If the queue was initially empty, then we need to wake up the file write
|
||||
// thread at this time.
|
||||
if (isQueueEmpty)
|
||||
{
|
||||
this->_fileWriteThread->execute(&RunAviFileWrite, this->_fs);
|
||||
|
@ -468,39 +480,31 @@ void ClientAVCaptureObject::StreamWriteFinish()
|
|||
//converts 16bpp to 24bpp and flips
|
||||
void ClientAVCaptureObject::ConvertVideoSlice555Xto888(const VideoConvertParam ¶m)
|
||||
{
|
||||
const size_t lineCount = param.lastLineIndex - param.firstLineIndex + 1;
|
||||
const u16 *__restrict src = (const u16 *__restrict)param.src;
|
||||
u8 *__restrict dst = param.dst;
|
||||
|
||||
for (size_t y = param.firstLineIndex; y <= param.lastLineIndex; y++)
|
||||
{
|
||||
ColorspaceConvertBuffer555XTo888<true, false>(src, dst, param.frameWidth);
|
||||
src += param.frameWidth;
|
||||
dst -= param.frameWidth * 3;
|
||||
}
|
||||
ColorspaceConvertBuffer555XTo888<false, false>(src, dst, param.frameWidth * lineCount);
|
||||
}
|
||||
|
||||
//converts 32bpp to 24bpp and flips
|
||||
void ClientAVCaptureObject::ConvertVideoSlice888Xto888(const VideoConvertParam ¶m)
|
||||
{
|
||||
const size_t lineCount = param.lastLineIndex - param.firstLineIndex + 1;
|
||||
const u32 *__restrict src = (const u32 *__restrict)param.src;
|
||||
u8 *__restrict dst = param.dst;
|
||||
|
||||
for (size_t y = param.firstLineIndex; y <= param.lastLineIndex; y++)
|
||||
{
|
||||
ColorspaceConvertBuffer888XTo888<true, false>(src, dst, param.frameWidth);
|
||||
src += param.frameWidth;
|
||||
dst -= param.frameWidth * 3;
|
||||
}
|
||||
ColorspaceConvertBuffer888XTo888<false, false>(src, dst, param.frameWidth * lineCount);
|
||||
}
|
||||
|
||||
void ClientAVCaptureObject::ReadVideoFrame(const void *srcVideoFrame, const size_t inFrameWidth, const size_t inFrameHeight, const NDSColorFormat colorFormat)
|
||||
void ClientAVCaptureObject::CaptureVideoFrame(const void *srcVideoFrame, const size_t inFrameWidth, const size_t inFrameHeight, const NDSColorFormat colorFormat)
|
||||
{
|
||||
//dont do anything if prescale has changed, it's just going to be garbage
|
||||
if (!this->_isCapturingVideo ||
|
||||
(srcVideoFrame == NULL) ||
|
||||
(this->_videoFrameSize == 0) ||
|
||||
(this->_videoFrameWidth != inFrameWidth) ||
|
||||
(this->_videoFrameHeight != (inFrameHeight * 2)))
|
||||
(this->_videoFrameHeight != inFrameHeight))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -548,7 +552,7 @@ void ClientAVCaptureObject::ReadVideoFrame(const void *srcVideoFrame, const size
|
|||
}
|
||||
}
|
||||
|
||||
void ClientAVCaptureObject::ReadAudioFrames(const void *srcAudioBuffer, const size_t inSampleCount)
|
||||
void ClientAVCaptureObject::CaptureAudioFrames(const void *srcAudioBuffer, const size_t inSampleCount)
|
||||
{
|
||||
if (!this->_isCapturingAudio || (srcAudioBuffer == NULL))
|
||||
{
|
||||
|
|
|
@ -253,8 +253,8 @@ public:
|
|||
void ConvertVideoSlice555Xto888(const VideoConvertParam ¶m);
|
||||
void ConvertVideoSlice888Xto888(const VideoConvertParam ¶m);
|
||||
|
||||
void ReadVideoFrame(const void *srcVideoFrame, const size_t inFrameWidth, const size_t inFrameHeight, const NDSColorFormat colorFormat);
|
||||
void ReadAudioFrames(const void *srcAudioBuffer, const size_t inSampleCount);
|
||||
void CaptureVideoFrame(const void *srcVideoFrame, const size_t inFrameWidth, const size_t inFrameHeight, const NDSColorFormat colorFormat);
|
||||
void CaptureAudioFrames(const void *srcAudioBuffer, const size_t inSampleCount);
|
||||
};
|
||||
|
||||
#endif // _CLIENT_AV_CAPTURE_OBJECT_H_
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "../../gdbstub.h"
|
||||
#include "../../rtc.h"
|
||||
|
||||
#include "ClientAVCaptureObject.h"
|
||||
#include "ClientExecutionControl.h"
|
||||
|
||||
// Need to include assert.h this way so that GDB stub will work
|
||||
|
@ -144,9 +145,15 @@ ClientAVCaptureObject* ClientExecutionControl::GetClientAVCaptureObjectApplied()
|
|||
void ClientExecutionControl::SetClientAVCaptureObject(ClientAVCaptureObject *theCaptureObject)
|
||||
{
|
||||
pthread_mutex_lock(&this->_mutexSettingsPendingOnNDSExec);
|
||||
this->_settingsPending.avCaptureObject = theCaptureObject;
|
||||
|
||||
this->_newSettingsPendingOnNDSExec = true;
|
||||
if (this->_settingsPending.avCaptureObject != theCaptureObject)
|
||||
{
|
||||
this->_settingsPending.avCaptureObject = theCaptureObject;
|
||||
|
||||
this->_needResetFramesToSkip = true;
|
||||
this->_newSettingsPendingOnNDSExec = true;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&this->_mutexSettingsPendingOnNDSExec);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,11 +22,13 @@
|
|||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "ClientAVCaptureObject.h"
|
||||
#include "ClientInputHandler.h"
|
||||
|
||||
#include "../../slot1.h"
|
||||
|
||||
#ifdef BOOL
|
||||
#undef BOOL
|
||||
#endif
|
||||
|
||||
#define SPEED_SCALAR_QUARTER 0.25 // Speed scalar for quarter execution speed.
|
||||
#define SPEED_SCALAR_HALF 0.5 // Speed scalar for half execution speed.
|
||||
|
@ -43,6 +45,8 @@
|
|||
#define FRAME_SKIP_BIAS 0.1 // May be any real number. This value acts as a vector addition to the frame skip.
|
||||
#define MAX_FRAME_SKIP (DS_FRAMES_PER_SECOND / 2.98)
|
||||
|
||||
class ClientAVCaptureObject;
|
||||
|
||||
enum ExecutionBehavior
|
||||
{
|
||||
ExecutionBehavior_Pause = 0,
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#import "cocoa_util.h"
|
||||
|
||||
#include "macOS_driver.h"
|
||||
#include "ClientAVCaptureObject.h"
|
||||
#include "ClientExecutionControl.h"
|
||||
#include "ClientInputHandler.h"
|
||||
|
||||
|
@ -1118,7 +1119,7 @@ static void* RunCoreThread(void *arg)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (avCaptureObject != NULL)
|
||||
if ( (avCaptureObject != NULL) && !avCaptureObject->IsCapturingVideo() )
|
||||
{
|
||||
avCaptureObject->StreamWriteStart();
|
||||
}
|
||||
|
@ -1186,7 +1187,7 @@ static void* RunCoreThread(void *arg)
|
|||
{
|
||||
case ExecutionBehavior_Run:
|
||||
{
|
||||
if (execControl->GetEnableFrameSkipApplied())
|
||||
if (execControl->GetEnableFrameSkipApplied() && !avCaptureObject)
|
||||
{
|
||||
if (framesToSkip > 0)
|
||||
{
|
||||
|
@ -1203,14 +1204,17 @@ static void* RunCoreThread(void *arg)
|
|||
|
||||
case ExecutionBehavior_FrameJump:
|
||||
{
|
||||
if (framesToSkip > 0)
|
||||
if (!avCaptureObject)
|
||||
{
|
||||
NDS_SkipNextFrame();
|
||||
execControl->SetFramesToSkip(framesToSkip - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
execControl->SetFramesToSkip( (uint8_t)((DS_FRAMES_PER_SECOND * 1.0) + 0.85) );
|
||||
if (framesToSkip > 0)
|
||||
{
|
||||
NDS_SkipNextFrame();
|
||||
execControl->SetFramesToSkip(framesToSkip - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
execControl->SetFramesToSkip( (uint8_t)((DS_FRAMES_PER_SECOND * 1.0) + 0.85) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -23,9 +23,13 @@
|
|||
#import "cocoa_util.h"
|
||||
#include "ClientDisplayView.h"
|
||||
#include "ClientExecutionControl.h"
|
||||
#include "ClientAVCaptureObject.h"
|
||||
#undef BOOL
|
||||
|
||||
#ifdef BOOL
|
||||
#undef BOOL
|
||||
#endif
|
||||
|
||||
|
||||
class ClientAVCaptureObject;
|
||||
@class NSImage;
|
||||
@class NSBitmapImageRep;
|
||||
|
||||
|
@ -122,9 +126,14 @@
|
|||
@interface CocoaDSVideoCapture : CocoaDSDisplay
|
||||
{
|
||||
ClientDisplay3DPresenter *_cdp;
|
||||
ClientAVCaptureObject *avCaptureObject;
|
||||
uint32_t *_videoCaptureBuffer;
|
||||
|
||||
pthread_mutex_t _mutexCaptureBuffer;
|
||||
}
|
||||
|
||||
@property (assign, nonatomic, getter=clientDisplay3DPresenter, setter=setClientDisplay3DPresenter:) ClientDisplay3DPresenter *_cdp;
|
||||
@property (assign, nonatomic) ClientAVCaptureObject *avCaptureObject;
|
||||
|
||||
- (void) handleReceiveGPUFrame;
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#import "cocoa_core.h"
|
||||
#include "sndOSX.h"
|
||||
|
||||
#include "ClientAVCaptureObject.h"
|
||||
|
||||
#include "../../NDSSystem.h"
|
||||
#include "../../common.h"
|
||||
#include "../../GPU.h"
|
||||
|
@ -34,7 +36,9 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#ifdef BOOL
|
||||
#undef BOOL
|
||||
#endif
|
||||
|
||||
|
||||
@implementation CocoaDSOutput
|
||||
|
@ -556,21 +560,63 @@
|
|||
@implementation CocoaDSVideoCapture
|
||||
|
||||
@synthesize _cdp;
|
||||
@synthesize avCaptureObject;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self == nil)
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
_cdp = NULL;
|
||||
avCaptureObject = NULL;
|
||||
_videoCaptureBuffer = NULL;
|
||||
|
||||
pthread_mutex_init(&_mutexCaptureBuffer, NULL);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
pthread_mutex_lock(&_mutexCaptureBuffer);
|
||||
free_aligned(_videoCaptureBuffer);
|
||||
pthread_mutex_unlock(&_mutexCaptureBuffer);
|
||||
|
||||
pthread_mutex_destroy(&_mutexCaptureBuffer);
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) handleReceiveGPUFrame
|
||||
{
|
||||
[super handleReceiveGPUFrame];
|
||||
|
||||
if (_cdp == NULL)
|
||||
if ( (_cdp == NULL) || (avCaptureObject == NULL) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ClientDisplayPresenterProperties &cdpProperty = _cdp->GetPresenterProperties();
|
||||
|
||||
_cdp->LoadDisplays();
|
||||
_cdp->ProcessDisplays();
|
||||
_cdp->UpdateLayout();
|
||||
//_cdp->CopyFrameToBuffer((uint32_t *)[newImageRep bitmapData]);
|
||||
//avCaptureObject->ReadVideoFrame(NULL, 0, 0, NDSColorFormat_BGR888_Rev);
|
||||
|
||||
pthread_mutex_lock(&_mutexCaptureBuffer);
|
||||
|
||||
if (_videoCaptureBuffer == NULL)
|
||||
{
|
||||
_videoCaptureBuffer = (uint32_t *)malloc_alignedPage(cdpProperty.clientWidth * cdpProperty.clientHeight * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
_cdp->CopyFrameToBuffer(_videoCaptureBuffer);
|
||||
avCaptureObject->CaptureVideoFrame(_videoCaptureBuffer, (size_t)cdpProperty.clientWidth, (size_t)cdpProperty.clientHeight, NDSColorFormat_BGR888_Rev);
|
||||
avCaptureObject->StreamWriteStart();
|
||||
|
||||
pthread_mutex_unlock(&_mutexCaptureBuffer);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -16,8 +16,10 @@
|
|||
*/
|
||||
|
||||
#include "macOS_driver.h"
|
||||
#include "ClientAVCaptureObject.h"
|
||||
#include "ClientExecutionControl.h"
|
||||
|
||||
|
||||
pthread_mutex_t* macOS_driver::GetCoreThreadMutexLock()
|
||||
{
|
||||
return this->__mutexThreadExecute;
|
||||
|
@ -52,7 +54,7 @@ void macOS_driver::AVI_SoundUpdate(void *soundData, int soundLen)
|
|||
return;
|
||||
}
|
||||
|
||||
avCaptureObject->ReadAudioFrames(soundData, soundLen);
|
||||
avCaptureObject->CaptureAudioFrames(soundData, soundLen);
|
||||
}
|
||||
|
||||
bool macOS_driver::AVI_IsRecording()
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2739,6 +2739,11 @@
|
|||
{
|
||||
[(NSMenuItem*)theItem setTitle:([cdsCore isFrameSkipEnabled]) ? NSSTRING_TITLE_DISABLE_AUTO_FRAME_SKIP : NSSTRING_TITLE_ENABLE_AUTO_FRAME_SKIP];
|
||||
}
|
||||
|
||||
if ([avCaptureToolDelegate isRecording])
|
||||
{
|
||||
enable = NO;
|
||||
}
|
||||
}
|
||||
else if (theAction == @selector(toggleCheats:))
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue