[feat] remove dependence on ffmpeg for MacOSx

This commit is contained in:
dijunkun
2025-05-08 11:33:04 +08:00
parent e89d385f99
commit e2a469ed65
22 changed files with 10 additions and 2927 deletions

View File

@@ -1,212 +0,0 @@
#include "screen_capturer_avf.h"
#include <ApplicationServices/ApplicationServices.h>
#include <iostream>
#include "rd_log.h"
#define USE_SCALE_FACTOR 0
ScreenCapturerAvf::ScreenCapturerAvf() {}
ScreenCapturerAvf::~ScreenCapturerAvf() {
if (inited_ && capture_thread_.joinable()) {
capture_thread_.join();
inited_ = false;
}
if (nv12_frame_) {
delete[] nv12_frame_;
nv12_frame_ = nullptr;
}
if (pFormatCtx_) {
avformat_close_input(&pFormatCtx_);
pFormatCtx_ = nullptr;
}
if (pCodecCtx_) {
avcodec_free_context(&pCodecCtx_);
pCodecCtx_ = nullptr;
}
if (options_) {
av_dict_free(&options_);
options_ = nullptr;
}
if (pFrame_) {
av_frame_free(&pFrame_);
pFrame_ = nullptr;
}
if (packet_) {
av_packet_free(&packet_);
packet_ = nullptr;
}
#if USE_SCALE_FACTOR
if (img_convert_ctx_) {
sws_freeContext(img_convert_ctx_);
img_convert_ctx_ = nullptr;
}
#endif
}
int ScreenCapturerAvf::Init(const int fps, cb_desktop_data cb) {
if (cb) {
_on_data = cb;
}
av_log_set_level(AV_LOG_QUIET);
pFormatCtx_ = avformat_alloc_context();
avdevice_register_all();
// grabbing frame rate
av_dict_set(&options_, "framerate", "60", 0);
av_dict_set(&options_, "pixel_format", "nv12", 0);
// show remote cursor
av_dict_set(&options_, "capture_cursor", "0", 0);
// Make the grabbed area follow the mouse
// av_dict_set(&options_, "follow_mouse", "centered", 0);
// Video frame size. The default is to capture the full screen
// av_dict_set(&options_, "video_size", "1440x900", 0);
ifmt_ = (AVInputFormat *)av_find_input_format("avfoundation");
if (!ifmt_) {
printf("Couldn't find_input_format\n");
}
// Grab at position 10,20
if (avformat_open_input(&pFormatCtx_, "Capture screen 0", ifmt_, &options_) !=
0) {
printf("Couldn't open input stream.\n");
return -1;
}
if (avformat_find_stream_info(pFormatCtx_, NULL) < 0) {
printf("Couldn't find stream information.\n");
return -1;
}
videoindex_ = -1;
for (i_ = 0; i_ < pFormatCtx_->nb_streams; i_++)
if (pFormatCtx_->streams[i_]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoindex_ = i_;
break;
}
if (videoindex_ == -1) {
printf("Didn't find a video stream.\n");
return -1;
}
pCodecParam_ = pFormatCtx_->streams[videoindex_]->codecpar;
pCodecCtx_ = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(pCodecCtx_, pCodecParam_);
pCodec_ = const_cast<AVCodec *>(avcodec_find_decoder(pCodecCtx_->codec_id));
if (pCodec_ == NULL) {
printf("Codec not found.\n");
return -1;
}
if (avcodec_open2(pCodecCtx_, pCodec_, NULL) < 0) {
printf("Could not open codec.\n");
return -1;
}
const int screen_w = pFormatCtx_->streams[videoindex_]->codecpar->width;
const int screen_h = pFormatCtx_->streams[videoindex_]->codecpar->height;
pFrame_ = av_frame_alloc();
pFrame_->width = screen_w;
pFrame_->height = screen_h;
#if USE_SCALE_FACTOR
pFrame_resized_ = av_frame_alloc();
pFrame_resized_->width = CGDisplayPixelsWide(CGMainDisplayID());
pFrame_resized_->height = CGDisplayPixelsHigh(CGMainDisplayID());
img_convert_ctx_ =
sws_getContext(pFrame_->width, pFrame_->height, pCodecCtx_->pix_fmt,
pFrame_resized_->width, pFrame_resized_->height,
AV_PIX_FMT_NV12, SWS_BICUBIC, NULL, NULL, NULL);
#endif
if (!nv12_frame_) {
nv12_frame_ = new unsigned char[screen_w * screen_h * 3 / 2];
}
packet_ = (AVPacket *)av_malloc(sizeof(AVPacket));
inited_ = true;
return 0;
}
int ScreenCapturerAvf::Destroy() {
running_ = false;
return 0;
}
int ScreenCapturerAvf::Start() {
if (running_) {
return 0;
}
running_ = true;
capture_thread_ = std::thread([this]() {
while (running_) {
if (av_read_frame(pFormatCtx_, packet_) >= 0) {
if (packet_->stream_index == videoindex_) {
avcodec_send_packet(pCodecCtx_, packet_);
av_packet_unref(packet_);
got_picture_ = avcodec_receive_frame(pCodecCtx_, pFrame_);
if (!got_picture_) {
#if USE_SCALE_FACTOR
av_image_fill_arrays(pFrame_resized_->data,
pFrame_resized_->linesize, nv12_frame_,
AV_PIX_FMT_NV12, pFrame_resized_->width,
pFrame_resized_->height, 1);
sws_scale(img_convert_ctx_, pFrame_->data, pFrame_->linesize, 0,
pFrame_->height, pFrame_resized_->data,
pFrame_resized_->linesize);
_on_data((unsigned char *)nv12_frame_,
pFrame_resized_->width * pFrame_resized_->height * 3 / 2,
pFrame_resized_->width, pFrame_resized_->height);
#else
memcpy(nv12_frame_, pFrame_->data[0],
pFrame_->linesize[0] * pFrame_->height);
memcpy(nv12_frame_ + pFrame_->linesize[0] * pFrame_->height,
pFrame_->data[1],
pFrame_->linesize[1] * pFrame_->height / 2);
_on_data((unsigned char *)nv12_frame_,
pFrame_->width * pFrame_->height * 3 / 2, pFrame_->width,
pFrame_->height);
#endif
}
}
}
}
});
return 0;
}
int ScreenCapturerAvf::Stop() {
running_ = false;
return 0;
}
int ScreenCapturerAvf::Pause() { return 0; }
int ScreenCapturerAvf::Resume() { return 0; }
void ScreenCapturerAvf::OnFrame() {}
void ScreenCapturerAvf::CleanUp() {}

View File

