mirror of
https://github.com/Lorenzooone/cc3dsfs.git
synced 2026-04-24 06:57:05 -05:00
Switch to buffer requests without memcpy
Some checks are pending
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linux32 flags:32 name:Linux GCC 32 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linux64 flags:64 name:Linux GCC x64 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linuxarm32 flags:arm32 name:Linux GCC ARM 32 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linuxarm64 flags:arm64 name:Linux GCC ARM 64 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:macos name:macOS Apple Silicon os:macos-14]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:win32 flags:-A Win32 name:Windows VS2022 Win32 os:windows-2022]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:win64 flags:-A x64 name:Windows VS2022 x64 os:windows-2022]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:winarm64 flags:-A ARM64 name:Windows VS2022 ARM os:windows-2022]) (push) Waiting to run
CD / Create Pi Mono Setup (push) Blocked by required conditions
CD / Publishing (push) Blocked by required conditions
Some checks are pending
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linux32 flags:32 name:Linux GCC 32 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linux64 flags:64 name:Linux GCC x64 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linuxarm32 flags:arm32 name:Linux GCC ARM 32 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linuxarm64 flags:arm64 name:Linux GCC ARM 64 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:macos name:macOS Apple Silicon os:macos-14]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:win32 flags:-A Win32 name:Windows VS2022 Win32 os:windows-2022]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:win64 flags:-A x64 name:Windows VS2022 x64 os:windows-2022]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:winarm64 flags:-A ARM64 name:Windows VS2022 ARM os:windows-2022]) (push) Waiting to run
CD / Create Pi Mono Setup (push) Blocked by required conditions
CD / Publishing (push) Blocked by required conditions
This commit is contained in:
parent
365c0625bd
commit
fb6de81c52
|
|
@ -4,7 +4,7 @@
|
|||
#include "capture_structs.hpp"
|
||||
#include "devicecapture.hpp"
|
||||
|
||||
#define FTD3_CONCURRENT_BUFFERS 4
|
||||
#define FTD3_CONCURRENT_BUFFERS NUM_CONCURRENT_DATA_BUFFER_WRITERS
|
||||
|
||||
struct ftd3_device_device_handlers {
|
||||
void* usb_handle = NULL;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ struct ftd3_async_callback_data {
|
|||
void* actual_user_data;
|
||||
void* transfer_data;
|
||||
std::mutex transfer_data_access;
|
||||
int internal_index;
|
||||
};
|
||||
|
||||
int ftd3_libusb_ctrl_in(ftd3_device_device_handlers* handlers, uint32_t timeout, uint8_t* buf, int length, uint8_t request, uint16_t value, uint16_t index, int* transferred);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@
|
|||
uint64_t ftd3_get_capture_size(CaptureData* capture_data);
|
||||
std::string ftd3_get_serial(std::string serial_string, int &curr_serial_extra_id);
|
||||
void ftd3_insert_device(std::vector<CaptureDevice> &devices_list, std::string serial_string, int &curr_serial_extra_id, bool is_driver);
|
||||
void data_output_update(CaptureReceived* received_buffer, size_t read_data, CaptureData* capture_data, std::chrono::time_point<std::chrono::high_resolution_clock> &base_time);
|
||||
void data_output_update(int inner_index, size_t read_data, CaptureData* capture_data, std::chrono::time_point<std::chrono::high_resolution_clock> &base_time);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -8,14 +8,11 @@
|
|||
#include <chrono>
|
||||
|
||||
// Sometimes the CC returns a 2 length packet, if you're too fast
|
||||
#define BASE_NUM_CAPTURE_RECEIVED_DATA_BUFFERS 4
|
||||
#define NUM_CAPTURE_RECEIVED_DATA_0_MULTIPLIER 2
|
||||
#define NUM_CAPTURE_RECEIVED_DATA_BUFFERS (BASE_NUM_CAPTURE_RECEIVED_DATA_BUFFERS * NUM_CAPTURE_RECEIVED_DATA_0_MULTIPLIER)
|
||||
#define NUM_CAPTURE_RECEIVED_DATA_BUFFERS NUM_CONCURRENT_DATA_BUFFER_WRITERS
|
||||
|
||||
typedef void (*fdt2_async_callback_function)(void* user_data, int transfer_length, int transfer_status);
|
||||
|
||||
struct ftd2_async_callback_data {
|
||||
FTD2OldDSCaptureReceivedRaw buffer_raw;
|
||||
fdt2_async_callback_function function;
|
||||
void* actual_user_data;
|
||||
void* transfer_data;
|
||||
|
|
@ -34,6 +31,8 @@ struct FTD2CaptureReceivedData {
|
|||
int* status;
|
||||
uint32_t index;
|
||||
uint32_t* last_used_index;
|
||||
uint8_t* buffer_raw;
|
||||
uint32_t* buffer_target;
|
||||
size_t* curr_offset;
|
||||
CaptureData* capture_data;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start;
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@
|
|||
#include "capture_structs.hpp"
|
||||
#include "display_structs.hpp"
|
||||
|
||||
#define NUM_CAPTURE_RECEIVED_DATA_BUFFERS 4
|
||||
#define NUM_CAPTURE_RECEIVED_DATA_BUFFERS NUM_CONCURRENT_DATA_BUFFER_WRITERS
|
||||
|
||||
struct ISDeviceCaptureReceivedData {
|
||||
volatile bool in_use;
|
||||
uint32_t index;
|
||||
CaptureReceived buffer;
|
||||
SharedConsumerMutex* is_buffer_free_shared_mutex;
|
||||
int* status;
|
||||
uint32_t* last_index;
|
||||
|
|
@ -24,10 +23,10 @@ struct ISDeviceCaptureReceivedData {
|
|||
int set_acquisition_mode(is_device_device_handlers* handlers, CaptureScreensType capture_type, CaptureSpeedsType capture_speed, const is_device_usb_device* usb_device_desc);
|
||||
int EndAcquisition(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, bool do_drain_frames, int start_frames, CaptureScreensType capture_type);
|
||||
int EndAcquisition(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers, bool do_drain_frames, int start_frames, CaptureScreensType capture_type);
|
||||
int is_device_read_frame_and_output(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock> &clock_start);
|
||||
int is_device_read_frame_and_output(CaptureData* capture_data, int internal_index, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock> &clock_start);
|
||||
void is_device_read_frame_request(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, CaptureScreensType curr_capture_type, uint32_t index);
|
||||
uint64_t usb_is_device_get_video_in_size(CaptureScreensType capture_type, is_device_type device_type);
|
||||
void output_to_thread(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, size_t read_size);
|
||||
void output_to_thread(CaptureData* capture_data, int internal_index, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, size_t read_size);
|
||||
|
||||
ISDeviceCaptureReceivedData* is_device_get_free_buffer(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data);
|
||||
bool is_device_are_buffers_all_free(ISDeviceCaptureReceivedData* is_device_capture_recv_data);
|
||||
|
|
|
|||
|
|
@ -3,12 +3,11 @@
|
|||
|
||||
#include "cypress_nisetro_communications.hpp"
|
||||
|
||||
#define NUM_CAPTURE_RECEIVED_DATA_BUFFERS 4
|
||||
#define NUM_CAPTURE_RECEIVED_DATA_BUFFERS NUM_CONCURRENT_DATA_BUFFER_WRITERS
|
||||
|
||||
struct CypressDeviceCaptureReceivedData {
|
||||
volatile bool in_use;
|
||||
uint32_t index;
|
||||
CaptureReceived buffer;
|
||||
SharedConsumerMutex* is_buffer_free_shared_mutex;
|
||||
size_t* scheduled_special_read;
|
||||
uint32_t* active_special_read_index;
|
||||
|
|
@ -20,7 +19,6 @@ struct CypressDeviceCaptureReceivedData {
|
|||
int* consecutive_output_to_thread;
|
||||
CaptureData* capture_data;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start;
|
||||
CaptureScreensType curr_capture_type;
|
||||
cyni_async_callback_data cb_data;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -26,12 +26,13 @@ enum CaptureScreensType { CAPTURE_SCREENS_BOTH, CAPTURE_SCREENS_TOP, CAPTURE_SCR
|
|||
enum CaptureSpeedsType { CAPTURE_SPEEDS_FULL, CAPTURE_SPEEDS_HALF, CAPTURE_SPEEDS_THIRD, CAPTURE_SPEEDS_QUARTER, CAPTURE_SPEEDS_ENUM_END };
|
||||
|
||||
// Readers are Audio and Video. So 2.
|
||||
// Use 2 extra buffers. One for writing in case the other 2 are busy,
|
||||
// Use 6 extra buffers. 5 for async writing in case the other 2 are busy,
|
||||
// and the other for writing without overwriting the latest stuff in
|
||||
// a worst case scenario...
|
||||
enum CaptureReaderType { CAPTURE_READER_VIDEO, CAPTURE_READER_AUDIO, CAPTURE_READER_ENUM_END };
|
||||
#define NUM_CONCURRENT_DATA_BUFFER_WRITERS 5
|
||||
#define NUM_CONCURRENT_DATA_BUFFER_READERS ((int)CAPTURE_READER_ENUM_END)
|
||||
#define NUM_CONCURRENT_DATA_BUFFERS (NUM_CONCURRENT_DATA_BUFFER_READERS + 2)
|
||||
#define NUM_CONCURRENT_DATA_BUFFERS (NUM_CONCURRENT_DATA_BUFFER_READERS + 1 + NUM_CONCURRENT_DATA_BUFFER_WRITERS)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
|
|
@ -149,6 +150,11 @@ struct ALIGNED(16) PACKED ISTWLCaptureReceived {
|
|||
|
||||
#pragma pack(pop)
|
||||
|
||||
struct ALIGNED(16) FTD2OldDSCaptureReceivedNormalPlusRaw {
|
||||
FTD2OldDSCaptureReceived data;
|
||||
FTD2OldDSCaptureReceivedRaw raw_data;
|
||||
};
|
||||
|
||||
union CaptureReceived {
|
||||
FTD3_3DSCaptureReceived ftd3_received;
|
||||
FTD3_3DSCaptureReceived_3D ftd3_received_3d;
|
||||
|
|
@ -156,7 +162,7 @@ union CaptureReceived {
|
|||
USB3DSCaptureReceived_3D usb_received_3ds_3d;
|
||||
USBOldDSCaptureReceived usb_received_old_ds;
|
||||
FTD2OldDSCaptureReceived ftd2_received_old_ds;
|
||||
FTD2OldDSCaptureReceivedRaw ftd2_received_old_ds_raw;
|
||||
FTD2OldDSCaptureReceivedNormalPlusRaw ftd2_received_old_ds_normal_plus_raw;
|
||||
ISNitroCaptureReceived is_nitro_capture_received;
|
||||
ISTWLCaptureReceived is_twl_capture_received;
|
||||
CypressNisetroDSCaptureReceived cypress_nisetro_capture_received;
|
||||
|
|
@ -215,6 +221,7 @@ struct CaptureStatus {
|
|||
struct CaptureDataSingleBuffer {
|
||||
CaptureScreensType capture_type;
|
||||
uint64_t read;
|
||||
size_t unused_offset;
|
||||
CaptureReceived capture_buf;
|
||||
double time_in_buf;
|
||||
uint32_t inner_index;
|
||||
|
|
@ -225,16 +232,18 @@ public:
|
|||
CaptureDataBuffers();
|
||||
CaptureDataSingleBuffer* GetReaderBuffer(CaptureReaderType reader_type);
|
||||
void ReleaseReaderBuffer(CaptureReaderType reader_type);
|
||||
void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type = CAPTURE_SCREENS_BOTH, size_t offset = 0);
|
||||
void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, size_t offset);
|
||||
CaptureDataSingleBuffer* GetWriterBuffer();
|
||||
void ReleaseWriterBuffer();
|
||||
void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type, size_t offset, int index);
|
||||
void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type, int index);
|
||||
void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, size_t offset, int index);
|
||||
void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, int index);
|
||||
CaptureDataSingleBuffer* GetWriterBuffer(int index = 0);
|
||||
void ReleaseWriterBuffer(int index = 0, bool update_last_curr_in = true);
|
||||
private:
|
||||
uint32_t inner_index = 0;
|
||||
std::mutex access_mutex;
|
||||
int last_curr_in;
|
||||
int curr_writer_pos;
|
||||
int curr_writer_pos[NUM_CONCURRENT_DATA_BUFFER_WRITERS];
|
||||
int curr_reader_pos[NUM_CONCURRENT_DATA_BUFFER_READERS];
|
||||
bool is_being_written_to[NUM_CONCURRENT_DATA_BUFFERS];
|
||||
int num_readers[NUM_CONCURRENT_DATA_BUFFERS];
|
||||
bool has_read_data[NUM_CONCURRENT_DATA_BUFFERS][NUM_CONCURRENT_DATA_BUFFER_READERS];
|
||||
CaptureDataSingleBuffer buffers[NUM_CONCURRENT_DATA_BUFFERS];
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@
|
|||
|
||||
CaptureDataBuffers::CaptureDataBuffers() {
|
||||
last_curr_in = 0;
|
||||
curr_writer_pos = -1;
|
||||
for(int i = 0; i < NUM_CONCURRENT_DATA_BUFFER_WRITERS; i++) {
|
||||
curr_writer_pos[i] = -1;
|
||||
is_being_written_to[i] = false;
|
||||
}
|
||||
for(int i = 0; i < NUM_CONCURRENT_DATA_BUFFER_READERS; i++)
|
||||
curr_reader_pos[i] = -1;
|
||||
for(int i = 0; i < NUM_CONCURRENT_DATA_BUFFERS; i++) {
|
||||
|
|
@ -24,13 +27,19 @@ static int reader_to_index(CaptureReaderType reader_type) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool is_writer_index_valid(int index) {
|
||||
if((index < 0) || (index >= NUM_CONCURRENT_DATA_BUFFER_WRITERS))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
CaptureDataSingleBuffer* CaptureDataBuffers::GetReaderBuffer(CaptureReaderType reader_type) {
|
||||
int index = reader_to_index(reader_type);
|
||||
CaptureDataSingleBuffer* retval = NULL;
|
||||
access_mutex.lock();
|
||||
if(curr_reader_pos[index] != -1)
|
||||
retval = &buffers[curr_reader_pos[index]];
|
||||
else if(!has_read_data[last_curr_in][index]) {
|
||||
return &buffers[curr_reader_pos[index]];
|
||||
access_mutex.lock();
|
||||
if(!has_read_data[last_curr_in][index]) {
|
||||
has_read_data[last_curr_in][index] = true;
|
||||
num_readers[last_curr_in] += 1;
|
||||
retval = &buffers[last_curr_in];
|
||||
|
|
@ -40,61 +49,84 @@ CaptureDataSingleBuffer* CaptureDataBuffers::GetReaderBuffer(CaptureReaderType r
|
|||
return retval;
|
||||
}
|
||||
|
||||
CaptureDataSingleBuffer* CaptureDataBuffers::GetWriterBuffer() {
|
||||
CaptureDataSingleBuffer* CaptureDataBuffers::GetWriterBuffer(int index) {
|
||||
if(!is_writer_index_valid(index))
|
||||
return NULL;
|
||||
if(curr_writer_pos[index] != -1)
|
||||
return &buffers[curr_writer_pos[index]];
|
||||
CaptureDataSingleBuffer* retval = NULL;
|
||||
access_mutex.lock();
|
||||
if(curr_writer_pos != -1)
|
||||
retval = &buffers[curr_writer_pos];
|
||||
else
|
||||
for(int i = 0; i < NUM_CONCURRENT_DATA_BUFFERS; i++)
|
||||
if((num_readers[i] == 0) && (i != last_curr_in)) {
|
||||
retval = &buffers[i];
|
||||
curr_writer_pos = i;
|
||||
for(int j = 0; j < NUM_CONCURRENT_DATA_BUFFER_READERS; j++)
|
||||
has_read_data[i][j] = false;
|
||||
break;
|
||||
}
|
||||
for(int i = 0; i < NUM_CONCURRENT_DATA_BUFFERS; i++)
|
||||
if((num_readers[i] == 0) && (i != last_curr_in) && (!is_being_written_to[i])) {
|
||||
retval = &buffers[i];
|
||||
is_being_written_to[i] = true;
|
||||
curr_writer_pos[index] = i;
|
||||
for(int j = 0; j < NUM_CONCURRENT_DATA_BUFFER_READERS; j++)
|
||||
has_read_data[i][j] = true;
|
||||
break;
|
||||
}
|
||||
access_mutex.unlock();
|
||||
return retval;
|
||||
}
|
||||
|
||||
void CaptureDataBuffers::ReleaseReaderBuffer(CaptureReaderType reader_type) {
|
||||
int index = reader_to_index(reader_type);
|
||||
if(curr_reader_pos[index] == -1)
|
||||
return;
|
||||
access_mutex.lock();
|
||||
if(curr_reader_pos[index] != -1) {
|
||||
num_readers[curr_reader_pos[index]] -= 1;
|
||||
curr_reader_pos[index] = -1;
|
||||
}
|
||||
num_readers[curr_reader_pos[index]] -= 1;
|
||||
curr_reader_pos[index] = -1;
|
||||
access_mutex.unlock();
|
||||
}
|
||||
|
||||
void CaptureDataBuffers::ReleaseWriterBuffer() {
|
||||
void CaptureDataBuffers::ReleaseWriterBuffer(int index, bool update_last_curr_in) {
|
||||
if(!is_writer_index_valid(index))
|
||||
return;
|
||||
if(curr_writer_pos[index] == -1)
|
||||
return;
|
||||
access_mutex.lock();
|
||||
if(curr_writer_pos != -1) {
|
||||
buffers[curr_writer_pos].inner_index = inner_index++;
|
||||
last_curr_in = curr_writer_pos;
|
||||
curr_writer_pos = -1;
|
||||
if(update_last_curr_in) {
|
||||
for(int j = 0; j < NUM_CONCURRENT_DATA_BUFFER_READERS; j++)
|
||||
has_read_data[curr_writer_pos[index]][j] = false;
|
||||
last_curr_in = curr_writer_pos[index];
|
||||
}
|
||||
is_being_written_to[curr_writer_pos[index]] = false;
|
||||
curr_writer_pos[index] = -1;
|
||||
access_mutex.unlock();
|
||||
}
|
||||
|
||||
void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type, size_t offset) {
|
||||
void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type, size_t offset, int index) {
|
||||
if(offset >= read)
|
||||
return;
|
||||
CaptureDataSingleBuffer* target = this->GetWriterBuffer();
|
||||
if(!is_writer_index_valid(index))
|
||||
return;
|
||||
CaptureDataSingleBuffer* target = this->GetWriterBuffer(index);
|
||||
// How did we end here?!
|
||||
if(target == NULL)
|
||||
return;
|
||||
memcpy(&target->capture_buf, ((uint8_t*)buffer) + offset, read - offset);
|
||||
// Make sure to also copy the extra needed data, if any
|
||||
if((device->cc_type == CAPTURE_CONN_USB) && (!device->is_3ds))
|
||||
memcpy(&target->capture_buf.usb_received_old_ds.frameinfo, &buffer->usb_received_old_ds.frameinfo, sizeof(buffer->usb_received_old_ds.frameinfo));
|
||||
target->read = read;
|
||||
if(buffer != NULL) {
|
||||
memcpy(&target->capture_buf, ((uint8_t*)buffer) + offset, read - offset);
|
||||
// Make sure to also copy the extra needed data, if any
|
||||
if((device->cc_type == CAPTURE_CONN_USB) && (!device->is_3ds))
|
||||
memcpy(&target->capture_buf.usb_received_old_ds.frameinfo, &buffer->usb_received_old_ds.frameinfo, sizeof(buffer->usb_received_old_ds.frameinfo));
|
||||
target->unused_offset = 0;
|
||||
}
|
||||
else
|
||||
target->unused_offset = offset;
|
||||
target->read = read - offset;
|
||||
target->time_in_buf = time_in_buf;
|
||||
target->capture_type = capture_type;
|
||||
this->ReleaseWriterBuffer();
|
||||
this->ReleaseWriterBuffer(index);
|
||||
}
|
||||
|
||||
void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, size_t offset) {
|
||||
return this->WriteToBuffer(buffer, read, time_in_buf, device, CAPTURE_SCREENS_BOTH, offset);
|
||||
void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type, int index) {
|
||||
return this->WriteToBuffer(buffer, read, time_in_buf, device, capture_type, 0, index);
|
||||
}
|
||||
|
||||
void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, size_t offset, int index) {
|
||||
return this->WriteToBuffer(buffer, read, time_in_buf, device, CAPTURE_SCREENS_BOTH, offset, index);
|
||||
}
|
||||
|
||||
void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, int index) {
|
||||
return this->WriteToBuffer(buffer, read, time_in_buf, device, CAPTURE_SCREENS_BOTH, 0, index);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
#include <chrono>
|
||||
|
||||
struct FTD3XXReceivedDataBuffer {
|
||||
CaptureReceived capture_buf;
|
||||
OVERLAPPED overlap;
|
||||
ULONG read_buffer;
|
||||
};
|
||||
|
|
@ -35,7 +34,9 @@ static void fast_capture_call(FTD3XXReceivedDataBuffer* received_buffer, Capture
|
|||
}
|
||||
|
||||
for (inner_curr_in = 0; inner_curr_in < FTD3_CONCURRENT_BUFFERS - 1; ++inner_curr_in) {
|
||||
ftStatus = FT_ASYNC_CALL(handle, fifo_channel, (UCHAR*)&received_buffer[inner_curr_in].capture_buf, ftd3_get_capture_size(capture_data), &received_buffer[inner_curr_in].read_buffer, &received_buffer[inner_curr_in].overlap);
|
||||
CaptureDataSingleBuffer* data_buf = capture_data->data_buffers.GetWriterBuffer(inner_curr_in);
|
||||
uint8_t* buffer = (uint8_t*)&data_buf->capture_buf;
|
||||
ftStatus = FT_ASYNC_CALL(handle, fifo_channel, buffer, ftd3_get_capture_size(capture_data), &received_buffer[inner_curr_in].read_buffer, &received_buffer[inner_curr_in].overlap);
|
||||
if(ftStatus != FT_IO_PENDING) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Read failed");
|
||||
return;
|
||||
|
|
@ -47,8 +48,9 @@ static void fast_capture_call(FTD3XXReceivedDataBuffer* received_buffer, Capture
|
|||
auto clock_start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
while (capture_data->status.connected && capture_data->status.running) {
|
||||
|
||||
ftStatus = FT_ASYNC_CALL(handle, fifo_channel, (UCHAR*)&received_buffer[inner_curr_in].capture_buf, ftd3_get_capture_size(capture_data), &received_buffer[inner_curr_in].read_buffer, &received_buffer[inner_curr_in].overlap);
|
||||
CaptureDataSingleBuffer* data_buf = capture_data->data_buffers.GetWriterBuffer(inner_curr_in);
|
||||
uint8_t* buffer = (uint8_t*)&data_buf->capture_buf;
|
||||
ftStatus = FT_ASYNC_CALL(handle, fifo_channel, buffer, ftd3_get_capture_size(capture_data), &received_buffer[inner_curr_in].read_buffer, &received_buffer[inner_curr_in].overlap);
|
||||
if(ftStatus != FT_IO_PENDING) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Read failed");
|
||||
return;
|
||||
|
|
@ -62,7 +64,7 @@ static void fast_capture_call(FTD3XXReceivedDataBuffer* received_buffer, Capture
|
|||
return;
|
||||
}
|
||||
|
||||
data_output_update(&received_buffer[inner_curr_in].capture_buf, received_buffer[inner_curr_in].read_buffer, capture_data, clock_start);
|
||||
data_output_update(inner_curr_in, received_buffer[inner_curr_in].read_buffer, capture_data, clock_start);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -72,17 +74,19 @@ static bool safe_capture_call(FTD3XXReceivedDataBuffer* received_buffer, Capture
|
|||
|
||||
while(capture_data->status.connected && capture_data->status.running) {
|
||||
|
||||
CaptureDataSingleBuffer* data_buf = capture_data->data_buffers.GetWriterBuffer(0);
|
||||
uint8_t* buffer = (uint8_t*)&data_buf->capture_buf;
|
||||
#ifdef _WIN32
|
||||
FT_STATUS ftStatus = FT_ReadPipeEx(handle, fifo_channel, (UCHAR*)&received_buffer->capture_buf, ftd3_get_capture_size(capture_data), &received_buffer->read_buffer, NULL);
|
||||
FT_STATUS ftStatus = FT_ReadPipeEx(handle, fifo_channel, buffer, ftd3_get_capture_size(capture_data), &received_buffer->read_buffer, NULL);
|
||||
#else
|
||||
FT_STATUS ftStatus = FT_ReadPipeEx(handle, fifo_channel, (UCHAR*)&received_buffer->capture_buf, ftd3_get_capture_size(capture_data), &received_buffer->read_buffer, 1000);
|
||||
FT_STATUS ftStatus = FT_ReadPipeEx(handle, fifo_channel, buffer, ftd3_get_capture_size(capture_data), &received_buffer->read_buffer, 1000);
|
||||
#endif
|
||||
if(FT_FAILED(ftStatus)) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Read failed");
|
||||
return true;
|
||||
}
|
||||
|
||||
data_output_update(&received_buffer->capture_buf, received_buffer->read_buffer, capture_data, clock_start);
|
||||
data_output_update(0, received_buffer->read_buffer, capture_data, clock_start);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -97,6 +101,7 @@ static FTD3XXReceivedDataBuffer* init_received_buffer() {
|
|||
|
||||
static void close_received_buffer(FTD3XXReceivedDataBuffer* received_buffer, CaptureData* capture_data) {
|
||||
if(ftd3_driver_get_is_bad()) {
|
||||
capture_data->data_buffers.ReleaseWriterBuffer(0, false);
|
||||
delete received_buffer;
|
||||
return;
|
||||
}
|
||||
|
|
@ -107,6 +112,7 @@ static void close_received_buffer(FTD3XXReceivedDataBuffer* received_buffer, Cap
|
|||
if(FT_ReleaseOverlapped(handle, &received_buffer[inner_curr_in].overlap)) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Release failed");
|
||||
}
|
||||
capture_data->data_buffers.ReleaseWriterBuffer(inner_curr_in, false);
|
||||
}
|
||||
delete []received_buffer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@
|
|||
struct FTD3LibusbCaptureReceivedData {
|
||||
bool in_use;
|
||||
uint32_t index;
|
||||
int internal_index;
|
||||
CaptureData* capture_data;
|
||||
CaptureReceived buffer;
|
||||
uint32_t* last_index;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> *clock_start;
|
||||
SharedConsumerMutex *is_buffer_free_shared_mutex;
|
||||
|
|
@ -78,31 +78,35 @@ static void ftd3_libusb_read_frame_request(CaptureData* capture_data, FTD3Libusb
|
|||
return;
|
||||
ftd3_libusb_capture_recv_data->index = index;
|
||||
ftd3_libusb_capture_recv_data->cb_data.function = ftd3_libusb_read_frame_cb;
|
||||
ftd3_libusb_async_in_start((ftd3_device_device_handlers*)capture_data->handle, pipe, MAX_TIME_WAIT * 1000, (uint8_t*)&ftd3_libusb_capture_recv_data->buffer, ftd3_get_capture_size(capture_data), &ftd3_libusb_capture_recv_data->cb_data);
|
||||
CaptureDataSingleBuffer* data_buf = capture_data->data_buffers.GetWriterBuffer(ftd3_libusb_capture_recv_data->internal_index);
|
||||
uint8_t* buffer = (uint8_t*)&data_buf->capture_buf;
|
||||
ftd3_libusb_async_in_start((ftd3_device_device_handlers*)capture_data->handle, pipe, MAX_TIME_WAIT * 1000, buffer, ftd3_get_capture_size(capture_data), &ftd3_libusb_capture_recv_data->cb_data);
|
||||
}
|
||||
|
||||
static void end_ftd3_libusb_read_frame_cb(FTD3LibusbCaptureReceivedData* ftd3_libusb_capture_recv_data) {
|
||||
static void end_ftd3_libusb_read_frame_cb(FTD3LibusbCaptureReceivedData* ftd3_libusb_capture_recv_data, bool early_release) {
|
||||
if(early_release)
|
||||
ftd3_libusb_capture_recv_data->capture_data->data_buffers.ReleaseWriterBuffer(ftd3_libusb_capture_recv_data->internal_index, false);
|
||||
ftd3_libusb_capture_recv_data->in_use = false;
|
||||
ftd3_libusb_capture_recv_data->is_buffer_free_shared_mutex->specific_unlock(ftd3_libusb_capture_recv_data->cb_data.internal_index);
|
||||
ftd3_libusb_capture_recv_data->is_buffer_free_shared_mutex->specific_unlock(ftd3_libusb_capture_recv_data->internal_index);
|
||||
}
|
||||
|
||||
static void ftd3_libusb_read_frame_cb(void* user_data, int transfer_length, int transfer_status) {
|
||||
FTD3LibusbCaptureReceivedData* ftd3_libusb_capture_recv_data = (FTD3LibusbCaptureReceivedData*)user_data;
|
||||
if((*ftd3_libusb_capture_recv_data->status) < 0)
|
||||
return end_ftd3_libusb_read_frame_cb(ftd3_libusb_capture_recv_data);
|
||||
return end_ftd3_libusb_read_frame_cb(ftd3_libusb_capture_recv_data, true);
|
||||
if(transfer_status != LIBUSB_TRANSFER_COMPLETED) {
|
||||
*ftd3_libusb_capture_recv_data->status = LIBUSB_ERROR_OTHER;
|
||||
return end_ftd3_libusb_read_frame_cb(ftd3_libusb_capture_recv_data);
|
||||
return end_ftd3_libusb_read_frame_cb(ftd3_libusb_capture_recv_data, true);
|
||||
}
|
||||
|
||||
if(((int32_t)(ftd3_libusb_capture_recv_data->index - (*ftd3_libusb_capture_recv_data->last_index))) <= 0) {
|
||||
//*ftd3_libusb_capture_recv_data->status = LIBUSB_ERROR_INTERRUPTED;
|
||||
return end_ftd3_libusb_read_frame_cb(ftd3_libusb_capture_recv_data);
|
||||
return end_ftd3_libusb_read_frame_cb(ftd3_libusb_capture_recv_data, true);
|
||||
}
|
||||
*ftd3_libusb_capture_recv_data->last_index = ftd3_libusb_capture_recv_data->index;
|
||||
|
||||
data_output_update(&ftd3_libusb_capture_recv_data->buffer, transfer_length, ftd3_libusb_capture_recv_data->capture_data, *ftd3_libusb_capture_recv_data->clock_start);
|
||||
end_ftd3_libusb_read_frame_cb(ftd3_libusb_capture_recv_data);
|
||||
data_output_update(ftd3_libusb_capture_recv_data->internal_index, transfer_length, ftd3_libusb_capture_recv_data->capture_data, *ftd3_libusb_capture_recv_data->clock_start);
|
||||
end_ftd3_libusb_read_frame_cb(ftd3_libusb_capture_recv_data, false);
|
||||
}
|
||||
|
||||
static int ftd3_libusb_get_num_free_buffers(FTD3LibusbCaptureReceivedData* ftd3_libusb_capture_recv_data) {
|
||||
|
|
@ -216,6 +220,7 @@ void ftd3_libusb_capture_main_loop(CaptureData* capture_data, int pipe) {
|
|||
for(int i = 0; i < FTD3_CONCURRENT_BUFFERS; i++) {
|
||||
ftd3_libusb_capture_recv_data[i].in_use = false;
|
||||
ftd3_libusb_capture_recv_data[i].index = i;
|
||||
ftd3_libusb_capture_recv_data[i].internal_index = i;
|
||||
ftd3_libusb_capture_recv_data[i].capture_data = capture_data;
|
||||
ftd3_libusb_capture_recv_data[i].last_index = &last_index;
|
||||
ftd3_libusb_capture_recv_data[i].clock_start = &clock_start;
|
||||
|
|
@ -223,7 +228,6 @@ void ftd3_libusb_capture_main_loop(CaptureData* capture_data, int pipe) {
|
|||
ftd3_libusb_capture_recv_data[i].status = &status;
|
||||
ftd3_libusb_capture_recv_data[i].cb_data.actual_user_data = &ftd3_libusb_capture_recv_data[i];
|
||||
ftd3_libusb_capture_recv_data[i].cb_data.transfer_data = NULL;
|
||||
ftd3_libusb_capture_recv_data[i].cb_data.internal_index = i;
|
||||
}
|
||||
ftd3_libusb_start_thread(&async_processing_thread, &is_done_thread);
|
||||
ftd3_libusb_capture_main_loop_processing(ftd3_libusb_capture_recv_data, pipe);
|
||||
|
|
|
|||
|
|
@ -32,11 +32,11 @@ void list_devices_ftd3(std::vector<CaptureDevice> &devices_list, std::vector<no_
|
|||
ftd3_list_devices_compat(devices_list, no_access_list, valid_3dscapture_descriptions);
|
||||
}
|
||||
|
||||
void data_output_update(CaptureReceived* received_buffer, size_t read_data, CaptureData* capture_data, std::chrono::time_point<std::chrono::high_resolution_clock> &base_time) {
|
||||
void data_output_update(int inner_index, size_t read_data, CaptureData* capture_data, std::chrono::time_point<std::chrono::high_resolution_clock> &base_time) {
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - base_time;
|
||||
base_time = curr_time;
|
||||
capture_data->data_buffers.WriteToBuffer(received_buffer, read_data, diff.count(), &capture_data->status.device);
|
||||
capture_data->data_buffers.WriteToBuffer(NULL, read_data, diff.count(), &capture_data->status.device, inner_index);
|
||||
|
||||
if(capture_data->status.cooldown_curr_in)
|
||||
capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1;
|
||||
|
|
|
|||
|
|
@ -71,13 +71,15 @@ static size_t get_initial_offset_buffer(uint16_t* in_u16, size_t real_length) {
|
|||
return ignored_halfwords * 2;
|
||||
}
|
||||
|
||||
static void data_output_update(CaptureReceived* buffer, CaptureData* capture_data, int read_amount, std::chrono::time_point<std::chrono::high_resolution_clock> &base_time) {
|
||||
static void data_output_update(int curr_data_buffer_index, CaptureData* capture_data, int read_amount, std::chrono::time_point<std::chrono::high_resolution_clock> &base_time) {
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - base_time;
|
||||
base_time = curr_time;
|
||||
CaptureDataSingleBuffer* curr_full_data_buf = capture_data->data_buffers.GetWriterBuffer(curr_data_buffer_index);
|
||||
CaptureReceived* buffer = &curr_full_data_buf->capture_buf;
|
||||
size_t buffer_real_len = remove_synch_from_final_length((uint32_t*)buffer, read_amount);
|
||||
size_t initial_offset = get_initial_offset_buffer((uint16_t*) buffer, buffer_real_len);
|
||||
capture_data->data_buffers.WriteToBuffer(buffer, buffer_real_len, diff.count(), &capture_data->status.device, initial_offset);
|
||||
capture_data->data_buffers.WriteToBuffer(NULL, buffer_real_len, diff.count(), &capture_data->status.device, initial_offset, curr_data_buffer_index);
|
||||
|
||||
if(capture_data->status.cooldown_curr_in)
|
||||
capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1;
|
||||
|
|
@ -96,28 +98,30 @@ void ftd2_capture_main_loop_driver(CaptureData* capture_data) {
|
|||
int inner_curr_in = 0;
|
||||
int retval = 0;
|
||||
auto clock_start = std::chrono::high_resolution_clock::now();
|
||||
CaptureReceived* data_buffer = new CaptureReceived[NUM_CAPTURE_RECEIVED_DATA_BUFFERS];
|
||||
int curr_data_buffer = 0;
|
||||
int next_data_buffer = 0;
|
||||
int curr_data_buffer_index = 0;
|
||||
int next_data_buffer_index = 0;
|
||||
const size_t full_size = get_capture_size(capture_data->status.device.is_rgb_888);
|
||||
size_t next_size = full_size;
|
||||
size_t bytesIn;
|
||||
|
||||
while (capture_data->status.connected && capture_data->status.running) {
|
||||
curr_data_buffer = next_data_buffer;
|
||||
retval = ftd2_read(capture_data->handle, is_libftdi, ((uint8_t*)(&data_buffer[curr_data_buffer]) + (full_size - next_size)), next_size, &bytesIn);
|
||||
curr_data_buffer_index = next_data_buffer_index;
|
||||
CaptureDataSingleBuffer* curr_full_data_buf = capture_data->data_buffers.GetWriterBuffer(curr_data_buffer_index);
|
||||
CaptureReceived* curr_data_buffer = &curr_full_data_buf->capture_buf;
|
||||
retval = ftd2_read(capture_data->handle, is_libftdi, ((uint8_t*)curr_data_buffer) + (full_size - next_size), next_size, &bytesIn);
|
||||
if(ftd2_is_error(retval, is_libftdi)) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Read failed");
|
||||
break;
|
||||
}
|
||||
if(bytesIn < next_size)
|
||||
continue;
|
||||
next_data_buffer = (curr_data_buffer + 1) % NUM_CAPTURE_RECEIVED_DATA_BUFFERS;
|
||||
bool has_synch_failed = !synchronization_check((uint16_t*)(&data_buffer[curr_data_buffer]), full_size, (uint16_t*)(&data_buffer[next_data_buffer]), &next_size, true);
|
||||
next_data_buffer_index = (curr_data_buffer_index + 1) % NUM_CAPTURE_RECEIVED_DATA_BUFFERS;
|
||||
CaptureDataSingleBuffer* next_full_data_buf = capture_data->data_buffers.GetWriterBuffer(next_data_buffer_index);
|
||||
CaptureReceived* next_data_buffer = &next_full_data_buf->capture_buf;
|
||||
bool has_synch_failed = !synchronization_check((uint16_t*)curr_data_buffer, full_size, (uint16_t*)next_data_buffer, &next_size, true);
|
||||
if(has_synch_failed) {
|
||||
continue;
|
||||
}
|
||||
data_output_update(&data_buffer[curr_data_buffer], capture_data, full_size, clock_start);
|
||||
data_output_update(curr_data_buffer_index, capture_data, full_size, clock_start);
|
||||
}
|
||||
delete []data_buffer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -375,10 +375,16 @@ bool synchronization_check(uint16_t* data_buffer, size_t size, uint16_t* next_da
|
|||
|
||||
size_t remove_synch_from_final_length(uint32_t* out_buffer, size_t real_length) {
|
||||
// Ignore synch for final length
|
||||
const uint32_t check_value = FTD2_OLDDS_SYNCH_VALUES | (FTD2_OLDDS_SYNCH_VALUES << 16);
|
||||
while((real_length >= 4) && ((out_buffer)[(real_length / 4) - 1] == check_value))
|
||||
real_length -= 4;
|
||||
if((real_length < 4) && (out_buffer[0] == check_value))
|
||||
uint32_t check_value = FTD2_OLDDS_SYNCH_VALUES | (FTD2_OLDDS_SYNCH_VALUES << 16);
|
||||
size_t check_size = sizeof(uint32_t);
|
||||
while((real_length >= check_size) && (out_buffer[(real_length / check_size) - 1] == check_value))
|
||||
real_length -= check_size;
|
||||
check_value = FTD2_OLDDS_SYNCH_VALUES;
|
||||
uint16_t* u16_buffer = (uint16_t*)out_buffer;
|
||||
check_size = sizeof(uint16_t);
|
||||
while((real_length >= check_size) && (u16_buffer[(real_length / check_size) - 1] == check_value))
|
||||
real_length -= check_size;
|
||||
if((real_length < check_size) && (u16_buffer[0] == check_value))
|
||||
real_length = 0;
|
||||
return real_length;
|
||||
}
|
||||
|
|
@ -393,6 +399,8 @@ void ftd2_capture_main_loop_shared(CaptureData* capture_data) {
|
|||
}
|
||||
|
||||
void ftd2_capture_cleanup_shared(CaptureData* capture_data) {
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
capture_data->data_buffers.ReleaseWriterBuffer(i, false);
|
||||
bool is_libftdi = capture_data->status.device.descriptor != NULL;
|
||||
if(ftd2_close(capture_data->handle, is_libftdi)) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Close failed");
|
||||
|
|
|
|||
|
|
@ -309,7 +309,7 @@ static void STDCALL libftdi_read_callback(libusb_transfer* transfer) {
|
|||
}
|
||||
|
||||
// Read from bulk
|
||||
static void libftdi_schedule_read(ftd2_async_callback_data* cb_data, int length) {
|
||||
static void libftdi_schedule_read(ftd2_async_callback_data* cb_data, uint8_t* buffer_raw, int length) {
|
||||
const int max_packet_size = MAX_PACKET_SIZE_USB2;
|
||||
libusb_transfer *transfer_in = libusb_alloc_transfer(0);
|
||||
if(!transfer_in)
|
||||
|
|
@ -320,7 +320,7 @@ static void libftdi_schedule_read(ftd2_async_callback_data* cb_data, int length)
|
|||
length += ((length + (max_packet_size - FTD2_INTRA_PACKET_HEADER_SIZE) - 1) / (max_packet_size - FTD2_INTRA_PACKET_HEADER_SIZE)) * FTD2_INTRA_PACKET_HEADER_SIZE;
|
||||
cb_data->requested_length = length;
|
||||
ftdi_context* in_handle = (ftdi_context*)cb_data->handle;
|
||||
libusb_fill_bulk_transfer(transfer_in, in_handle->usb_dev, in_handle->out_ep, (uint8_t*)&cb_data->buffer_raw, length, libftdi_read_callback, (void*)cb_data, in_handle->usb_read_timeout * NUM_CAPTURE_RECEIVED_DATA_BUFFERS);
|
||||
libusb_fill_bulk_transfer(transfer_in, in_handle->usb_dev, in_handle->out_ep, buffer_raw, length, libftdi_read_callback, (void*)cb_data, in_handle->usb_read_timeout * NUM_CAPTURE_RECEIVED_DATA_BUFFERS);
|
||||
transfer_in->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
||||
libusb_submit_transfer(transfer_in);
|
||||
cb_data->transfer_data_access.unlock();
|
||||
|
|
@ -391,6 +391,7 @@ static int libftdi_full_read(void* handle, uint8_t* buffer_raw, uint8_t* buffer_
|
|||
|
||||
static void libftdi_copy_buffer_to_target_and_skip(uint8_t* buffer_written, uint8_t* buffer_target, const int max_packet_size, size_t length, size_t header_packet_size, size_t ignored_bytes) {
|
||||
// This could be made faster for small "ignored_bytes", however this scales well...
|
||||
// Plus, most of the time is used up by the memcpy routine, so...
|
||||
|
||||
// Remove the small headers every 512 bytes...
|
||||
// The "- header_packet_size" instead of "-1" covers for partial header transfers...
|
||||
|
|
@ -511,11 +512,17 @@ static FTD2CaptureReceivedData* libftdi_get_free_buffer(FTD2CaptureReceivedData*
|
|||
static void libftdi_start_read(FTD2CaptureReceivedData* received_data_buffer, int index, size_t size) {
|
||||
if(received_data_buffer == NULL)
|
||||
return;
|
||||
CaptureDataSingleBuffer* full_data_buf = received_data_buffer->capture_data->data_buffers.GetWriterBuffer(received_data_buffer->cb_data.internal_index);
|
||||
CaptureReceived* data_buffer = &full_data_buf->capture_buf;
|
||||
received_data_buffer->buffer_raw = (uint8_t*)&data_buffer->ftd2_received_old_ds_normal_plus_raw.raw_data;
|
||||
received_data_buffer->buffer_target = (uint32_t*)data_buffer;
|
||||
received_data_buffer->index = index;
|
||||
libftdi_schedule_read(&received_data_buffer->cb_data, size);
|
||||
libftdi_schedule_read(&received_data_buffer->cb_data, received_data_buffer->buffer_raw, size);
|
||||
}
|
||||
|
||||
static void end_libftdi_read_frame_cb(FTD2CaptureReceivedData* received_data_buffer) {
|
||||
static void end_libftdi_read_frame_cb(FTD2CaptureReceivedData* received_data_buffer, bool has_succeded) {
|
||||
if(!has_succeded)
|
||||
received_data_buffer->capture_data->data_buffers.ReleaseWriterBuffer(received_data_buffer->cb_data.internal_index, false);
|
||||
received_data_buffer->in_use = false;
|
||||
received_data_buffer->is_buffer_free_shared_mutex->specific_unlock(received_data_buffer->cb_data.internal_index);
|
||||
}
|
||||
|
|
@ -528,10 +535,8 @@ static size_t libftdi_copy_buffer_to_target_and_skip_synch(uint8_t* in_buffer, u
|
|||
while((ignored_halfwords < (real_length / 2)) && (in_u16[ignored_halfwords + 1 + (ignored_halfwords / (MAX_PACKET_SIZE_USB2 / 2))] == FTD2_OLDDS_SYNCH_VALUES))
|
||||
ignored_halfwords++;
|
||||
size_t copy_offset = ignored_halfwords * 2;
|
||||
if(ignored_halfwords >= ((MAX_PACKET_SIZE_USB2 - FTD2_INTRA_PACKET_HEADER_SIZE) / 2))
|
||||
copy_offset = 0;
|
||||
libftdi_copy_buffer_to_target_and_skip(in_buffer, (uint8_t*)out_buffer, MAX_PACKET_SIZE_USB2, read_length, FTD2_INTRA_PACKET_HEADER_SIZE, copy_offset);
|
||||
if(copy_offset == 0) {
|
||||
if((copy_offset == 0) || (copy_offset >= (MAX_PACKET_SIZE_USB2 - FTD2_INTRA_PACKET_HEADER_SIZE))) {
|
||||
size_t internal_sync_offset = 0;
|
||||
bool is_synced = synchronization_check((uint16_t*)out_buffer, real_length, NULL, &internal_sync_offset);
|
||||
if(!is_synced) {
|
||||
|
|
@ -549,18 +554,15 @@ static size_t libftdi_copy_buffer_to_target_and_skip_synch(uint8_t* in_buffer, u
|
|||
return remove_synch_from_final_length(out_buffer, real_length);
|
||||
}
|
||||
|
||||
static void output_to_thread(CaptureData* capture_data, uint8_t* buffer, std::chrono::time_point<std::chrono::high_resolution_clock> &base_time, int read_length, size_t* sync_offset) {
|
||||
static void output_to_thread(CaptureData* capture_data, int internal_index, uint8_t* buffer_raw, uint32_t* buffer_target, std::chrono::time_point<std::chrono::high_resolution_clock> &base_time, int read_length, size_t* sync_offset) {
|
||||
// For some reason, there is usually one.
|
||||
// Though make this generic enough
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - base_time;
|
||||
base_time = curr_time;
|
||||
CaptureDataSingleBuffer* target = capture_data->data_buffers.GetWriterBuffer();
|
||||
// Copy data to buffer, with special memcpy which accounts for ftd2 header data and skips synch bytes
|
||||
size_t real_length = libftdi_copy_buffer_to_target_and_skip_synch(buffer, (uint32_t*)&target->capture_buf, read_length, sync_offset);
|
||||
target->read = real_length;
|
||||
target->time_in_buf = diff.count();
|
||||
capture_data->data_buffers.ReleaseWriterBuffer();
|
||||
size_t real_length = libftdi_copy_buffer_to_target_and_skip_synch(buffer_raw, buffer_target, read_length, sync_offset);
|
||||
capture_data->data_buffers.WriteToBuffer(NULL, real_length, diff.count(), &capture_data->status.device, internal_index);
|
||||
|
||||
if(capture_data->status.cooldown_curr_in)
|
||||
capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1;
|
||||
|
|
@ -574,21 +576,24 @@ static void libftdi_capture_process_data(void* in_user_data, int transfer_length
|
|||
// It's because the code is too fast...
|
||||
FTD2CaptureReceivedData* user_data = (FTD2CaptureReceivedData*)in_user_data;
|
||||
if((*user_data->status) < 0)
|
||||
return end_libftdi_read_frame_cb(user_data);
|
||||
return end_libftdi_read_frame_cb(user_data, false);
|
||||
if(transfer_status != LIBUSB_TRANSFER_COMPLETED) {
|
||||
*user_data->status = LIBUSB_ERROR_OTHER;
|
||||
return end_libftdi_read_frame_cb(user_data);
|
||||
return end_libftdi_read_frame_cb(user_data, false);
|
||||
}
|
||||
if(transfer_length < user_data->cb_data.requested_length)
|
||||
return end_libftdi_read_frame_cb(user_data);
|
||||
return end_libftdi_read_frame_cb(user_data, false);
|
||||
if(((int32_t)(user_data->index - (*user_data->last_used_index))) <= 0) {
|
||||
//*user_data->status = LIBUSB_ERROR_INTERRUPTED;
|
||||
return end_libftdi_read_frame_cb(user_data);
|
||||
return end_libftdi_read_frame_cb(user_data, false);
|
||||
}
|
||||
*user_data->last_used_index = user_data->index;
|
||||
|
||||
output_to_thread(user_data->capture_data, (uint8_t*)&user_data->cb_data.buffer_raw, *user_data->clock_start, transfer_length, user_data->curr_offset);
|
||||
end_libftdi_read_frame_cb(user_data);
|
||||
// For some reason, saving the raw buffer and then passing it
|
||||
// like this is way faster than loading it.
|
||||
// Even if it's still needed to get the writer buffer...
|
||||
output_to_thread(user_data->capture_data, user_data->cb_data.internal_index, user_data->buffer_raw, user_data->buffer_target, *user_data->clock_start, transfer_length, user_data->curr_offset);
|
||||
end_libftdi_read_frame_cb(user_data, true);
|
||||
}
|
||||
|
||||
static void resync_offset(FTD2CaptureReceivedData* received_data_buffers, uint32_t &index, size_t full_size) {
|
||||
|
|
@ -676,6 +681,7 @@ void ftd2_capture_main_loop_libftdi(CaptureData* capture_data) {
|
|||
received_data_buffers[i].cb_data.transfer_data = NULL;
|
||||
received_data_buffers[i].cb_data.handle = capture_data->handle;
|
||||
received_data_buffers[i].cb_data.is_transfer_done_mutex = &is_transfer_done_mutex;
|
||||
received_data_buffers[i].cb_data.internal_index = i;
|
||||
received_data_buffers[i].cb_data.requested_length = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -210,27 +210,13 @@ int EndAcquisition(const is_device_usb_device* usb_device_desc, is_device_device
|
|||
}
|
||||
}
|
||||
|
||||
void output_to_thread(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, size_t read_size) {
|
||||
void output_to_thread(CaptureData* capture_data, int internal_index, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, size_t read_size) {
|
||||
// Output to the other threads...
|
||||
const is_device_usb_device* usb_device_info = (const is_device_usb_device*)capture_data->status.device.descriptor;
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - (*clock_start);
|
||||
*clock_start = curr_time;
|
||||
if(usb_device_info->device_type == IS_TWL_CAPTURE_DEVICE) {
|
||||
CaptureDataSingleBuffer* target = capture_data->data_buffers.GetWriterBuffer();
|
||||
// Copy data to buffer, with special memcpy which accounts for ftd2 header data and skips synch bytes
|
||||
size_t video_size = usb_is_device_get_video_in_size(curr_capture_type, usb_device_info->device_type);
|
||||
memcpy(&target->capture_buf.is_twl_capture_received.video_capture_in, &capture_buf->is_twl_capture_received.video_capture_in, video_size);
|
||||
if(read_size > video_size) {
|
||||
size_t audio_size = ((read_size - video_size) / sizeof(ISTWLCaptureSoundData)) * sizeof(ISTWLCaptureAudioReceived);
|
||||
memcpy(&target->capture_buf.is_twl_capture_received.audio_capture_in, &capture_buf->is_twl_capture_received.audio_capture_in, audio_size);
|
||||
}
|
||||
target->read = read_size;
|
||||
target->time_in_buf = diff.count();
|
||||
capture_data->data_buffers.ReleaseWriterBuffer();
|
||||
}
|
||||
else
|
||||
capture_data->data_buffers.WriteToBuffer(capture_buf, read_size, diff.count(), &capture_data->status.device, curr_capture_type);
|
||||
capture_data->data_buffers.WriteToBuffer(NULL, read_size, diff.count(), &capture_data->status.device, curr_capture_type, internal_index);
|
||||
|
||||
if (capture_data->status.cooldown_curr_in)
|
||||
capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1;
|
||||
|
|
@ -238,17 +224,21 @@ void output_to_thread(CaptureData* capture_data, CaptureReceived* capture_buf, C
|
|||
capture_data->status.audio_wait.unlock();
|
||||
}
|
||||
|
||||
static void output_to_thread(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start) {
|
||||
static void output_to_thread(CaptureData* capture_data, int internal_index, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start) {
|
||||
const is_device_usb_device* usb_device_info = (const is_device_usb_device*)capture_data->status.device.descriptor;
|
||||
output_to_thread(capture_data, capture_buf, curr_capture_type, clock_start, usb_is_device_get_video_in_size(curr_capture_type, usb_device_info->device_type));
|
||||
output_to_thread(capture_data, internal_index, curr_capture_type, clock_start, usb_is_device_get_video_in_size(curr_capture_type, usb_device_info->device_type));
|
||||
}
|
||||
|
||||
int is_device_read_frame_and_output(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock> &clock_start) {
|
||||
int is_device_read_frame_and_output(CaptureData* capture_data, int internal_index, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock> &clock_start) {
|
||||
const is_device_usb_device* usb_device_info = (const is_device_usb_device*)capture_data->status.device.descriptor;
|
||||
int ret = ReadFrame((is_device_device_handlers*)capture_data->handle, (uint8_t*)capture_buf, usb_is_device_get_video_in_size(curr_capture_type, usb_device_info->device_type), usb_device_info);
|
||||
if (ret < 0)
|
||||
CaptureDataSingleBuffer* target = capture_data->data_buffers.GetWriterBuffer(internal_index);
|
||||
CaptureReceived* buffer = &target->capture_buf;
|
||||
int ret = ReadFrame((is_device_device_handlers*)capture_data->handle, (uint8_t*)buffer, usb_is_device_get_video_in_size(curr_capture_type, usb_device_info->device_type), usb_device_info);
|
||||
if (ret < 0) {
|
||||
capture_data->data_buffers.ReleaseWriterBuffer(internal_index, false);
|
||||
return ret;
|
||||
output_to_thread(capture_data, capture_buf, curr_capture_type, &clock_start);
|
||||
}
|
||||
output_to_thread(capture_data, internal_index, curr_capture_type, &clock_start);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -261,10 +251,14 @@ void is_device_read_frame_request(CaptureData* capture_data, ISDeviceCaptureRece
|
|||
is_device_capture_recv_data->index = index;
|
||||
is_device_capture_recv_data->curr_capture_type = curr_capture_type;
|
||||
is_device_capture_recv_data->cb_data.function = is_device_read_frame_cb;
|
||||
ReadFrameAsync((is_device_device_handlers*)capture_data->handle, (uint8_t*)&is_device_capture_recv_data->buffer, usb_is_device_get_video_in_size(curr_capture_type, usb_device_info->device_type), usb_device_info, &is_device_capture_recv_data->cb_data);
|
||||
CaptureDataSingleBuffer* target = capture_data->data_buffers.GetWriterBuffer(is_device_capture_recv_data->cb_data.internal_index);
|
||||
CaptureReceived* buffer = &target->capture_buf;
|
||||
ReadFrameAsync((is_device_device_handlers*)capture_data->handle, (uint8_t*)buffer, usb_is_device_get_video_in_size(curr_capture_type, usb_device_info->device_type), usb_device_info, &is_device_capture_recv_data->cb_data);
|
||||
}
|
||||
|
||||
static void end_is_device_read_frame_cb(ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
static void end_is_device_read_frame_cb(ISDeviceCaptureReceivedData* is_device_capture_recv_data, bool pre_release) {
|
||||
if(pre_release)
|
||||
is_device_capture_recv_data->capture_data->data_buffers.ReleaseWriterBuffer(is_device_capture_recv_data->cb_data.internal_index, false);
|
||||
is_device_capture_recv_data->in_use = false;
|
||||
is_device_capture_recv_data->is_buffer_free_shared_mutex->specific_unlock(is_device_capture_recv_data->cb_data.internal_index);
|
||||
}
|
||||
|
|
@ -272,20 +266,20 @@ static void end_is_device_read_frame_cb(ISDeviceCaptureReceivedData* is_device_c
|
|||
static void is_device_read_frame_cb(void* user_data, int transfer_length, int transfer_status) {
|
||||
ISDeviceCaptureReceivedData* is_device_capture_recv_data = (ISDeviceCaptureReceivedData*)user_data;
|
||||
if((*is_device_capture_recv_data->status) < 0)
|
||||
return end_is_device_read_frame_cb(is_device_capture_recv_data);
|
||||
return end_is_device_read_frame_cb(is_device_capture_recv_data, true);
|
||||
if(transfer_status != LIBUSB_TRANSFER_COMPLETED) {
|
||||
*is_device_capture_recv_data->status = LIBUSB_ERROR_OTHER;
|
||||
return end_is_device_read_frame_cb(is_device_capture_recv_data);
|
||||
return end_is_device_read_frame_cb(is_device_capture_recv_data, true);
|
||||
}
|
||||
|
||||
if(((int32_t)(is_device_capture_recv_data->index - (*is_device_capture_recv_data->last_index))) <= 0) {
|
||||
//*is_device_capture_recv_data->status = LIBUSB_ERROR_INTERRUPTED;
|
||||
return end_is_device_read_frame_cb(is_device_capture_recv_data);
|
||||
return end_is_device_read_frame_cb(is_device_capture_recv_data, true);
|
||||
}
|
||||
*is_device_capture_recv_data->last_index = is_device_capture_recv_data->index;
|
||||
|
||||
output_to_thread(is_device_capture_recv_data->capture_data, &is_device_capture_recv_data->buffer, is_device_capture_recv_data->curr_capture_type, is_device_capture_recv_data->clock_start);
|
||||
end_is_device_read_frame_cb(is_device_capture_recv_data);
|
||||
output_to_thread(is_device_capture_recv_data->capture_data, is_device_capture_recv_data->cb_data.internal_index, is_device_capture_recv_data->curr_capture_type, is_device_capture_recv_data->clock_start);
|
||||
end_is_device_read_frame_cb(is_device_capture_recv_data, false);
|
||||
}
|
||||
|
||||
int is_device_get_num_free_buffers(ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
|
|
@ -467,6 +461,8 @@ void is_device_acquisition_main_loop(CaptureData* capture_data) {
|
|||
void usb_is_device_acquisition_cleanup(CaptureData* capture_data) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
capture_data->data_buffers.ReleaseWriterBuffer(i, false);
|
||||
is_device_connection_end((is_device_device_handlers*)capture_data->handle, (const is_device_usb_device*)capture_data->status.device.descriptor);
|
||||
capture_data->handle = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,18 +15,18 @@
|
|||
#define AUDIO_ADDRESS_RING_BUFFER_END 0x01880000
|
||||
#define VIDEO_ADDRESS_RING_BUFFER_END 0x01000000
|
||||
|
||||
static void output_to_thread_reset_processed_data(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, size_t video_processed_size, size_t &video_length_processed, size_t &audio_length_processed) {
|
||||
output_to_thread(capture_data, capture_buf, curr_capture_type, clock_start, video_processed_size + ((audio_length_processed / sizeof(ISTWLCaptureAudioReceived)) * sizeof(ISTWLCaptureSoundData)));
|
||||
static void output_to_thread_reset_processed_data(CaptureData* capture_data, int internal_index, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, size_t video_processed_size, size_t &video_length_processed, size_t &audio_length_processed) {
|
||||
output_to_thread(capture_data, internal_index, curr_capture_type, clock_start, video_processed_size + ((audio_length_processed / sizeof(ISTWLCaptureAudioReceived)) * sizeof(ISTWLCaptureSoundData)));
|
||||
video_length_processed = 0;
|
||||
audio_length_processed = 0;
|
||||
}
|
||||
|
||||
static int process_frame_and_read(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, CaptureSpeedsType curr_capture_speed, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, uint32_t &last_read_frame_index, uint32_t video_address, uint32_t video_length, size_t &video_length_processed, uint32_t audio_address, uint32_t audio_length, size_t &audio_length_processed, bool &processed, float &last_frame_length, bool &reprocess) {
|
||||
static int process_frame_and_read(CaptureData* capture_data, int internal_index, CaptureScreensType curr_capture_type, CaptureSpeedsType curr_capture_speed, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, uint32_t &last_read_frame_index, uint32_t video_address, uint32_t video_length, size_t &video_length_processed, uint32_t audio_address, uint32_t audio_length, size_t &audio_length_processed, bool &processed, float &last_frame_length, bool &reprocess) {
|
||||
const size_t video_processed_size = usb_is_device_get_video_in_size(curr_capture_type, IS_TWL_CAPTURE_DEVICE);
|
||||
processed = false;
|
||||
if((video_length == 0) && (audio_length == 0)) {
|
||||
if(reprocess)
|
||||
output_to_thread_reset_processed_data(capture_data, capture_buf, curr_capture_type, clock_start, video_processed_size, video_length_processed, audio_length_processed);
|
||||
output_to_thread_reset_processed_data(capture_data, internal_index, curr_capture_type, clock_start, video_processed_size, video_length_processed, audio_length_processed);
|
||||
reprocess = false;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -63,6 +63,8 @@ static int process_frame_and_read(CaptureData* capture_data, CaptureReceived* ca
|
|||
audio_processed_diff_from_max = 0;
|
||||
else
|
||||
audio_length_processed = max_audio_length - audio_length;
|
||||
CaptureDataSingleBuffer* target = capture_data->data_buffers.GetWriterBuffer(internal_index);
|
||||
CaptureReceived* capture_buf = &target->capture_buf;
|
||||
int ret = ReadFrame(handlers, ((uint8_t*)&capture_buf->is_twl_capture_received.audio_capture_in) + audio_length_processed, audio_address, audio_length, usb_device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
|
|
@ -91,7 +93,7 @@ static int process_frame_and_read(CaptureData* capture_data, CaptureReceived* ca
|
|||
reprocess = true;
|
||||
return 0;
|
||||
}
|
||||
output_to_thread_reset_processed_data(capture_data, capture_buf, curr_capture_type, clock_start, video_processed_size, video_length_processed, audio_length_processed);
|
||||
output_to_thread_reset_processed_data(capture_data, internal_index, curr_capture_type, clock_start, video_processed_size, video_length_processed, audio_length_processed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -227,10 +229,10 @@ void is_twl_acquisition_capture_main_loop(CaptureData* capture_data, ISDeviceCap
|
|||
capture_error_print(true, capture_data, "Frame Info Read: Failed");
|
||||
return;
|
||||
}
|
||||
ret = process_frame_and_read(capture_data, &is_device_capture_recv_data[0].buffer, curr_capture_type, curr_capture_speed, &clock_last_frame, last_read_frame_index, video_address, video_length, video_length_processed, audio_address, audio_length, audio_length_processed, processed, last_frame_length, reprocess);
|
||||
ret = process_frame_and_read(capture_data, 0, curr_capture_type, curr_capture_speed, &clock_last_frame, last_read_frame_index, video_address, video_length, video_length_processed, audio_address, audio_length, audio_length_processed, processed, last_frame_length, reprocess);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Frame Read: Error " + std::to_string(ret));
|
||||
return;
|
||||
capture_error_print(true, capture_data, "Frame Read: Error " + std::to_string(ret));
|
||||
return;
|
||||
}
|
||||
if(processed) {
|
||||
curr_capture_speed = capture_data->status.capture_speed;
|
||||
|
|
|
|||
|
|
@ -175,44 +175,48 @@ static int find_first_vsync_byte(CaptureReceived* capture_buf, size_t read_size)
|
|||
return pos;
|
||||
}
|
||||
|
||||
void cypress_output_to_thread(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, size_t read_size, size_t* scheduled_special_read, bool* recalibration_request) {
|
||||
void cypress_output_to_thread(CaptureData* capture_data, int internal_index, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, size_t read_size, size_t* scheduled_special_read, bool* recalibration_request) {
|
||||
// Output to the other threads...
|
||||
int offset = find_first_vsync_byte(capture_buf, read_size);
|
||||
CaptureDataSingleBuffer* data_buf = capture_data->data_buffers.GetWriterBuffer(internal_index);
|
||||
int offset = find_first_vsync_byte(&data_buf->capture_buf, read_size);
|
||||
const cyni_device_usb_device* usb_device_info = (const cyni_device_usb_device*)capture_data->status.device.descriptor;
|
||||
if(offset) {
|
||||
if(offset % usb_device_info->max_usb_packet_size)
|
||||
*recalibration_request = true;
|
||||
else
|
||||
*scheduled_special_read = offset;
|
||||
capture_data->data_buffers.ReleaseWriterBuffer(internal_index, false);
|
||||
return;
|
||||
}
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - (*clock_start);
|
||||
*clock_start = curr_time;
|
||||
capture_data->data_buffers.WriteToBuffer(capture_buf, read_size, diff.count(), &capture_data->status.device, curr_capture_type);
|
||||
capture_data->data_buffers.WriteToBuffer(NULL, read_size, diff.count(), &capture_data->status.device, internal_index);
|
||||
if (capture_data->status.cooldown_curr_in)
|
||||
capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1;
|
||||
capture_data->status.video_wait.unlock();
|
||||
capture_data->status.audio_wait.unlock();
|
||||
}
|
||||
|
||||
int cypress_device_read_frame_and_output(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock> &clock_start, size_t* scheduled_special_read, bool* recalibration_request) {
|
||||
int cypress_device_read_frame_and_output(CaptureData* capture_data, int internal_index, std::chrono::time_point<std::chrono::high_resolution_clock> &clock_start, size_t* scheduled_special_read, bool* recalibration_request) {
|
||||
const cyni_device_usb_device* usb_device_info = (const cyni_device_usb_device*)capture_data->status.device.descriptor;
|
||||
size_t read_size = cyni_device_get_video_in_size(usb_device_info->device_type);
|
||||
if(*scheduled_special_read)
|
||||
read_size = *scheduled_special_read;
|
||||
int ret = ReadFrame((cyni_device_device_handlers*)capture_data->handle, (uint8_t*)capture_buf, read_size, usb_device_info);
|
||||
CaptureDataSingleBuffer* data_buf = capture_data->data_buffers.GetWriterBuffer(internal_index);
|
||||
uint8_t* buffer = (uint8_t*)&data_buf->capture_buf;
|
||||
int ret = ReadFrame((cyni_device_device_handlers*)capture_data->handle, buffer, read_size, usb_device_info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if(*scheduled_special_read) {
|
||||
*scheduled_special_read = 0;
|
||||
return ret;
|
||||
}
|
||||
cypress_output_to_thread(capture_data, capture_buf, curr_capture_type, &clock_start, read_size, scheduled_special_read, recalibration_request);
|
||||
cypress_output_to_thread(capture_data, internal_index, &clock_start, read_size, scheduled_special_read, recalibration_request);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cypress_device_read_frame_request(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, CaptureScreensType curr_capture_type, uint32_t index) {
|
||||
int cypress_device_read_frame_request(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, uint32_t index) {
|
||||
if(cypress_device_capture_recv_data == NULL)
|
||||
return LIBUSB_SUCCESS;
|
||||
if((*cypress_device_capture_recv_data->status) < 0) {
|
||||
|
|
@ -221,7 +225,6 @@ int cypress_device_read_frame_request(CaptureData* capture_data, CypressDeviceCa
|
|||
}
|
||||
const cyni_device_usb_device* usb_device_info = (const cyni_device_usb_device*)capture_data->status.device.descriptor;
|
||||
cypress_device_capture_recv_data->index = index;
|
||||
cypress_device_capture_recv_data->curr_capture_type = curr_capture_type;
|
||||
cypress_device_capture_recv_data->cb_data.function = cypress_device_read_frame_cb;
|
||||
size_t read_size = cyni_device_get_video_in_size(usb_device_info->device_type);
|
||||
if(*cypress_device_capture_recv_data->scheduled_special_read) {
|
||||
|
|
@ -230,10 +233,14 @@ int cypress_device_read_frame_request(CaptureData* capture_data, CypressDeviceCa
|
|||
*cypress_device_capture_recv_data->is_active_special_read = true;
|
||||
*cypress_device_capture_recv_data->scheduled_special_read = 0;
|
||||
}
|
||||
return ReadFrameAsync((cyni_device_device_handlers*)capture_data->handle, (uint8_t*)&cypress_device_capture_recv_data->buffer, read_size, usb_device_info, &cypress_device_capture_recv_data->cb_data);
|
||||
CaptureDataSingleBuffer* data_buf = capture_data->data_buffers.GetWriterBuffer(cypress_device_capture_recv_data->cb_data.internal_index);
|
||||
uint8_t* buffer = (uint8_t*)&data_buf->capture_buf;
|
||||
return ReadFrameAsync((cyni_device_device_handlers*)capture_data->handle, buffer, read_size, usb_device_info, &cypress_device_capture_recv_data->cb_data);
|
||||
}
|
||||
|
||||
static void end_cypress_device_read_frame_cb(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
static void end_cypress_device_read_frame_cb(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, bool early_release) {
|
||||
if(early_release)
|
||||
cypress_device_capture_recv_data->capture_data->data_buffers.ReleaseWriterBuffer(cypress_device_capture_recv_data->cb_data.internal_index, false);
|
||||
cypress_device_capture_recv_data->in_use = false;
|
||||
cypress_device_capture_recv_data->is_buffer_free_shared_mutex->specific_unlock(cypress_device_capture_recv_data->cb_data.internal_index);
|
||||
}
|
||||
|
|
@ -241,7 +248,7 @@ static void end_cypress_device_read_frame_cb(CypressDeviceCaptureReceivedData* c
|
|||
static void cypress_device_read_frame_cb(void* user_data, int transfer_length, int transfer_status) {
|
||||
CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data = (CypressDeviceCaptureReceivedData*)user_data;
|
||||
if((*cypress_device_capture_recv_data->status) < 0)
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data);
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data, true);
|
||||
if(transfer_status != LIBUSB_TRANSFER_COMPLETED) {
|
||||
int error = LIBUSB_ERROR_OTHER;
|
||||
if(transfer_status == LIBUSB_TRANSFER_TIMED_OUT)
|
||||
|
|
@ -251,12 +258,12 @@ static void cypress_device_read_frame_cb(void* user_data, int transfer_length, i
|
|||
*cypress_device_capture_recv_data->consecutive_output_to_thread = 0;
|
||||
}
|
||||
*cypress_device_capture_recv_data->status = error;
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data);
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data, true);
|
||||
}
|
||||
|
||||
if(((int32_t)(cypress_device_capture_recv_data->index - (*cypress_device_capture_recv_data->last_index))) <= 0) {
|
||||
//*cypress_device_capture_recv_data->status = LIBUSB_ERROR_INTERRUPTED;
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data);
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data, true);
|
||||
}
|
||||
*cypress_device_capture_recv_data->consecutive_output_to_thread += 1;
|
||||
if((*cypress_device_capture_recv_data->consecutive_output_to_thread) > NUM_CONSECUTIVE_NEEDED_OUTPUT)
|
||||
|
|
@ -266,14 +273,14 @@ static void cypress_device_read_frame_cb(void* user_data, int transfer_length, i
|
|||
// Realign, with multiple of max_usb_packet_size
|
||||
if((*cypress_device_capture_recv_data->is_active_special_read) && (((int32_t)(cypress_device_capture_recv_data->index - (*cypress_device_capture_recv_data->active_special_read_index))) >= 0)) {
|
||||
*cypress_device_capture_recv_data->is_active_special_read = false;
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data);
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data, true);
|
||||
}
|
||||
|
||||
if((*cypress_device_capture_recv_data->scheduled_special_read) || (*cypress_device_capture_recv_data->is_active_special_read) || (*cypress_device_capture_recv_data->recalibration_request))
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data);
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data, true);
|
||||
|
||||
cypress_output_to_thread(cypress_device_capture_recv_data->capture_data, &cypress_device_capture_recv_data->buffer, cypress_device_capture_recv_data->curr_capture_type, cypress_device_capture_recv_data->clock_start, transfer_length, cypress_device_capture_recv_data->scheduled_special_read, cypress_device_capture_recv_data->recalibration_request);
|
||||
end_cypress_device_read_frame_cb(cypress_device_capture_recv_data);
|
||||
cypress_output_to_thread(cypress_device_capture_recv_data->capture_data, cypress_device_capture_recv_data->cb_data.internal_index, cypress_device_capture_recv_data->clock_start, transfer_length, cypress_device_capture_recv_data->scheduled_special_read, cypress_device_capture_recv_data->recalibration_request);
|
||||
end_cypress_device_read_frame_cb(cypress_device_capture_recv_data, false);
|
||||
}
|
||||
|
||||
int cypress_device_get_num_free_buffers(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
|
|
@ -395,7 +402,7 @@ void reset_cypress_device_status(CypressDeviceCaptureReceivedData* cypress_devic
|
|||
error_cypress_device_status(cypress_device_capture_recv_data, 0);
|
||||
}
|
||||
|
||||
void recalibration_reads(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, CypressDeviceCaptureReceivedData* chosen_buffer, uint32_t &index, CaptureScreensType curr_capture_type) {
|
||||
void recalibration_reads(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, CypressDeviceCaptureReceivedData* chosen_buffer, uint32_t &index) {
|
||||
// Enforce properly synchronized reads.
|
||||
// Reduces complexity and latency, at the cost of some extra
|
||||
// time between lid reopening and visible video output.
|
||||
|
|
@ -415,12 +422,12 @@ void recalibration_reads(cyni_device_device_handlers* handlers, const cyni_devic
|
|||
default_sleep();
|
||||
*chosen_buffer->recalibration_request = false;
|
||||
chosen_buffer->in_use = true;
|
||||
int ret = cypress_device_read_frame_request(capture_data, chosen_buffer, curr_capture_type, index++);
|
||||
int ret = cypress_device_read_frame_request(capture_data, chosen_buffer, index++);
|
||||
if(ret < 0) {
|
||||
error_cypress_device_status(cypress_device_capture_recv_data, ret);
|
||||
return;
|
||||
}
|
||||
ret = cypress_device_read_frame_request(capture_data, next_buffer, curr_capture_type, index++);
|
||||
ret = cypress_device_read_frame_request(capture_data, next_buffer, index++);
|
||||
if(ret < 0) {
|
||||
next_buffer->in_use = false;
|
||||
error_cypress_device_status(cypress_device_capture_recv_data, ret);
|
||||
|
|
@ -437,8 +444,6 @@ static bool cyni_device_acquisition_loop(CaptureData* capture_data, CypressDevic
|
|||
cyni_device_device_handlers* handlers = (cyni_device_device_handlers*)capture_data->handle;
|
||||
const cyni_device_usb_device* usb_device_desc = (const cyni_device_usb_device*)capture_data->status.device.descriptor;
|
||||
uint32_t index = 0;
|
||||
CaptureScreensType curr_capture_type = capture_data->status.capture_type;
|
||||
CaptureSpeedsType curr_capture_speed = capture_data->status.capture_speed;
|
||||
int ret = capture_start(handlers, usb_device_desc);
|
||||
if (ret < 0) {
|
||||
capture_error_print(true, capture_data, "Capture Start: Failed");
|
||||
|
|
@ -448,7 +453,7 @@ static bool cyni_device_acquisition_loop(CaptureData* capture_data, CypressDevic
|
|||
auto clock_last_reset = std::chrono::high_resolution_clock::now();
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
CypressDeviceCaptureReceivedData* chosen_buffer = cypress_device_get_free_buffer(capture_data, cypress_device_capture_recv_data);
|
||||
ret = cypress_device_read_frame_request(capture_data, chosen_buffer, curr_capture_type, index++);
|
||||
ret = cypress_device_read_frame_request(capture_data, chosen_buffer, index++);
|
||||
if(ret < 0) {
|
||||
chosen_buffer->in_use = false;
|
||||
error_cypress_device_status(cypress_device_capture_recv_data, ret);
|
||||
|
|
@ -478,9 +483,9 @@ static bool cyni_device_acquisition_loop(CaptureData* capture_data, CypressDevic
|
|||
error_cypress_device_status(cypress_device_capture_recv_data, LIBUSB_ERROR_TIMEOUT);
|
||||
if(chosen_buffer && (*chosen_buffer->recalibration_request)) {
|
||||
*chosen_buffer->recalibration_request = false;
|
||||
recalibration_reads(handlers, usb_device_desc, cypress_device_capture_recv_data, chosen_buffer, index, curr_capture_type);
|
||||
recalibration_reads(handlers, usb_device_desc, cypress_device_capture_recv_data, chosen_buffer, index);
|
||||
}
|
||||
ret = cypress_device_read_frame_request(capture_data, chosen_buffer, curr_capture_type, index++);
|
||||
ret = cypress_device_read_frame_request(capture_data, chosen_buffer, index++);
|
||||
if(ret < 0) {
|
||||
chosen_buffer->in_use = false;
|
||||
error_cypress_device_status(cypress_device_capture_recv_data, ret);
|
||||
|
|
@ -549,6 +554,8 @@ void cyni_device_acquisition_main_loop(CaptureData* capture_data) {
|
|||
void usb_cyni_device_acquisition_cleanup(CaptureData* capture_data) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
capture_data->data_buffers.ReleaseWriterBuffer(i, false);
|
||||
cypress_nisetro_connection_end((cyni_device_device_handlers*)capture_data->handle, (const cyni_device_usb_device*)capture_data->status.device.descriptor);
|
||||
capture_data->handle = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,6 @@
|
|||
#define FIRST_3D_VERSION 6
|
||||
#define CAPTURE_SKIP_TIMEOUT_SECONDS 1.0
|
||||
|
||||
#define NUM_DS_3DS_CONCURRENT_DATA_BUFFERS 4
|
||||
#define NUM_DS_3DS_CONCURRENT_REQUESTS 4
|
||||
|
||||
enum usb_capture_status {
|
||||
USB_CAPTURE_SUCCESS = 0,
|
||||
USB_CAPTURE_SKIP,
|
||||
|
|
@ -46,25 +43,6 @@ struct usb_device {
|
|||
int bitstream_3dscfg_ver;
|
||||
};
|
||||
|
||||
struct usb_ds_status {
|
||||
uint32_t framecount;
|
||||
uint8_t lcd_on;
|
||||
uint8_t capture_in_progress;
|
||||
};
|
||||
|
||||
struct usb_ds_3ds_general_data {
|
||||
SharedConsumerMutex* is_there_ready_buffer;
|
||||
SharedConsumerMutex* is_buffer_usage_done;
|
||||
uint32_t index;
|
||||
uint32_t* last_index;
|
||||
int real_index;
|
||||
bool in_use;
|
||||
CaptureData* capture_data;
|
||||
CaptureReceived capture_buf;
|
||||
size_t read_amount;
|
||||
double time_in;
|
||||
};
|
||||
|
||||
static const usb_device usb_3ds_desc = {
|
||||
.is_3ds = true,
|
||||
.vid = 0x16D0, .pid = 0x06A3,
|
||||
|
|
@ -94,51 +72,6 @@ static const usb_device* usb_devices_desc_list[] = {
|
|||
&usb_old_ds_desc,
|
||||
};
|
||||
|
||||
static void unlock_buffer(usb_ds_3ds_general_data* buffer_data) {
|
||||
buffer_data->in_use = false;
|
||||
buffer_data->is_buffer_usage_done->specific_unlock(buffer_data->real_index);
|
||||
}
|
||||
|
||||
static void ds_3ds_usb_thread_function(bool* usb_thread_run, usb_ds_3ds_general_data* buffer_data) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
while(*usb_thread_run) {
|
||||
int processing_index = *buffer_data[0].last_index;
|
||||
int dummy = 0;
|
||||
for(int i = 0; i < NUM_DS_3DS_CONCURRENT_DATA_BUFFERS; i++) {
|
||||
if(!buffer_data[i].in_use)
|
||||
continue;
|
||||
int diff = (int)(processing_index - buffer_data[i].index);
|
||||
if(diff > 0)
|
||||
unlock_buffer(&buffer_data[i]);
|
||||
else if(diff == 0) {
|
||||
buffer_data[i].capture_data->data_buffers.WriteToBuffer(&buffer_data[i].capture_buf, buffer_data[i].read_amount, buffer_data[i].time_in, &buffer_data[i].capture_data->status.device);
|
||||
if(buffer_data[i].capture_data->status.cooldown_curr_in)
|
||||
buffer_data[i].capture_data->status.cooldown_curr_in = buffer_data[i].capture_data->status.cooldown_curr_in - 1;
|
||||
buffer_data[i].capture_data->status.video_wait.unlock();
|
||||
buffer_data[i].capture_data->status.audio_wait.unlock();
|
||||
unlock_buffer(&buffer_data[i]);
|
||||
}
|
||||
}
|
||||
buffer_data[0].is_there_ready_buffer->general_timed_lock(&dummy);
|
||||
}
|
||||
}
|
||||
|
||||
static void ds_3ds_start_thread(std::thread* thread_ptr, bool* usb_thread_run, usb_ds_3ds_general_data* buffer_data) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
*usb_thread_run = true;
|
||||
*thread_ptr = std::thread(ds_3ds_usb_thread_function, usb_thread_run, buffer_data);
|
||||
}
|
||||
|
||||
static void ds_3ds_close_thread(std::thread* thread_ptr, bool* usb_thread_run, usb_ds_3ds_general_data* buffer_data) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
*usb_thread_run = false;
|
||||
buffer_data[0].is_there_ready_buffer->specific_unlock(0);
|
||||
thread_ptr->join();
|
||||
}
|
||||
|
||||
// Read vendor request from control endpoint. Returns bytes transferred (<0 = libusb error)
|
||||
static int vend_in(libusb_device_handle *handle, const usb_device* usb_device_desc, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength, uint8_t *buf) {
|
||||
return libusb_control_transfer(handle, ((uint8_t)LIBUSB_REQUEST_TYPE_VENDOR | (uint8_t)LIBUSB_ENDPOINT_IN), bRequest, wValue, wIndex, buf, wLength, usb_device_desc->control_timeout);
|
||||
|
|
@ -278,9 +211,10 @@ static uint64_t get_capture_size(const usb_device* usb_device_desc, bool enabled
|
|||
return sizeof(USB3DSCaptureReceived) - EXTRA_DATA_BUFFER_USB_SIZE;
|
||||
}
|
||||
|
||||
static usb_capture_status capture_read_oldds_3ds(usb_ds_3ds_general_data* chosen_buffer) {
|
||||
CaptureData* capture_data = chosen_buffer->capture_data;
|
||||
CaptureReceived* data_buffer = &chosen_buffer->capture_buf;
|
||||
static usb_capture_status capture_read_oldds_3ds(CaptureData* capture_data, size_t *read_amount) {
|
||||
*read_amount = 0;
|
||||
CaptureDataSingleBuffer* full_data_buf = capture_data->data_buffers.GetWriterBuffer(0);
|
||||
CaptureReceived* data_buffer = &full_data_buf->capture_buf;
|
||||
libusb_device_handle* handle = (libusb_device_handle*)capture_data->handle;
|
||||
const usb_device* usb_device_desc = get_usb_device_desc(capture_data);
|
||||
const bool enabled_3d = capture_data->status.enabled_3d;
|
||||
|
|
@ -332,73 +266,49 @@ static usb_capture_status capture_read_oldds_3ds(usb_ds_3ds_general_data* chosen
|
|||
#endif
|
||||
}
|
||||
|
||||
chosen_buffer->read_amount = bytesIn;
|
||||
*read_amount = bytesIn;
|
||||
return USB_CAPTURE_SUCCESS;
|
||||
}
|
||||
|
||||
static void process_usb_capture_result(usb_capture_status result, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, bool* done, usb_ds_3ds_general_data* chosen_buffer) {
|
||||
static void process_usb_capture_result(usb_capture_status result, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, bool* done, CaptureData* capture_data, size_t read_amount) {
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - (*clock_start);
|
||||
bool wrote_to_buffer = false;
|
||||
|
||||
switch(result) {
|
||||
case USB_CAPTURE_SKIP:
|
||||
/*
|
||||
if(diff.count() >= CAPTURE_SKIP_TIMEOUT_SECONDS) {
|
||||
capture_error_print(true, chosen_buffer->capture_data, "Disconnected: Too long since last read");
|
||||
capture_error_print(true, capture_data, "Disconnected: Too long since last read");
|
||||
done = true;
|
||||
}
|
||||
*/
|
||||
break;
|
||||
case USB_CAPTURE_PIPE_ERROR:
|
||||
capture_error_print(true, chosen_buffer->capture_data, "Disconnected: Pipe error");
|
||||
capture_error_print(true, capture_data, "Disconnected: Pipe error");
|
||||
*done = true;
|
||||
break;
|
||||
case USB_CAPTURE_FRAMEINFO_ERROR:
|
||||
capture_error_print(true, chosen_buffer->capture_data, "Disconnected: Frameinfo error");
|
||||
capture_error_print(true, capture_data, "Disconnected: Frameinfo error");
|
||||
*done = true;
|
||||
break;
|
||||
case USB_CAPTURE_SUCCESS:
|
||||
*clock_start = curr_time;
|
||||
chosen_buffer->time_in = diff.count();
|
||||
chosen_buffer->index = (*chosen_buffer->last_index) + 1;
|
||||
chosen_buffer->is_buffer_usage_done->specific_try_lock(chosen_buffer->real_index);
|
||||
chosen_buffer->in_use = true;
|
||||
(*chosen_buffer->last_index) += 1;
|
||||
chosen_buffer->is_there_ready_buffer->specific_unlock(chosen_buffer->real_index);
|
||||
wrote_to_buffer = true;
|
||||
if(capture_data->status.cooldown_curr_in)
|
||||
capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1;
|
||||
capture_data->data_buffers.WriteToBuffer(NULL, read_amount, diff.count(), &capture_data->status.device, 0);
|
||||
capture_data->status.video_wait.unlock();
|
||||
capture_data->status.audio_wait.unlock();
|
||||
break;
|
||||
default:
|
||||
capture_error_print(true, chosen_buffer->capture_data, "Disconnected: Error");
|
||||
capture_error_print(true, capture_data, "Disconnected: Error");
|
||||
*done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static usb_ds_3ds_general_data* get_free_buffer(usb_ds_3ds_general_data* buffer_data) {
|
||||
usb_ds_3ds_general_data* out_data = NULL;
|
||||
int dummy = 0;
|
||||
while(!out_data) {
|
||||
for(int i = 0; i < NUM_DS_3DS_CONCURRENT_DATA_BUFFERS; i++) {
|
||||
if(!buffer_data[i].in_use) {
|
||||
buffer_data[i].is_there_ready_buffer->specific_try_lock(i);
|
||||
out_data = &buffer_data[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!out_data)
|
||||
buffer_data[0].is_buffer_usage_done->general_timed_lock(&dummy);
|
||||
}
|
||||
return out_data;
|
||||
}
|
||||
|
||||
static void wait_all_free_buffer(usb_ds_3ds_general_data* buffer_data) {
|
||||
for(int i = 0; i < NUM_DS_3DS_CONCURRENT_DATA_BUFFERS; i++)
|
||||
buffer_data[i].index = (*buffer_data[0].last_index) - 1;
|
||||
for(int i = 0; i < NUM_DS_3DS_CONCURRENT_DATA_BUFFERS; i++) {
|
||||
while(buffer_data[i].in_use) {
|
||||
buffer_data[i].is_there_ready_buffer->specific_unlock(i);
|
||||
buffer_data[i].is_buffer_usage_done->specific_timed_lock(i);
|
||||
}
|
||||
}
|
||||
if(!wrote_to_buffer)
|
||||
capture_data->data_buffers.ReleaseWriterBuffer(0, false);
|
||||
}
|
||||
|
||||
void list_devices_usb_ds_3ds(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list) {
|
||||
|
|
@ -477,38 +387,20 @@ void usb_capture_main_loop(CaptureData* capture_data) {
|
|||
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> clock_start = std::chrono::high_resolution_clock::now();
|
||||
bool done = false;
|
||||
usb_ds_3ds_general_data* general_data = new usb_ds_3ds_general_data[NUM_DS_3DS_CONCURRENT_DATA_BUFFERS];
|
||||
SharedConsumerMutex is_there_ready_buffer(NUM_DS_3DS_CONCURRENT_DATA_BUFFERS);
|
||||
SharedConsumerMutex is_buffer_usage_done(NUM_DS_3DS_CONCURRENT_DATA_BUFFERS);
|
||||
uint32_t last_index = -1;
|
||||
for(int i = 0; i < NUM_DS_3DS_CONCURRENT_DATA_BUFFERS; i++) {
|
||||
general_data[i].is_there_ready_buffer = &is_there_ready_buffer;
|
||||
general_data[i].is_buffer_usage_done = &is_buffer_usage_done;
|
||||
general_data[i].last_index = &last_index;
|
||||
general_data[i].capture_data = capture_data;
|
||||
general_data[i].in_use = false;
|
||||
general_data[i].real_index = i;
|
||||
}
|
||||
bool usb_thread_run;
|
||||
std::thread processing_thread;
|
||||
ds_3ds_start_thread(&processing_thread, &usb_thread_run, general_data);
|
||||
size_t read_amount = 0;
|
||||
|
||||
usb_ds_3ds_general_data* chosen_buffer = get_free_buffer(general_data);
|
||||
while((!done) && capture_data->status.connected && capture_data->status.running) {
|
||||
usb_capture_status result = capture_read_oldds_3ds(chosen_buffer);
|
||||
usb_capture_status result = capture_read_oldds_3ds(capture_data, &read_amount);
|
||||
|
||||
process_usb_capture_result(result, &clock_start, &done, chosen_buffer);
|
||||
if(!done)
|
||||
chosen_buffer = get_free_buffer(general_data);
|
||||
process_usb_capture_result(result, &clock_start, &done, capture_data, read_amount);
|
||||
}
|
||||
wait_all_free_buffer(general_data);
|
||||
ds_3ds_close_thread(&processing_thread, &usb_thread_run, general_data);
|
||||
delete []general_data;
|
||||
}
|
||||
|
||||
void usb_capture_cleanup(CaptureData* capture_data) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
|
||||
capture_data->data_buffers.ReleaseWriterBuffer(0, false);
|
||||
const usb_device* usb_device_desc = get_usb_device_desc(capture_data);
|
||||
capture_end((libusb_device_handle*)capture_data->handle, usb_device_desc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@ bool Audio::onGetData(sf::SoundStream::Chunk &data) {
|
|||
}
|
||||
loaded_samples = samples.size();
|
||||
if((loaded_samples <= 0) && this->hasTooMuchTimeElapsedInside()) {
|
||||
// This is needed by MacOS...
|
||||
// But it also causes some trailing noise when
|
||||
// closing the lid on the devices.
|
||||
inside_onGetData = false;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -577,10 +577,11 @@ static int mainVideoOutputCall(AudioData* audio_data, CaptureData* capture_data,
|
|||
if(no_data_consecutive > NO_DATA_CONSECUTIVE_THRESHOLD)
|
||||
no_data_consecutive = NO_DATA_CONSECUTIVE_THRESHOLD;
|
||||
capture_data->status.video_wait.update_time_multiplier(get_time_multiplier(capture_data, no_data_consecutive >= NO_DATA_CONSECUTIVE_THRESHOLD));
|
||||
|
||||
bool timed_out = !capture_data->status.video_wait.timed_lock();
|
||||
|
||||
bool data_processed = false;
|
||||
CaptureDataSingleBuffer* data_buffer = capture_data->data_buffers.GetReaderBuffer(CAPTURE_READER_VIDEO);
|
||||
|
||||
if(data_buffer != NULL) {
|
||||
last_frame_time = data_buffer->time_in_buf;
|
||||
if(data_buffer->read >= get_video_in_size(capture_data)) {
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ static void usb_is_device_convertVideoToOutput(CaptureReceived *p_in, VideoOutpu
|
|||
}
|
||||
|
||||
bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status) {
|
||||
CaptureReceived *p_in = &data_buffer->capture_buf;
|
||||
CaptureReceived* p_in = (CaptureReceived*)(((uint8_t*)&data_buffer->capture_buf) + data_buffer->unused_offset);
|
||||
bool converted = false;
|
||||
CaptureDevice* chosen_device = &status->device;
|
||||
#ifdef USE_FTD3
|
||||
|
|
@ -310,7 +310,7 @@ bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, Capt
|
|||
bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status) {
|
||||
if(!status->device.has_audio)
|
||||
return true;
|
||||
CaptureReceived *p_in = &data_buffer->capture_buf;
|
||||
CaptureReceived* p_in = (CaptureReceived*)(((uint8_t*)&data_buffer->capture_buf) + data_buffer->unused_offset);
|
||||
uint8_t* base_ptr = NULL;
|
||||
#ifdef USE_FTD3
|
||||
if(status->device.cc_type == CAPTURE_CONN_FTD3) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user