#define _CRTDBG_MAP_ALLOC
#include <iostream>
#include "ANSRTSP.h"
#include "ANSFilePlayer.h"
#include "ANSVideoPlayer.h"
#include "ANSWEBCAM.h"
#include "ReadBarcode.h"
#include <opencv2/imgproc.hpp> // Include this header for boundingRect
#include "ANSOpenCV.h"
#include <crtdbg.h>
#include <turbojpeg.h>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>

using namespace ANSCENTER;
using namespace cv;
using namespace std;
cv::Mat JpegStringToMat(const std::string& jpegStr) {
    if (jpegStr.length() > 10) {
        try {
            // Convert the string to a vector of bytes
            std::vector<uchar> jpegData(jpegStr.begin(), jpegStr.end());
            // Decode the JPEG data into a cv::Mat
            cv::Mat image = cv::imdecode(jpegData, cv::IMREAD_COLOR);
            return image;
        }
        catch (std::exception& e)
        {
            cv::Mat emptyImage;
            std::cout << "ANSGStreamerReader::JpegStringToMat. Error:" << e.what();
            return emptyImage;
        }
        catch (...) {
            // Catch any other exceptions that were not caught by previous catch blocks
            cv::Mat emptyImage;
            std::cout << "ANSGStreamerReader::JpegStringToMat. Unknown error";
            return emptyImage;
        }
    }
    else {
        cv::Mat emptyImage;
        return emptyImage;
    }
}
int VideoTestClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    ANSVIDEOPLAYER* filePlayerClient;
    std::string testVideoFile = "C:\\Programs\\DemoAssets\\Videos\\FireNSmoke\\SimFire.mp4";
    CreateANSVideoPlayerHandle(&filePlayerClient, "", testVideoFile.c_str());

    StartVideoPlayer(&filePlayerClient);
    cv::namedWindow("Image", cv::WINDOW_NORMAL);  // Create a resizable window.
    cv::resizeWindow("Image", 1920, 1080);  // Set initial size of the window.
    std::string jpegImage;
    int index = 0;
    while (true) {
        index++;
        GetVideoPlayerStrImage(&filePlayerClient, width, height, pts, jpegImage);
        if (jpegImage.empty()) {
            sleep(1);
            continue;  // Skip the rest of the loop if image is empty
        }
        cv::Mat image = JpegStringToMat(jpegImage);
        cv::Mat resizedImage;
        cv::resize(image, resizedImage, cv::Size(width, height));
        cv::imshow("Image", resizedImage);  // Show the resized image inside the window.
        if (cv::waitKey(30) == 27) {
            break;
        }
    }
    cv::destroyAllWindows();  // Destroy all OpenCV windows
    StopVideoPlayer(&filePlayerClient);
    ReleaseANSVideoPlayerHandle(&filePlayerClient);
    return 0;

}

int FilePlayerTestClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    ANSFILEPLAYER_CV* filePlayerClient;
    std::string testVideoFile =  "C:\\Programs\\DemoAssets\\Videos\\FireNSmoke\\ANSFireFull.mp4";
    CreateANSFilePlayerHandle(&filePlayerClient, "", testVideoFile.c_str());

    StartFilePlayer(&filePlayerClient);
    cv::namedWindow("Image", cv::WINDOW_NORMAL);  // Create a resizable window.
    cv::resizeWindow("Image", 1920, 1080);  // Set initial size of the window.
    SetFilePlayerImageRotation(&filePlayerClient, 0);// Rotate 90
    std::string jpegImage;
    int index = 0;
    while (true) {
        index++;
		std::cout << "Index=" << index << std::endl;
        if ((index == 20) || (index == 80) || (index == 120))  StopFilePlayer(&filePlayerClient);
        if ((index == 40) || (index == 100) || (index == 150)) StartFilePlayer(&filePlayerClient);
       // if (index > 200) break;
        GetFilePlayerStrImage(&filePlayerClient, width, height, pts, jpegImage);
        if (jpegImage.empty()) {
            sleep(1);
            continue;  // Skip the rest of the loop if image is empty
        }
        cv::Mat image = JpegStringToMat(jpegImage);
        cv::Mat resizedImage;
        cv::resize(image, resizedImage, cv::Size(width, height));
        cv::imshow("Image", resizedImage);  // Show the resized image inside the window.
        //std::cout << "Size: " << width << "x" << height << ". Timestamp: " << pts << std::endl;
        if (cv::waitKey(30) == 27) {
            break;
        }
    }
    cv::destroyAllWindows();  // Destroy all OpenCV windows
    StopFilePlayer(&filePlayerClient);
    ReleaseANSFilePlayerHandle(&filePlayerClient);
    return 0;

}
int FilePlayerDoubleStartTestClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    ANSFILEPLAYER_CV* filePlayerClient;
    std::string testVideoFile = "C:\\Programs\\Silversea\\PeopleCountCam.mp4";
    
    // "C:\\Programs\\Documentation\\Video\\BM\\OriginalRes.mp4";// "C:\\Programs\\LPRVideo\\test_1.mp4";
    CreateANSFilePlayerHandle(&filePlayerClient, "", testVideoFile.c_str());
    StartFilePlayer(&filePlayerClient);
    StopFilePlayer(&filePlayerClient);
    StartFilePlayer(&filePlayerClient);
    StopFilePlayer(&filePlayerClient);
    ReleaseANSFilePlayerHandle(&filePlayerClient);
    return 0;
}
int WebcamPlayerTestClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    std::vector<std::string> cameraNames;
    ANSWEBCAMPlayer* filePlayerClient;
    std::string cameraName;
    ScanStrANSWebcamPlayer(cameraNames);
    if ((!cameraNames.empty()) && (cameraNames.size() > 0)) {
        for (int i = 0; i < cameraNames.size(); i++) {
            std::cout << "Camera name:" << cameraNames.at(i) << std::endl;
        }
    }
    cameraName = "Integrated Camera";// "AIRHUG 02";"Intel Virtual Camera";// 

    CreateANSWebcamPlayerHandle(&filePlayerClient, "", cameraName.c_str());
    SetWebcamImageRotation(&filePlayerClient, 0);
    StartWebcamPlayer(&filePlayerClient);
    cv::namedWindow("Image", cv::WINDOW_NORMAL);  // Create a resizable window.
    cv::resizeWindow("Image", 1920, 1080);  // Set initial size of the window.
    std::string jpegImage;
    int index = 0;
    while (true) {
		std::cout << "Index=" << index << std::endl;
        index++;
        if ((index == 10) || (index == 80) || (index == 120))  StopWebcamPlayer(&filePlayerClient); //SetCropFlagFilePlayer(&filePlayerClient, 0);// 
        if ((index == 20) || (index == 100) || (index == 150))  StartWebcamPlayer(&filePlayerClient);//SetCropFlagFilePlayer(&filePlayerClient, 1);
        if (index > 200) break;
        GetWebcamStrImage(&filePlayerClient, width, height, pts, jpegImage);
        cv::Mat image = JpegStringToMat(jpegImage);
        if (jpegImage.empty()) {
            continue;  // Skip the rest of the loop if image is empty
        }
        /*
        auto start = std::chrono::system_clock::now();
		StartWebcamPlayer(&filePlayerClient);
        auto end1 = std::chrono::system_clock::now();
        
        GetWebcamStrImage(&filePlayerClient, width, height, pts, jpegImage);
        cv::Mat image = JpegStringToMat(jpegImage);
        auto end2 = std::chrono::system_clock::now();

        StopWebcamPlayer(&filePlayerClient);
        auto end3 = std::chrono::system_clock::now();

        auto elapsed1 = std::chrono::duration_cast<std::chrono::milliseconds>(end1 - start);
        std::cout << "Time to start camera:" << elapsed1.count() << "ms" << std::endl;
        auto elapsed2 = std::chrono::duration_cast<std::chrono::milliseconds>(end2 - end1);
        std::cout << "Time to get image:" << elapsed2.count() << "ms" << std::endl;
        auto elapsed3 = std::chrono::duration_cast<std::chrono::milliseconds>(end3 - end2);
        std::cout << "Time to stop camera:" << elapsed3.count() << "ms" << std::endl;*/
        cv::Mat resizedImage;
        cv::resize(image, resizedImage, cv::Size(width, height));
        cv::imshow("Image", resizedImage);  // Show the resized image inside the window.
       // std::cout << "Size: " << width << "x" << height << ". Timestamp: " << pts << std::endl;
        if (cv::waitKey(30) == 27) {
            break;
        }
    }
    cv::destroyAllWindows();  // Destroy all OpenCV windows
    StopWebcamPlayer(&filePlayerClient);
    ReleaseANSWebcamPlayerHandle(&filePlayerClient);
    return 0;

}
int WebcamPlayerDoubleTestClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    std::vector<std::string> cameraNames;
    ANSWEBCAMPlayer* filePlayerClient;
    std::string cameraName;
    ScanStrANSWebcamPlayer(cameraNames);
    if ((!cameraNames.empty()) && (cameraNames.size() > 0)) {
        for (int i = 0; i < cameraNames.size(); i++) {
            std::cout << "Camera name:" << cameraNames.at(i) << std::endl;
        }
        cameraName = cameraNames.at(0);
    }
    CreateANSWebcamPlayerHandle(&filePlayerClient, "", cameraName.c_str());
    StartWebcamPlayer(&filePlayerClient);
    StopWebcamPlayer(&filePlayerClient);
    StartWebcamPlayer(&filePlayerClient);
    StopWebcamPlayer(&filePlayerClient);
    StartWebcamPlayer(&filePlayerClient);
    StartWebcamPlayer(&filePlayerClient);
    StopWebcamPlayer(&filePlayerClient);
    StopWebcamPlayer(&filePlayerClient);

    StartWebcamPlayer(&filePlayerClient);
    cv::namedWindow("Image", cv::WINDOW_NORMAL);  // Create a resizable window.
    cv::resizeWindow("Image", 1920, 1080);  // Set initial size of the window.
    std::string jpegImage;
    int index = 0;
    while (true) {
        index++;
        if((index ==200)||(index==800)||(index==1200))    StopWebcamPlayer(&filePlayerClient);
        if((index == 400)||(index==1000)||(index==1500))   StartWebcamPlayer(&filePlayerClient);
        if (index > 2000) break;
        GetWebcamStrImage(&filePlayerClient, width, height, pts, jpegImage);
        if (jpegImage.empty()) {
            continue;  // Skip the rest of the loop if image is empty
        }
        cv::Mat image = JpegStringToMat(jpegImage);
        cv::Mat resizedImage;
        cv::resize(image, resizedImage, cv::Size(width, height));
        cv::imshow("Image", resizedImage);  // Show the resized image inside the window.
        std::cout << "Size: " << width << "x" << height << ". Timestamp: " << pts << std::endl;
        if (cv::waitKey(30) == 27) {
            break;
        }
    }
    cv::destroyAllWindows();  // Destroy all OpenCV windows
    
    StopWebcamPlayer(&filePlayerClient);
    ReleaseANSWebcamPlayerHandle(&filePlayerClient);
    return 0;

}
void PrintCapabilities(IAMStreamConfig* pConfig)
{
    int iCount = 0, iSize = 0;
    HRESULT hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);

    if (SUCCEEDED(hr) && iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
    {
        for (int iFormat = 0; iFormat < iCount; iFormat++)
        {
            VIDEO_STREAM_CONFIG_CAPS scc;
            AM_MEDIA_TYPE* pmtConfig;
            hr = pConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);

            if (SUCCEEDED(hr))
            {
                if (pmtConfig->formattype == FORMAT_VideoInfo)
                {
                    VIDEOINFOHEADER* pVih = (VIDEOINFOHEADER*)pmtConfig->pbFormat;
                    std::cout << "Resolution: " << pVih->bmiHeader.biWidth << " x " << pVih->bmiHeader.biHeight << std::endl;
                }
                //DeleteMediaType(pmtConfig);
            }
        }
    }
}
void EnumerateDevices()
{
    ICreateDevEnum* pDevEnum = NULL;
    IEnumMoniker* pEnum = NULL;

    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));

    if (SUCCEEDED(hr))
    {
        hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
        if (hr == S_OK)
        {
            IMoniker* pMoniker = NULL;
            while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
            {
                IPropertyBag* pPropBag;
                hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
                if (FAILED(hr))
                {
                    pMoniker->Release();
                    continue;
                }

                VARIANT var;
                VariantInit(&var);

                hr = pPropBag->Read(L"FriendlyName", &var, 0);
                if (SUCCEEDED(hr))
                {
                    std::wcout << var.bstrVal << std::endl;

                    IBaseFilter* pCap = NULL;
                    hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
                    if (SUCCEEDED(hr))
                    {
                        IAMStreamConfig* pConfig = NULL;
                        hr = pCap->QueryInterface(IID_IAMStreamConfig, (void**)&pConfig);
                        if (SUCCEEDED(hr))
                        {
                            PrintCapabilities(pConfig);
                            pConfig->Release();
                        }
                        pCap->Release();
                    }
                }

                VariantClear(&var);
                pPropBag->Release();
                pMoniker->Release();
            }
            pEnum->Release();
        }
        pDevEnum->Release();
    }
}
int WebcamResolutionClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    std::vector<std::string> cameraNames;
	std::string supportedResolution;
    ANSWEBCAMPlayer* filePlayerClient;
    std::string cameraName;
    ScanStrANSWebcamPlayer(cameraNames);
	if ((!cameraNames.empty()) && (cameraNames.size() > 0)) {
		for (int i = 0; i < cameraNames.size(); i++) {
			std::cout << "Camera name:" << cameraNames.at(i) << std::endl;
		}
		cameraName = cameraNames.at(1);
	}
	cameraName = cameraNames.at(1);
	ScanSupportedResolutions(cameraName, cameraNames, supportedResolution);
	std::cout << "Supported resolution:" << supportedResolution << std::endl;
    ReleaseANSWebcamPlayerHandle(&filePlayerClient);
    return 0;
}
int RTSPStressTestClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    ANSRTSPClient* rtspClient;
    for (int i = 0; i < 2; i++) {
		std::cout << "Running the " << i << " time" << std::endl;
        CreateANSRTSPHandle(&rtspClient, "", "", "", "rtsp://admin:admin123@192.168.1.13:554");
        StartRTSP(&rtspClient);
        SetRTSPImageRotation(&rtspClient, 0);
        cv::namedWindow("Image", cv::WINDOW_NORMAL);  // Create a resizable window.
        cv::resizeWindow("Image", 1920, 1080);  // Set initial size of the window.
        std::string jpegImage;
        int index = 0;
        while (true) {
            index++;
            if ((index == 100) || (index == 300) || (index == 500))  StopRTSP(&rtspClient);
            if ((index == 200) || (index == 400) || (index == 600)) StartRTSP(&rtspClient);
            if (index > 10) break;
            GetRTSPStrImage(&rtspClient, width, height, pts, jpegImage);
            if (jpegImage.empty()) {
                sleep(1);
                std::cout << "Empty image" << std::endl;
                continue;  // Skip the rest of the loop if image is empty
            }
            std::cout << "Index=" << index << ". Size: " << width << "x" << height << ". Timestamp: " << pts << std::endl;

            cv::Mat image = JpegStringToMat(jpegImage);
            cv::Mat resizedImage;
            cv::resize(image, resizedImage, cv::Size(width, height));
            cv::imshow("Image", resizedImage);  // Show the resized image inside the window.
            if (cv::waitKey(30) == 27) {
                break;
            }
	
        }
        //cv::destroyAllWindows();  // Destroy all OpenCV windows
        StopRTSP(&rtspClient);
        ReleaseANSRTSPHandle(&rtspClient);
    }
  

    return 0;

}

// TurboJPEG Encoder
std::vector<unsigned char> encodeJpeg(const cv::Mat& img, int quality = 80) {
    tjhandle jpegCompressor = tjInitCompress();
    unsigned char* jpegBuf = nullptr; // Will hold the compressed image data
    unsigned long jpegSize = 0; // Will hold the size of the compressed data

    int width = img.cols;
    int height = img.rows;
    int pixelFormat = TJPF_BGR; // OpenCV uses BGR format

    // Compress the image to JPEG format
    int result = tjCompress2(
        jpegCompressor, img.data, width, 0, height, pixelFormat,
        &jpegBuf, &jpegSize, TJSAMP_420, quality, TJFLAG_FASTDCT // TJSAMP_420 for faster compression
    );

    // Check for compression errors
    if (result < 0) {
        std::cerr << "TurboJPEG compression error: " << tjGetErrorStr() << std::endl;
        tjFree(jpegBuf);
        tjDestroy(jpegCompressor);
        return {}; // Return empty vector on failure
    }

    // Copy the compressed data into a vector
    std::vector<unsigned char> encodedImage(jpegBuf, jpegBuf + jpegSize);

    // Free the TurboJPEG-allocated buffer and destroy the compressor
    tjFree(jpegBuf);
    tjDestroy(jpegCompressor);

    return encodedImage; // Return the JPEG-encoded image data
}