@@ -1,87 +0,0 @@
/*
* @Author: DI JUNKUN
* @Date: 2023-12-01
* Copyright (c) 2023 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _SCREEN_CAPTURER_AVF_H_
#define _SCREEN_CAPTURER_AVF_H_
#include <atomic>
#include <functional>
#include <string>
#include <thread>
#include "screen_capturer.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
#ifdef __cplusplus
};
#endif
class ScreenCapturerAvf : public ScreenCapturer {
public:
ScreenCapturerAvf();
~ScreenCapturerAvf();
public:
virtual int Init(const int fps, cb_desktop_data cb);
virtual int Destroy();
virtual int Start();
virtual int Stop();
int Pause();
int Resume();
void OnFrame();
protected:
void CleanUp();
private:
std::atomic_bool _paused;
std::atomic_bool _inited;
std::thread _thread;
std::string _device_name;
int _fps;
cb_desktop_data _on_data;
private:
int i_ = 0;
int videoindex_ = 0;
int got_picture_ = 0;
bool inited_ = false;
// ffmpeg
AVFormatContext *pFormatCtx_ = nullptr;
AVCodecContext *pCodecCtx_ = nullptr;
AVCodec *pCodec_ = nullptr;
AVCodecParameters *pCodecParam_ = nullptr;
AVDictionary *options_ = nullptr;
AVInputFormat *ifmt_ = nullptr;
AVFrame *pFrame_ = nullptr;
AVFrame *pFrame_resized_ = nullptr;
AVPacket *packet_ = nullptr;
struct SwsContext *img_convert_ctx_ = nullptr;
unsigned char *nv12_frame_ = nullptr;
// thread
std::thread capture_thread_;
std::atomic_bool running_;
};
#endif

View File

@@ -1,104 +0,0 @@
#include <IOSurface/IOSurface.h>
#include <utility>
#include "rd_log.h"
#include "screen_capturer_cgd.h"
ScreenCapturerCg::ScreenCapturerCg() {}
ScreenCapturerCg::~ScreenCapturerCg() {}
int ScreenCapturerCg::Init(const int fps, cb_desktop_data cb) {
if (cb) {
_on_data = cb;
}
size_t pixel_width = 1280;
size_t pixel_height = 720;
CGDirectDisplayID display_id = 0;
CGDisplayStreamFrameAvailableHandler handler =
^(CGDisplayStreamFrameStatus status, uint64_t display_time,
IOSurfaceRef frame_surface, CGDisplayStreamUpdateRef updateRef) {
if (status == kCGDisplayStreamFrameStatusStopped) return;
// Only pay attention to frame updates.
if (status != kCGDisplayStreamFrameStatusFrameComplete) return;
// size_t count = 0;
// const CGRect* rects = CGDisplayStreamUpdateGetRects(
// updateRef, kCGDisplayStreamUpdateDirtyRects, &count);
// 获取帧数据
void* frameData = IOSurfaceGetBaseAddressOfPlane(frame_surface, 0);
size_t width = IOSurfaceGetWidthOfPlane(frame_surface, 0);
size_t height = IOSurfaceGetHeightOfPlane(frame_surface, 0);
};
CFDictionaryRef properties_dictionary = CFDictionaryCreate(
kCFAllocatorDefault, (const void*[]){kCGDisplayStreamShowCursor},
(const void*[]){kCFBooleanFalse}, 1, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CGDisplayStreamRef display_stream =
CGDisplayStreamCreate(display_id, pixel_width, pixel_height, 'BGRA',
properties_dictionary, handler);
if (display_stream) {
CGError error = CGDisplayStreamStart(display_stream);
if (error != kCGErrorSuccess) return -1;
CFRunLoopSourceRef source = CGDisplayStreamGetRunLoopSource(display_stream);
CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes);
display_streams_.push_back(display_stream);
}
CFRelease(properties_dictionary);
return 0;
}
int ScreenCapturerCg::Destroy() {
running_ = false;
return 0;
}
int ScreenCapturerCg::Start() {
if (_running) {
return 0;
}
running_ = true;
capture_thread_ = std::thread([this]() {
while (running_) {
CFRunLoopRun();
}
});
return 0;
}
int ScreenCapturerCg::Stop() {
running_ = false;
return 0;
}
int ScreenCapturerCg::Pause() { return 0; }
int ScreenCapturerCg::Resume() { return 0; }
void ScreenCapturerCg::OnFrame() {}
void ScreenCapturerCg::CleanUp() {}
//
void ScreenCapturerCg::UnregisterRefreshAndMoveHandlers() {
for (CGDisplayStreamRef stream : display_streams_) {
CFRunLoopSourceRef source = CGDisplayStreamGetRunLoopSource(stream);
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes);
CGDisplayStreamStop(stream);
CFRelease(stream);
}
display_streams_.clear();
}

View File

@@ -1,56 +0,0 @@
/*
* @Author: DI JUNKUN
* @Date: 2024-10-16
* Copyright (c) 2024 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _SCREEN_CAPTURER_CGD_H_
#define _SCREEN_CAPTURER_CGD_H_
#include <CoreGraphics/CoreGraphics.h>
#include <atomic>
#include <functional>
#include <memory>
#include <string>
#include <thread>
#include <vector>
#include "screen_capturer.h"
class ScreenCapturerCg : public ScreenCapturer {
public:
ScreenCapturerCg();
~ScreenCapturerCg();
public:
virtual int Init(const int fps, cb_desktop_data cb);
virtual int Destroy();
virtual int Start();
virtual int Stop();
int Pause();
int Resume();
void OnFrame();
protected:
void CleanUp();
private:
int _fps;
cb_desktop_data _on_data;
// thread
std::thread capture_thread_;
std::atomic_bool running_;
private:
};
#endif

View File

@@ -1,303 +0,0 @@
// MyAudioSink.cpp : 定义控制台应用程序的入口点。
//
// #define _CRT_SECURE_NO_WARNINGS
#include <Audioclient.h>
#include <Devicetopology.h>
#include <Endpointvolume.h>
#include <Mmdeviceapi.h>
#include <tchar.h>
#include <iostream>
//-----------------------------------------------------------
// Record an audio stream from the default audio capture
// device. The RecordAudioStream function allocates a shared
// buffer big enough to hold one second of PCM audio data.
// The function uses this buffer to stream data from the
// capture device. The main loop runs every 1/2 second.
//-----------------------------------------------------------
// REFERENCE_TIME time units per second and per millisecond
#define REFTIMES_PER_SEC 10000000
#define REFTIMES_PER_MILLISEC 10000
#define EXIT_ON_ERROR(hres) \
if (FAILED(hres)) { \
goto Exit; \
}
#define SAFE_RELEASE(punk) \
if ((punk) != NULL) { \
(punk)->Release(); \
(punk) = NULL; \
}
#define IS_INPUT_DEVICE 0 // 切换输入和输出音频设备
#define BUFFER_TIME_100NS (5 * 10000000)
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
const IID IID_IAudioClient = __uuidof(IAudioClient);
const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
const IID IID_IDeviceTopology = __uuidof(IDeviceTopology);
const IID IID_IAudioVolumeLevel = __uuidof(IAudioVolumeLevel);
const IID IID_IPart = __uuidof(IPart);
const IID IID_IConnector = __uuidof(IConnector);
const IID IID_IAudioEndpointVolume = __uuidof(IAudioEndpointVolume);
class MyAudioSink {
public:
// WAVEFORMATEX *pwfx = NULL;
int SetFormat(WAVEFORMATEX *pwfx);
int CopyData(SHORT *pData, UINT32 numFramesAvailable, BOOL *pbDone);
};
int MyAudioSink::SetFormat(WAVEFORMATEX *pwfx) {
printf("wFormatTag is %x\n", pwfx->wFormatTag);
printf("nChannels is %x\n", pwfx->nChannels);
printf("nSamplesPerSec is %d\n", pwfx->nSamplesPerSec);
printf("nAvgBytesPerSec is %d\n", pwfx->nAvgBytesPerSec);
printf("wBitsPerSample is %d\n", pwfx->wBitsPerSample);
return 0;
}
FILE *fp;
int MyAudioSink::CopyData(SHORT *pData, UINT32 numFramesAvailable,
BOOL *pbDone) {
if (pData != NULL) {
size_t t = sizeof(SHORT);
for (int i = 0; i < numFramesAvailable / t; i++) {
double dbVal = pData[i];
pData[i] = dbVal; // 可以通过不同的分母来控制声音大小
}
fwrite(pData, numFramesAvailable, 1, fp);
}
return 0;
}
/// pwfx->nSamplesPerSec = 44100;
/// 不支持修改采样率, 看来只能等得到数据之后再 swr 转换了
BOOL AdjustFormatTo16Bits(WAVEFORMATEX *pwfx) {
BOOL bRet(FALSE);
if (pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
pwfx->wFormatTag = WAVE_FORMAT_PCM;
pwfx->wBitsPerSample = 16;
pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;
pwfx->nAvgBytesPerSec = pwfx->nBlockAlign * pwfx->nSamplesPerSec;
bRet = TRUE;
} else if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
PWAVEFORMATEXTENSIBLE pEx = reinterpret_cast<PWAVEFORMATEXTENSIBLE>(pwfx);
if (IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, pEx->SubFormat)) {
pEx->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
pEx->Samples.wValidBitsPerSample = 16;
pwfx->wBitsPerSample = 16;
pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;
pwfx->nAvgBytesPerSec = pwfx->nBlockAlign * pwfx->nSamplesPerSec;
bRet = TRUE;
}
}
return bRet;
}
typedef unsigned long long uint64_t;
static bool have_clockfreq = false;
static LARGE_INTEGER clock_freq;
static inline uint64_t get_clockfreq(void) {
if (!have_clockfreq) QueryPerformanceFrequency(&clock_freq);
return clock_freq.QuadPart;
}
uint64_t os_gettime_ns(void) {
LARGE_INTEGER current_time;
double time_val;
QueryPerformanceCounter(&current_time);
time_val = (double)current_time.QuadPart;
time_val *= 1000000000.0;
time_val /= (double)get_clockfreq();
return (uint64_t)time_val;
}
HRESULT RecordAudioStream(MyAudioSink *pMySink) {
HRESULT hr;
REFERENCE_TIME hnsActualDuration;
UINT32 bufferFrameCount;
UINT32 numFramesAvailable;
BYTE *pData;
DWORD flags;
REFERENCE_TIME hnsDefaultDevicePeriod(0);
REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDevice *pDevice = NULL;
IAudioClient *pAudioClient = NULL;
IAudioCaptureClient *pCaptureClient = NULL;
WAVEFORMATEX *pwfx = NULL;
UINT32 packetLength = 0;
BOOL bDone = FALSE;
HANDLE hTimerWakeUp = NULL;
UINT64 pos, ts;
hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,
IID_IMMDeviceEnumerator, (void **)&pEnumerator);
EXIT_ON_ERROR(hr)
if (IS_INPUT_DEVICE)
hr = pEnumerator->GetDefaultAudioEndpoint(eCapture, eCommunications,
&pDevice); // 输入
else
hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole,
&pDevice); // 输出
// wchar_t *w_id;
// os_utf8_to_wcs_ptr(device_id.c_str(), device_id.size(), &w_id);
// hr = pEnumerator->GetDevice(w_id, &pDevice);
// bfree(w_id);
EXIT_ON_ERROR(hr)
hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL,
(void **)&pAudioClient);
EXIT_ON_ERROR(hr)
hr = pAudioClient->GetMixFormat(&pwfx);
EXIT_ON_ERROR(hr)
// The GetDevicePeriod method retrieves the length of the periodic interval
// separating successive processing passes by the audio engine on the data in
// the endpoint buffer.
hr = pAudioClient->GetDevicePeriod(&hnsDefaultDevicePeriod, NULL);
EXIT_ON_ERROR(hr)
AdjustFormatTo16Bits(pwfx);
// 平时创建定时器使用的是WINAPI SetTimer不过该函数一般用于有界面的时候。
// 无界面的情况下可以选择微软提供的CreateWaitableTimer和SetWaitableTimer
// API。
hTimerWakeUp = CreateWaitableTimer(NULL, FALSE, NULL);
DWORD flag;
if (IS_INPUT_DEVICE)
flag = 0;
else
flag = AUDCLNT_STREAMFLAGS_LOOPBACK;
if (IS_INPUT_DEVICE)
hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, flag /*0*/, 0, 0,
pwfx, NULL); // 输入
else
hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, flag /*0*/, 0, 0,
pwfx, NULL); // 输出
EXIT_ON_ERROR(hr)
// Get the size of the allocated buffer.
hr = pAudioClient->GetBufferSize(&bufferFrameCount);
EXIT_ON_ERROR(hr)
hr = pAudioClient->GetService(IID_IAudioCaptureClient,
(void **)&pCaptureClient);
EXIT_ON_ERROR(hr)
LARGE_INTEGER liFirstFire;
liFirstFire.QuadPart =
-hnsDefaultDevicePeriod / 2; // negative means relative time
LONG lTimeBetweenFires = (LONG)hnsDefaultDevicePeriod / 2 /
(10 * 1000); // convert to milliseconds
BOOL bOK = SetWaitableTimer(hTimerWakeUp, &liFirstFire, lTimeBetweenFires,
NULL, NULL, FALSE);
// Notify the audio sink which format to use.
hr = pMySink->SetFormat(pwfx);
EXIT_ON_ERROR(hr)
// Calculate the actual duration of the allocated buffer.
hnsActualDuration =
(double)REFTIMES_PER_SEC * bufferFrameCount / pwfx->nSamplesPerSec;
/*************************************************************/
hr = pAudioClient->Start(); // Start recording.
EXIT_ON_ERROR(hr)
HANDLE waitArray[1] = {/*htemp hEventStop,*/ hTimerWakeUp};
// Each loop fills about half of the shared buffer.
while (bDone == FALSE) {
// Sleep for half the buffer duration.
// Sleep(hnsActualDuration/REFTIMES_PER_MILLISEC/2);//这句貌似不加也可以
// WaitForSingleObject(hTimerWakeUp,INFINITE);
int a = sizeof(waitArray);
int aa = sizeof(waitArray[0]);
WaitForMultipleObjects(sizeof(waitArray) / sizeof(waitArray[0]), waitArray,
FALSE, INFINITE);
// WaitForMultipleObjects(sizeof(waitArray) / sizeof(waitArray[0]),
// waitArray, FALSE, INFINITE);
hr = pCaptureClient->GetNextPacketSize(&packetLength);
EXIT_ON_ERROR(hr)
while (packetLength != 0) {
// Get the available data in the shared buffer.
hr = pCaptureClient->GetBuffer(&pData, &numFramesAvailable, &flags, NULL,
&ts);
ts = ts * 100;
uint64_t timestamp =
os_gettime_ns(); // ts是设备时间timestamp是系统时间
EXIT_ON_ERROR(hr)
// 位运算flags的标志符为2静音状态将pData置为NULL
if (flags & AUDCLNT_BUFFERFLAGS_SILENT) {
pData = NULL; // Tell CopyData to write silence.
}
// Copy the available capture data to the audio sink.
hr = pMySink->CopyData((SHORT *)pData,
numFramesAvailable * pwfx->nBlockAlign, &bDone);
EXIT_ON_ERROR(hr)
hr = pCaptureClient->ReleaseBuffer(numFramesAvailable);
EXIT_ON_ERROR(hr)
hr = pCaptureClient->GetNextPacketSize(&packetLength);
EXIT_ON_ERROR(hr)
}
}
hr = pAudioClient->Stop(); // Stop recording.
EXIT_ON_ERROR(hr)
Exit:
CoTaskMemFree(pwfx);
SAFE_RELEASE(pEnumerator)
SAFE_RELEASE(pDevice)
SAFE_RELEASE(pAudioClient)
SAFE_RELEASE(pCaptureClient)
return hr;
}
int _tmain(int argc, _TCHAR *argv[]) {
fopen_s(&fp, "record.pcm", "wb");
CoInitialize(NULL);
MyAudioSink test;
RecordAudioStream(&test);
return 0;
}

View File

