#include "Channel.h" #include #include LinkObject* Channel::audioInput = nullptr; LinkObject* Channel::audioOutput = nullptr; LinkObject* Channel::rtspServer = nullptr; LinkObject* Channel::file = nullptr; LinkObject* Channel::audioDecoder = nullptr; LinkObject* Channel::videoDecoder = nullptr; extern LinkObject* vo; extern LinkObject* vo1; const char* VideoPath = "/root/usb/videos"; const char* SnapPath = "/root/usb/snap"; Channel::Channel(QObject* parent) : QObject(parent) { timer = new QTimer(); timer->setInterval(duration); timer->stop(); videoInput = nullptr; videoOutput = nullptr; videoEncoder = nullptr; audioEncoder = nullptr; record = nullptr; rtsp = nullptr; snap = Link::create("EncodeV"); overLay = Link::create("Overlay"); if (audioInput == nullptr) { audioInput = Link::create("InputAlsa"); QVariantMap dataIn; dataIn["path"] = "hw:0,0"; audioInput->start(dataIn); } if (audioOutput == nullptr) { audioOutput = Link::create("OutputAlsa"); QVariantMap dataOut; dataOut["path"] = "hw:0,0"; audioOutput->start(dataOut); } if (rtspServer == nullptr) { rtspServer = Link::create("Rtsp"); rtspServer->start(); } if (file == nullptr) { file = Link::create("InputFile"); // one video playback end connect(file, &LinkObject::newEvent, [=](QString type, QVariant) { if (type == "EOF") { qDebug() << "one video playback end"; } }); } if (audioDecoder == nullptr) { audioDecoder = Link::create("DecodeA"); audioDecoder->start(); file->linkA(audioDecoder)->linkA(audioOutput); } if (videoDecoder == nullptr) { videoDecoder = Link::create("DecodeV"); videoDecoder->start(); file->linkV(videoDecoder); } connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout())); } /** * @brief load configuration and init components */ void Channel::init() { if (channelName.isEmpty()) { qDebug() << "channel name is empty!"; return; } if (channelName == "HDMI-A") { videoOutput = vo; } else { videoOutput = vo1; } // init video input by channel name videoInput = Link::create("InputVi"); QVariantMap dataVi; dataVi["interface"] = channelName; videoInput->start(dataVi); // start water mask // overLay->start(); // link video input and output, and add water mask videoInput->linkV(videoOutput); // capture picture from video QVariantMap dataSnap; dataSnap["codec"] = "jpeg"; dataSnap["snap"] = true; dataSnap["width"] = 1920; dataSnap["height"] = 1080; snap->start(dataSnap); videoInput->linkV(snap); // sleep 1s, if didnt sleep , function snap would return flase and capture failed QThread::sleep(1); // video encode videoEncoder = Link::create("EncodeV"); videoEncoder->start(videoEncoderParams); // audio encode audioEncoder = Link::create("EncodeA"); audioEncoder->start(audioEncoderParams); // record record = Link::create("Mux"); QVariantMap dataMp4; dataMp4["format"] = "mp4"; record->setData(dataMp4); videoInput->linkV(videoEncoder)->linkV(record); audioInput->linkA(audioEncoder)->linkA(record); // rtsp rtsp = Link::create("Mux"); QVariantMap dataRtsp; dataRtsp["path"] = QString("mem://%1").arg(pushCode); dataRtsp["format"] = "rtsp"; rtsp->start(dataRtsp); videoInput->linkV(videoEncoder)->linkV(rtsp)->linkV(rtspServer); audioInput->linkA(audioEncoder)->linkA(rtsp)->linkA(rtspServer); } /** * @brief end previous record and start new record */ void Channel::onTimeout() { record->stop(true); timer->stop(); if (!isMountDisk()) { return; } QString curTime = QDateTime::currentDateTime().toString("yyyy-MM-dd_hh:mm:ss"); QVariantMap dataRecord; dataRecord["path"] = QString("%1/%2/%3.mp4").arg(VideoPath).arg(channelName).arg(curTime); record->setData(dataRecord); record->start(); timer->start(); snap->invoke("snapSync", QString("%1/%2/%3.jpg").arg(SnapPath).arg(channelName).arg(curTime)); } /** * @brief start record */ void Channel::startRecord() { if (!isMountDisk()) { return; } QString curTime = QDateTime::currentDateTime().toString("yyyy-MM-dd_hh:mm:ss"); QVariantMap dataRecord; // /usb/root/videos/HDMI-A/2024-1-1_10:00:00 dataRecord["path"] = QString("%1/%2/%3.mp4").arg(VideoPath).arg(channelName).arg(curTime); record->setData(dataRecord); record->start(); // setOverlay("Record"); timer->start(); snap->invoke("snapSync", QString("%1/%2/%3.jpg").arg(SnapPath).arg(channelName).arg(curTime)); } /** * @brief stop record */ void Channel::stopRecord() { record->stop(true); // setOverlay("No Record"); timer->stop(); } /** * @brief start playback and output hdmi signals * @param fileName */ void Channel::startPlayback(QString fileName) { QString path = QString("%1/%2/%3").arg(VideoPath).arg(channelName).arg(fileName); // break video input and output videoInput->unLinkV(videoOutput); videoDecoder->linkV(videoOutput); QVariantMap dataFile; dataFile["path"] = path; file->start(dataFile); isPlayback = true; } /** * @brief play live */ void Channel::startPlayLive() { videoDecoder->unLinkV(videoOutput); file->stop(true); videoInput->linkV(videoOutput); isPlayback = false; } /** * @brief playback -10s */ void Channel::back() { qDebug() << "back 10s"; int curPos = file->invoke("getPosition").toInt(); curPos -= 10 * 100; file->invoke("seek", curPos); } /** * @brief playback +10s */ void Channel::forward() { qDebug() << "forward 10s"; int curPos = file->invoke("getPosition").toInt(); curPos += 10 * 100; file->invoke("seek", curPos); } /** * @brief Channel::togglePause */ void Channel::togglePause() { isPause = !isPause; file->invoke("pause", isPause); } /** * @brief open console process, and use it by command * @param com * @return */ QString Channel::writeCom(const QString& com) { QProcess proc; QStringList argList; argList << "-c" << com; proc.start("/bin/sh", argList); // wait process start proc.waitForFinished(); proc.waitForReadyRead(); // read data from console QByteArray procOutput = proc.readAll(); proc.close(); return QString(procOutput); } /** * @brief judge the disk whether mounted * @return */ bool Channel::isMountDisk() { QString mount = writeCom("df /root/usb"); if (!mount.contains("/root/usb")) return false; return true; }