// TurboJPEG Decoder
cv::Mat decodeJpeg(const std::vector<unsigned char>& jpegBuf) {
    tjhandle jpegDecompressor = tjInitDecompress();

    int width, height, jpegSubsamp, jpegColorspace;
    tjDecompressHeader3(jpegDecompressor, jpegBuf.data(), jpegBuf.size(), &width, &height, &jpegSubsamp, &jpegColorspace);

    cv::Mat img(height, width, CV_8UC3); // Assuming output is 3 channels (BGR)

    int pixelFormat = TJPF_BGR; // OpenCV uses BGR format

    int result = tjDecompress2(jpegDecompressor, jpegBuf.data(), jpegBuf.size(),
        img.data, width, 0, height, pixelFormat, TJFLAG_FASTDCT);

    if (result < 0) {
        std::cerr << "TurboJPEG decompression error: " << tjGetErrorStr() << std::endl;
    }

    tjDestroy(jpegDecompressor);

    return img;
}


int FilePlayerOpenCVTestClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    ANSFILEPLAYER_CV* filePlayerClient;
    //std::string testVideoFile = "C:\\Programs\\DemoAssets\\Videos\\ALRP\\3725.mp4";
    std::string testVideoFile = "C:\\Programs\\DemoAssets\\Videos\\SecureAgility\\TFNSW-AT-TCS2811-01_small.mp4";

    cv::namedWindow("Image", cv::WINDOW_NORMAL);  // Create a resizable window.
    cv::resizeWindow("Image", 1920, 1080);  // Set initial size of the window.
    int index = 0;
    cv::VideoCapture capture(testVideoFile);

    while (true) {
        cv::Mat frame;
        if (!capture.read(frame)) // if not success, break loop
        {
            std::cout << "\n Cannot read the video file. please check your video.\n";
            break;
        }

        auto start = std::chrono::system_clock::now();
        std::vector<uchar> imageData;
        bool success = cv::imencode(".jpg", frame, imageData);
		if (!success) {
			std::cout << "Failed to encode the image" << std::endl;
			break;
		}
        std::string jpegImage(imageData.begin(), imageData.end());
        cv::Mat image =  JpegStringToMat(jpegImage);

        auto end = std::chrono::system_clock::now();
        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        std::cout << "Time to decode the image:" << elapsed.count() << "ms" << std::endl;

        cv::Mat resizedImage;
        cv::resize(image, resizedImage, cv::Size(frame.cols, frame.rows));
        cv::imshow("Image", resizedImage);  // Show the resized image inside the window.
        //std::cout << "Size: " << width << "x" << height << ". Timestamp: " << pts << std::endl;
        if (cv::waitKey(30) == 27) {
            break;
        }
    }
    cv::destroyAllWindows();  // Destroy all OpenCV windows
    return 0;

}
int FilePlayerTurboJpegTestClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    ANSFILEPLAYER_CV* filePlayerClient;
    std::string testVideoFile = "C:\\Programs\\DemoAssets\\Videos\\SecureAgility\\TFNSW-AT-TCS2811-01_small.mp4";

    //std::string testVideoFile = "C:\\Programs\\DemoAssets\\Videos\\ALRP\\3725.mp4";
    cv::namedWindow("Image", cv::WINDOW_NORMAL);  // Create a resizable window.
    cv::resizeWindow("Image", 1920, 1080);  // Set initial size of the window.
    int index = 0;
    cv::VideoCapture capture(testVideoFile);

    while (true) {
        cv::Mat frame;
        if (!capture.read(frame)) // if not success, break loop
        {
            std::cout << "\n Cannot read the video file. please check your video.\n";
            break;
        }
        auto start = std::chrono::system_clock::now();
        std::vector<uchar> imageData;
        imageData=encodeJpeg(frame, 80); // Quality set to 80
        std::string jpegImage(imageData.begin(), imageData.end());
        std::vector<uchar> jpegData(jpegImage.begin(), jpegImage.end());
        cv::Mat image = decodeJpeg(jpegData);
        auto end = std::chrono::system_clock::now();
        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        std::cout << "Time to decode the image:" << elapsed.count() << "ms" << std::endl;
        cv::Mat resizedImage;
        cv::resize(image, resizedImage, cv::Size(frame.cols, frame.rows));
        cv::imshow("Image", resizedImage);  // Show the resized image inside the window.
        //std::cout << "Size: " << width << "x" << height << ". Timestamp: " << pts << std::endl;
        if (cv::waitKey(30) == 27) {
            break;
        }
    }
    cv::destroyAllWindows();  // Destroy all OpenCV windows
    return 0;

}
int FilePlayerDriverTestClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    ANSFILEPLAYER_CV* filePlayerClient;
    std::string testVideoFile = "C:\\Programs\\DemoAssets\\Videos\\ALRP\\3725.mp4";
    //std::string testVideoFile = "C:\\Programs\\DemoAssets\\Videos\\classroom.mp4";

    CreateANSFilePlayerHandle(&filePlayerClient, "", testVideoFile.c_str());
    StartFilePlayer(&filePlayerClient);
    cv::namedWindow("Image", cv::WINDOW_NORMAL);  // Create a resizable window.
    cv::resizeWindow("Image", 1920, 1080);  // Set initial size of the window.
    SetFilePlayerImageRotation(&filePlayerClient, 0);// Rotate 90
    SetBBoxFilePlayer(&filePlayerClient, 0, 0, 1920, 1080);
    SetCropFlagFilePlayer(&filePlayerClient, 1);
    std::string jpegImage;
    int index = 0;
    while (true) {
        index++;
        if ((index == 200) || (index == 800) || (index == 1200))  StopFilePlayer(&filePlayerClient); //SetCropFlagFilePlayer(&filePlayerClient, 0);// 
        if ((index == 400) || (index == 1000) || (index == 1500))  StartFilePlayer(&filePlayerClient);//SetCropFlagFilePlayer(&filePlayerClient, 1);
        if (index > 2000) break;
        auto start = std::chrono::system_clock::now();
        GetFilePlayerStrImage(&filePlayerClient, width, height, pts, jpegImage);
        if (jpegImage.empty()) {
            sleep(1);
            continue;  // Skip the rest of the loop if image is empty
        }
        cv::Mat image = JpegStringToMat(jpegImage);
        auto end = std::chrono::system_clock::now();
        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        std::cout << "Time to decode the image:" << elapsed.count() << "ms" << std::endl;
       // std::cout << "Size: " << width << "x" << height << ". Timestamp: " << pts << std::endl;


       /* auto start = std::chrono::system_clock::now();
        StartFilePlayer(&filePlayerClient);
        auto end1 = std::chrono::system_clock::now();

        GetFilePlayerStrImage(&filePlayerClient, width, height, pts, jpegImage);
        cv::Mat image = JpegStringToMat(jpegImage);
        auto end2 = std::chrono::system_clock::now();

        StopFilePlayer(&filePlayerClient);
        auto end3 = std::chrono::system_clock::now();

        auto elapsed1 = std::chrono::duration_cast<std::chrono::milliseconds>(end1 - start);
        std::cout << "Time to start camera:" << elapsed1.count() << "ms" << std::endl;
        auto elapsed2 = std::chrono::duration_cast<std::chrono::milliseconds>(end2 - end1);
        std::cout << "Time to get image:" << elapsed2.count() << "ms" << std::endl;
        auto elapsed3 = std::chrono::duration_cast<std::chrono::milliseconds>(end3 - end2);
        std::cout << "Time to stop camera:" << elapsed3.count() << "ms" << std::endl;*/


        cv::Mat resizedImage;
        cv::resize(image, resizedImage, cv::Size(width, height));
        cv::imshow("Image", resizedImage);  // Show the resized image inside the window.
        if (cv::waitKey(30) == 27) {
            break;
        }
    }
    cv::destroyAllWindows();  // Destroy all OpenCV windows
    StopFilePlayer(&filePlayerClient);
    ReleaseANSFilePlayerHandle(&filePlayerClient);
    return 0;

}
int FilePlayerDriverBigFileTestClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    ANSFILEPLAYER_CV* filePlayerClient;
    std::string testVideoFile = "C:\\Programs\\DemoAssets\\Videos\\SecureAgility\\TFNSW-AT-TCS2811-01.mp4";
    CreateANSFilePlayerHandle(&filePlayerClient, "", testVideoFile.c_str());
    SetBBoxFilePlayer(&filePlayerClient, 0, 0, 300, 300);

    StartFilePlayer(&filePlayerClient);
    cv::namedWindow("Image", cv::WINDOW_NORMAL);  // Create a resizable window.
    //cv::resizeWindow("Image", 1920, 1080);  // Set initial size of the window.
    SetFilePlayerImageRotation(&filePlayerClient, 0);// Rotate 90
    std::string jpegImage;
    int index = 0;
    while (true) {
        index++;
        //if ((index == 200) || (index == 800) || (index == 1200))  StopFilePlayer(&filePlayerClient); //SetCropFlagFilePlayer(&filePlayerClient, 0);// 
        //if ((index == 400) || (index == 1000) || (index == 1500))  StartFilePlayer(&filePlayerClient);//SetCropFlagFilePlayer(&filePlayerClient, 1);
        //if (index > 2000) break;
        auto start = std::chrono::system_clock::now();
        GetFilePlayerStrImage(&filePlayerClient, width, height, pts, jpegImage);
        if (jpegImage.empty()) {
            sleep(1);
            continue;  // Skip the rest of the loop if image is empty
        }
        cv::Mat image = JpegStringToMat(jpegImage);
        auto end = std::chrono::system_clock::now();
        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        //std::cout << "Time to decode the image:" << elapsed.count() << "ms" << std::endl;
        cv::Mat resizedImage;
        cv::resize(image, resizedImage, cv::Size(width, height));
        std::cout << "Size: " << width << "x" << height << ". Timestamp: " << pts << std::endl;

        cv::imshow("Image", resizedImage);  // Show the resized image inside the window.
        if (cv::waitKey(30) == 27) {
            break;
        }
    }
    cv::destroyAllWindows();  // Destroy all OpenCV windows
    StopFilePlayer(&filePlayerClient);
    ReleaseANSFilePlayerHandle(&filePlayerClient);
    return 0;

}
int FilePlayerDriverStressClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    ANSFILEPLAYER_CV* filePlayerClient;
    std::string testVideoFile = "C:\\Programs\\DemoAssets\\Videos\\ALRP\\3725.mp4";
    //std::string testVideoFile = "C:\\Programs\\DemoAssets\\Videos\\classroom.mp4";

    CreateANSFilePlayerHandle(&filePlayerClient, "", testVideoFile.c_str());
    StartFilePlayer(&filePlayerClient);
    cv::namedWindow("Image", cv::WINDOW_NORMAL);  // Create a resizable window.
    cv::resizeWindow("Image", 1920, 1080);  // Set initial size of the window.
    SetFilePlayerImageRotation(&filePlayerClient, 0);// Rotate 90

    std::string jpegImage;
    int index = 0;
    while (true) {
        index++;
        if (index > 10) break;
        auto start = std::chrono::system_clock::now();
        GetFilePlayerStrImage(&filePlayerClient, width, height, pts, jpegImage);
        if (jpegImage.empty()) {
            sleep(1);
            continue;  // Skip the rest of the loop if image is empty
        }
        cv::Mat image = JpegStringToMat(jpegImage);
        auto end = std::chrono::system_clock::now();
        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
        //std::cout << "Time to decode the image:" << elapsed.count() << "ms" << std::endl;
        std::cout << "Size: " << width << "x" << height << ". Timestamp: " << pts << std::endl;
        cv::Mat resizedImage;
        cv::resize(image, resizedImage, cv::Size(width, height));
        cv::imshow("Image", resizedImage);  // Show the resized image inside the window.
        if (cv::waitKey(30) == 27) {
            break;
        }
    }
    cv::destroyAllWindows();  // Destroy all OpenCV windows
    StopFilePlayer(&filePlayerClient);
    ReleaseANSFilePlayerHandle(&filePlayerClient);
    return 0;

}
int RSTPTestClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    ANSRTSPClient* rtspClient;
    //rtspClient.Init("","rtsp://root:abcd1234@118.70.125.152:5656/cam/realmonitor?channel=1&subtype=0");
    //rtspClient.Init("", "rtsp://anscamuser:SonTay2020@anssontay.tplinkdns.com:554/Streaming/Channels/301");  
     //rtspClient.Init("","root", "abcd1234", "rtsp://118.70.125.152:5656/cam/realmonitor?channel=1&subtype=0");
    //rtspClient.Init("", "anscamuser", "SonTay2020", "rtsp://anssontay.tplinkdns.com:554/Streaming/Channels/101");
   // CreateANSRTSPHandle(&rtspClient, "", "", "", "rtsp://root:abcd1234@118.70.125.152:5656/cam/realmonitor?channel=1&subtype=0");
    //int createdObject=CreateANSRTSPHandle(&rtspClient, "", "admin", "Minhanhvu@14695", "rtsp://192.168.0.230:554/Streaming/Channels/101");
    //int createdObject = CreateANSRTSPHandle(&rtspClient, "", "", "", "rtsp://103.147.186.175:8554/9L02DA3PAJF8FF7");
   // int createdObject= CreateANSRTSPHandle(&rtspClient, "", "anscamuser", "SonTay2020", "rtsp://anssontay.tplinkdns.com:554/Streaming/Channels/101");
   // std::cout << "Created object:" << createdObject << std::endl;
    //rtsp://camduongphotrauhoi.ddns.net:559/rtsp/streaming?channel=01&subtype=0
    //rtsp://ad1:admin123@camduongphotrauhoi.ddns.net:555/1/1
    //rtsp://ad1:admin123@cam3thang2.ddns.net:554/1/1
    //rtsp://admin:JA!uV_mx@42.1.117.99:8081/1/1
    //rtsp://admin:JA!uV_mx@42.1.117.99:8085/1/1
    //rtsp://admin:admin123@42.1.117.243:8001/1/1
   //std::string rtspUrl = "rtsp://anscamuser:SonTay2020@anssontay.tplinkdns.com:554/Streaming/Channels/401";// "rtsp://alex:admin123@192.168.1.11:554";
   // std::string rtspUrl =  "rtsp://admin:admin123@192.168.1.17:554";//"rtsp://alex:admin123@192.168.1.11:554";//
    std::string rtspUrl = "rtsp://admin:AnsHome16%&@192.168.1.104:554";//"rtsp://alex:admin123@192.168.1.11:554";//112
   // std::string rtspUrl = "rtsp://admin:admin123@192.168.1.87:554";//"rtsp://alex:admin123@192.168.1.11:554";//
   // std::string rtspUrl = "rtsp://admin:12345678@192.168.0.251:554/profile1";//"rtsp://alex:admin123@192.168.1.11:554";//

    //std::string rtspUrl = "rtsp://admin:Minhanhvu@14695@192.168.0.230:554/Streaming/Channels/101";//"rtsp://alex:admin123@192.168.1.11:554";//
    //std::cout << "RTSP URL:" << rtspUrl << std::endl;

    //std::string rtspUrl = "rtsp://admin:admin123@42.1.117.243:8001/1/1";// "rtsp://admin:admin123@42.1.117.245:8004/1/1";// "rtsp://admin:JA!uV_mx@42.1.117.99:8085/1/1";// "rtsp://admin:JA!uV_mx@42.1.117.99:8081/1/1";

    // Testing
    //std::string rtspUrl = "rtsp://camduongphotrauhoi.ddns.net:559/rtsp/streaming?channel=01&subtype=0";//"rtsp://alex:admin123@192.168.1.11:554";//
    //std::string rtspUrl = "rtsp://ad1:admin123@camduongphotrauhoi.ddns.net:555/1/1";//"rtsp://alex:admin123@192.168.1.11:554";//
    //std::string rtspUrl = "rtsp://ad1:admin123@cam3thang2.ddns.net:554/1/1";
    //std::string rtspUrl = "rtsp://admin:JA!uV_mx@42.1.117.99:8085/1/1";
   // std::string rtspUrl = "rtsp://khachtest:lamson2025@anninhlasuco.dssddns.net:5525/cam/realmonitor?channel=23&subtype=0";

    //std::string rtspUrl = "rtsp://anscamuser:SonTay2020@anssontay.tplinkdns.com:554/Streaming/Channels/401";
    //std::string rtspUrl = "rtsp://root:A@bcd1234@172.28.5.3/axis-media/media.amp?videocodec=h264&camera=1";// "rtsp://admin:JA!uV_mx@42.1.117.99:8081/1/1";
    //std::string rtspUrl = "rtsp://172.28.5.3/axis-media/media.amp?videocodec=h264&camera=1";// "rtsp://admin:JA!uV_mx@42.1.117.99:8081/1/1";

    //std::string rtspUrl = "rtsp://115.79.54.30:1024/Streaming/Channels/302";// "rtsp://admin:JA!uV_mx@42.1.117.99:8081/1/1"
    //CreateANSRTSPHandle(&rtspClient, "", "admin", "Ttgs113pmh", rtspUrl.c_str());

    //std::string rtspUrl = "rtsp://anscamuser:SonTay2020@anssontay.tplinkdns.com:554/Streaming/Channels/401";
    CreateANSRTSPHandle(&rtspClient, "", "", "", rtspUrl.c_str());

    //SetBBoxRTSP(&rtspClient, 0, 0, 1920, 1080);
    //SetCropFlagRTSP(&rtspClient, 1);
    StartRTSP(&rtspClient);
    //SetRTSPImageRotation(&rtspClient,0);
    cv::namedWindow("Image", cv::WINDOW_NORMAL);  // Create a resizable window.
    cv::resizeWindow("Image", 1080, 1920);  // Set initial size of the window.
    std::string jpegImage;
    int index = 0;
    while (true) {
        index++;
		std::cout << "Index=" << index << std::endl;
        if ((index == 200) || (index == 800) || (index == 1200)) { StopRTSP(&rtspClient);  }
        if ((index == 400) || (index == 1000) || (index == 1500)) { StartRTSP(&rtspClient); }
        //if (index > 2000) break;

        //if ((index == 100)) { StopRTSP(&rtspClient); }
        //if ((index == 150) ) { StartRTSP(&rtspClient); }
        ////if (index > 2000) break;

        //if (index > 300) StopRTSP(&rtspClient);
        auto start = std::chrono::system_clock::now();
        GetRTSPStrImage(&rtspClient, width, height, pts, jpegImage);
        auto end1 = std::chrono::system_clock::now();
        auto elapsed1 = std::chrono::duration_cast<std::chrono::milliseconds>(end1 - start);
        if(elapsed1.count()>0)std::cout << "Time to get image:" << elapsed1.count() << "ms" << std::endl;

        if (jpegImage.empty()) {
            sleep(1);
            continue;  // Skip the rest of the loop if image is empty
        }

        //      auto start = std::chrono::system_clock::now();
        //      StartRTSP(&rtspClient);
        //      auto end1 = std::chrono::system_clock::now();
        //      GetRTSPStrImage(&rtspClient, width, height, pts, jpegImage);
        //      if (jpegImage.empty()) {
        //          sleep(1);
              //	std::cout << "Empty image" << std::endl;
        //          continue;  // Skip the rest of the loop if image is empty
        //      }
              //auto end2 = std::chrono::system_clock::now();
        //      StopRTSP(&rtspClient);
              //auto end3 = std::chrono::system_clock::now();
        //      auto elapsed1 = std::chrono::duration_cast<std::chrono::milliseconds>(end1-start);
        //      auto elapsed2 = std::chrono::duration_cast<std::chrono::milliseconds>(end2 - end1);
        //      auto elapsed3 = std::chrono::duration_cast<std::chrono::milliseconds>(end3 - end2);
        //      
        //      std::cout << "Time to start camera:" << elapsed1.count() << "ms" << std::endl;
        //      std::cout << "Time to get image:" << elapsed2.count() << "ms" << std::endl;
        //      std::cout << "Time to get stop:" << elapsed3.count() << "ms" << std::endl;
        //      sleep(1);

        cv::Mat image = JpegStringToMat(jpegImage);
        cv::Mat resizedImage;
        cv::resize(image, resizedImage, cv::Size(width, height));
        cv::imshow("Image", resizedImage);  // Show the resized image inside the window.
        //std::cout << "Index="<<index<<". Size: " << width << "x" << height << ". Timestamp: " << pts << std::endl;
        if (cv::waitKey(30) == 27) {
            std::cout << "Break" << std::endl;
            break;
        }
    }
    cv::destroyAllWindows();  // Destroy all OpenCV windows
    StopRTSP(&rtspClient);
    ReleaseANSRTSPHandle(&rtspClient);
    return 0;

}
int RSTPTestCVClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    ANSRTSPClient* rtspClient;
    //rtsp://anscamuser:SonTay2020@anssontay.tplinkdns.com:554/Streaming/Channels/401
    //rtspClient.Init("","rtsp://root:abcd1234@118.70.125.152:5656/cam/realmonitor?channel=1&subtype=0");
    //rtspClient.Init("", "rtsp://anscamuser:SonTay2020@anssontay.tplinkdns.com:554/Streaming/Channels/301");  
     //rtspClient.Init("","root", "abcd1234", "rtsp://118.70.125.152:5656/cam/realmonitor?channel=1&subtype=0");
    //rtspClient.Init("", "anscamuser", "SonTay2020", "rtsp://anssontay.tplinkdns.com:554/Streaming/Channels/101");
   // CreateANSRTSPHandle(&rtspClient, "", "", "", "rtsp://root:abcd1234@118.70.125.152:5656/cam/realmonitor?channel=1&subtype=0");
    //int createdObject=CreateANSRTSPHandle(&rtspClient, "", "admin", "Minhanhvu@14695", "rtsp://192.168.0.230:554/Streaming/Channels/101");
    //int createdObject = CreateANSRTSPHandle(&rtspClient, "", "", "", "rtsp://103.147.186.175:8554/9L02DA3PAJF8FF7");
   // int createdObject= CreateANSRTSPHandle(&rtspClient, "", "anscamuser", "SonTay2020", "rtsp://anssontay.tplinkdns.com:554/Streaming/Channels/101");
   // std::cout << "Created object:" << createdObject << std::endl;
    //rtsp://camduongphotrauhoi.ddns.net:559/rtsp/streaming?channel=01&subtype=0
    //rtsp://ad1:admin123@camduongphotrauhoi.ddns.net:555/1/1
    //rtsp://ad1:admin123@cam3thang2.ddns.net:554/1/1
    //rtsp://admin:JA!uV_mx@42.1.117.99:8081/1/1
    //rtsp://admin:JA!uV_mx@42.1.117.99:8085/1/1
    //rtsp://admin:admin123@42.1.117.243:8001/1/1
   //std::string rtspUrl = "rtsp://anscamuser:SonTay2020@anssontay.tplinkdns.com:554/Streaming/Channels/401";// "rtsp://alex:admin123@192.168.1.11:554";
   // std::string rtspUrl =  "rtsp://admin:admin123@192.168.1.17:554";//"rtsp://alex:admin123@192.168.1.11:554";//
    //std::string rtspUrl = "rtsp://admin:JA!uV_mx@42.1.117.99:8093/1/1";//"rtsp://alex:admin123@192.168.1.11:554";//

    // std::string rtspUrl = "rtsp://admin:admin123@192.168.1.87:554";//"rtsp://alex:admin123@192.168.1.11:554";//
    // std::string rtspUrl = "rtsp://admin:12345678@192.168.0.251:554/profile1";//"rtsp://alex:admin123@192.168.1.11:554";//

     //std::string rtspUrl = "rtsp://admin:Minhanhvu@14695@192.168.0.230:554/Streaming/Channels/101";//"rtsp://alex:admin123@192.168.1.11:554";//
     //std::cout << "RTSP URL:" << rtspUrl << std::endl;

     //std::string rtspUrl = "rtsp://admin:admin123@42.1.117.243:8001/1/1";// "rtsp://admin:admin123@42.1.117.245:8004/1/1";// "rtsp://admin:JA!uV_mx@42.1.117.99:8085/1/1";// "rtsp://admin:JA!uV_mx@42.1.117.99:8081/1/1";

     // Testing
     //std::string rtspUrl = "rtsp://camduongphotrauhoi.ddns.net:559/rtsp/streaming?channel=01&subtype=0";//"rtsp://alex:admin123@192.168.1.11:554";//
     //std::string rtspUrl = "rtsp://ad1:admin123@camduongphotrauhoi.ddns.net:555/1/1";//"rtsp://alex:admin123@192.168.1.11:554";//
     //std::string rtspUrl = "rtsp://ad1:admin123@cam3thang2.ddns.net:554/1/1";
    // std::string rtspUrl = "rtsp://admin:JA!uV_mx@42.1.117.99:8081/1/1";
    // std::string rtspUrl = "rtsp://admin:JA!uV_mx@42.1.117.99:8085/1/1";
     // std::string rtspUrl = "rtsp://admin:JA!uV_mx@42.1.117.99:8093/1/1";
    // std::string rtspUrl = "rtsp://khachtest:lamson2025@anninhlasuco.dssddns.net:5525/cam/realmonitor?channel=23&subtype=0";
   // std::string rtspUrl = "rtsp://admin:admin123@103.156.0.133:8002/snl/live/1/1";
    // std::string rtspUrl = "rtsp://admin:admin123@192.168.1.23:554";//"rtsp://alex:admin123@192.168.1.11:554";//
    //std::string rtspUrl = "rtsp://anscamuser:SonTay2020@anssontay.tplinkdns.com:554/Streaming/Channels/401";// "rtsp://admin:JA!uV_mx@42.1.117.99:8093/1/1";
    
    std::string rtspUrl = "rtsp://admin:AnsHome16%&@192.168.1.104:554";//"rtsp://alex:admin123@192.168.1.11:554";//112

    CreateANSRTSPHandle(&rtspClient, "", "", "", rtspUrl.c_str());
    //void SetRTSPImageQuality(ANSCENTER::ANSRTSPClient** Handle, int mode)
    SetRTSPImageQuality(&rtspClient,0);
    //SetBBoxRTSP(&rtspClient, 0, 0, 1920, 1080);
    //SetCropFlagRTSP(&rtspClient, 1);
    StartRTSP(&rtspClient);
    //SetRTSPImageRotation(&rtspClient,0);
    cv::namedWindow("Image", cv::WINDOW_NORMAL);  // Create a resizable window.
    cv::resizeWindow("Image", 1920, 1080);  // Set initial size of the window (landscape).
    std::string jpegImage;
    int index = 0;
    while (true) {
        index++;
        std::cout << "Index=" << index << std::endl;
        if ((index == 200) || (index == 800) || (index == 1200)) { StopRTSP(&rtspClient); }
        if ((index == 400) || (index == 1000) || (index == 1500)) { StartRTSP(&rtspClient);  }
        if ((index == 1800) || (index == 2200) || (index == 2500)) { StartRTSP(&rtspClient); }
        if ((index == 2000) || (index == 2300) || (index == 2700)) { StartRTSP(&rtspClient); }

        if (index > 20000) break;
        auto start = std::chrono::system_clock::now();
        cv::Mat* image = nullptr;  // ✅ Use a pointer to hold the allocated image
        GetRTSPCVImage(&rtspClient, width, height, pts,&image);
        auto end1 = std::chrono::system_clock::now();
        auto elapsed1 = std::chrono::duration_cast<std::chrono::milliseconds>(end1 - start);
        if (elapsed1.count() > 0)std::cout << "Time to get image:" << elapsed1.count() << "ms" << std::endl;

        // ✅ Check if the image is valid BEFORE accessing it
        if (!image || image->empty()) {
            ANSCV_ReleaseImage_S(&image);
            std::this_thread::sleep_for(std::chrono::seconds(1));
            continue;  // Skip processing if the image is empty
        }

        // High-quality downscale for display: INTER_LANCZOS4 preserves sharpness and edges
        cv::Mat displayImage;
        if (image->cols > 1920) {
            double scale = 1920.0 / image->cols;
            cv::resize(*image, displayImage, cv::Size(), scale, scale, cv::INTER_LANCZOS4);
        }
        else {
            displayImage = *image;
        }
        cv::imshow("Image", displayImage);

        ANSCV_ReleaseImage_S(&image);
        //std::cout << "Index="<<index<<". Size: " << width << "x" << height << ". Timestamp: " << pts << std::endl;
        if (cv::waitKey(30) == 27) {
            std::cout << "Break" << std::endl;
            break;
        }
    }
    cv::destroyAllWindows();  // Destroy all OpenCV windows
    StopRTSP(&rtspClient);
    ReleaseANSRTSPHandle(&rtspClient);
    return 0;

}
int WebcamVCPlayerTestClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    std::vector<std::string> cameraNames;
    ANSWEBCAMPlayer* filePlayerClient = nullptr;
    std::string cameraName;
    ScanStrANSWebcamPlayer(cameraNames);
    if (cameraNames.empty()) {
        std::cerr << "No webcam devices found!" << std::endl;
        return -1;
    }
    for (size_t i = 0; i < cameraNames.size(); i++) {
        std::cout << "Camera [" << i << "]: " << cameraNames.at(i) << std::endl;
    }
    // Use the first available camera
    cameraName = cameraNames.at(0);
    std::cout << ">>> Using camera: " << cameraName << std::endl;

    int createResult = CreateANSWebcamPlayerWithMaxResoHandle(&filePlayerClient, "", cameraName.c_str());
    std::cout << ">>> CreateANSWebcamPlayerHandle result=" << createResult << ", handle=" << (void*)filePlayerClient << std::endl;
    if (createResult != 1 || !filePlayerClient) {
        std::cerr << "Failed to create webcam handle! Result=" << createResult << std::endl;
        return -1;
    }

    SetWebcamImageRotation(&filePlayerClient, 0);
    int startResult = StartWebcamPlayer(&filePlayerClient);
    std::cout << ">>> StartWebcamPlayer result=" << startResult << std::endl;

    cv::namedWindow("Image", cv::WINDOW_NORMAL);
    cv::resizeWindow("Image", 1920, 1080);
    int index = 0;
    while (true) {
        index++;

        // Stop/Start cycle test:
        // Stop at index 100, 300, 500, 700, 900
        // Start at index 200, 400, 600, 800, 1000
        if (index == 100 || index == 300 || index == 500 || index == 700 || index == 900) {
            std::cout << ">>> [Index=" << index << "] STOPPING webcam" << std::endl;
            int stopRes = StopWebcamPlayer(&filePlayerClient);
            std::cout << ">>> StopWebcamPlayer result=" << stopRes << std::endl;
        }
        if (index == 200 || index == 400 || index == 600 || index == 800 || index == 1000) {
            std::cout << ">>> [Index=" << index << "] STARTING webcam" << std::endl;
            int startRes = StartWebcamPlayer(&filePlayerClient);
            std::cout << ">>> StartWebcamPlayer result=" << startRes << std::endl;
        }
        if (index > 1100) {
            std::cout << ">>> [Index=" << index << "] Test complete, exiting loop" << std::endl;
            break;
        }

        auto start = std::chrono::system_clock::now();
        cv::Mat* image = nullptr;

        int imgResult = GetWebcamCVImage(&filePlayerClient, width, height, pts, &image);
        auto end1 = std::chrono::system_clock::now();
        auto elapsed1 = std::chrono::duration_cast<std::chrono::milliseconds>(end1 - start);

        // Print log around stop/start boundaries and every 50 frames
        bool printLog = (index % 50 == 0) || (index <= 5)
            || (index >= 98 && index <= 103) || (index >= 198 && index <= 203)
            || (index >= 298 && index <= 303) || (index >= 398 && index <= 403)
            || (index >= 498 && index <= 503);
        if (printLog) {
            std::cout << "Index=" << index << ". ImgResult=" << imgResult
                << ". W=" << width << " H=" << height << " PTS=" << pts
                << " Time=" << elapsed1.count() << "ms" << std::endl;
        }

        if (!image || image->empty()) {
            if (printLog) {
                std::cout << "Index=" << index << ". No image (stopped or not ready)" << std::endl;
            }
            ANSCV_ReleaseImage_S(&image);
            std::this_thread::sleep_for(std::chrono::milliseconds(33));
            continue;
        }

        cv::imshow("Image", *image);
        ANSCV_ReleaseImage_S(&image);

        if (cv::waitKey(30) == 27) {
            std::cout << "Break (ESC pressed)" << std::endl;
            break;
        }
    }
    cv::destroyAllWindows();
    StopWebcamPlayer(&filePlayerClient);
    ReleaseANSWebcamPlayerHandle(&filePlayerClient);
    return 0;
}
int FPTestCVClient() {
    int width = 0;
    int height = 0;
    int64_t pts = 0;
    ANSFILEPLAYER_CV* rtspClient;
    std::string testVideoFile = "C:\\Programs\\DemoAssets\\Videos\\ALRP\\3725.mp4";


    CreateANSFilePlayerHandle(&rtspClient, "", testVideoFile.c_str());

    StartFilePlayer(&rtspClient);
    //SetRTSPImageRotation(&rtspClient,0);
    cv::namedWindow("Image", cv::WINDOW_NORMAL);  // Create a resizable window.
    cv::resizeWindow("Image", 1080, 1920);  // Set initial size of the window.
    std::string jpegImage;
    int index = 0;
    while (true) {
        index++;
        //std::cout << "Index=" << index << std::endl;
  //      if ((index == 200) || (index == 800) || (index == 1200)) { StopRTSP(&rtspClient); SetCropFlagRTSP(&rtspClient, 1); }
  //      if ((index == 400) || (index == 1000) || (index == 1500)) { StartRTSP(&rtspClient); SetCropFlagRTSP(&rtspClient, 0); }
  //      if (index > 2000) break;
        auto start = std::chrono::system_clock::now();
        cv::Mat* image = nullptr;  // ✅ Use a pointer to hold the allocated image
        GetFilePlayerCVImage(&rtspClient, width, height, pts, &image);
        auto end1 = std::chrono::system_clock::now();
        auto elapsed1 = std::chrono::duration_cast<std::chrono::milliseconds>(end1 - start);
        if (elapsed1.count() > 0)std::cout << "Time to get image:" << elapsed1.count() << "ms" << std::endl;

        // ✅ Check if the image is valid BEFORE accessing it
        if (!image || image->empty()) {
            ANSCV_ReleaseImage_S(&image);
            std::this_thread::sleep_for(std::chrono::seconds(1));
            continue;  // Skip processing if the image is empty
        }

        //cv::Mat resizedImage;
        //cv::resize(image, resizedImage, cv::Size(width, height));
        cv::imshow("Image", *image);  // Show the resized image inside the window.

        ANSCV_ReleaseImage_S(&image);
        //std::cout << "Index="<<index<<". Size: " << width << "x" << height << ". Timestamp: " << pts << std::endl;
        if (cv::waitKey(30) == 27) {
            std::cout << "Break" << std::endl;
            break;
        }
    }
    cv::destroyAllWindows();  // Destroy all OpenCV windows
    StopFilePlayer(&rtspClient);
    ReleaseANSFilePlayerHandle(&rtspClient);
    return 0;

}
int ImageManagementRefTest() {
    std::string testImageFile = "C:\\Programs\\DemoAssets\\Images\\bus.jpg";
    cv::Mat* sharedImage = nullptr;
    cv::Mat* imageOut = nullptr;
    ANSCV_CreateImageFromFile_S(testImageFile.c_str(), &sharedImage);

    std::thread t1([&]() {
		std::cout << "Thread 1 running:..." << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        ANSCV_ReleaseImage_S(&sharedImage);
        std::cout << "Thread 1 complete:..." << std::endl;

        });

    std::thread t2([&]() {
        std::cout << "Thread 2 running:..." << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(0));
        ANSCV_ReSizeImage_S(&sharedImage, 100, 100);
        std::cout << "Thread 2 complete:..." << std::endl;
        });

    std::thread t3([&]() {
        std::cout << "Thread 3 running:..." << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        int newWidth = 0, newHeight = 0;
		std::string strHandle;
        ANSCV_GetImage_CPP(&sharedImage, 1080, 80, newWidth, newHeight, strHandle);
        std::cout << "Thread 3 complete:..." << std::endl;
        });

    std::thread t4([&]() {
        std::cout << "Thread 4 running:..." << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        cv::Mat* clonedImage = nullptr;
        ANSCV_CloneImage_S(&sharedImage, &clonedImage);
        int width = 0, height = 0;
        ANSCV_GetImageInfo_S(&clonedImage, width, height);
        int xcrop = 0, ycrop = 0, wcrop = 100, hcrop = 100;
        ANSCV_CropImage_S(&clonedImage, xcrop, ycrop, wcrop, hcrop);
        ANSCV_ReleaseImage_S(&clonedImage);
        std::cout << "Thread 4 complete:..." << std::endl;
        });

    std::thread t5([&]() {
        std::cout << "Thread 5 running:..." << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        cv::Mat* clonedImage1 = nullptr;
        ANSCV_CloneImage_S(&sharedImage, &clonedImage1);
        int width = 0, height = 0;
        ANSCV_GetImageInfo_S(&clonedImage1, width, height);
        int xcrop = 0, ycrop = 0, wcrop = 100, hcrop = 100;
        ANSCV_CropImage_S(&clonedImage1, xcrop, ycrop, wcrop, hcrop);
        LStrHandle strHandle1 = nullptr;
        ANSCV_GetImageAndRemoveImgRef_S(&clonedImage1,1280,100, width,height, strHandle1);
        std::cout << "Thread 4 complete:..." << std::endl;
        });
    // Join all threads
    t1.join();
    t2.join();
    t3.join();
    t4.join();
	t5.join();

    return 0;
}
void runParallelTest() {
    std::vector<std::thread> threads;

    for (int i = 0; i < 100; ++i) {
        threads.emplace_back(ImageManagementRefTest);  // Start thread
    }

    for (auto& t : threads) {
        if (t.joinable()) t.join();  // Wait for all threads to finish
    }
}
int TestCreateImageFromFile() {
	std::string testImageFile = "C:\\Programs\\DemoAssets\\Images\\bus.jpg";
	cv::Mat* sharedImage = nullptr;
    for (int i = 0; i < 5; i++) {
        ANSCV_CreateImageFromFile_S(testImageFile.c_str(), &sharedImage);
        int width = 0, height = 0;
        ANSCV_GetImageInfo_S(&sharedImage, width, height);
        std::cout << "Width:" << width << " Height:" << height << std::endl;
        ANSCV_ReleaseImage_S(&sharedImage);
    }
	return 0;
}
bool readFileToString(const std::string& filePath, std::string& outBuffer) {
    std::ifstream file(filePath, std::ios::binary | std::ios::ate);
    if (!file) {
        std::cerr << "Error opening file: " << filePath << std::endl;
        return false;
    }

    std::streamsize size = file.tellg();
    if (size <= 0) {
        std::cerr << "File is empty or error getting file size: " << filePath << std::endl;
        return false;
    }

    outBuffer.resize(static_cast<size_t>(size));
    file.seekg(0, std::ios::beg);

    if (!file.read(&outBuffer[0], size)) {
        std::cerr << "Error reading file contents: " << filePath << std::endl;
        return false;
    }

    return true;
}
int TestCreateImageFromJpegStringFile() {
    std::string testImageFile = "C:\\Programs\\DemoAssets\\Images\\bus.jpg";

    // Correctly open the file
    std::ifstream file(testImageFile, std::ios::binary);
    if (!file) {
        std::cerr << "Error opening file: " << testImageFile << std::endl;
        return -1;
    }

    // Read entire file into a string
    std::string jpegImage((std::istreambuf_iterator<char>(file)),
        std::istreambuf_iterator<char>());

    // Close the file (optional, handled automatically by destructor)
    file.close();
    unsigned char* inputImage;
	// Convert string to unsigned char*
	inputImage = reinterpret_cast<unsigned char*>(const_cast<char*>(jpegImage.data()));
	unsigned int bufferLength = jpegImage.size();
	// Create image from jpeg string
    cv::Mat* sharedImage = nullptr;
    for (int i = 0; i < 500; i++) {
        ANSCV_CreateImageFromJpegString_S(inputImage, bufferLength, &sharedImage);
        // draw sharedImage image
		//cv::imshow("Image", *sharedImage);
		//cv::waitKey(0);
		// Release the image
        int width = 0, height = 0;
        ANSCV_GetImageInfo_S(&sharedImage, width, height);
        std::cout << "Width:" << width << " Height:" << height << std::endl;
        ANSCV_ReleaseImage_S(&sharedImage);
    }

    return 0;
}