@@ -1,232 +0,0 @@
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavfilter/avfilter.h>
#include <libavformat/avformat.h>
#include <libavutil/channel_layout.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#include <libavutil/samplefmt.h>
#include <libswresample/swresample.h>
#include <libswscale/swscale.h>
};
static int get_format_from_sample_fmt(const char **fmt,
enum AVSampleFormat sample_fmt) {
int i;
struct sample_fmt_entry {
enum AVSampleFormat sample_fmt;
const char *fmt_be, *fmt_le;
} sample_fmt_entries[] = {
{AV_SAMPLE_FMT_U8, "u8", "u8"},
{AV_SAMPLE_FMT_S16, "s16be", "s16le"},
{AV_SAMPLE_FMT_S32, "s32be", "s32le"},
{AV_SAMPLE_FMT_FLT, "f32be", "f32le"},
{AV_SAMPLE_FMT_DBL, "f64be", "f64le"},
};
*fmt = NULL;
for (i = 0; i < FF_ARRAY_ELEMS(sample_fmt_entries); i++) {
struct sample_fmt_entry *entry = &sample_fmt_entries[i];
if (sample_fmt == entry->sample_fmt) {
*fmt = AV_NE(entry->fmt_be, entry->fmt_le);
return 0;
}
}
fprintf(stderr, "Sample format %s not supported as output format\n",
av_get_sample_fmt_name(sample_fmt));
return AVERROR(EINVAL);
}
/**
* Fill dst buffer with nb_samples, generated starting from t. <20><><EFBFBD><EFBFBD>ģʽ<C4A3><CABD>
*/
static void fill_samples(double *dst, int nb_samples, int nb_channels,
int sample_rate, double *t) {
int i, j;
double tincr = 1.0 / sample_rate, *dstp = dst;
const double c = 2 * M_PI * 440.0;
/* generate sin tone with 440Hz frequency and duplicated channels */
for (i = 0; i < nb_samples; i++) {
*dstp = sin(c * *t);
for (j = 1; j < nb_channels; j++) dstp[j] = dstp[0];
dstp += nb_channels;
*t += tincr;
}
}
int main(int argc, char **argv) {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int64_t src_ch_layout = AV_CH_LAYOUT_MONO;
int src_rate = 44100;
enum AVSampleFormat src_sample_fmt = AV_SAMPLE_FMT_DBL;
int src_nb_channels = 0;
uint8_t **src_data = NULL; // <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
int src_linesize;
int src_nb_samples = 1024;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int64_t dst_ch_layout = AV_CH_LAYOUT_STEREO;
int dst_rate = 48000;
enum AVSampleFormat dst_sample_fmt = AV_SAMPLE_FMT_S16;
int dst_nb_channels = 0;
uint8_t **dst_data = NULL; // <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
int dst_linesize;
int dst_nb_samples;
int max_dst_nb_samples;
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
const char *dst_filename = NULL; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>pcm<63><6D><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>Ȼ<EFBFBD>󲥷<EFBFBD><F3B2A5B7><EFBFBD>֤
FILE *dst_file;
int dst_bufsize;
const char *fmt;
// <20>ز<EFBFBD><D8B2><EFBFBD>ʵ<EFBFBD><CAB5>
struct SwrContext *swr_ctx;
double t;
int ret;
dst_filename = "res.pcm";
dst_file = fopen(dst_filename, "wb");
if (!dst_file) {
fprintf(stderr, "Could not open destination file %s\n", dst_filename);
exit(1);
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD>
/* create resampler context */
swr_ctx = swr_alloc();
if (!swr_ctx) {
fprintf(stderr, "Could not allocate resampler context\n");
ret = AVERROR(ENOMEM);
goto end;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/* set options */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0);
av_opt_set_int(swr_ctx, "in_sample_rate", src_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0);
av_opt_set_int(swr_ctx, "out_sample_rate", dst_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0);
// <20><>ʼ<EFBFBD><CABC><EFBFBD>ز<EFBFBD><D8B2><EFBFBD>
/* initialize the resampling context */
if ((ret = swr_init(swr_ctx)) < 0) {
fprintf(stderr, "Failed to initialize the resampling context\n");
goto end;
}
/* allocate source and destination samples buffers */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>ռ<EFBFBD>
ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize,
src_nb_channels, src_nb_samples,
src_sample_fmt, 0);
if (ret < 0) {
fprintf(stderr, "Could not allocate source samples\n");
goto end;
}
/* compute the number of converted samples: buffering is avoided
* ensuring that the output buffer will contain at least all the
* converted input samples */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
max_dst_nb_samples = dst_nb_samples =
av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
/* buffer is going to be directly written to a rawaudio file, no alignment
*/
dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize,
dst_nb_channels, dst_nb_samples,
dst_sample_fmt, 0);
if (ret < 0) {
fprintf(stderr, "Could not allocate destination samples\n");
goto end;
}
t = 0;
do {
/* generate synthetic audio */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
fill_samples((double *)src_data[0], src_nb_samples, src_nb_channels,
src_rate, &t);
/* compute destination number of samples */
int64_t delay = swr_get_delay(swr_ctx, src_rate);
dst_nb_samples =
av_rescale_rnd(delay + src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
if (dst_nb_samples > max_dst_nb_samples) {
av_freep(&dst_data[0]);
ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
dst_nb_samples, dst_sample_fmt, 1);
if (ret < 0) break;
max_dst_nb_samples = dst_nb_samples;
}
// int fifo_size = swr_get_out_samples(swr_ctx,src_nb_samples);
// printf("fifo_size:%d\n", fifo_size);
// if(fifo_size < 1024)
// continue;
/* convert to destination format */
// ret = swr_convert(swr_ctx, dst_data, dst_nb_samples, (const
// uint8_t **)src_data, src_nb_samples);
ret = swr_convert(swr_ctx, dst_data, dst_nb_samples,
(const uint8_t **)src_data, src_nb_samples);
if (ret < 0) {
fprintf(stderr, "Error while converting\n");
goto end;
}
dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
ret, dst_sample_fmt, 1);
if (dst_bufsize < 0) {
fprintf(stderr, "Could not get sample buffer size\n");
goto end;
}
printf("t:%f in:%d out:%d\n", t, src_nb_samples, ret);
fwrite(dst_data[0], 1, dst_bufsize, dst_file);
} while (t < 10);
ret = swr_convert(swr_ctx, dst_data, dst_nb_samples, NULL, 0);
if (ret < 0) {
fprintf(stderr, "Error while converting\n");
goto end;
}
dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels, ret,
dst_sample_fmt, 1);
if (dst_bufsize < 0) {
fprintf(stderr, "Could not get sample buffer size\n");
goto end;
}
printf("flush in:%d out:%d\n", 0, ret);
fwrite(dst_data[0], 1, dst_bufsize, dst_file);
if ((ret = get_format_from_sample_fmt(&fmt, dst_sample_fmt)) < 0) goto end;
fprintf(stderr,
"Resampling succeeded. Play the output file with the command:\n"
"ffplay -f %s -channel_layout %" PRId64 " -channels %d -ar %d %s\n",
fmt, dst_ch_layout, dst_nb_channels, dst_rate, dst_filename);
end:
fclose(dst_file);
if (src_data) av_freep(&src_data[0]);
av_freep(&src_data);
if (dst_data) av_freep(&dst_data[0]);
av_freep(&dst_data);
swr_free(&swr_ctx);
return ret < 0;
}

View File

@@ -1,96 +0,0 @@
/*
Demonstrates how to implement loopback recording.
This example simply captures data from your default playback device until you
press Enter. The output is saved to the file specified on the command line.
Loopback mode is when you record audio that is played from a given speaker. It
is only supported on WASAPI, but can be used indirectly with PulseAudio by
choosing the appropriate loopback device after enumeration.
To use loopback mode you just need to set the device type to
ma_device_type_loopback and set the capture device config properties. The output
buffer in the callback will be null whereas the input buffer will be valid.
*/
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
#include <stdio.h>
#include <stdlib.h>
FILE* fp;
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput,
ma_uint32 frameCount) {
// ma_encoder* pEncoder = (ma_encoder*)pDevice->pUserData;
// MA_ASSERT(pEncoder != NULL);
// ma_encoder_write_pcm_frames(pEncoder, pInput, frameCount, NULL);
fwrite(pInput, frameCount * ma_get_bytes_per_frame(ma_format_s16, 1), 1, fp);
(void)pOutput;
}
int main(int argc, char** argv) {
ma_result result;
ma_encoder_config encoderConfig;
ma_encoder encoder;
ma_device_config deviceConfig;
ma_device device;
fopen_s(&fp, "miniaudio.pcm", "wb");
/* Loopback mode is currently only supported on WASAPI. */
ma_backend backends[] = {ma_backend_wasapi};
// if (argc < 2) {
// printf("No output file.\n");
// return -1;
// }
// encoderConfig =
// ma_encoder_config_init(ma_encoding_format_wav, ma_format_s16, 1,
// 48000);
// if (ma_encoder_init_file(argv[1], &encoderConfig, &encoder) != MA_SUCCESS)
// {
// printf("Failed to initialize output file.\n");
// return -1;
// }
deviceConfig = ma_device_config_init(ma_device_type_loopback);
deviceConfig.capture.pDeviceID =
NULL; /* Use default device for this example. Set this to the ID of a
_playback_ device if you want to capture from a specific device.
*/
deviceConfig.capture.format = ma_format_s16;
deviceConfig.capture.channels = 1;
deviceConfig.sampleRate = 48000;
deviceConfig.dataCallback = data_callback;
deviceConfig.pUserData = nullptr;
result = ma_device_init_ex(backends, sizeof(backends) / sizeof(backends[0]),
NULL, &deviceConfig, &device);
if (result != MA_SUCCESS) {
printf("Failed to initialize loopback device.\n");
return -2;
}
result = ma_device_start(&device);
if (result != MA_SUCCESS) {
ma_device_uninit(&device);
printf("Failed to start device.\n");
return -3;
}
printf("Press Enter to stop recording...\n");
getchar();
fclose(fp);
ma_device_uninit(&device);
// ma_encoder_uninit(&encoder);
return 0;
}

View File

@@ -1,53 +0,0 @@
#include <SDL2/SDL.h>
int main(int argc, char *argv[]) {
int ret;
SDL_AudioSpec wanted_spec, obtained_spec;
// Initialize SDL
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize SDL: %s",
SDL_GetError());
return -1;
}
// Set audio format
wanted_spec.freq = 44100; // Sample rate
wanted_spec.format =
AUDIO_F32SYS; // Sample format (32-bit float, system byte order)
wanted_spec.channels = 2; // Number of channels (stereo)
wanted_spec.samples = 1024; // Buffer size (in samples)
wanted_spec.callback = NULL; // Audio callback function (not used here)
// Open audio device
ret = SDL_OpenAudio(&wanted_spec, &obtained_spec);
if (ret < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to open audio device: %s", SDL_GetError());
return -1;
}
// Start playing audio
SDL_PauseAudio(0);
// Write PCM data to audio buffer
float *pcm_data = ...; // PCM data buffer (float, interleaved)
int pcm_data_size = ...; // Size of PCM data buffer (in bytes)
int bytes_written = SDL_QueueAudio(0, pcm_data, pcm_data_size);
// Wait until audio buffer is empty
while (SDL_GetQueuedAudioSize(0) > 0) {
SDL_Delay(100);
}
// Stop playing audio
SDL_PauseAudio(1);
// Close audio device
SDL_CloseAudio();
// Quit SDL
SDL_Quit();
return 0;
}

View File

@@ -1,89 +0,0 @@
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[]) {
if (SDL_Init(SDL_INIT_AUDIO)) {
printf("SDL init error\n");
return -1;
}
// SDL_AudioSpec
SDL_AudioSpec wanted_spec;
SDL_zero(wanted_spec);
wanted_spec.freq = 48000;
wanted_spec.format = AUDIO_S16LSB;
wanted_spec.channels = 2;
wanted_spec.silence = 0;
wanted_spec.samples = 960;
wanted_spec.callback = NULL;
SDL_AudioDeviceID deviceID = 0;
// <20><><EFBFBD><EFBFBD><EFBFBD>
if ((deviceID = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, NULL,
SDL_AUDIO_ALLOW_FREQUENCY_CHANGE)) < 2) {
printf("could not open audio device: %s\n", SDL_GetError());
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD>ϵͳ
SDL_Quit();
return 0;
}
SDL_PauseAudioDevice(deviceID, 0);
FILE* fp = nullptr;
fopen_s(&fp, "ls.pcm", "rb+");
if (fp == NULL) {
printf("cannot open this file\n");
return -1;
}
if (fp == NULL) {
printf("error \n");
}
Uint32 buffer_size = 4096;
char* buffer = (char*)malloc(buffer_size);
while (true) {
if (fread(buffer, 1, buffer_size, fp) != buffer_size) {
printf("end of file\n");
break;
}
SDL_QueueAudio(deviceID, buffer, buffer_size);
}
printf("Play...\n");
SDL_Delay(10000);
// Uint32 residueAudioLen = 0;
// while (true) {
// residueAudioLen = SDL_GetQueuedAudioSize(deviceID);
// printf("%10d\n", residueAudioLen);
// if (residueAudioLen <= 0) break;
// SDL_Delay(1);
// }
// while (true) {
// printf("1 <20><>ͣ 2 <20><><EFBFBD><EFBFBD> 3 <20>˳<EFBFBD> \n");
// int flag = 0;
// scanf_s("%d", &flag);
// if (flag == 1)
// SDL_PauseAudioDevice(deviceID, 1);
// else if (flag == 2)
// SDL_PauseAudioDevice(deviceID, 0);
// else if (flag == 3)
// break;
// }
SDL_CloseAudio();
SDL_Quit();
fclose(fp);
return 0;
}

View File

@@ -1,225 +0,0 @@
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavfilter/avfilter.h>
#include <libavformat/avformat.h>
#include <libavutil/channel_layout.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#include <libavutil/samplefmt.h>
#include <libswresample/swresample.h>
#include <libswscale/swscale.h>
};
static SDL_AudioDeviceID input_dev;
static SDL_AudioDeviceID output_dev;
static Uint8 *buffer = 0;
static int in_pos = 0;
static int out_pos = 0;
int64_t src_ch_layout = AV_CH_LAYOUT_MONO;
int src_rate = 48000;
enum AVSampleFormat src_sample_fmt = AV_SAMPLE_FMT_S16;
int src_nb_channels = 0;
uint8_t **src_data = NULL; // <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
int src_linesize;
int src_nb_samples = 480;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int64_t dst_ch_layout = AV_CH_LAYOUT_MONO;
int dst_rate = 48000;
enum AVSampleFormat dst_sample_fmt = AV_SAMPLE_FMT_S16;
int dst_nb_channels = 0;
uint8_t **dst_data = NULL; // <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
int dst_linesize;
int dst_nb_samples;
int max_dst_nb_samples;
static unsigned char audio_buffer[960 * 3];
static int audio_len = 0;
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
const char *dst_filename = NULL; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>pcm<63><6D><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>Ȼ<EFBFBD>󲥷<EFBFBD><F3B2A5B7><EFBFBD>֤
FILE *dst_file;
int dst_bufsize;
const char *fmt;
// <20>ز<EFBFBD><D8B2><EFBFBD>ʵ<EFBFBD><CAB5>
struct SwrContext *swr_ctx;
double t;
int ret;
char *out = "audio_old.pcm";
FILE *outfile = fopen(out, "wb+");
void cb_in(void *userdata, Uint8 *stream, int len) {
// If len < 4, the printf below will probably segfault
// SDL_QueueAudio(output_dev, stream, len);
int64_t delay = swr_get_delay(swr_ctx, src_rate);
dst_nb_samples =
av_rescale_rnd(delay + src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
if (dst_nb_samples > max_dst_nb_samples) {
av_freep(&dst_data[0]);
ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
dst_nb_samples, dst_sample_fmt, 1);
if (ret < 0) return;
max_dst_nb_samples = dst_nb_samples;
}
ret = swr_convert(swr_ctx, dst_data, dst_nb_samples,
(const uint8_t **)&stream, src_nb_samples);
if (ret < 0) {
fprintf(stderr, "Error while converting\n");
return;
}
dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels, ret,
dst_sample_fmt, 1);
if (dst_bufsize < 0) {
fprintf(stderr, "Could not get sample buffer size\n");
return;
}
printf("t:%f in:%d out:%d %d\n", t, src_nb_samples, ret, len);
memcpy(audio_buffer, dst_data[0], len);
// SDL_QueueAudio(output_dev, dst_data[0], len);
audio_len = len;
}
void cb_out(void *userdata, Uint8 *stream, int len) {
// If len < 4, the printf below will probably segfault
printf("cb_out len = %d\n", len);
SDL_memset(stream, 0, len);
if (audio_len == 0) return;
len = (len > audio_len ? audio_len : len);
SDL_MixAudioFormat(stream, audio_buffer, AUDIO_S16LSB, len,
SDL_MIX_MAXVOLUME);
}
int init() {
dst_filename = "res.pcm";
dst_file = fopen(dst_filename, "wb");
if (!dst_file) {
fprintf(stderr, "Could not open destination file %s\n", dst_filename);
exit(1);
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD>
/* create resampler context */
swr_ctx = swr_alloc();
if (!swr_ctx) {
fprintf(stderr, "Could not allocate resampler context\n");
ret = AVERROR(ENOMEM);
return -1;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/* set options */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0);
av_opt_set_int(swr_ctx, "in_sample_rate", src_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0);
av_opt_set_int(swr_ctx, "out_sample_rate", dst_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0);
// <20><>ʼ<EFBFBD><CABC><EFBFBD>ز<EFBFBD><D8B2><EFBFBD>
/* initialize the resampling context */
if ((ret = swr_init(swr_ctx)) < 0) {
fprintf(stderr, "Failed to initialize the resampling context\n");
return -1;
}
/* allocate source and destination samples buffers */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>ռ<EFBFBD>
ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize,
src_nb_channels, src_nb_samples,
src_sample_fmt, 0);
if (ret < 0) {
fprintf(stderr, "Could not allocate source samples\n");
return -1;
}
/* compute the number of converted samples: buffering is avoided
* ensuring that the output buffer will contain at least all the
* converted input samples */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
max_dst_nb_samples = dst_nb_samples =
av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
/* buffer is going to be directly written to a rawaudio file, no alignment */
dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize,
dst_nb_channels, dst_nb_samples,
dst_sample_fmt, 0);
if (ret < 0) {
fprintf(stderr, "Could not allocate destination samples\n");
return -1;
}
}
int main() {
init();
SDL_Init(SDL_INIT_AUDIO);
// 16Mb should be enough; the test lasts 5 seconds
buffer = (Uint8 *)malloc(16777215);
SDL_AudioSpec want_in, want_out, have_in, have_out;
SDL_zero(want_in);
want_in.freq = 48000;
want_in.format = AUDIO_S16LSB;
want_in.channels = 1;
want_in.samples = 480;
want_in.callback = cb_in;
input_dev = SDL_OpenAudioDevice(NULL, 1, &want_in, &have_in, 0);
printf("%d %d %d %d\n", have_in.freq, have_in.format, have_in.channels,
have_in.samples);
if (input_dev == 0) {
SDL_Log("Failed to open input: %s", SDL_GetError());
return 1;
}
SDL_zero(want_out);
want_out.freq = 48000;
want_out.format = AUDIO_S16LSB;
want_out.channels = 1;
want_out.samples = 480;
want_out.callback = cb_out;
output_dev = SDL_OpenAudioDevice(NULL, 0, &want_out, &have_out, 0);
printf("%d %d %d %d\n", have_out.freq, have_out.format, have_out.channels,
have_out.samples);
if (output_dev == 0) {
SDL_Log("Failed to open input: %s", SDL_GetError());
return 1;
}
SDL_PauseAudioDevice(input_dev, 0);
SDL_PauseAudioDevice(output_dev, 0);
while (1) {
}
SDL_CloseAudioDevice(output_dev);
SDL_CloseAudioDevice(input_dev);
free(buffer);
fclose(outfile);
}

View File

@@ -1,95 +0,0 @@
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int ret;
AVFrame *frame = NULL;
AVFrame *resampled_frame = NULL;
AVCodecContext *codec_ctx = NULL;
SwrContext *swr_ctx = NULL;
// Initialize FFmpeg
av_log_set_level(AV_LOG_INFO);
av_register_all();
// Allocate input frame
frame = av_frame_alloc();
if (!frame) {
av_log(NULL, AV_LOG_ERROR, "Failed to allocate input frame\n");
return -1;
}
// Allocate output frame for resampled data
resampled_frame = av_frame_alloc();
if (!resampled_frame) {
av_log(NULL, AV_LOG_ERROR, "Failed to allocate output frame\n");
return -1;
}
// Set input frame properties
frame->format = AV_SAMPLE_FMT_FLTP; // Input sample format (float planar)
frame->channel_layout = AV_CH_LAYOUT_STEREO; // Input channel layout (stereo)
frame->sample_rate = 44100; // Input sample rate (44100 Hz)
frame->nb_samples = 1024; // Number of input samples
// Set output frame properties
resampled_frame->format =
AV_SAMPLE_FMT_S16; // Output sample format (signed 16-bit)
resampled_frame->channel_layout =
AV_CH_LAYOUT_STEREO; // Output channel layout (stereo)
resampled_frame->sample_rate = 48000; // Output sample rate (48000 Hz)
resampled_frame->nb_samples = av_rescale_rnd(
frame->nb_samples, resampled_frame->sample_rate, frame->sample_rate,
AV_ROUND_UP); // Number of output samples
// Initialize resampler context
swr_ctx = swr_alloc_set_opts(
NULL, av_get_default_channel_layout(resampled_frame->channel_layout),
av_get_default_sample_fmt(resampled_frame->format),
resampled_frame->sample_rate,
av_get_default_channel_layout(frame->channel_layout),
av_get_default_sample_fmt(frame->format), frame->sample_rate, 0, NULL);
if (!swr_ctx) {
av_log(NULL, AV_LOG_ERROR, "Failed to allocate resampler context\n");
return -1;
}
// Initialize and configure the resampler
if ((ret = swr_init(swr_ctx)) < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to initialize resampler context: %s\n",
av_err2str(ret));
return -1;
}
// Allocate buffer for output samples
ret = av_samples_alloc(resampled_frame->data, resampled_frame->linesize,
resampled_frame->channels, resampled_frame->nb_samples,
resampled_frame->format, 0);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to allocate output samples buffer: %s\n",
av_err2str(ret));
return -1;
}
// Resample the input data
ret = swr_convert(swr_ctx, resampled_frame->data, resampled_frame->nb_samples,
(const uint8_t **)frame->data, frame->nb_samples);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to resample input data: %s\n",
av_err2str(ret));
return -1;
}
// Cleanup and free resources
swr_free(&swr_ctx);
av_frame_free(&frame);
av_frame_free(&resampled_frame);
return 0;
}

View File

@@ -1,205 +0,0 @@
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavfilter/avfilter.h>
#include <libavformat/avformat.h>
#include <libavutil/channel_layout.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#include <libavutil/samplefmt.h>
#include <libswresample/swresample.h>
#include <libswscale/swscale.h>
};
static SDL_AudioDeviceID input_dev;
static SDL_AudioDeviceID output_dev;
static Uint8 *buffer = 0;
static int in_pos = 0;
static int out_pos = 0;
int64_t src_ch_layout = AV_CH_LAYOUT_MONO;
int src_rate = 48000;
enum AVSampleFormat src_sample_fmt = AV_SAMPLE_FMT_FLT;
int src_nb_channels = 0;
uint8_t **src_data = NULL; // <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
int src_linesize;
int src_nb_samples = 480;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int64_t dst_ch_layout = AV_CH_LAYOUT_STEREO;
int dst_rate = 48000;
enum AVSampleFormat dst_sample_fmt = AV_SAMPLE_FMT_S16;
int dst_nb_channels = 0;
uint8_t **dst_data = NULL; // <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
int dst_linesize;
int dst_nb_samples;
int max_dst_nb_samples;
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
const char *dst_filename = NULL; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>pcm<63><6D><EFBFBD><EFBFBD><EFBFBD>أ<EFBFBD>Ȼ<EFBFBD>󲥷<EFBFBD><F3B2A5B7><EFBFBD>֤
FILE *dst_file;
int dst_bufsize;
const char *fmt;
// <20>ز<EFBFBD><D8B2><EFBFBD>ʵ<EFBFBD><CAB5>
struct SwrContext *swr_ctx;
double t;
int ret;
char *out = "audio_old.pcm";
FILE *outfile = fopen(out, "wb+");
void cb_in(void *userdata, Uint8 *stream, int len) {
// If len < 4, the printf below will probably segfault
{
fwrite(stream, 1, len, outfile);
fflush(outfile);
}
{
int64_t delay = swr_get_delay(swr_ctx, src_rate);
dst_nb_samples =
av_rescale_rnd(delay + src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
if (dst_nb_samples > max_dst_nb_samples) {
av_freep(&dst_data[0]);
ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
dst_nb_samples, dst_sample_fmt, 1);
if (ret < 0) return;
max_dst_nb_samples = dst_nb_samples;
}
ret = swr_convert(swr_ctx, dst_data, dst_nb_samples,
(const uint8_t **)&stream, src_nb_samples);
if (ret < 0) {
fprintf(stderr, "Error while converting\n");
return;
}
dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
ret, dst_sample_fmt, 1);
if (dst_bufsize < 0) {
fprintf(stderr, "Could not get sample buffer size\n");
return;
}
printf("t:%f in:%d out:%d\n", t, src_nb_samples, ret);
fwrite(dst_data[0], 1, dst_bufsize, dst_file);
}
}
void cb_out(void *userdata, Uint8 *stream, int len) {
// If len < 4, the printf below will probably segfault
SDL_memcpy(buffer + out_pos, stream, len);
out_pos += len;
}
int init() {
dst_filename = "res.pcm";
dst_file = fopen(dst_filename, "wb");
if (!dst_file) {
fprintf(stderr, "Could not open destination file %s\n", dst_filename);
exit(1);
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD>
/* create resampler context */
swr_ctx = swr_alloc();
if (!swr_ctx) {
fprintf(stderr, "Could not allocate resampler context\n");
ret = AVERROR(ENOMEM);
return -1;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/* set options */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0);
av_opt_set_int(swr_ctx, "in_sample_rate", src_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0);
av_opt_set_int(swr_ctx, "out_sample_rate", dst_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0);
// <20><>ʼ<EFBFBD><CABC><EFBFBD>ز<EFBFBD><D8B2><EFBFBD>
/* initialize the resampling context */
if ((ret = swr_init(swr_ctx)) < 0) {
fprintf(stderr, "Failed to initialize the resampling context\n");
return -1;
}
/* allocate source and destination samples buffers */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>ռ<EFBFBD>
ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize,
src_nb_channels, src_nb_samples,
src_sample_fmt, 0);
if (ret < 0) {
fprintf(stderr, "Could not allocate source samples\n");
return -1;
}
/* compute the number of converted samples: buffering is avoided
* ensuring that the output buffer will contain at least all the
* converted input samples */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
max_dst_nb_samples = dst_nb_samples =
av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
/* buffer is going to be directly written to a rawaudio file, no alignment */
dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize,
dst_nb_channels, dst_nb_samples,
dst_sample_fmt, 0);
if (ret < 0) {
fprintf(stderr, "Could not allocate destination samples\n");
return -1;
}
}
int main() {
init();
SDL_Init(SDL_INIT_AUDIO);
// 16Mb should be enough; the test lasts 5 seconds
buffer = (Uint8 *)malloc(16777215);
SDL_AudioSpec want_in, want_out, have_in, have_out;
SDL_zero(want_in);
want_in.freq = 48000;
want_in.format = AUDIO_F32LSB;
want_in.channels = 2;
want_in.samples = 960;
want_in.callback = cb_in;
input_dev = SDL_OpenAudioDevice(NULL, 1, &want_in, &have_in,
SDL_AUDIO_ALLOW_ANY_CHANGE);
printf("%d %d %d %d\n", have_in.freq, have_in.format, have_in.channels,
have_in.samples);
if (input_dev == 0) {
SDL_Log("Failed to open input: %s", SDL_GetError());
return 1;
}
SDL_PauseAudioDevice(input_dev, 0);
SDL_PauseAudioDevice(output_dev, 0);
SDL_Delay(5000);
SDL_CloseAudioDevice(output_dev);
SDL_CloseAudioDevice(input_dev);
free(buffer);
fclose(outfile);
}

View File

@@ -1,123 +0,0 @@
#define __STDC_CONSTANT_MACROS
extern "C" {
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavutil/log.h>
#include <libswresample/swresample.h>
}
#include <windows.h>
#include <memory>
#include <string>
#include <vector>
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avdevice.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "Winmm.lib")
using std::shared_ptr;
using std::string;
using std::vector;
void capture_audio() {
// windows api <20><>ȡ<EFBFBD><C8A1>Ƶ<EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ffmpeg <20><><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><E1B9A9>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><E8B1B8>api<70><69>
int nDeviceNum = waveInGetNumDevs();
vector<string> vecDeviceName;
for (int i = 0; i < nDeviceNum; ++i) {
WAVEINCAPS wic;
waveInGetDevCaps(i, &wic, sizeof(wic));
// ת<><D7AA>utf-8
int nSize = WideCharToMultiByte(CP_UTF8, 0, wic.szPname,
wcslen(wic.szPname), NULL, 0, NULL, NULL);
shared_ptr<char> spDeviceName(new char[nSize + 1]);
memset(spDeviceName.get(), 0, nSize + 1);
WideCharToMultiByte(CP_UTF8, 0, wic.szPname, wcslen(wic.szPname),
spDeviceName.get(), nSize, NULL, NULL);
vecDeviceName.push_back(spDeviceName.get());
av_log(NULL, AV_LOG_DEBUG, "audio input device : %s \n",
spDeviceName.get());
}
if (vecDeviceName.size() <= 0) {
av_log(NULL, AV_LOG_ERROR, "not find audio input device.\n");
return;
}
string sDeviceName = "audio=" + vecDeviceName[0]; // ʹ<>õ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ƶ<EFBFBD>
// ffmpeg
avdevice_register_all(); // ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
AVInputFormat* ifmt =
(AVInputFormat*)av_find_input_format("dshow"); // <20><><EFBFBD>òɼ<C3B2><C9BC><EFBFBD>ʽ dshow
if (ifmt == NULL) {
av_log(NULL, AV_LOG_ERROR, "av_find_input_format for dshow fail.\n");
return;
}
AVFormatContext* fmt_ctx = NULL; // format <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int ret = avformat_open_input(&fmt_ctx, sDeviceName.c_str(), ifmt,
NULL); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>
if (ret != 0) {
av_log(NULL, AV_LOG_ERROR, "avformat_open_input fail. return %d.\n", ret);
return;
}
AVPacket pkt;
int64_t src_rate = 44100;
int64_t dst_rate = 48000;
SwrContext* swr_ctx = swr_alloc();
uint8_t** dst_data = NULL;
int dst_linesize = 0;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
av_opt_set_int(swr_ctx, "in_channel_layout", AV_CH_LAYOUT_MONO, 0);
av_opt_set_int(swr_ctx, "in_sample_rate", src_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
av_opt_set_int(swr_ctx, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
av_opt_set_int(swr_ctx, "out_sample_rate", dst_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
// <20><>ʼ<EFBFBD><CABC>SwrContext
swr_init(swr_ctx);
FILE* fp = fopen("dst.pcm", "wb");
int count = 0;
while (count++ < 10) {
ret = av_read_frame(fmt_ctx, &pkt);
if (ret != 0) {
av_log(NULL, AV_LOG_ERROR, "av_read_frame fail, return %d .\n", ret);
break;
}
int out_samples_per_channel =
(int)av_rescale_rnd(1024, dst_rate, src_rate, AV_ROUND_UP);
int out_buffer_size = av_samples_get_buffer_size(
NULL, 1, out_samples_per_channel, AV_SAMPLE_FMT_S16, 0);
// uint8_t* out_buffer = (uint8_t*)av_malloc(out_buffer_size);
ret = av_samples_alloc_array_and_samples(
&dst_data, &dst_linesize, 2, out_buffer_size, AV_SAMPLE_FMT_S16, 0);
// <20><><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><D8B2><EFBFBD>
swr_convert(swr_ctx, dst_data, out_samples_per_channel,
(const uint8_t**)&pkt.data, 1024);
fwrite(dst_data[1], 1, out_buffer_size, fp);
av_packet_unref(&pkt); // <20><><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD>pkt<6B><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ棬<DAB4><E6A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>й¶
}
fflush(fp); // ˢ<><CBA2><EFBFBD>ļ<EFBFBD>io<69><6F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
fclose(fp);
avformat_close_input(&fmt_ctx);
}
int main(int argc, char** argv) {
av_log_set_level(AV_LOG_DEBUG); // <20><><EFBFBD><EFBFBD>ffmpeg<65><67>־<EFBFBD><D6BE><EFBFBD>ȼ<EFBFBD>
capture_audio();
Sleep(1);
}

View File

@@ -1,150 +0,0 @@
#include <X11/Xlib.h>
#include <fcntl.h>
#include <linux/uinput.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
#include <sstream>
using namespace std;
int fd;
Display *dpy;
void initMouse();
void destroyMouse();
void mouseLeftClick();
void mouseRightClick();
void mouseGetPosition(int &x, int &y);
void mouseMove(int xdelta, int ydelta);
void initMouse() {
fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
ioctl(fd, UI_SET_EVBIT, EV_KEY);
ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT);
ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
ioctl(fd, UI_SET_EVBIT, EV_ABS);
ioctl(fd, UI_SET_ABSBIT, ABS_X);
ioctl(fd, UI_SET_ABSBIT, ABS_Y);
ioctl(fd, UI_SET_EVBIT, EV_REL);
struct uinput_user_dev uidev;
memset(&uidev, 0, sizeof(uidev));
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "VirtualMouse");
uidev.id.bustype = BUS_USB;
uidev.id.version = 1;
uidev.id.vendor = 0x1;
uidev.id.product = 0x1;
uidev.absmin[ABS_X] = 0;
uidev.absmax[ABS_X] = 3200;
uidev.absmin[ABS_Y] = 0;
uidev.absmax[ABS_Y] = 900;
write(fd, &uidev, sizeof(uidev));
ioctl(fd, UI_DEV_CREATE);
sleep(2);
}
void mouseLeftClick() {
struct input_event ev_click, ev_sync;
memset(&ev_click, 0, sizeof(ev_click));
memset(&ev_sync, 0, sizeof(ev_sync));
ev_click.type = EV_KEY;
ev_click.code = BTN_LEFT;
ev_click.value = 1;
// write left click event
write(fd, &ev_click, sizeof(ev_click));
// sync left click event
ev_sync.type = EV_SYN;
write(fd, &ev_sync, sizeof(ev_sync));
}
void mouseRightClick() {
struct input_event ev_click, ev_sync;
memset(&ev_click, 0, sizeof(ev_click));
memset(&ev_sync, 0, sizeof(ev_sync));
ev_click.type = EV_KEY;
ev_click.code = BTN_RIGHT;
ev_click.value = 1;
// write right click event
write(fd, &ev_click, sizeof(ev_click));
// sync right click event
ev_sync.type = EV_SYN;
write(fd, &ev_sync, sizeof(ev_sync));
}
void mouseSetPosition(int x, int y) {
struct input_event ev[2], ev_sync;
memset(ev, 0, sizeof(ev));
memset(&ev_sync, 0, sizeof(ev_sync));
ev[0].type = EV_ABS;
ev[0].code = ABS_X;
ev[0].value = x;
ev[1].type = EV_ABS;
ev[1].code = ABS_Y;
ev[1].value = y;
int res_w = write(fd, ev, sizeof(ev));
std::cout << "res w : " << res_w << "\n";
ev_sync.type = EV_SYN;
ev_sync.value = 0;
ev_sync.code = 0;
int res_ev_sync = write(fd, &ev_sync, sizeof(ev_sync));
std::cout << "res syn : " << res_ev_sync << "\n";
}
void initDisplay() { dpy = XOpenDisplay(NULL); }
void destroyMouse() { ioctl(fd, UI_DEV_DESTROY); }
void mouseMove(int xdelta, int ydelta) {
int xx, yy;
mouseGetPosition(xx, yy);
mouseSetPosition(xx + xdelta, yy + ydelta);
}
void mouseGetPosition(int &x, int &y) {
Window root, child;
int rootX, rootY, winX, winY;
unsigned int mask;
XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child, &rootX, &rootY,
&winX, &winY, &mask);
std::cout << "root x : " << rootX << "\n";
std::cout << "root y : " << rootY << "\n";
x = rootX;
y = rootY;
}
int main() {
initMouse();
initDisplay();
int tempx, tempy;
for (int i = 0; i < 5; ++i) {
mouseMove(100, 100);
sleep(1);
std::cout << "i : " << i << "\n";
}
destroyMouse();
return 0;
}

View File

@@ -1,309 +0,0 @@
#include <stdio.h>
#define __STDC_CONSTANT_MACROS
#ifdef _WIN32
// Windows
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
#include "SDL2/SDL.h"
};
#else
// Linux...
#ifdef __cplusplus
extern "C" {
#endif
#include <SDL2/SDL.h>
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
#ifdef __cplusplus
};
#endif
#endif
#include <chrono>
// Output YUV420P
#define OUTPUT_YUV420P 0
//'1' Use Dshow
//'0' Use GDIgrab
#define USE_DSHOW 0
// Refresh Event
#define SFM_REFRESH_EVENT (SDL_USEREVENT + 1)
#define SFM_BREAK_EVENT (SDL_USEREVENT + 2)
#define NV12_BUFFER_SIZE 1280 * 720 * 3 / 2
int thread_exit = 0;
SDL_Texture *sdlTexture = nullptr;
SDL_Renderer *sdlRenderer = nullptr;
SDL_Rect sdlRect;
unsigned char nv12_buffer[NV12_BUFFER_SIZE];
std::chrono::_V2::system_clock::time_point last_frame_time;
const int pixel_w = 1280, pixel_h = 720;
int screen_w = 1280, screen_h = 720;
bool done = false;
int YUV420ToNV12FFmpeg(unsigned char *src_buffer, int width, int height,
unsigned char *des_buffer) {
AVFrame *Input_pFrame = av_frame_alloc();
AVFrame *Output_pFrame = av_frame_alloc();
struct SwsContext *img_convert_ctx = sws_getContext(
width, height, AV_PIX_FMT_NV12, width, height, AV_PIX_FMT_YUV420P,
SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
av_image_fill_arrays(Input_pFrame->data, Input_pFrame->linesize, src_buffer,
AV_PIX_FMT_NV12, width, height, 1);
av_image_fill_arrays(Output_pFrame->data, Output_pFrame->linesize, des_buffer,
AV_PIX_FMT_YUV420P, width, height, 1);
sws_scale(img_convert_ctx, (uint8_t const **)Input_pFrame->data,
Input_pFrame->linesize, 0, height, Output_pFrame->data,
Output_pFrame->linesize);
if (Input_pFrame) av_free(Input_pFrame);
if (Output_pFrame) av_free(Output_pFrame);
if (img_convert_ctx) sws_freeContext(img_convert_ctx);
return 0;
}
int sfp_refresh_thread(void *opaque) {
thread_exit = 0;
while (!thread_exit) {
SDL_Event event;
event.type = SFM_REFRESH_EVENT;
SDL_PushEvent(&event);
SDL_Delay(30);
printf("sfp_refresh_thread\n");
}
thread_exit = 0;
// Break
SDL_Event event;
event.type = SFM_BREAK_EVENT;
SDL_PushEvent(&event);
printf("exit sfp_refresh_thread\n");
return 0;
}
int main(int argc, char *argv[]) {
AVFormatContext *pFormatCtx;
int i, videoindex;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVCodecParameters *pCodecParam;
// avformat_network_init();
pFormatCtx = avformat_alloc_context();
// Open File
char filepath[] = "out.h264";
// avformat_open_input(&pFormatCtx, filepath, NULL, NULL);
// Register Device
avdevice_register_all();
// Windows
// Linux
AVDictionary *options = NULL;
// Set some options
// grabbing frame rate
av_dict_set(&options, "framerate", "30", 0);
// Make the grabbed area follow the mouse
// av_dict_set(&options, "follow_mouse", "centered", 0);
// Video frame size. The default is to capture the full screen
av_dict_set(&options, "video_size", "1280x720", 0);
AVInputFormat *ifmt = (AVInputFormat *)av_find_input_format("x11grab");
if (!ifmt) {
printf("Couldn't find_input_format\n");
}
// Grab at position 10,20
if (avformat_open_input(&pFormatCtx, ":0.0", ifmt, &options) != 0) {
printf("Couldn't open input stream.\n");
return -1;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
printf("Couldn't find stream information.\n");
return -1;
}
videoindex = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++)
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoindex = i;
break;
}
if (videoindex == -1) {
printf("Didn't find a video stream.\n");
return -1;
}
pCodecParam = pFormatCtx->streams[videoindex]->codecpar;
pCodecCtx = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(pCodecCtx, pCodecParam);
pCodec = const_cast<AVCodec *>(avcodec_find_decoder(pCodecCtx->codec_id));
if (pCodec == NULL) {
printf("Codec not found.\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
printf("Could not open codec.\n");
return -1;
}
AVFrame *pFrame, *pFrameYUV, *pFrameNV12;
pFrame = av_frame_alloc();
pFrameYUV = av_frame_alloc();
pFrameNV12 = av_frame_alloc();
// unsigned char *out_buffer=(unsigned char
// *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width,
// pCodecCtx->height)); avpicture_fill((AVPicture *)pFrameYUV, out_buffer,
// AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
// SDL----------------------------
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
printf("Could not initialize SDL - %s\n", SDL_GetError());
return -1;
}
// const SDL_VideoInfo *vi = SDL_GetVideoInfo();
// Half of the Desktop's width and height.
screen_w = 1280;
screen_h = 720;
// SDL_Surface *screen;
// screen = SDL_SetVideoMode(screen_w, screen_h, 0, 0);
SDL_Window *screen;
screen = SDL_CreateWindow("Linux Capture", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, screen_w, screen_h,
SDL_WINDOW_RESIZABLE);
if (!screen) {
printf("SDL: could not set video mode - exiting:%s\n", SDL_GetError());
return -1;
}
// SDL_Overlay *bmp;
// bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,
// SDL_YV12_OVERLAY, screen);
sdlRenderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);
Uint32 pixformat = 0;
pixformat = SDL_PIXELFORMAT_NV12;
SDL_Texture *sdlTexture = nullptr;
sdlTexture = SDL_CreateTexture(sdlRenderer, pixformat,
SDL_TEXTUREACCESS_STREAMING, pixel_w, pixel_h);
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = screen_w;
rect.h = screen_h;
// SDL End------------------------
int ret, got_picture;
AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
struct SwsContext *img_convert_ctx;
img_convert_ctx = sws_getContext(
pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width,
pCodecCtx->height, AV_PIX_FMT_NV12, SWS_BICUBIC, NULL, NULL, NULL);
//------------------------------
SDL_Thread *video_tid = SDL_CreateThread(sfp_refresh_thread, NULL, NULL);
//
// SDL_WM_SetCaption("Simplest FFmpeg Grab Desktop", NULL);
// Event Loop
SDL_Event event;
last_frame_time = std::chrono::steady_clock::now();
for (;;) {
// Wait
SDL_WaitEvent(&event);
if (1) {
//------------------------------
if (av_read_frame(pFormatCtx, packet) >= 0) {
if (packet->stream_index == videoindex) {
avcodec_send_packet(pCodecCtx, packet);
av_packet_unref(packet);
got_picture = avcodec_receive_frame(pCodecCtx, pFrame);
// ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,
// packet);
if (ret < 0) {
printf("Decode Error.\n");
return -1;
}
printf("xxxxxxxxxxxxxxxxxxx\n");
if (!got_picture) {
auto now_time = std::chrono::steady_clock::now();
std::chrono::duration<double> duration = now_time - last_frame_time;
auto tc = duration.count() * 1000;
printf("duration: %f\n", tc);
last_frame_time = now_time;
av_image_fill_arrays(pFrameNV12->data, pFrameNV12->linesize,
nv12_buffer, AV_PIX_FMT_NV12, pFrame->width,
pFrame->height, 1);
sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0,
pFrame->height, pFrameNV12->data, pFrameNV12->linesize);
SDL_UpdateTexture(sdlTexture, NULL, nv12_buffer, pixel_w);
// FIX: If window is resize
sdlRect.x = 0;
sdlRect.y = 0;
sdlRect.w = screen_w;
sdlRect.h = screen_h;
SDL_RenderClear(sdlRenderer);
SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &sdlRect);
SDL_RenderPresent(sdlRenderer);
}
}
// av_free_packet(packet);
} else {
// Exit Thread
// thread_exit = 1;
// printf("No frame read\n");
}
} else if (event.type == SDL_QUIT) {
printf("SDL_QUIT\n");
thread_exit = 1;
} else if (event.type == SFM_BREAK_EVENT) {
break;
}
}
sws_freeContext(img_convert_ctx);
#if OUTPUT_YUV420P
fclose(fp_yuv);
#endif
SDL_Quit();
// av_free(out_buffer);
av_frame_free(&pFrameNV12);
av_free(pFrameYUV);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
getchar();
return 0;
}

View File

@@ -1,286 +0,0 @@
#include <stdio.h>
#define __STDC_CONSTANT_MACROS
#ifdef _WIN32
// Windows
extern "C" {
#include "SDL/SDL.h"
#include "libavcodec/avcodec.h"
#include "libavdevice/avdevice.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
};
#else
// Linux...
#ifdef __cplusplus
extern "C" {
#endif
#include <SDL2/SDL.h>
#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#ifdef __cplusplus
};
#endif
#endif
// Output YUV420P
#define OUTPUT_YUV420P 0
//'1' Use Dshow
//'0' Use GDIgrab
#define USE_DSHOW 0
// Refresh Event
#define SFM_REFRESH_EVENT (SDL_USEREVENT + 1)
#define SFM_BREAK_EVENT (SDL_USEREVENT + 2)
int thread_exit = 0;
int sfp_refresh_thread(void *opaque) {
thread_exit = 0;
while (!thread_exit) {
SDL_Event event;
event.type = SFM_REFRESH_EVENT;
SDL_PushEvent(&event);
SDL_Delay(40);
}
thread_exit = 0;
// Break
SDL_Event event;
event.type = SFM_BREAK_EVENT;
SDL_PushEvent(&event);
return 0;
}
// Show AVFoundation Device
void show_avfoundation_device() {
AVFormatContext *pFormatCtx = avformat_alloc_context();
AVDictionary *options = NULL;
av_dict_set(&options, "list_devices", "true", 0);
AVInputFormat *iformat =
(AVInputFormat *)av_find_input_format("avfoundation");
printf("==AVFoundation Device Info===\n");
avformat_open_input(&pFormatCtx, "", iformat, &options);
printf("=============================\n");
}
int main(int argc, char *argv[]) {
AVFormatContext *pFormatCtx;
int i, videoindex;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
avformat_network_init();
pFormatCtx = avformat_alloc_context();
// Open File
// char filepath[]="src01_480x272_22.h265";
// avformat_open_input(&pFormatCtx,filepath,NULL,NULL)
// Register Device
avdevice_register_all();
// Windows
#ifdef _WIN32
#if USE_DSHOW
// Use dshow
//
// Need to Install screen-capture-recorder
// screen-capture-recorder
// Website: http://sourceforge.net/projects/screencapturer/
//
AVInputFormat *ifmt = av_find_input_format("dshow");
if (avformat_open_input(&pFormatCtx, "video=screen-capture-recorder", ifmt,
NULL) != 0) {
printf("Couldn't open input stream.\n");
return -1;
}
#else
// Use gdigrab
AVDictionary *options = NULL;
// Set some options
// grabbing frame rate
// av_dict_set(&options,"framerate","5",0);
// The distance from the left edge of the screen or desktop
// av_dict_set(&options,"offset_x","20",0);
// The distance from the top edge of the screen or desktop
// av_dict_set(&options,"offset_y","40",0);
// Video frame size. The default is to capture the full screen
// av_dict_set(&options,"video_size","640x480",0);
AVInputFormat *ifmt = av_find_input_format("gdigrab");
if (avformat_open_input(&pFormatCtx, "desktop", ifmt, &options) != 0) {
printf("Couldn't open input stream.\n");
return -1;
}
#endif
#elif defined linux
// Linux
AVDictionary *options = NULL;
// Set some options
// grabbing frame rate
// av_dict_set(&options,"framerate","5",0);
// Make the grabbed area follow the mouse
// av_dict_set(&options,"follow_mouse","centered",0);
// Video frame size. The default is to capture the full screen
// av_dict_set(&options,"video_size","640x480",0);
AVInputFormat *ifmt = av_find_input_format("x11grab");
// Grab at position 10,20
if (avformat_open_input(&pFormatCtx, ":0.0+10,20", ifmt, &options) != 0) {
printf("Couldn't open input stream.\n");
return -1;
}
#else
show_avfoundation_device();
// Mac
AVInputFormat *ifmt = (AVInputFormat *)av_find_input_format("avfoundation");
// Avfoundation
//[video]:[audio]
if (avformat_open_input(&pFormatCtx, "1", ifmt, NULL) != 0) {
printf("Couldn't open input stream.\n");
return -1;
}
#endif
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
printf("Couldn't find stream information.\n");
return -1;
}
videoindex = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++)
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
videoindex = i;
break;
}
if (videoindex == -1) {
printf("Didn't find a video stream.\n");
return -1;
}
pCodecCtx = pFormatCtx->streams[videoindex]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
printf("Codec not found.\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
printf("Could not open codec.\n");
return -1;
}
AVFrame *pFrame, *pFrameYUV;
pFrame = av_frame_alloc();
pFrameYUV = av_frame_alloc();
// unsigned char *out_buffer=(unsigned char
// *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width,
// pCodecCtx->height)); avpicture_fill((AVPicture *)pFrameYUV, out_buffer,
// AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
// SDL----------------------------
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
printf("Could not initialize SDL - %s\n", SDL_GetError());
return -1;
}
int screen_w = 640, screen_h = 360;
const SDL_VideoInfo *vi = SDL_GetVideoInfo();
// Half of the Desktop's width and height.
screen_w = vi->current_w / 2;
screen_h = vi->current_h / 2;
SDL_Surface *screen;
screen = SDL_SetVideoMode(screen_w, screen_h, 0, 0);
if (!screen) {
printf("SDL: could not set video mode - exiting:%s\n", SDL_GetError());
return -1;
}
SDL_Overlay *bmp;
bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,
SDL_YV12_OVERLAY, screen);
SDL_Rect rect;
rect.x = 0;
rect.y = 0;
rect.w = screen_w;
rect.h = screen_h;
// SDL End------------------------
int ret, got_picture;
AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
#if OUTPUT_YUV420P
FILE *fp_yuv = fopen("output.yuv", "wb+");
#endif
struct SwsContext *img_convert_ctx;
img_convert_ctx = sws_getContext(
pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width,
pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
//------------------------------
SDL_Thread *video_tid = SDL_CreateThread(sfp_refresh_thread, NULL);
//
SDL_WM_SetCaption("Simplest FFmpeg Grab Desktop", NULL);
// Event Loop
SDL_Event event;
for (;;) {
// Wait
SDL_WaitEvent(&event);
if (event.type == SFM_REFRESH_EVENT) {
//------------------------------
if (av_read_frame(pFormatCtx, packet) >= 0) {
if (packet->stream_index == videoindex) {
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if (ret < 0) {
printf("Decode Error.\n");
return -1;
}
if (got_picture) {
SDL_LockYUVOverlay(bmp);
pFrameYUV->data[0] = bmp->pixels[0];
pFrameYUV->data[1] = bmp->pixels[2];
pFrameYUV->data[2] = bmp->pixels[1];
pFrameYUV->linesize[0] = bmp->pitches[0];
pFrameYUV->linesize[1] = bmp->pitches[2];
pFrameYUV->linesize[2] = bmp->pitches[1];
sws_scale(img_convert_ctx,
(const unsigned char *const *)pFrame->data,
pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data,
pFrameYUV->linesize);
#if OUTPUT_YUV420P
int y_size = pCodecCtx->width * pCodecCtx->height;
fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv); // Y
fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv); // U
fwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv); // V
#endif
SDL_UnlockYUVOverlay(bmp);
SDL_DisplayYUVOverlay(bmp, &rect);
}
}
av_free_packet(packet);
} else {
// Exit Thread
thread_exit = 1;
}
} else if (event.type == SDL_QUIT) {
thread_exit = 1;
} else if (event.type == SFM_BREAK_EVENT) {
break;
}
}
sws_freeContext(img_convert_ctx);
#if OUTPUT_YUV420P
fclose(fp_yuv);
#endif
SDL_Quit();
// av_free(out_buffer);
av_free(pFrameYUV);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
return 0;
}

View File

@@ -1,208 +0,0 @@
package("ffmpeg")
set_homepage("https://www.ffmpeg.org")
set_description("A collection of libraries to process multimedia content such as audio, video, subtitles and related metadata.")
set_license("LGPL-3.0")
if is_plat("windows", "mingw") then
add_urls("https://www.gyan.dev/ffmpeg/builds/packages/ffmpeg-$(version)-full_build-shared.7z")
add_versions("5.1.2", "d9eb97b72d7cfdae4d0f7eaea59ccffb8c364d67d88018ea715d5e2e193f00e9")
add_versions("5.0.1", "ded28435b6f04b74f5ef5a6a13761233bce9e8e9f8ecb0eabe936fd36a778b0c")
add_configs("shared", {description = "Download shared binaries.", default = true, type = "boolean", readonly = true})
add_configs("vs_runtime", {description = "Set vs compiler runtime.", default = "MD", readonly = true})
else
add_urls("https://ffmpeg.org/releases/ffmpeg-$(version).tar.bz2", {alias = "home"})
add_urls("https://github.com/FFmpeg/FFmpeg/archive/n$(version).zip", {alias = "github"})
add_urls("https://git.ffmpeg.org/ffmpeg.git", "https://github.com/FFmpeg/FFmpeg.git", {alias = "git"})
add_versions("home:5.1.2", "39a0bcc8d98549f16c570624678246a6ac736c066cebdb409f9502e915b22f2b")
add_versions("home:5.1.1", "cd0e16f903421266d5ccddedf7b83b9e5754aef4b9f7a7f06ce9e4c802f0545b")
add_versions("home:5.0.1", "28df33d400a1c1c1b20d07a99197809a3b88ef765f5f07dc1ff067fac64c59d6")
add_versions("home:4.0.2", "346c51735f42c37e0712e0b3d2f6476c86ac15863e4445d9e823fe396420d056")
add_versions("github:5.1.2", "0c99f3609160f40946e2531804175eea16416320c4b6365ad075e390600539db")
add_versions("github:5.1.1", "a886fcc94792764c27c88ebe71dffbe5f0d37df8f06f01efac4833ac080c11bf")
add_versions("github:5.0.1", "f9c2e06cafa4381df8d5c9c9e14d85d9afcbc10c516c6a206f821997cc7f6440")
add_versions("github:4.0.2", "4df1ef0bf73b7148caea1270539ef7bd06607e0ea8aa2fbf1bb34062a097f026")
add_versions("git:5.1.2", "n5.1.2")
add_versions("git:5.1.1", "n5.1.1")
add_versions("git:5.0.1", "n5.0.1")
add_versions("git:4.0.2", "n4.0.2")
add_configs("gpl", {description = "Enable GPL code", default = false, type = "boolean"})
add_configs("ffprobe", {description = "Enable ffprobe program.", default = false, type = "boolean"})
add_configs("ffmpeg", {description = "Enable ffmpeg program.", default = true, type = "boolean"})
add_configs("ffplay", {description = "Enable ffplay program.", default = false, type = "boolean"})
add_configs("zlib", {description = "Enable zlib compression library.", default = false, type = "boolean"})
add_configs("lzma", {description = "Enable liblzma compression library.", default = false, type = "boolean"})
add_configs("bzlib", {description = "Enable bzlib compression library.", default = false, type = "boolean"})
add_configs("libx264", {description = "Enable libx264 decoder.", default = false, type = "boolean"})
add_configs("libx265", {description = "Enable libx265 decoder.", default = false, type = "boolean"})
add_configs("iconv", {description = "Enable libiconv library.", default = false, type = "boolean"})
add_configs("vaapi", {description = "Enable vaapi library.", default = false, type = "boolean"})
add_configs("vdpau", {description = "Enable vdpau library.", default = false, type = "boolean"})
add_configs("hardcoded-tables", {description = "Enable hardcoded tables.", default = true, type = "boolean"})
add_configs("asm", {description = "Enable asm", default = false, type = "boolean"})
add_configs("libopenh264", {description = "Enable libopenh264", default = false, type = "boolean"})
add_configs("libxcb", {description = "Enable libxcb", default = true, type = "boolean"})
end
add_links("avfilter", "avdevice", "avformat", "avcodec", "swscale", "swresample", "avutil", "postproc")
if is_plat("macosx") then
add_frameworks("CoreFoundation", "Foundation", "CoreVideo", "CoreMedia", "AudioToolbox", "VideoToolbox", "Security")
elseif is_plat("linux") then
-- add_syslinks("pthread", "openh264")
add_syslinks("pthread")
end
if is_plat("linux", "macosx") then
add_deps("yasm")
end
if on_fetch then
on_fetch("mingw", "linux", "macosx", function (package, opt)
import("lib.detect.find_tool")
if opt.system then
local result
for _, name in ipairs({"libavcodec", "libavdevice", "libavfilter", "libavformat", "libavutil", "libpostproc", "libswresample", "libswscale"}) do
local pkginfo = package:find_package("pkgconfig::" .. name, opt)
if pkginfo then
pkginfo.version = nil
if not result then
result = pkginfo
else
result = result .. pkginfo
end
else
return
end
end
local ffmpeg = find_tool("ffmpeg", {check = "-help", version = true, command = "-version", parse = "%d+%.?%d+%.?%d+", force = true})
if ffmpeg then
result.version = ffmpeg.version
end
return result
end
end)
end
on_load("linux", "macosx", "android", function (package)
local configdeps = {zlib = "zlib",
bzlib = "bzip2",
lzma = "xz",
libx264 = "x264",
libx265 = "x265",
iconv = "libiconv"}
for name, dep in pairs(configdeps) do
if package:config(name) then
package:add("deps", dep)
end
end
-- https://www.ffmpeg.org/platform.html#toc-Advanced-linking-configuration
if package:config("pic") ~= false and not package:is_plat("macosx") then
package:add("shflags", "-Wl,-Bsymbolic")
package:add("ldflags", "-Wl,-Bsymbolic")
end
if not package:config("gpl") then
package:set("license", "LGPL-3.0")
end
end)
on_install("windows|x64", "mingw|x86_64", function (package)
os.cp("bin", package:installdir())
os.cp("include", package:installdir())
os.cp("lib", package:installdir())
package:addenv("PATH", "bin")
end)
on_install("linux", "macosx", "android@linux,macosx", function (package)
local configs = {"--enable-version3",
"--disable-doc"}
if package:config("gpl") then
table.insert(configs, "--enable-gpl")
end
if package:is_plat("macosx") and macos.version():ge("10.8") then
table.insert(configs, "--enable-videotoolbox")
end
for name, enabled in pairs(package:configs()) do
if not package:extraconf("configs", name, "builtin") then
if enabled then
table.insert(configs, "--enable-" .. name)
else
table.insert(configs, "--disable-" .. name)
end
end
end
if package:config("shared") then
table.insert(configs, "--enable-shared")
table.insert(configs, "--disable-static")
else
table.insert(configs, "--enable-static")
table.insert(configs, "--disable-shared")
end
if package:debug() then
table.insert(configs, "--enable-debug")
else
table.insert(configs, "--disable-debug")
end
if package:is_plat("android") then
import("core.base.option")
import("core.tool.toolchain")
local ndk = toolchain.load("ndk", {plat = package:plat(), arch = package:arch()})
local bin = ndk:bindir()
local ndk_sdkver = ndk:config("ndk_sdkver")
local arch, cpu, triple, cross_prefix
if package:is_arch("arm64-v8a") then
arch = "arm64"
cpu = "armv8-a"
triple = "aarch64-linux-android"
cross_prefix = path.join(bin, "aarch64-linux-android-")
elseif package:arch():startswith("arm") then
arch = "arm"
cpu = "armv7-a"
triple = "armv7a-linux-androideabi"
cross_prefix = path.join(bin, "arm-linux-androideabi-")
else
raise("unknown arch(%s) for android!", package:arch())
end
local sysroot = path.join(path.directory(bin), "sysroot")
local cflags = table.join(table.wrap(package:config("cxflags")), table.wrap(package:config("cflags")), table.wrap(get_config("cxflags")), get_config("cflags"))
local cxxflags = table.join(table.wrap(package:config("cxflags")), table.wrap(package:config("cxxflags")), table.wrap(get_config("cxflags")), get_config("cxxflags"))
assert(os.isdir(sysroot), "we do not support old version ndk!")
if package:is_arch("arm64-v8a") then
table.insert(cflags, "-mfpu=neon")
table.insert(cflags, "-mfloat-abi=soft")
else
table.insert(cflags, "-mfpu=neon")
table.insert(cflags, "-mfloat-abi=soft")
end
table.insert(configs, "--enable-neon")
table.insert(configs, "--enable-asm")
table.insert(configs, "--enable-jni")
table.insert(configs, "--target-os=android")
table.insert(configs, "--enable-cross-compile")
table.insert(configs, "--disable-avdevice")
table.insert(configs, "--arch=" .. arch)
table.insert(configs, "--cpu=" .. cpu)
table.insert(configs, "--cc=" .. path.join(bin, triple .. ndk_sdkver .. "-clang"))
table.insert(configs, "--cxx=" .. path.join(bin, triple .. ndk_sdkver .. "-clang++"))
table.insert(configs, "--extra-cflags=" .. table.concat(cflags, ' '))
table.insert(configs, "--extra-cxxflags=" .. table.concat(cxxflags, ' '))
table.insert(configs, "--sysroot=" .. sysroot)
table.insert(configs, "--cross-prefix=" .. cross_prefix)
table.insert(configs, "--prefix=" .. package:installdir())
os.vrunv("./configure", configs)
local argv = {"-j4"}
if option.get("verbose") then
table.insert(argv, "V=1")
end
os.vrunv("make", argv)
os.vrun("make install")
else
import("package.tools.autoconf").install(package, configs)
end
package:addenv("PATH", "bin")
end)
on_test(function (package)
assert(package:has_cfuncs("avformat_open_input", {includes = "libavformat/avformat.h"}))
end)

