[C++][C++/FLIR] RTSP Streamer 활용 가이드

조회수 449

RTSP 스트리밍, FLIR 열화상 카메라, FLIR A400, Spinnaker SDK, OpenCV FFmpeg, H.264 RTSP, RTSP URL 설정, rtsp_transport=tcp, Producer-Consumer 패턴, MSX 기능


개발 환경


항목

버전 / 권장 값

IDE

Visual Studio 2019 (64‑bit)

Spinnaker SDK

3.2.0.57

OpenCV

4.7 (x64)

기타

MFC · C++14 · FFmpeg backend



🔔 DLL 주의 – 브라우저 ZIP 다운로드 시 OpenCV DLL 이 누락·손상될 수 있습니다.

실행 오류가 나면 opencv_world**.dll 파일 크기를 꼭 확인하세요.


1. RTSP란?

  • Real‑Time Streaming Protocol — 영상·음성 등 멀티미디어 스트림의 제어(Play, Pause, Seek) 에 특화된 표준 프로토콜입니다.

  • HTTP와 달리 지속적 세션을 유지하며, TCP/UDP 양쪽 전송 계층을 모두 지원합니다.

  • 명령만 RTSP로, 실제 미디어 데이터는 RTP/RTCP로 전송되는 구조라 지연 시간을 최소화할 수 있습니다.





1‑1 RTSP의 장점



항목

설명

낮은 지연

헤더가 작고 세션 기반이라 프레임‑투‑프레임 딜레이를 최소화

범용성

VLC, FFmpeg, 웹플레이어 등 거의 모든 재생기가 기본 지원

확장성

멀티캐스트·TLS(RTSPS)·Onvif Profile T 등 고급 기능과 호환



🔎 쉬운 비유 — RTSP는 ‘원격 리모컨’, RTP는 ‘콘센트에 꽂힌 전원선’이라고 생각하면 이해가 빠릅니다.



2. FLIR 열화상 카메라에서 RTSP 사용하기

  1. 웹 UI 로그인 → Setup › Streaming 메뉴에서 RTSP Enable 체크.

  2. Video Encoding 을 H.264 (Main) 으로 설정하면 OpenCV 디코딩 호환성이 높아집니다.

  3. RTSP URL 포맷

  4. rtsp://<ID>:<PW>@<카메라-IP>:554/avc

  • avc 는 열화상 스트림(AX8) 기본 경로이며, 일부 모델은 /stream1, /video 등으로 다를 수 있습니다.

  1. 방화벽 또는 NAT 환경이라면 TCP 모드(?rtsp_transport=tcp) 권장.


2‑1 RTSP URL 옵션 



옵션 키‑값

예시

용도 / 비고

Path

/avc, /stream1

스트림 종류 선택 (열화상/가시광)

rtsp_transport=tcp

?rtsp_transport=tcp

패킷 손실 ↓, 안정 ↑

buffer_size=N (byte)

?buffer_size=102400

내부 디코더 버퍼 크기 설정

recv_timeout_ms=10000

?recv_timeout_ms=10000

수신 타임아웃 (ms)

pkt_size=1316

?pkt_size=1316

RTP 패킷 크기 (UDP 전용)

live=1

?live=1

LIVE 지연 최소화 (일부 펌웨어)

조합

/avc?rtsp_transport=tcp&buffer_size=102400

다중 옵션 ‘&’ 로 연결



✅ 팁 — FLIR AX8·A400 시리즈는 RTSP 서버를 내장하고 있어 별도 라이센스 없이 바로 사용 가능합니다.



2‑2 MSX(Multi‑Spectral Dynamic Imaging) 기능 살펴보기


  • MSX 는 FLIR 카메라만의 특허 기술로, 가시광 영상의 윤곽선(edges)과 열화상 데이터를 실시간으로 합성해 “디테일이 살아 있는 열화상 이미지” 만들어 줍니다.

한마디로  *"온도 정보는 그대로 두고, 주변 형상을 뚜렷하게 그려 넣는 오버레이"*라고 이해하면 쉽습니다.



구분

내용

작동 원리

가시광 스트림에서 Canny Edge 등을 활용해 윤곽선만 추출 → α‑Blending 으로 열화상 위에 매핑

이점

직관성 ↑ – 전기 패널·배관·PCB 패턴 등이 선명측정값 보존 – 픽셀 IR 값을 변경하지 않음

(Radiometric OK)후공정 호환 – 원본 열화상·MSX 두 스트림을 동시에 저장 가능

지원 모델

AX8, A400/A500 시리즈 등 듀얼 센서(Visible + Thermal) 탑재 모델

해상도 조건

두 센서의 FOV 차이가 크면 미세 오차 발생 → cv::remap() 또는 cv::resize()로 보정



 

📸  Thermal (원본) /  MSX (원본)




3. MDS_RtspStreamer 클래스 구조

  • MDS_RtspStreamer 는 RTSP URL 하나만 받아 Producer‑Consumer 패턴을 자동 구성하는 경량 래퍼입니다.



class MDS_RtspStreamer { public:    explicit MDS_RtspStreamer(const std::string& rtspUrl);    void Start();                       // 쓰레드 시작    void Stop();                        // 안전 종료    void EnableVisualSnap(bool on);     // 스냅샷 플래그    void TriggerVisualSnap(int camIdx,  // 스냅샷 트리거                            const std::shared_ptr<cv::Mat>& img); private:    static UINT AFX_CDECL ProducerThread(LPVOID p); // 수신    static UINT AFX_CDECL ConsumerThread(LPVOID p); // 처리    void ProcessFrame(const cv::Mat& frame);        // 후처리 → UI };




4.  핵심 포인트



구성 요소

역할

메모

ProducerThread

카메라 → PC, 프레임 수신

최신 프레임만 큐에 유지해 지연 ↓

ConsumerThread

큐 → UI, 프레임 후처리

ProcessFrame() 내부에서 디스패치

EnableVisualSnap()

스냅샷 플래그 토글

트리거 후 자동 OFF 되도록 구현

TriggerVisualSnap()

스냅 요청 → 메시지 전파

DB 저장·알람 등 연동에 활용




5. 코드 하이라이트

5‑1 Start / Stop



void MDS_RtspStreamer::Start() {    if (m_producerThread || m_consumerThread) return; // 중복 방지    m_stopFlag = false;    m_producerThread = AfxBeginThread(ProducerThread, this);    m_consumerThread = AfxBeginThread(ConsumerThread, this); } void MDS_RtspStreamer::Stop() {    if (!m_producerThread && !m_consumerThread) return;    m_stopFlag = true;  m_queueCond.notify_all();    WaitForSingleObject(m_producerThread->m_hThread, INFINITE);    WaitForSingleObject(m_consumerThread->m_hThread, INFINITE); }



5‑2 ProducerThread — 프레임 수신



UINT MDS_RtspStreamer::ProducerThread(LPVOID p) {    auto self = static_cast<MDS_RtspStreamer*>(p);    std::string url = self->m_rtspUrl + "?rtsp_transport=tcp&buffer_size=102400";    cv::VideoCapture cap(url, cv::CAP_FFMPEG);    if (!cap.isOpened()) return 0;    cap.set(cv::CAP_PROP_BUFFERSIZE, 1); // 지연 최소화    while (!self->m_stopFlag) {        cv::Mat f;  if (cap.read(f)) {            std::lock_guard<std::mutex> g(self->m_queueMutex);            while (!self->m_frameQueue.empty()) self->m_frameQueue.pop();            self->m_frameQueue.push(f);            self->m_queueCond.notify_one();        } else Sleep(1);    }    return 0; }



5‑3 ConsumerThread — 프레임 처리



UINT MDS_RtspStreamer::ConsumerThread(LPVOID p) {    auto self = static_cast<MDS_RtspStreamer*>(p);    for (;;) {        std::unique_lock<std::mutex> lk(self->m_queueMutex);        self->m_queueCond.wait(lk, [self]{            return !self->m_frameQueue.empty() || self->m_stopFlag;});        if (self->m_stopFlag && self->m_frameQueue.empty()) break;        cv::Mat frame = self->m_frameQueue.front(); self->m_frameQueue.pop();        lk.unlock();        self->ProcessFrame(frame);    }    return 0; }



5‑4 ProcessFrame — UI 연동 & 스냅샷



void MDS_RtspStreamer::ProcessFrame(const cv::Mat& frame) {    if (frame.empty()) return;    auto pkg = new ImageDataPackage{ nullptr, nullptr,        std::make_shared<cv::Mat>(frame.clone()) };    AfxGetApp()->GetMainWnd()->PostMessage(WM_UPDATE_VISUAL_IMAGE,                                           (WPARAM)pkg, 0);    if (VisualTriggerSnapFlag) {        TriggerVisualSnap(0, std::make_shared<cv::Mat>(frame.clone()));        EnableVisualSnap(false);    } }



5‑5 예제:  클래스에서 RTSP 연동



// 1) URL 생성 (열화상 스트림 + TCP + 버퍼 옵션) CString ip = _T("192.168.0.100"); CString url; url.Format(_T("rtsp://user:pass@%s/avc?rtsp_transport=tcp&buffer_size=102400"), ip); std::string rtspUrl = CT2A(url); // 2) 스트림 시작 m_rtspStreamer = std::make_unique<MDS_RtspStreamer>(rtspUrl); m_rtspStreamer->Start(); // … 필요 시 … // m_rtspStreamer->EnableVisualSnap(true); // 3) 종료 시 m_rtspStreamer->Stop(); m_rtspStreamer.reset();



✅ 팁 — URL 옵션을 바꿀 때는 문자열 포매팅 으로 즉시 적용할 수 있습니다.

예) "/avc?live=1" 는 지연 시간을 수 ms 단위로 줄여 줍니다.





6. 실행 체크리스트

  1. opencv_world470.dll 이 실행 파일 옆에 있는지 확인.

  2. 카메라와 PC IP 대역이 같은지(또는 라우터 포트포워딩) 점검.

  3. 위 예제 코드처럼 Start() 호출 후 윈도우 메시지가 정상적으로 올라오는지 확인.

  4. Stop() 호출했을 때 메모리 릭/쓰레드 핸들 릭이 없는지 Visual Studio Diagnostics 로 검증






RTSP는 열화상·보안·산업 카메라 영역에서 여전히 표준으로 자리잡고 있습니다.

RTSP Streamer 예제를 기반으로 ▲AI 데이터셋 생성 ▲온도 이상 감지 알람 ▲WebRTC 뷰어

등의 프로젝트에 도전해 보세요!



cb530f16b3e14.png

Contact us.

블로그 바로가기
www.blog.naver.com/mdstec_flir

블로그 방문하기

MDS 교육 수강하기
상반기/ 하반기 진행시 오픈 예정

수강신청 바로가기


@MDS Tech Inc. All Rights Reserved.

Youtube↖︎

Instagram↖︎

Facebook↖︎

주소 : 13493 경기도 성남시 분당구 대왕판교로 644번길 49 DTC타워 9층TEL: 031-627-3000 FAX:031-627-3008

사업자등록번호 : 117-81-22859대표자 : 이창열, 이정승


©MDS Tech Inc. All Rights Reserved.

주소 : 13493 경기도 성남시 분당구 대왕판교로 644번길 49 DTC타워 9층

TEL: 031-627-3000 FAX:031-627-3008

사업자등록번호 : 117-81-22859대표자 : 이창열, 이정승

©MDS Tech Inc. All Rights Reserved.