// Function to URL encode special characters
std::string urlEncode(const std::string& str) {
    std::ostringstream encoded;
    encoded.fill('0');
    encoded << std::hex;
    for (char c : str) {
        // Keep alphanumeric and some safe characters
        if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
            encoded << c;
        }
        else {
            // Encode special characters
            encoded << '%' << std::setw(2) << int(static_cast<unsigned char>(c));
        }
    }

    return encoded.str();
}
int PureOpenCV()
{
    // RTSP connection parameters - configure these for your camera
    std::string username = "root";  // Username can contain @ symbol
    std::string password = "A@bcd1234";
    // Build RTSP URL without credentials first
    std::string base_url = "172.28.5.3/axis-media/media.amp?videocodec=h264&camera=1";

	std::string rtspUrl = "rtsp://" + base_url; // Use the base URL directly
    std::cout << "Connecting to RTSP stream: " << base_url << std::endl;

    // Create VideoCapture object
    cv::VideoCapture cap;

    // Method 1: Try using OpenCV's built-in credential handling
    // Set username and password separately using VideoCapture properties
    cap.open(rtspUrl);

    // If the above doesn't work, try Method 2: Manual URL encoding
    if (!cap.isOpened()) {
        std::cout << "Trying with embedded credentials..." << std::endl;

        // URL encode username and password to handle special characters
        std::string encoded_username = urlEncode(username);
        std::string encoded_password = urlEncode(password);

        // Build complete RTSP URL with encoded credentials
        std::string rtsp_url = "rtsp://" + encoded_username + ":" + encoded_password +
            "@" + base_url;

        cap.open(rtsp_url);
    }

    // Method 3: Try alternative authentication method using CAP_PROP_* (OpenCV 4.x)
    if (!cap.isOpened()) {
        std::cout << "Trying alternative authentication method..." << std::endl;
        cap.open(rtspUrl);
    }

    // Check if camera opened successfully
    if (!cap.isOpened()) {
        std::cerr << "Error: Could not open RTSP stream!" << std::endl;
        std::cerr << "Please check:" << std::endl;
        std::cerr << "1. RTSP URL is correct" << std::endl;
        std::cerr << "2. Camera is accessible from your network" << std::endl;
        std::cerr << "3. Username/password are correct (if required)" << std::endl;
        return -1;
    }

    // Set buffer size to reduce latency (optional)
    cap.set(cv::CAP_PROP_BUFFERSIZE, 1);

    // Get video properties
    int frame_width = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH));
    int frame_height = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
    double fps = cap.get(cv::CAP_PROP_FPS);

    std::cout << "Stream connected successfully!" << std::endl;
    std::cout << "Resolution: " << frame_width << "x" << frame_height << std::endl;
    std::cout << "FPS: " << fps << std::endl;
    std::cout << "Press ESC to exit..." << std::endl;

    cv::Mat frame;

    while (true) {
        // Capture frame-by-frame
        bool ret = cap.read(frame);

        if (!ret) {
            std::cerr << "Error: Failed to grab frame from stream!" << std::endl;
            std::cerr << "Stream may have ended or connection lost." << std::endl;
            break;
        }

        // Display the frame
        cv::imshow("RTSP H264 Stream", frame);

        // Check for ESC key press (ASCII code 27)
        int key = cv::waitKey(1) & 0xFF;
        if (key == 27) { // ESC key
            std::cout << "ESC pressed. Exiting..." << std::endl;
            break;
        }
    }

    // Release everything
    cap.release();
    cv::destroyAllWindows();

    std::cout << "Application closed successfully." << std::endl;
    return 0;
}
int TestGetImage() {
	std::string testImageFile = "C:\\Programs\\DemoAssets\\Images\\bus.jpg";
	cv::Mat*imageIn;
	// Create image from file

    int createImage= ANSCV_CreateImageFromFile_S(testImageFile.c_str(), &imageIn);
    if( createImage != 1) {
        std::cerr << "Error: Could not create cv::Mat from file!" << std::endl;
        return -1;
	}

    std::string outputImage;
	int width = 1080;
	int quality = 80; // Set desired quality (0-100)
	int newWidth = 0, newHeight = 0;
    for (int i = 0; i < 20; i++) {
        auto start1 = std::chrono::system_clock::now();
        int result = ANSCV_GetImage_CPP(&imageIn, width, quality, newWidth, newHeight, outputImage);
        auto end1 = std::chrono::system_clock::now();
        auto elapsed1 = std::chrono::duration_cast<std::chrono::milliseconds>(end1 - start1);
        std::cout << "Time to get image: " << elapsed1.count() << " ms" << std::endl;
        if (result != 1) {
            std::cerr << "Error: Could not convert cv::Mat to ANSCV image format!" << std::endl;
            return -1;
        }

    }
	std::cout << "Image converted successfully!" << std::endl;
	std::cout << "New Width: " << newWidth << ", New Height: " << newHeight << std::endl;
	//std::cout << "Jpeg string:" << outputImage <<  std::endl;
	// Draw the image imageIn
	//cv::imshow("Image", *imageIn);
	//cv::waitKey(0); // Wait for a key press to close the window
    ANSCV_ReleaseImage_S(&imageIn);


}
int GenerateVideo() {
   std::string imageFolder = "E:\\Programs\\DemoAssets\\ImageSeries\\TestImages";
   std::string outputVideoPath = "E:\\Programs\\DemoAssets\\ImageSeries\\output.mp4";
   bool conversionResult = ANSCV_ImagesToMP4_S(imageFolder.c_str(), outputVideoPath.c_str(), 3.5);
   if (!conversionResult) {
       std::cerr << "Failed to convert images to MP4." << std::endl;
      return -1;
   }
   return 0;
}

int OpenCVFunctionTest() {
    ANSCENTER::ANSOPENCV* cvHandle = new ANSCENTER::ANSOPENCV();
    const char* licenseKey = "";
    cvHandle->Init(licenseKey);
    cv::Mat inputFrame = cv::imread("E:\\Programs\\DemoAssets\\Images\\bus.jpg");
    cv::Rect roi(0, 0, 300, 100);
	cv::Mat outputFrame = cvHandle->ShiftImage(inputFrame, 200,200);

    //cv::Mat outputFrame = cvHandle->ToGray(inputFrame);

    std::string jpegData = cvHandle->MatToBinaryData(outputFrame);

    // Check if encoding was successful
    if (jpegData.empty()) {
        std::cerr << "Error: Failed to encode image to JPEG" << std::endl;
    }
    else {
        std::cout << "JPEG data size: " << jpegData.size() << " bytes" << std::endl;

        // Save jpegData to file
        std::ofstream outFile("E:\\Programs\\DemoAssets\\Images\\output_gray.jpg", std::ios::binary);
        if (outFile.is_open()) {
            outFile.write(jpegData.data(), jpegData.size());  // <-- THIS WAS MISSING!
            outFile.close();
            std::cout << "File saved successfully" << std::endl;
        }
        else {
            std::cerr << "Error: Could not open output file" << std::endl;
        }
    }

    cv::imshow("Cropped Image", outputFrame);
    cv::waitKey(0);

    delete cvHandle;

}


