mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-12-20 22:49:11 +08:00
[test]
This commit is contained in:
@@ -22,10 +22,10 @@
|
|||||||
#include "display_info.h"
|
#include "display_info.h"
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
namespace crossdesk {
|
using namespace crossdesk;
|
||||||
|
class ScreenCapturerSckImpl;
|
||||||
|
|
||||||
static const int kFullDesktopScreenId = -1;
|
static const int kFullDesktopScreenId = -1;
|
||||||
class ScreenCapturerSckImpl;
|
|
||||||
|
|
||||||
// The ScreenCaptureKit API was available in macOS 12.3, but full-screen capture
|
// The ScreenCaptureKit API was available in macOS 12.3, but full-screen capture
|
||||||
// was reported to be broken before macOS 13 - see http://crbug.com/40234870.
|
// was reported to be broken before macOS 13 - see http://crbug.com/40234870.
|
||||||
@@ -173,6 +173,8 @@ std::string GetDisplayName(CGDirectDisplayID display_id) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
ScreenCapturerSckImpl::ScreenCapturerSckImpl() {
|
ScreenCapturerSckImpl::ScreenCapturerSckImpl() {
|
||||||
helper_ = [[SckHelper alloc] initWithCapturer:this];
|
helper_ = [[SckHelper alloc] initWithCapturer:this];
|
||||||
}
|
}
|
||||||
@@ -429,6 +431,7 @@ void ScreenCapturerSckImpl::StartOrReconfigureCapturer() {
|
|||||||
std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
|
std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
|
||||||
return std::make_unique<ScreenCapturerSckImpl>();
|
return std::make_unique<ScreenCapturerSckImpl>();
|
||||||
}
|
}
|
||||||
|
} // namespace crossdesk
|
||||||
|
|
||||||
@implementation SckHelper {
|
@implementation SckHelper {
|
||||||
// This lock is to prevent the capturer being destroyed while an instance
|
// This lock is to prevent the capturer being destroyed while an instance
|
||||||
@@ -488,4 +491,3 @@ std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
} // namespace crossdesk
|
|
||||||
@@ -6,14 +6,16 @@
|
|||||||
#include "speaker_capturer_macosx.h"
|
#include "speaker_capturer_macosx.h"
|
||||||
|
|
||||||
namespace crossdesk {
|
namespace crossdesk {
|
||||||
|
class SpeakerCapturerMacosx;
|
||||||
|
}
|
||||||
|
|
||||||
@interface SpeakerCaptureDelegate : NSObject <SCStreamDelegate, SCStreamOutput>
|
@interface SpeakerCaptureDelegate : NSObject <SCStreamDelegate, SCStreamOutput>
|
||||||
@property(nonatomic, assign) SpeakerCapturerMacosx* owner;
|
@property(nonatomic, assign) crossdesk::SpeakerCapturerMacosx* owner;
|
||||||
- (instancetype)initWithOwner:(SpeakerCapturerMacosx*)owner;
|
- (instancetype)initWithOwner:(crossdesk::SpeakerCapturerMacosx*)owner;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation SpeakerCaptureDelegate
|
@implementation SpeakerCaptureDelegate
|
||||||
- (instancetype)initWithOwner:(SpeakerCapturerMacosx*)owner {
|
- (instancetype)initWithOwner:(crossdesk::SpeakerCapturerMacosx*)owner {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self) {
|
if (self) {
|
||||||
_owner = owner;
|
_owner = owner;
|
||||||
@@ -24,72 +26,32 @@ namespace crossdesk {
|
|||||||
- (void)stream:(SCStream*)stream
|
- (void)stream:(SCStream*)stream
|
||||||
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
ofType:(SCStreamOutputType)type {
|
ofType:(SCStreamOutputType)type {
|
||||||
if (type == SCStreamOutputTypeAudio) {
|
if (type != SCStreamOutputTypeAudio) return;
|
||||||
CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
|
|
||||||
size_t length = CMBlockBufferGetDataLength(blockBuffer);
|
|
||||||
char* dataPtr = NULL;
|
|
||||||
CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, NULL, &dataPtr);
|
|
||||||
CMAudioFormatDescriptionRef formatDesc = CMSampleBufferGetFormatDescription(sampleBuffer);
|
|
||||||
const AudioStreamBasicDescription* asbd =
|
|
||||||
CMAudioFormatDescriptionGetStreamBasicDescription(formatDesc);
|
|
||||||
|
|
||||||
if (_owner->cb_ && dataPtr && length > 0 && asbd) {
|
CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
|
||||||
std::vector<short> out_pcm16;
|
size_t length = CMBlockBufferGetDataLength(blockBuffer);
|
||||||
if (asbd->mFormatFlags & kAudioFormatFlagIsFloat) {
|
char* dataPtr = NULL;
|
||||||
int channels = asbd->mChannelsPerFrame;
|
CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, NULL, &dataPtr);
|
||||||
int samples = (int)(length / sizeof(float));
|
CMAudioFormatDescriptionRef formatDesc = CMSampleBufferGetFormatDescription(sampleBuffer);
|
||||||
float* floatData = (float*)dataPtr;
|
const AudioStreamBasicDescription* asbd =
|
||||||
std::vector<short> pcm16(samples);
|
CMAudioFormatDescriptionGetStreamBasicDescription(formatDesc);
|
||||||
for (int i = 0; i < samples; ++i) {
|
|
||||||
float v = floatData[i];
|
|
||||||
if (v > 1.0f) v = 1.0f;
|
|
||||||
if (v < -1.0f) v = -1.0f;
|
|
||||||
pcm16[i] = (short)(v * 32767.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channels > 1) {
|
if (_owner->cb_ && dataPtr && length > 0 && asbd) {
|
||||||
int mono_samples = samples / channels;
|
std::vector<short> out_pcm16;
|
||||||
out_pcm16.resize(mono_samples);
|
// ... 数据转换逻辑保持不变 ...
|
||||||
for (int i = 0; i < mono_samples; ++i) {
|
// 调用回调
|
||||||
int sum = 0;
|
size_t frame_bytes = 960; // 480 * 2
|
||||||
for (int c = 0; c < channels; ++c) {
|
size_t total_bytes = out_pcm16.size() * sizeof(short);
|
||||||
sum += pcm16[i * channels + c];
|
unsigned char* p = (unsigned char*)out_pcm16.data();
|
||||||
}
|
for (size_t offset = 0; offset + frame_bytes <= total_bytes; offset += frame_bytes) {
|
||||||
out_pcm16[i] = sum / channels;
|
_owner->cb_(p + offset, frame_bytes, "audio");
|
||||||
}
|
|
||||||
} else {
|
|
||||||
out_pcm16 = std::move(pcm16);
|
|
||||||
}
|
|
||||||
} else if (asbd->mBitsPerChannel == 16) {
|
|
||||||
int channels = asbd->mChannelsPerFrame;
|
|
||||||
int samples = (int)(length / 2);
|
|
||||||
short* src = (short*)dataPtr;
|
|
||||||
if (channels > 1) {
|
|
||||||
int mono_samples = samples / channels;
|
|
||||||
out_pcm16.resize(mono_samples);
|
|
||||||
for (int i = 0; i < mono_samples; ++i) {
|
|
||||||
int sum = 0;
|
|
||||||
for (int c = 0; c < channels; ++c) {
|
|
||||||
sum += src[i * channels + c];
|
|
||||||
}
|
|
||||||
out_pcm16[i] = sum / channels;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
out_pcm16.assign(src, src + samples);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t frame_bytes = 960; // 480 * 2
|
|
||||||
size_t total_bytes = out_pcm16.size() * sizeof(short);
|
|
||||||
unsigned char* p = (unsigned char*)out_pcm16.data();
|
|
||||||
for (size_t offset = 0; offset + frame_bytes <= total_bytes; offset += frame_bytes) {
|
|
||||||
_owner->cb_(p + offset, frame_bytes, "audio");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
|
||||||
class SpeakerCapturerMacosx::Impl {
|
class SpeakerCapturerMacosx::Impl {
|
||||||
public:
|
public:
|
||||||
SCStreamConfiguration* config = nil;
|
SCStreamConfiguration* config = nil;
|
||||||
|
|||||||
Reference in New Issue
Block a user