View File

@@ -1,7 +1 @@
includes("projectx")
if is_plat("windows") then
elseif is_plat("linux") then
includes("ffmpeg")
elseif is_plat("macosx") then
includes("ffmpeg")
end
includes("projectx")

View File

@@ -33,13 +33,11 @@ elseif is_os("linux") then
add_links("SDL2", "cuda", "nvidia-encode", "nvcuvid", "X11", "Xtst")
add_cxflags("-Wno-unused-variable")
elseif is_os("macosx") then
add_requires("ffmpeg 5.1.2", {system = false})
add_requires("libxcb", {system = false})
add_packages("libxcb")
add_links("SDL2", "SDL2main")
add_ldflags("-Wl,-ld_classic")
add_cxflags("-Wno-unused-variable")
add_frameworks("OpenGL", "IOSurface", "ScreenCaptureKit")
add_frameworks("OpenGL", "IOSurface", "ScreenCaptureKit", "AVFoundation",
"CoreMedia", "CoreVideo")
end
add_packages("spdlog", "imgui")
@@ -67,14 +65,11 @@ target("screen_capturer")
add_files("src/screen_capturer/windows/*.cpp")
add_includedirs("src/screen_capturer/windows", {public = true})
elseif is_os("macosx") then
add_packages("ffmpeg")
add_files("src/screen_capturer/macosx/avfoundation/*.cpp",
"src/screen_capturer/macosx/screen_capturer_kit/*.cpp",
"src/screen_capturer/macosx/screen_capturer_kit/*.mm")
add_includedirs("src/screen_capturer/macosx/avfoundation",
"src/screen_capturer/macosx/screen_capturer_kit", {public = true})
add_files("src/screen_capturer/macosx/*.cpp",
"src/screen_capturer/macosx/*.mm")
add_includedirs("src/screen_capturer/macosx", {public = true})
elseif is_os("linux") then
add_packages("libyuv", "ffmpeg")
add_packages("libyuv")
add_files("src/screen_capturer/linux/*.cpp")
add_includedirs("src/screen_capturer/linux", {public = true})
end
@@ -129,12 +124,8 @@ target("localization")
target("single_window")
set_kind("object")
add_packages("libyuv", "openssl3")
add_deps("rd_log", "common", "localization", "config_center", "projectx", "screen_capturer", "speaker_capturer", "device_controller")
if is_os("macosx") then
add_packages("ffmpeg")
elseif is_os("linux") then
add_packages("ffmpeg")
end
add_deps("rd_log", "common", "localization", "config_center", "projectx",
"screen_capturer", "speaker_capturer", "device_controller")
add_files("src/single_window/*.cpp")
add_includedirs("src/single_window", {public = true})
add_includedirs("fonts", {public = true})
@@ -145,77 +136,8 @@ target("remote_desk")
if is_os("windows") then
add_files("icon/app.rc")
elseif is_os("macosx") then
add_packages("ffmpeg")
-- add_rules("xcode.application")
-- add_files("Info.plist")
elseif is_os("linux") then
add_packages("ffmpeg")
end
add_files("src/gui/main.cpp")
-- target("miniaudio_capture")
-- set_kind("binary")
-- add_packages("miniaudio")
-- if is_os("windows") then
-- add_files("test/audio_capture/miniaudio.cpp")
-- end
-- target("screen_capturer")
-- set_kind("binary")
-- add_packages("sdl2", "imgui", "ffmpeg", "openh264")
-- add_files("test/screen_capturer/linux_capture.cpp")
-- add_ldflags("-lavformat", "-lavdevice", "-lavfilter", "-lavcodec",
-- "-lswscale", "-lavutil", "-lswresample",
-- "-lasound", "-lxcb-shape", "-lxcb-xfixes", "-lsndio", "-lxcb",
-- "-lxcb-shm", "-lXext", "-lX11", "-lXv", "-lpthread", "-lSDL2", "-lopenh264",
-- "-ldl", {force = true})
-- target("screen_capturer")
-- set_kind("binary")
-- add_packages("sdl2", "imgui", "ffmpeg", "openh264")
-- add_files("test/screen_capturer/mac_capture.cpp")
-- add_ldflags("-lavformat", "-lavdevice", "-lavfilter", "-lavcodec",
-- "-lswscale", "-lavutil", "-lswresample",
-- "-lasound", "-lxcb-shape", "-lxcb-xfixes", "-lsndio", "-lxcb",
-- "-lxcb-shm", "-lXext", "-lX11", "-lXv", "-lpthread", "-lSDL2", "-lopenh264",
-- "-ldl", {force = true})
-- target("audio_capture")
-- set_kind("binary")
-- add_packages("ffmpeg")
-- add_files("test/audio_capture/sdl2_audio_capture.cpp")
-- add_includedirs("test/audio_capture")
-- add_ldflags("-lavformat", "-lavdevice", "-lavfilter", "-lavcodec",
-- "-lswscale", "-lavutil", "-lswresample",
-- "-lasound", "-lxcb-shape", "-lxcb-xfixes", "-lsndio", "-lxcb",
-- "-lxcb-shm", "-lXext", "-lX11", "-lXv", "-lpthread", "-lSDL2", "-lopenh264",
-- "-ldl", {force = true})
-- add_links("Shlwapi", "Strmiids", "Vfw32", "Secur32", "Mfuuid")
-- target("play_audio")
-- set_kind("binary")
-- add_packages("ffmpeg")
-- add_files("test/audio_capture/play_loopback.cpp")
-- add_includedirs("test/audio_capture")
-- add_ldflags("-lavformat", "-lavdevice", "-lavfilter", "-lavcodec",
-- "-lswscale", "-lavutil", "-lswresample",
-- "-lasound", "-lxcb-shape", "-lxcb-xfixes", "-lsndio", "-lxcb",
-- "-lxcb-shm", "-lXext", "-lX11", "-lXv", "-lpthread", "-lSDL2", "-lopenh264",
-- "-ldl", {force = true})
-- add_links("Shlwapi", "Strmiids", "Vfw32", "Secur32", "Mfuuid")
-- target("audio_capture")
-- set_kind("binary")
-- add_packages("libopus")
-- add_files("test/audio_capture/sdl2_audio_capture.cpp")
-- add_includedirs("test/audio_capture")
-- add_ldflags("-lavformat", "-lavdevice", "-lavfilter", "-lavcodec",
-- "-lswscale", "-lavutil", "-lswresample",
-- "-lasound", "-lxcb-shape", "-lxcb-xfixes", "-lsndio", "-lxcb",
-- "-lxcb-shm", "-lXext", "-lX11", "-lXv", "-lpthread", "-lSDL2", "-lopenh264",
-- "-ldl", {force = true})
-- target("mouse_control")
-- set_kind("binary")
-- add_files("test/linux_mouse_control/mouse_control.cpp")
-- add_includedirs("test/linux_mouse_control")
add_files("src/gui/main.cpp")