int main()
{
   ANSCENTER::ANSOPENCV::InitCameraNetwork();
   //OpenCVFunctionTest();
   //GenerateVideo();
   //VideoTestClient();
  // TestGetImage();
   //PureOpenCV();
  //  RSTPTestClient();
   RSTPTestCVClient();
   //TestCreateImageFromJpegStringFile();
   //TestCreateImageFromFile();
   //for (int i = 0; i < 100; i++) {
   //    ImageManagementRefTest();
   //}
   //runParallelTest();
   //FPTestCVClient();
   //WebcamVCPlayerTestClient();
   //WebcamPlayerTestClient();
   //FilePlayerOpenCVTestClient();
   //FilePlayerTurboJpegTestClient();
   //FilePlayerOpenCVTestClient();
  //FilePlayerDriverBigFileTestClient();
  //FilePlayerDriverTestClient();
   //FilePlayerOpenCVTestClient();
  // FilePlayerTurboJpegTestClient();
   //WebcamResolutionClient();
   //for (int i = 0; i < 10; i++) {
   //    WebcamPlayerTestClient();
   //}
    //WebcamPlayerDoubleTestClient();
   //WebcamPlayerTestClient();
      //for (int i = 0; i < 5000; i++) {
      //  FilePlayerTestClient();
      //}
   //for (int i = 0; i < 30; i++) {
   //    //RTSPStressTestClient();
	  // std::cout << "Running the " << i << " time" << std::endl;
	  // FilePlayerDriverStressClient();
   //}
   //std::cout << "Complete the test " << std::endl;
    ///BrightEnhancement();
    //AutoWhiteBalance();
    //PatternMatching();
    //GetColour();
    //DetectRedCar();
    //DominantColour();
    //TestZingQRcode();
    //TestQRCode();
    //return WebcamPlayerDoubleTestClient();
    //return RSTPTestClient();
    //return FilePlayerTestClient();
    ANSCENTER::ANSOPENCV::DeinitCameraNetwork();
}