862 lines
26 KiB
C++
862 lines
26 KiB
C++
|
|
#include "ANSFilePlayer.h"
|
||
|
|
#include "ANSMatRegistry.h"
|
||
|
|
#include "ANSGpuFrameOps.h"
|
||
|
|
#include <memory>
|
||
|
|
#include <cstdint>
|
||
|
|
#include <libswscale/swscale.h>
|
||
|
|
#include <libavutil/imgutils.h>
|
||
|
|
#include <libavutil/frame.h>
|
||
|
|
#include "media_codec.h"
|
||
|
|
static bool ansfileplayerLicenceValid = false;
|
||
|
|
// Global once_flag to protect license checking
|
||
|
|
static std::once_flag ansfileplayerLicenseOnceFlag;
|
||
|
|
namespace ANSCENTER {
|
||
|
|
#define CHECK_CUDA(call) do { \
|
||
|
|
cudaError_t err = call; \
|
||
|
|
if (err != cudaSuccess) { \
|
||
|
|
std::cout<<"CUDA error: " + std::string(cudaGetErrorString(err)); \
|
||
|
|
} \
|
||
|
|
} while (0)
|
||
|
|
#define CHECK_NVJPEG(call) do { \
|
||
|
|
nvjpegStatus_t status = call; \
|
||
|
|
if (status != NVJPEG_STATUS_SUCCESS) { \
|
||
|
|
std::cout <<"nvJPEG error: " + std::to_string(status); \
|
||
|
|
} \
|
||
|
|
} while (0)
|
||
|
|
ANSFILEPLAYER::ANSFILEPLAYER() {
|
||
|
|
_url = "";
|
||
|
|
_imageRotateDeg = 0;
|
||
|
|
_imageWidth = 0;
|
||
|
|
_imageHeight = 0;
|
||
|
|
_pts = 0;
|
||
|
|
_isPlaying = false;
|
||
|
|
_lastJpegImage = "";
|
||
|
|
}
|
||
|
|
ANSFILEPLAYER::~ANSFILEPLAYER() noexcept {
|
||
|
|
try {
|
||
|
|
Destroy();
|
||
|
|
}
|
||
|
|
catch (...) {}
|
||
|
|
}
|
||
|
|
void ANSFILEPLAYER::Destroy() {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
try {
|
||
|
|
_url = "";
|
||
|
|
_imageRotateDeg = 0;
|
||
|
|
_isPlaying = false;
|
||
|
|
_lastJpegImage = "";
|
||
|
|
_pLastFrame.release();
|
||
|
|
if (_playerClient) {
|
||
|
|
_playerClient->close();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
_logger.LogError("ANSFILEPLAYER::Destroy. Exception:", e.what(), __FILE__, __LINE__);
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
_logger.LogError("ANSFILEPLAYER::Destroy.", "Unknown exception", __FILE__, __LINE__);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
void ANSFILEPLAYER::CheckLicense() {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
try {
|
||
|
|
_licenseValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(_licenseKey, 1007, "ANSCV");//Default productId=1005
|
||
|
|
}
|
||
|
|
catch (std::exception& e) {
|
||
|
|
this->_logger.LogFatal("ANSFILEPLAYER::CheckLicense. Error:", e.what(), __FILE__, __LINE__);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
bool ANSFILEPLAYER::Init(std::string licenseKey, std::string url) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
_licenseKey = licenseKey;
|
||
|
|
CheckLicense();
|
||
|
|
if (!_licenseValid) {
|
||
|
|
this->_logger.LogError("ANSFILEPLAYER::Init.", "Invalid license", __FILE__, __LINE__);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
//network_init();
|
||
|
|
//sys_buf_init(200);
|
||
|
|
//rtsp_parse_buf_init(200);
|
||
|
|
//http_msg_buf_init(200);
|
||
|
|
_url = url;
|
||
|
|
return Setup();
|
||
|
|
}
|
||
|
|
void ANSFILEPLAYER::SetBBox(cv::Rect bbox) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
_playerClient->setBbox(bbox);
|
||
|
|
}
|
||
|
|
void ANSFILEPLAYER::SetCrop(bool crop) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
_playerClient->setCrop(crop);
|
||
|
|
}
|
||
|
|
bool ANSFILEPLAYER::Setup() {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
return _playerClient->open(_url);
|
||
|
|
}
|
||
|
|
bool ANSFILEPLAYER::Reconnect() {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
_playerClient->close();
|
||
|
|
Setup();
|
||
|
|
return Start();
|
||
|
|
}
|
||
|
|
bool ANSFILEPLAYER::Start() {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
_isPlaying = _playerClient->play();
|
||
|
|
return _isPlaying;
|
||
|
|
}
|
||
|
|
bool ANSFILEPLAYER::Stop() {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
if (_playerClient->pause()) {
|
||
|
|
_isPlaying = false;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
bool ANSFILEPLAYER::IsPaused() {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
return _playerClient->isPaused();
|
||
|
|
}
|
||
|
|
bool ANSFILEPLAYER::IsPlaying() {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
return _playerClient->isPlaying();
|
||
|
|
}
|
||
|
|
bool ANSFILEPLAYER::IsRecording() {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
return _playerClient->isRecording();
|
||
|
|
}
|
||
|
|
std::string ANSFILEPLAYER::GetJpegImage(int& width, int& height, int64_t& pts) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
// If the player is playing, process the frame
|
||
|
|
if (_isPlaying) {
|
||
|
|
// Get a new frame from the player client
|
||
|
|
_lastJpegImage = _playerClient->getJpegImage(width, height, pts);
|
||
|
|
// Update internal state variables
|
||
|
|
_pts = pts;
|
||
|
|
_imageWidth = width;
|
||
|
|
_imageHeight = height;
|
||
|
|
// Return the frame
|
||
|
|
return _lastJpegImage;
|
||
|
|
}
|
||
|
|
// If the player is not playing, return the last known frame
|
||
|
|
else {
|
||
|
|
width = _imageWidth;
|
||
|
|
height = _imageHeight;
|
||
|
|
pts = _pts;
|
||
|
|
return _lastJpegImage;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
cv::Mat ANSFILEPLAYER::GetImage(int& width, int& height, int64_t& pts) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
if (!_isPlaying) {
|
||
|
|
width = _imageWidth;
|
||
|
|
height = _imageHeight;
|
||
|
|
pts = _pts;
|
||
|
|
return _pLastFrame;
|
||
|
|
}
|
||
|
|
|
||
|
|
_pLastFrame.release();
|
||
|
|
int imgW = 0, imgH = 0;
|
||
|
|
_pLastFrame = _playerClient->getImage(imgW, imgH, pts);
|
||
|
|
|
||
|
|
if (_pLastFrame.empty()) {
|
||
|
|
width = _imageWidth;
|
||
|
|
height = _imageHeight;
|
||
|
|
pts = _pts;
|
||
|
|
return _pLastFrame;
|
||
|
|
}
|
||
|
|
|
||
|
|
cv::Mat result = _pLastFrame;
|
||
|
|
|
||
|
|
// Apply rotation if needed
|
||
|
|
if (_imageRotateDeg >= 1 && _imageRotateDeg != 0) {
|
||
|
|
cv::Point2f center(imgW / 2.0f, imgH / 2.0f);
|
||
|
|
cv::Mat rotMat = cv::getRotationMatrix2D(center, _imageRotateDeg, 1.0);
|
||
|
|
cv::Mat rotated;
|
||
|
|
cv::warpAffine(result, rotated, rotMat, result.size(),
|
||
|
|
cv::INTER_CUBIC, cv::BORDER_CONSTANT, cv::Scalar());
|
||
|
|
result = rotated;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Store full-res for inference (before display resize)
|
||
|
|
_inferenceImage = result;
|
||
|
|
|
||
|
|
// Resize for display if display resolution is set
|
||
|
|
if (_displayWidth > 0 && _displayHeight > 0 &&
|
||
|
|
(result.cols != _displayWidth || result.rows != _displayHeight)) {
|
||
|
|
cv::Mat displayResult;
|
||
|
|
cv::resize(result, displayResult, cv::Size(_displayWidth, _displayHeight),
|
||
|
|
0, 0, cv::INTER_LINEAR);
|
||
|
|
result = displayResult;
|
||
|
|
}
|
||
|
|
|
||
|
|
_pts = pts;
|
||
|
|
width = result.cols;
|
||
|
|
height = result.rows;
|
||
|
|
_imageWidth = width;
|
||
|
|
_imageHeight = height;
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
void ANSFILEPLAYER::SetDisplayResolution(int width, int height) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
_displayWidth = width;
|
||
|
|
_displayHeight = height;
|
||
|
|
}
|
||
|
|
cv::Mat ANSFILEPLAYER::GetInferenceImage() {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
return _inferenceImage;
|
||
|
|
}
|
||
|
|
void ANSFILEPLAYER::EnableAudio(bool status) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
_playerClient->enableAudio(status);
|
||
|
|
}
|
||
|
|
void ANSFILEPLAYER::SetAudioVolume(int volume) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
_playerClient->setVolume(volume);
|
||
|
|
}
|
||
|
|
std::string ANSFILEPLAYER::MatToBinaryData(const cv::Mat& image) {
|
||
|
|
std::lock_guard<std::recursive_mutex> lock(_mutex);
|
||
|
|
if (!image.empty()) {
|
||
|
|
if ((image.data != nullptr) && (image.u != nullptr)) {
|
||
|
|
try {
|
||
|
|
std::vector<uchar> imageData;
|
||
|
|
bool success = cv::imencode(".jpg", image, imageData);
|
||
|
|
if (!success) {
|
||
|
|
this->_logger.LogError("ANSFILEPLAYER::MatToBinaryData. Error:", "Failed to encode the image.", __FILE__, __LINE__);
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
std::string binaryData(imageData.begin(), imageData.end());
|
||
|
|
return binaryData;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
this->_logger.LogFatal("ANSFILEPLAYER::MatToBinaryData. Error:", e.what(), __FILE__, __LINE__);
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
this->_logger.LogFatal("ANSFILEPLAYER::MatToBinaryData. Error:", "Caught unknown exception!", __FILE__, __LINE__);
|
||
|
|
return "";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else return "";
|
||
|
|
}
|
||
|
|
else return "";
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
static void VerifyGlobalANSFPLicense(const std::string& licenseKey) {
|
||
|
|
try {
|
||
|
|
ansfileplayerLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1007, "ANSCV");//Default productId=1005
|
||
|
|
if (!ansfileplayerLicenceValid) { // we also support ANSTS license
|
||
|
|
ansfileplayerLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1003, "ANSVIS");//Default productId=1003 (ANSVIS)
|
||
|
|
}
|
||
|
|
if (!ansfileplayerLicenceValid) { // we also support ANSTS license
|
||
|
|
ansfileplayerLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1008, "ANSTS");//Default productId=1008 (ANSTS)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (std::exception& e) {
|
||
|
|
ansfileplayerLicenceValid = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) int CreateANSFilePlayerHandle(ANSCENTER::ANSFILEPLAYER** Handle, const char* licenseKey, const char* url) {
|
||
|
|
if (!Handle || !licenseKey || !url) return -1;
|
||
|
|
try {
|
||
|
|
auto ptr = std::make_unique<ANSCENTER::ANSFILEPLAYER>();
|
||
|
|
bool result = ptr->Init(licenseKey, url);
|
||
|
|
if (result) {
|
||
|
|
*Handle = ptr.release();
|
||
|
|
extern void anscv_unregister_handle(void*);
|
||
|
|
extern void anscv_register_handle(void*, void(*)(void*));
|
||
|
|
anscv_register_handle(*Handle, [](void* p) {
|
||
|
|
auto* h = static_cast<ANSCENTER::ANSFILEPLAYER*>(p);
|
||
|
|
try { h->Stop(); } catch (...) {}
|
||
|
|
try { h->Destroy(); } catch (...) {}
|
||
|
|
try { delete h; } catch (...) {}
|
||
|
|
});
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
*Handle = nullptr;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
catch (...) { return 0; }
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) int ReleaseANSFilePlayerHandle(ANSCENTER::ANSFILEPLAYER** Handle) {
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
||
|
|
try {
|
||
|
|
extern void anscv_unregister_handle(void*);
|
||
|
|
anscv_unregister_handle(*Handle);
|
||
|
|
// Destructor calls Destroy() — no need to call it explicitly (avoids double-destroy)
|
||
|
|
std::unique_ptr<ANSCENTER::ANSFILEPLAYER> ptr(*Handle);
|
||
|
|
*Handle = nullptr;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
if (Handle) *Handle = nullptr;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) int GetFilePlayerStrImage(ANSCENTER::ANSFILEPLAYER** Handle, int& width, int& height, int64_t& timeStamp, std::string& jpegImage) {
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
||
|
|
try {
|
||
|
|
jpegImage = (*Handle)->GetJpegStringImage(width, height, timeStamp);
|
||
|
|
if (!jpegImage.empty()) return 1;
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error getting image data from FilePlayer client: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) int GetFilePlayerImage(ANSCENTER::ANSFILEPLAYER** Handle, int& width, int& height, int64_t& timeStamp, LStrHandle jpegImage) {
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
||
|
|
try {
|
||
|
|
std::string jpegString = (*Handle)->GetJpegStringImage(width, height, timeStamp);
|
||
|
|
int size = jpegString.length();
|
||
|
|
if (size > 0) {
|
||
|
|
MgErr error;
|
||
|
|
// Resize the jpegImage handle to hold the image data
|
||
|
|
error = DSSetHandleSize(jpegImage, sizeof(int32) + size * sizeof(uChar));
|
||
|
|
// Check if resizing the handle was successful
|
||
|
|
if (error == noErr) {
|
||
|
|
// Set the size of the image in the handle
|
||
|
|
(*jpegImage)->cnt = size;
|
||
|
|
// Use memcpy to copy the data from the std::string to the LStrHandle's str buffer
|
||
|
|
memcpy((*jpegImage)->str, jpegString.c_str(), size);
|
||
|
|
// Return success
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
// Return failure if there was an error in resizing the handle
|
||
|
|
std::cerr << "Error resizing jpegImage handle: " << error << std::endl;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
// If the JPEG image string is empty, return failure
|
||
|
|
std::cerr << "No image data retrieved from FilePlayer client." << std::endl;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error getting image data from FilePlayer client: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) int GetFilePlayerCVImage(ANSCENTER::ANSFILEPLAYER** Handle, int& width, int& height, int64_t& timeStamp, cv::Mat** image) {
|
||
|
|
if (!Handle || !(*Handle) || !image) {
|
||
|
|
std::cerr << "Error: Invalid input parameters in GetFilePlayerCVImage." << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
cv::Mat img = (*Handle)->GetImage(width, height, timeStamp);
|
||
|
|
if (img.empty()) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
anscv_mat_replace(image, std::move(img));
|
||
|
|
|
||
|
|
// Attach NV12/CUDA frames to registry for inference zero-copy (same as ANSRTSP/ANSVideoPlayer).
|
||
|
|
// CFilePlayer inherits getNV12Frame()/getCudaHWFrame() from CVideoPlayer.
|
||
|
|
int gpuIdx = (*Handle)->_playerClient->getHWDecodingGpuIndex();
|
||
|
|
AVFrame* cudaHW = (*Handle)->_playerClient->getCudaHWFrame();
|
||
|
|
if (cudaHW) {
|
||
|
|
AVFrame* cpuNV12 = (*Handle)->_playerClient->getNV12Frame();
|
||
|
|
gpu_frame_attach_cuda(*image, cudaHW, gpuIdx, timeStamp, cpuNV12);
|
||
|
|
} else {
|
||
|
|
AVFrame* nv12 = (*Handle)->_playerClient->getNV12Frame();
|
||
|
|
if (nv12) {
|
||
|
|
gpu_frame_attach(*image, nv12, gpuIdx, timeStamp);
|
||
|
|
} else {
|
||
|
|
// CPU-only fallback: attach full-res BGR clone for ANSRTYOLO
|
||
|
|
cv::Mat infImg = (*Handle)->GetInferenceImage();
|
||
|
|
if (!infImg.empty() && infImg.data != (*image)->data) {
|
||
|
|
(*Handle)->_inferenceClonePrev = (*Handle)->_inferenceCloneCurr;
|
||
|
|
(*Handle)->_inferenceCloneCurr = infImg.clone();
|
||
|
|
|
||
|
|
GpuFrameData data{};
|
||
|
|
data.avframe = nullptr;
|
||
|
|
data.yPlane = (*Handle)->_inferenceCloneCurr.data;
|
||
|
|
data.uvPlane = nullptr;
|
||
|
|
data.yLinesize = static_cast<int>((*Handle)->_inferenceCloneCurr.step[0]);
|
||
|
|
data.uvLinesize = 0;
|
||
|
|
data.width = (*Handle)->_inferenceCloneCurr.cols;
|
||
|
|
data.height = (*Handle)->_inferenceCloneCurr.rows;
|
||
|
|
data.pixelFormat = 1000; // ANSCV_PIX_FMT_BGR24
|
||
|
|
data.gpuIndex = -1;
|
||
|
|
data.pts = timeStamp;
|
||
|
|
data.isCudaDevicePtr = false;
|
||
|
|
data.cpuAvframe = nullptr;
|
||
|
|
data.cpuYPlane = nullptr;
|
||
|
|
data.cpuUvPlane = nullptr;
|
||
|
|
data.cpuYLinesize = 0;
|
||
|
|
data.cpuUvLinesize = 0;
|
||
|
|
|
||
|
|
ANSGpuFrameRegistry::instance().attach(*image, std::move(data));
|
||
|
|
auto pending = ANSGpuFrameRegistry::instance().drain_pending();
|
||
|
|
for (void* p : pending) {
|
||
|
|
AVFrame* stale = static_cast<AVFrame*>(p);
|
||
|
|
av_frame_free(&stale);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
catch (const cv::Exception& e) {
|
||
|
|
std::cerr << "OpenCV exception in GetFilePlayerCVImage: " << e.what() << std::endl;
|
||
|
|
return -2;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Exception in GetFilePlayerCVImage: " << e.what() << std::endl;
|
||
|
|
return -2;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
std::cerr << "Unknown exception in GetFilePlayerCVImage" << std::endl;
|
||
|
|
return -2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) int StartFilePlayer(ANSCENTER::ANSFILEPLAYER** Handle) {
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
||
|
|
try {
|
||
|
|
bool result = (*Handle)->Start();
|
||
|
|
if (result) return 1;
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error starting file player: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) int ReconnectFilePlayer(ANSCENTER::ANSFILEPLAYER** Handle) {
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
||
|
|
try {
|
||
|
|
bool result = (*Handle)->Reconnect();
|
||
|
|
if (result) return 1;
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error reconnecting file player: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) int StopFilePlayer(ANSCENTER::ANSFILEPLAYER** Handle) {
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
||
|
|
try {
|
||
|
|
bool result = (*Handle)->Stop();
|
||
|
|
if (result) return 1;
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error stopping file player: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) int IsFilePlayerPaused(ANSCENTER::ANSFILEPLAYER** Handle) {
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
||
|
|
try {
|
||
|
|
bool result = (*Handle)->IsPaused();
|
||
|
|
if (result) return 1;
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error checking if file player is paused: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) int IsFilePlayerRunning(ANSCENTER::ANSFILEPLAYER** Handle) {
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
||
|
|
try {
|
||
|
|
bool result = (*Handle)->IsPlaying();
|
||
|
|
if (result) return 1;
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error checking if file player is running: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) int IsFilePlayerRecording(ANSCENTER::ANSFILEPLAYER** Handle) {
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
||
|
|
try {
|
||
|
|
bool result = (*Handle)->IsRecording();
|
||
|
|
if (result) return 1;
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error checking if file player is recording: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) void SetFilePlayerAudioVolume(ANSCENTER::ANSFILEPLAYER** Handle, int volume)
|
||
|
|
{
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return;
|
||
|
|
try {
|
||
|
|
(*Handle)->SetAudioVolume(volume);
|
||
|
|
}
|
||
|
|
catch (...) { }
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) void EnableFilePlayerAudioVolume(ANSCENTER::ANSFILEPLAYER** Handle, int status)
|
||
|
|
{
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return;
|
||
|
|
try {
|
||
|
|
bool audioStatus = false;
|
||
|
|
if (status == 1)audioStatus = true;
|
||
|
|
(*Handle)->EnableAudio(audioStatus);
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error enabling audio for file player: " << e.what() << std::endl;
|
||
|
|
}
|
||
|
|
catch (...) { }
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) void SetFilePlayerImageRotation(ANSCENTER::ANSFILEPLAYER** Handle, double rotationAngle) {
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return;
|
||
|
|
try {
|
||
|
|
(*Handle)->SetImageRotate(rotationAngle);
|
||
|
|
}
|
||
|
|
catch (...) { }
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) int SetBBoxFilePlayer(ANSCENTER::ANSFILEPLAYER** Handle, int x, int y, int width, int height) {
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
||
|
|
try {
|
||
|
|
cv::Rect bbox(x, y, width, height);
|
||
|
|
(*Handle)->SetBBox(bbox);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error setting bounding box for file player: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
extern "C" __declspec(dllexport) int SetCropFlagFilePlayer(ANSCENTER::ANSFILEPLAYER** Handle, int cropFlag) {
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return -1;
|
||
|
|
try {
|
||
|
|
bool crop = false;
|
||
|
|
if (cropFlag == 1)crop = true;
|
||
|
|
(*Handle)->SetCrop(crop);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error setting crop flag for file player: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// V2 functions: accept uint64_t handleVal by value (LabVIEW-safe)
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) int GetFilePlayerImage_V2(uint64_t handleVal, int& width, int& height, int64_t& timeStamp, LStrHandle jpegImage) {
|
||
|
|
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
|
||
|
|
if (!h) return -1;
|
||
|
|
try {
|
||
|
|
std::string jpegString = h->GetJpegStringImage(width, height, timeStamp);
|
||
|
|
int size = jpegString.length();
|
||
|
|
if (size > 0) {
|
||
|
|
MgErr error;
|
||
|
|
error = DSSetHandleSize(jpegImage, sizeof(int32) + size * sizeof(uChar));
|
||
|
|
if (error == noErr) {
|
||
|
|
(*jpegImage)->cnt = size;
|
||
|
|
memcpy((*jpegImage)->str, jpegString.c_str(), size);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "Error resizing jpegImage handle: " << error << std::endl;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
std::cerr << "No image data retrieved from FilePlayer client." << std::endl;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error getting image data from FilePlayer client: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) int GetFilePlayerCVImage_V2(uint64_t handleVal, int& width, int& height, int64_t& timeStamp, cv::Mat** image) {
|
||
|
|
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
|
||
|
|
if (!h || !image) return -1;
|
||
|
|
try {
|
||
|
|
cv::Mat img = h->GetImage(width, height, timeStamp);
|
||
|
|
if (img.empty()) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
anscv_mat_replace(image, std::move(img));
|
||
|
|
|
||
|
|
// NV12/CUDA registry attach (same as V1)
|
||
|
|
int gpuIdx = h->_playerClient->getHWDecodingGpuIndex();
|
||
|
|
AVFrame* cudaHW = h->_playerClient->getCudaHWFrame();
|
||
|
|
if (cudaHW) {
|
||
|
|
AVFrame* cpuNV12 = h->_playerClient->getNV12Frame();
|
||
|
|
gpu_frame_attach_cuda(*image, cudaHW, gpuIdx, timeStamp, cpuNV12);
|
||
|
|
} else {
|
||
|
|
AVFrame* nv12 = h->_playerClient->getNV12Frame();
|
||
|
|
if (nv12) {
|
||
|
|
gpu_frame_attach(*image, nv12, gpuIdx, timeStamp);
|
||
|
|
} else {
|
||
|
|
cv::Mat infImg = h->GetInferenceImage();
|
||
|
|
if (!infImg.empty() && infImg.data != (*image)->data) {
|
||
|
|
h->_inferenceClonePrev = h->_inferenceCloneCurr;
|
||
|
|
h->_inferenceCloneCurr = infImg.clone();
|
||
|
|
|
||
|
|
GpuFrameData data{};
|
||
|
|
data.avframe = nullptr;
|
||
|
|
data.yPlane = h->_inferenceCloneCurr.data;
|
||
|
|
data.uvPlane = nullptr;
|
||
|
|
data.yLinesize = static_cast<int>(h->_inferenceCloneCurr.step[0]);
|
||
|
|
data.uvLinesize = 0;
|
||
|
|
data.width = h->_inferenceCloneCurr.cols;
|
||
|
|
data.height = h->_inferenceCloneCurr.rows;
|
||
|
|
data.pixelFormat = 1000;
|
||
|
|
data.gpuIndex = -1;
|
||
|
|
data.pts = timeStamp;
|
||
|
|
data.isCudaDevicePtr = false;
|
||
|
|
data.cpuAvframe = nullptr;
|
||
|
|
data.cpuYPlane = nullptr;
|
||
|
|
data.cpuUvPlane = nullptr;
|
||
|
|
data.cpuYLinesize = 0;
|
||
|
|
data.cpuUvLinesize = 0;
|
||
|
|
|
||
|
|
ANSGpuFrameRegistry::instance().attach(*image, std::move(data));
|
||
|
|
auto pending = ANSGpuFrameRegistry::instance().drain_pending();
|
||
|
|
for (void* p : pending) {
|
||
|
|
AVFrame* stale = static_cast<AVFrame*>(p);
|
||
|
|
av_frame_free(&stale);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
catch (const cv::Exception& e) {
|
||
|
|
std::cerr << "OpenCV exception in GetFilePlayerCVImage_V2: " << e.what() << std::endl;
|
||
|
|
return -2;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Exception in GetFilePlayerCVImage_V2: " << e.what() << std::endl;
|
||
|
|
return -2;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
std::cerr << "Unknown exception in GetFilePlayerCVImage_V2" << std::endl;
|
||
|
|
return -2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) int StartFilePlayer_V2(uint64_t handleVal) {
|
||
|
|
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
|
||
|
|
if (!h) return -1;
|
||
|
|
try {
|
||
|
|
bool result = h->Start();
|
||
|
|
if (result) return 1;
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error starting file player: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) int ReconnectFilePlayer_V2(uint64_t handleVal) {
|
||
|
|
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
|
||
|
|
if (!h) return -1;
|
||
|
|
try {
|
||
|
|
bool result = h->Reconnect();
|
||
|
|
if (result) return 1;
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error reconnecting file player: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) int StopFilePlayer_V2(uint64_t handleVal) {
|
||
|
|
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
|
||
|
|
if (!h) return -1;
|
||
|
|
try {
|
||
|
|
bool result = h->Stop();
|
||
|
|
if (result) return 1;
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error stopping file player: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) int IsFilePlayerPaused_V2(uint64_t handleVal) {
|
||
|
|
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
|
||
|
|
if (!h) return -1;
|
||
|
|
try {
|
||
|
|
bool result = h->IsPaused();
|
||
|
|
if (result) return 1;
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error checking if file player is paused: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) int IsFilePlayerRunning_V2(uint64_t handleVal) {
|
||
|
|
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
|
||
|
|
if (!h) return -1;
|
||
|
|
try {
|
||
|
|
bool result = h->IsPlaying();
|
||
|
|
if (result) return 1;
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error checking if file player is running: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) int IsFilePlayerRecording_V2(uint64_t handleVal) {
|
||
|
|
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
|
||
|
|
if (!h) return -1;
|
||
|
|
try {
|
||
|
|
bool result = h->IsRecording();
|
||
|
|
if (result) return 1;
|
||
|
|
else return 0;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error checking if file player is recording: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) void SetFilePlayerAudioVolume_V2(uint64_t handleVal, int volume) {
|
||
|
|
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
|
||
|
|
if (!h) return;
|
||
|
|
try {
|
||
|
|
h->SetAudioVolume(volume);
|
||
|
|
}
|
||
|
|
catch (...) { }
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) void EnableFilePlayerAudioVolume_V2(uint64_t handleVal, int status) {
|
||
|
|
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
|
||
|
|
if (!h) return;
|
||
|
|
try {
|
||
|
|
bool audioStatus = false;
|
||
|
|
if (status == 1) audioStatus = true;
|
||
|
|
h->EnableAudio(audioStatus);
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error enabling audio for file player: " << e.what() << std::endl;
|
||
|
|
}
|
||
|
|
catch (...) { }
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) void SetFilePlayerImageRotation_V2(uint64_t handleVal, double rotationAngle) {
|
||
|
|
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
|
||
|
|
if (!h) return;
|
||
|
|
try {
|
||
|
|
h->SetImageRotate(rotationAngle);
|
||
|
|
}
|
||
|
|
catch (...) { }
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) int SetBBoxFilePlayer_V2(uint64_t handleVal, int x, int y, int width, int height) {
|
||
|
|
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
|
||
|
|
if (!h) return -1;
|
||
|
|
try {
|
||
|
|
cv::Rect bbox(x, y, width, height);
|
||
|
|
h->SetBBox(bbox);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error setting bounding box for file player: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) int SetCropFlagFilePlayer_V2(uint64_t handleVal, int cropFlag) {
|
||
|
|
auto* h = reinterpret_cast<ANSCENTER::ANSFILEPLAYER*>(handleVal);
|
||
|
|
if (!h) return -1;
|
||
|
|
try {
|
||
|
|
bool crop = false;
|
||
|
|
if (cropFlag == 1) crop = true;
|
||
|
|
h->SetCrop(crop);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
catch (const std::exception& e) {
|
||
|
|
std::cerr << "Error setting crop flag for file player: " << e.what() << std::endl;
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
catch (...) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
extern "C" __declspec(dllexport) void SetFilePlayerDisplayResolution(ANSCENTER::ANSFILEPLAYER** Handle, int width, int height) {
|
||
|
|
if (Handle == nullptr || *Handle == nullptr) return;
|
||
|
|
try {
|
||
|
|
(*Handle)->SetDisplayResolution(width, height);
|
||
|
|
} catch (...) { }
|
||
|
|
}
|