한때, MFC를 많이 사용했다. 내가 느끼기에 MFC의 전성기는 Visual C++ 6.0이다. 손쉽게 윈도우즈 프로그래밍 가능했고 요즘은 다양한 편집기가 있지만, Visual C++ IDE는 편집기로써도 우수했다. 그러나 세상이 바뀌면서 좋은 도구가 많이 나오고 프로그래밍 언어도 늘어나면서 MFC의 가치는 떨어졌다. 전적으로 나의 개인적인 생각이다. 그에 반해 QT는 강력한 것 같다. 리눅스 시절, X상에서 UI 프로그래밍을 할 때 접했지만 큰 관심이 없어 지나갔던 QT였는데 OS에 상관없이 사용가능한 훌륭한 라이브러리가 되었다. ‘OS independent’라는 말은 그 자체로 효과적이다. 스크립트 언어의 장점 중의 하나가 OS에 상관없이 사용할 수 있다는 것인데 QT 또한 그와 같다. 또한, QT라고 해서 GUI 프로그래밍을 위한 도구는 아니다. QT에서 제공하는 라이브러리가 좋아서 console 프로그래밍에도 좋다. bmNVR도 QT 기반으로 하려고 한다.
먼저, testRTSPClient.cpp 만 아래와 같이 쪼개서 필드를 해봤다. 구조는 엉망이지만 돌리는 것이 목적이므로...
main.cpp 에서 bmNVR을 실행하는 형태로 시작을 하고... start()를 하면... 이런 저런 단계를 거쳐 bmNVRSink.cpp에서 대부분의 작업을 처리하게 해놨다. 제품을 만드는 것이 아니라 재미있는 놀이니 구조나 그런 것을 신경 쓰지 말자.
#include <QCoreApplication>
#include <QTimer>
#include "bmNVR.h"
bmNVR* g_bmNVR = NULL;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTimer::singleShot(0,[](){
g_bmNVR = new bmNVR();
g_bmNVR->start();
QCoreApplication::exit(0);
});
return a.exec();
}
앞서 했던 것 처럼 afterGettingFrame() 이 핵심이 되어 데이터를 저장한다.
void bmNVRSink::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes,
struct timeval presentationTime, unsigned /*durationInMicroseconds*/) {
// We've just received a frame of data. (Optionally) print out information about it:
if (numTruncatedBytes > 0) {
envir() << "Oops! numTruncatedBytes is larger than ZERO.\n";
exit(-1);
}
if (true == gFirst) {
if (0x67 == fReceiveBuffer[0]) {
gFirst = false;
}
}
if (false == gFirst) {
if (NULL == gOut) {
gOut = fopen("h264.dat", "wb");
if (NULL == gOut) {
envir() << "Oops! Cannot open the output file.\n";
exit(-1);
}
else {
envir() << "Start saving the file...\n";
}
}
if (NULL != gOut) {
fwrite(hdr, 1, sizeof(hdr), gOut);
fwrite(fReceiveBuffer, 1, frameSize, gOut);
fflush(gOut);
}
}
#ifdef DEBUG_PRINT_EACH_RECEIVED_FRAME
if (fStreamId != NULL) envir() << "Stream \"" << fStreamId << "\"; ";
envir() << fSubsession.mediumName() << "/" << fSubsession.codecName() << ":\tReceived " << frameSize << " bytes";
if (numTruncatedBytes > 0) envir() << " (with " << numTruncatedBytes << " bytes truncated)";
char uHexDump[(4*4)+1];
sprintf(uHexDump, "[%02X][%02X][%02X][%02X]", fReceiveBuffer[0], fReceiveBuffer[1], fReceiveBuffer[2], fReceiveBuffer[3]);
envir() << ".\t" << uHexDump;
char uSecsStr[6+1]; // used to output the 'microseconds' part of the presentation time
sprintf(uSecsStr, "%06u", (unsigned)presentationTime.tv_usec);
envir() << "\tPresentation time: " << (int)presentationTime.tv_sec << "." << uSecsStr;
if (fSubsession.rtpSource() != NULL && !fSubsession.rtpSource()->hasBeenSynchronizedUsingRTCP()) {
envir() << "!"; // mark the debugging output to indicate that this presentation time is not RTCP-synchronized
}
#ifdef DEBUG_PRINT_NPT
envir() << "\tNPT: " << fSubsession.getNormalPlayTime(presentationTime);
#endif
envir() << "\n";
#endif
// Then continue, to request the next frame of data:
continuePlaying();
}
이제 여기에 하나 둘 붙여보자.
2023.08.30 - [놀기/잡스러운 것] - [bmNVR] LIVE555 (ubuntu 20.04) 빌드
2023.08.30 - [놀기/잡스러운 것] - [bmNVR] h264 데이터를 ts(transport stream)로 만들기
'놀기 > 잡스러운 것' 카테고리의 다른 글
[NVR 만들기] H.265 지원 (1) | 2023.09.02 |
---|---|
[bmNVR] 수신한 데이터를 받을 Source 만들기 (ByteStreamMemoryBufferSource 참조) (0) | 2023.09.01 |
[bmNVR] h264 데이터를 ts(transport stream)로 만들기 (0) | 2023.08.30 |
[bmNVR] LIVE555 (ubuntu 20.04) 빌드 (0) | 2023.08.30 |
[FFMPEG] SMPTE Bar 영상 만들기 (with timecode) (0) | 2023.08.27 |
댓글