From 69a3997805e161de2f5c5264745d2059a664ef8f Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 19 Mar 2025 16:05:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0rtsp=20=E8=AE=A4=E8=AF=81?= =?UTF-8?q?=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/cpp/PhoneDevice.cpp | 115 +++++++++++++++--------- app/src/main/cpp/PhoneDevice.h | 9 +- app/src/main/cpp/media/RTSPRecorder.cpp | 15 ++-- app/src/main/cpp/netcamera/HangYuCtrl.h | 1 + 4 files changed, 93 insertions(+), 47 deletions(-) diff --git a/app/src/main/cpp/PhoneDevice.cpp b/app/src/main/cpp/PhoneDevice.cpp index 39ac3718..26f01981 100644 --- a/app/src/main/cpp/PhoneDevice.cpp +++ b/app/src/main/cpp/PhoneDevice.cpp @@ -1763,7 +1763,7 @@ bool CPhoneDevice::TakeVideoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c if (netHandle == 0) { // Wait about 10s - for (int idx = 0; idx < 84; idx++) + for (int idx = 0; idx < 128; idx++) { std::this_thread::sleep_for(std::chrono::milliseconds(128)); netHandle = GetEthnetHandle(); @@ -1792,12 +1792,7 @@ bool CPhoneDevice::TakeVideoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c // SetStaticIp(); std::this_thread::sleep_for(std::chrono::milliseconds(256)); - struct in_addr addr; - char ip[32] = { 0 }; - addr.s_addr = localPhotoInfo.ip; - strcpy(ip, inet_ntoa(addr)); - // strcpy(netPhotoInfo.outputPath, path.c_str()); - + std::string ip = GetIpStr(localPhotoInfo.ip); VendorCtrl* vendorCtrl = MakeVendorCtrl(localPhotoInfo.vendor, localPhotoInfo.channel, ip, localPhotoInfo.userName, localPhotoInfo.password, netHandle); if (vendorCtrl == NULL) { @@ -1864,62 +1859,98 @@ bool CPhoneDevice::TakeVideoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c bool CPhoneDevice::StartPushStreaming(IDevice::PHOTO_INFO& photoInfo, const std::string& url, std::vector& osds, std::shared_ptr powerCtrlPtr) { -#if 0 if (photoInfo.mediaType == XY_MEDIA_TYPE_STREAM) { - std::map >::iterator it = m_streamings.find(photoInfo.channel); - if (it != m_streamings.end()) + time_t ts = time(NULL); + uint32_t waitTime = photoInfo.selfTestingTime; + if(!GpioControl::GetSelftestStatus(waitTime)) { - it->second->stop(); - it->second.reset(); - m_streamings.erase(it); + m_isSelfTesting.store(true); + waitTime = (waitTime != 0) ? (waitTime * 1024) : 10240; + std::this_thread::sleep_for(std::chrono::milliseconds(waitTime)); + m_isSelfTesting.store(false); } - NET_PHOTO_INFO netPhotoInfo = { 0, 0 }; - if (photoInfo.vendor == 1) + XYLOG(XYLOG_SEVERITY_DEBUG, "Ethernet Power ON"); + std::shared_ptr ethernetPowerCtrl = std::make_shared(1); + // std::shared_ptr ethernetPowerCtrl; + + net_handle_t netHandle = GetEthnetHandle(); + if (netHandle == 0) { - // Hai Kang - netPhotoInfo.authType = HTTP_AUTH_TYPE_DIGEST; - snprintf(netPhotoInfo.url, sizeof(netPhotoInfo.url), "/ISAPI/Streaming/channels/1/picture?"); + // Wait about 10s + for (int idx = 0; idx < 84; idx++) + { + std::this_thread::sleep_for(std::chrono::milliseconds(128)); + netHandle = GetEthnetHandle(); + + if (netHandle != 0) + { + break; + } + } } - else if (photoInfo.vendor == 2) + + if (netHandle == 0) { - // Hang Yu - strcpy(netPhotoInfo.url, "/cgi-bin/snapshot.cgi"); + // timeout + XYLOG(XYLOG_SEVERITY_ERROR, "Ethernet not existing CH=%u PR=%X PHOTOID=%u", (uint32_t)photoInfo.channel, (uint32_t)photoInfo.preset, photoInfo.photoId); +#ifdef NDEBUG + TakePhotoCb(0, localPhotoInfo, "", 0); + return false; +#endif } - else if (photoInfo.vendor == 3) + else { - // Yu Shi - netPhotoInfo.authType = HTTP_AUTH_TYPE_DIGEST; - int streamSid = 0; // should put into config - // rtsp://192.168.0.13:554/media/video1 - snprintf(netPhotoInfo.url, sizeof(netPhotoInfo.url), "/media/video%u", (uint32_t)photoInfo.cameraId); - // strcpy(netPhotoInfo.url, "rtsp://192.168.50.224/live/0"); + XYLOG(XYLOG_SEVERITY_INFO, "Ethernet is Available CH=%u PR=%X PHOTOID=%u", (uint32_t)photoInfo.channel, (uint32_t)photoInfo.preset, photoInfo.photoId); } - else if (photoInfo.vendor == 5) + + // SetStaticIp(); + std::this_thread::sleep_for(std::chrono::milliseconds(256)); + + std::map::iterator it = m_streamings.find(photoInfo.channel); + if (it != m_streamings.end()) { - // Hang Yu - New - netPhotoInfo.authType = HTTP_AUTH_TYPE_BASIC; - // http://192.168.1.46/Snapshot/%u/RemoteImageCapture?ImageFormat=2&HorizontalPixel=1920&VerticalPixel=1080 - // http://192.168.1.101/Snapshot/1/2/RemoteImageCaptureV2?ImageFormat=jpg - // http://192.168.1.101/Snapshot/1/1/RemoteImageCaptureV2?ImageFormat=jpg - snprintf(netPhotoInfo.url, sizeof(netPhotoInfo.url), "/Snapshot/%u/1/RemoteImageCaptureV2?ImageFormat=jpg", (uint32_t)photoInfo.cameraId); + it->second.stream->stop(); + it->second.stream.reset(); + it->second.powerCtrl.reset(); + it->second.ethernetPowerCtrl.reset(); + m_streamings.erase(it); } - else + + std::string ip = GetIpStr(photoInfo.ip); + VendorCtrl* vendorCtrl = MakeVendorCtrl(photoInfo.vendor, photoInfo.channel, ip, photoInfo.userName, photoInfo.password, netHandle); + if (vendorCtrl == NULL) { XYLOG(XYLOG_SEVERITY_ERROR, "Vendor(%u) not Supported CH=%u PR=%X PHOTOID=%u", (uint32_t)photoInfo.vendor, (uint32_t)photoInfo.channel, (unsigned int)photoInfo.preset, photoInfo.photoId); TakePhotoCb(0, photoInfo, "", 0); return false; } + std::string streamingUrl = vendorCtrl->GetStreamingUrl(photoInfo.cameraId); + + if (streamingUrl.empty()) + { + XYLOG(XYLOG_SEVERITY_ERROR, "Invalid Streaming URL CH=%u PR=%X PHOTOID=%u", (uint32_t)photoInfo.channel, (unsigned int)photoInfo.preset, photoInfo.photoId); + TakePhotoCb(0, photoInfo, "", 0); + return false; + } + StreamForwarder* forwarder = new StreamForwarder(); - m_streamings[photoInfo.channel] = std::shared_ptr((Streaming*)forwarder); + // Initialize with RTSP input and RTMP output - if (!forwarder->initialize(std::string(netPhotoInfo.url), url)) { + if (!forwarder->initialize(streamingUrl, url)) { std::cerr << "Failed to initialize stream forwarder" << std::endl; + delete forwarder; return -1; } + STREAMING_CONTEXT ctx; + ctx.stream = std::shared_ptr((Streaming*)forwarder); + ctx.powerCtrl = powerCtrlPtr; + ctx.ethernetPowerCtrl = ethernetPowerCtrl; + m_streamings[photoInfo.channel] = ctx; + // Optional: Set callback to process video frames #if 0 forwarder->setFrameCallback([](uint8_t* data, int linesize, int width, int height) { @@ -1942,12 +1973,14 @@ bool CPhoneDevice::StartPushStreaming(IDevice::PHOTO_INFO& photoInfo, const std: auto it = m_streamings.find(photoInfo.channel); if (it != m_streamings.end()) { - it->second->stop(); - it->second.reset(); + it->second.stream->stop(); + it->second.stream.reset(); + it->second.powerCtrl.reset(); + it->second.ethernetPowerCtrl.reset(); m_streamings.erase(it); } } -#endif + return true; } diff --git a/app/src/main/cpp/PhoneDevice.h b/app/src/main/cpp/PhoneDevice.h index 5c4b330f..fd6206e6 100644 --- a/app/src/main/cpp/PhoneDevice.h +++ b/app/src/main/cpp/PhoneDevice.h @@ -157,6 +157,13 @@ class PowerControl; class VendorCtrl; class Streaming; +struct STREAMING_CONTEXT +{ + std::shared_ptr stream; + std::shared_ptr powerCtrl; + std::shared_ptr ethernetPowerCtrl; +}; + class CPhoneDevice : public IDevice { public: @@ -428,7 +435,7 @@ protected: std::atomic m_collecting; unsigned long long localDelayTime; - std::map > m_streamings; + std::map m_streamings; }; diff --git a/app/src/main/cpp/media/RTSPRecorder.cpp b/app/src/main/cpp/media/RTSPRecorder.cpp index 32706cb8..c06d69e8 100644 --- a/app/src/main/cpp/media/RTSPRecorder.cpp +++ b/app/src/main/cpp/media/RTSPRecorder.cpp @@ -222,22 +222,27 @@ void dumpRtspToMp4(const char* rtspUrl, const char* outputPath, uint32_t duratio // Set the custom log callback av_log_set_callback(ffmpeg_log_callback); - av_log_set_level(AV_LOG_WARNING); + av_log_set_level(AV_LOG_VERBOSE); #endif + std::string url = rtspUrl; AVDictionary* options = NULL; av_dict_set(&options, "rtsp_transport", "tcp", 0); av_dict_set(&options, "stimeout", "5000000", 0); if (!userName.empty()) { - // av_dict_set(&options, "rtsp_user", userName.c_str(), 0); // Replace with actual username - // av_dict_set(&options, "rtsp_password", password.c_str(), 0); // Replace with actual password - } + av_dict_set(&options, "username", userName.c_str(), 0); // Replace with actual username + av_dict_set(&options, "password", password.c_str(), 0); // Replace with actual password + + char auth[512] = { 0 }; + snprintf(auth, sizeof(auth), "%s:%s@", userName.c_str(), password.c_str()); + url.insert(url.begin() + 7, auth, auth + strlen(auth)); + } // Open input RTSP stream - int res = avformat_open_input(&inputFormatContext, rtspUrl, nullptr, &options); + int res = avformat_open_input(&inputFormatContext, url.c_str(), nullptr, &options); av_dict_free(&options); if (res != 0) { char errbuf[AV_ERROR_MAX_STRING_SIZE]; diff --git a/app/src/main/cpp/netcamera/HangYuCtrl.h b/app/src/main/cpp/netcamera/HangYuCtrl.h index 3cb86ede..4096fb45 100644 --- a/app/src/main/cpp/netcamera/HangYuCtrl.h +++ b/app/src/main/cpp/netcamera/HangYuCtrl.h @@ -19,6 +19,7 @@ public: virtual bool UpdateTime(time_t ts); virtual bool TakePhoto(std::vector& img); virtual bool TakeVideo(uint32_t duration, std::string path); + virtual bool HasAuthOnStreaming() const { return true; } private: