diff --git a/app/src/main/cpp/MicroPhoto.cpp b/app/src/main/cpp/MicroPhoto.cpp index a7f1a29c..fcf6e6a9 100644 --- a/app/src/main/cpp/MicroPhoto.cpp +++ b/app/src/main/cpp/MicroPhoto.cpp @@ -27,6 +27,12 @@ #include #endif +#ifdef USING_FFMPEG +extern "C" { +#include +} +#endif + #include #include @@ -235,6 +241,11 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) mosquitto_lib_init(); #endif +#ifdef USING_FFMPEG + // av_register_all(); + avformat_network_init(); +#endif + return result; } @@ -245,6 +256,11 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved) #endif curl_global_cleanup(); + +#ifdef USING_FFMPEG + // av_register_all(); + avformat_network_deinit(); +#endif } bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread) diff --git a/app/src/main/cpp/PhoneDevice.cpp b/app/src/main/cpp/PhoneDevice.cpp index 132cbe7c..39ac3718 100644 --- a/app/src/main/cpp/PhoneDevice.cpp +++ b/app/src/main/cpp/PhoneDevice.cpp @@ -1822,7 +1822,19 @@ bool CPhoneDevice::TakeVideoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c std::string tmpFile = m_appPath + (APP_PATH_TMP DIR_SEP_STR) + std::to_string(localPhotoInfo.photoId) + ".mp4"; // RTSPToMP4 dumper(netPhotoInfo.url, tmpFile.c_str(), localPhotoInfo.duration * 1000); // dumper.start(); - dumpRtspToMp4(streamingUrl.c_str(), tmpFile.c_str(), localPhotoInfo.duration * 1000, localPhotoInfo.userName, localPhotoInfo.password, GetEthnetHandle()); + XYLOG(XYLOG_SEVERITY_DEBUG, "Start Recording CH=%u PR=%X PHOTOID=%u", (uint32_t)localPhotoInfo.channel, (unsigned int)localPhotoInfo.preset, localPhotoInfo.photoId); + + if (vendorCtrl->HasAuthOnStreaming()) + { + dumpRtspToMp4(streamingUrl.c_str(), tmpFile.c_str(), localPhotoInfo.duration * 1000, localPhotoInfo.userName, localPhotoInfo.password, GetEthnetHandle()); + } + else + { + dumpRtspToMp4(streamingUrl.c_str(), tmpFile.c_str(), localPhotoInfo.duration * 1000, "", "", GetEthnetHandle()); + } + + XYLOG(XYLOG_SEVERITY_DEBUG, "Stop Recording CH=%u PR=%X PHOTOID=%u", (uint32_t)localPhotoInfo.channel, (unsigned int)localPhotoInfo.preset, localPhotoInfo.photoId); + ethernetPowerCtrl.reset(); XYLOG(XYLOG_SEVERITY_DEBUG, "Ethernet Power OFF"); @@ -1837,7 +1849,7 @@ bool CPhoneDevice::TakeVideoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c else { TakePhotoCb(0, localPhotoInfo, "", 0); - XYLOG(XYLOG_SEVERITY_ERROR, "Failed to TP on NET Camera CH=%u PR=%X PHOTOID=%u URL=http://%s%s", (uint32_t)localPhotoInfo.channel, (uint32_t)localPhotoInfo.preset, + XYLOG(XYLOG_SEVERITY_ERROR, "Failed to TP on NET Camera CH=%u PR=%X PHOTOID=%u URL=%s", (uint32_t)localPhotoInfo.channel, (uint32_t)localPhotoInfo.preset, localPhotoInfo.photoId, ip, streamingUrl.c_str()); } // Notify to take next photo diff --git a/app/src/main/cpp/media/RTSPRecorder.cpp b/app/src/main/cpp/media/RTSPRecorder.cpp index a7324a34..32706cb8 100644 --- a/app/src/main/cpp/media/RTSPRecorder.cpp +++ b/app/src/main/cpp/media/RTSPRecorder.cpp @@ -218,14 +218,11 @@ void dumpRtspToMp4(const char* rtspUrl, const char* outputPath, uint32_t duratio AVFormatContext* outputFormatContext = nullptr; AVPacket packet; - av_register_all(); - avformat_network_init(); - #ifndef NDEBUG // Set the custom log callback av_log_set_callback(ffmpeg_log_callback); - av_log_set_level(AV_LOG_TRACE); + av_log_set_level(AV_LOG_WARNING); #endif @@ -270,6 +267,11 @@ void dumpRtspToMp4(const char* rtspUrl, const char* outputPath, uint32_t duratio AVStream* inStream = inputFormatContext->streams[i]; const AVCodecParameters *in_codecpar = inStream->codecpar; + // Skip audio streams + if (inStream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + continue; + } + if (in_codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { // Copy video stream as-is const AVCodec *codec = avcodec_find_decoder(in_codecpar->codec_id); @@ -359,7 +361,7 @@ void dumpRtspToMp4(const char* rtspUrl, const char* outputPath, uint32_t duratio auto startTime = av_gettime(); // int64_t durationNs = (int64_t)duration * 1000000; - int64_t durationNs = (int64_t)duration * 1000; + int64_t durationNs = (int64_t)(duration + 32) * 1000; // Read packets from input and write them to output while (1) { @@ -385,8 +387,29 @@ void dumpRtspToMp4(const char* rtspUrl, const char* outputPath, uint32_t duratio #endif if (av_read_frame(inputFormatContext, &packet) < 0) break; - av_write_frame(outputFormatContext, &packet); + + // Skip audio packets + if (inputFormatContext->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) + { + av_packet_unref(&packet); + continue; + } + + // Adjust packet timebase + AVStream *in_stream = inputFormatContext->streams[packet.stream_index]; + AVStream *out_stream = outputFormatContext->streams[packet.stream_index]; + av_packet_rescale_ts(&packet, in_stream->time_base, out_stream->time_base); + packet.pos = -1; + + res = av_write_frame(outputFormatContext, &packet); + av_packet_unref(&packet); + + if (res < 0) + { + break; + } + } // stop_thread.join(); diff --git a/app/src/main/cpp/netcamera/VendorCtrl.h b/app/src/main/cpp/netcamera/VendorCtrl.h index 052fed9f..84676581 100644 --- a/app/src/main/cpp/netcamera/VendorCtrl.h +++ b/app/src/main/cpp/netcamera/VendorCtrl.h @@ -20,6 +20,7 @@ public: virtual bool UpdateTime(time_t ts) = 0; virtual bool TakePhoto(std::vector& img) = 0; virtual bool TakeVideo(uint32_t duration, std::string path) = 0; + virtual bool HasAuthOnStreaming() const { return false; } protected: