├── .gitignore ├── monitor ├── video_detect │ ├── CMakeLists.txt │ ├── video_detect.h │ ├── video_detect_impl.h │ └── video_detect_impl.cpp ├── live │ ├── CMakeLists.txt │ ├── rtmp_streamer.h │ ├── live.h │ ├── rtmp.h │ ├── streamer.h │ ├── rtmp_streamer.cpp │ └── rtmp.cpp ├── record │ ├── CMakeLists.txt │ ├── mp4_muxer.h │ ├── record.h │ ├── mp4_record.h │ ├── mp4_muxer.cpp │ └── mp4_record.cpp ├── common │ ├── CMakeLists.txt │ ├── system.h │ ├── res_code.h │ ├── config.h │ ├── buffer.h │ ├── config.cpp │ └── system.cpp ├── video_capture │ ├── CMakeLists.txt │ ├── video_capture.h │ ├── video_capture_impl.h │ └── video_capture_impl.cpp ├── video_codec │ ├── CMakeLists.txt │ ├── video_codec.h │ ├── video_codec_define.h │ ├── video_codec_impl.h │ └── video_codec_impl.cpp ├── video_process │ ├── CMakeLists.txt │ ├── osd.h │ ├── video_process.h │ ├── video_process_impl.h │ ├── osd.cpp │ └── video_process_impl.cpp ├── video │ ├── video_frame.h │ └── video_sink_interface.h ├── CMakeLists.txt ├── global.h └── main.cpp ├── README.md ├── conf └── config.json ├── LICENSE ├── CMakeLists.txt └── 3rdparty.cmake /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .vscode 3 | autobuild -------------------------------------------------------------------------------- /monitor/video_detect/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(video_detect 2 | video_detect_impl.cpp 3 | ) 4 | -------------------------------------------------------------------------------- /monitor/live/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(live 2 | rtmp.cpp 3 | rtmp_streamer.cpp 4 | ) 5 | 6 | add_dependencies(live 7 | common 8 | ) -------------------------------------------------------------------------------- /monitor/record/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(record 2 | mp4_muxer.cpp 3 | mp4_record.cpp 4 | ) 5 | 6 | add_dependencies(record 7 | common 8 | ) -------------------------------------------------------------------------------- /monitor/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(common 2 | config.cpp 3 | system.cpp 4 | ) 5 | 6 | add_dependencies(common 7 | thirdparty 8 | ) 9 | -------------------------------------------------------------------------------- /monitor/video_capture/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(video_capture 2 | video_capture_impl.cpp 3 | ) 4 | 5 | add_dependencies(video_capture 6 | common 7 | ) -------------------------------------------------------------------------------- /monitor/video_codec/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(video_codec 2 | video_codec_impl.cpp 3 | ) 4 | 5 | add_dependencies(video_codec 6 | common 7 | ) 8 | 9 | 10 | -------------------------------------------------------------------------------- /monitor/video_process/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(video_process 2 | video_process_impl.cpp 3 | ) 4 | 5 | 6 | add_dependencies(video_process 7 | common 8 | ) 9 | 10 | 11 | -------------------------------------------------------------------------------- /monitor/video/video_frame.h: -------------------------------------------------------------------------------- 1 | #ifndef VIDEO_FRAME_H_ 2 | #define VIDEO_FRAME_H_ 3 | 4 | namespace nvr 5 | { 6 | 7 | struct VideoFrame 8 | { 9 | virtual ~VideoFrame() = default; 10 | 11 | uint8_t *data; 12 | 13 | uint32_t len; 14 | 15 | uint64_t ts; 16 | 17 | int32_t type; 18 | }; 19 | 20 | } // namespace nvr 21 | 22 | #endif -------------------------------------------------------------------------------- /monitor/video/video_sink_interface.h: -------------------------------------------------------------------------------- 1 | #ifndef VIDEO_SINK_INTERFACE_H_ 2 | #define VIDEO_SINK_INTERFACE_H_ 3 | 4 | namespace nvr 5 | { 6 | 7 | template 8 | class VideoSinkInterface 9 | { 10 | public: 11 | virtual ~VideoSinkInterface() = default; 12 | 13 | virtual void OnFrame(const VideoFrameT &) = 0; 14 | }; 15 | 16 | } // namespace nvr 17 | 18 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 海思IPC 2 | ===== 3 | 4 | 5 | 基于 *****hi3516A***** SOC开发,可进行rtmp推流、移动侦测、mp4录制。 6 | 7 | #### 依赖库: 8 | - srs_rtmp 9 | - mp4v2 10 | - jsoncpp 11 | 12 | #### 编译方法: 13 | 已经将交叉编译后的库上传到[https://github.com/lam2003/monitor_3rdparty.git](https://github.com/lam2003/monitor_3rdparty.git) 14 | ``` 15 | #安装交叉工具链arm-hisiv500-linux(uclib) 16 | #进入源码根目录 17 | mkdir ./build 18 | cmake ../ 19 | #自动下载依赖 20 | make 21 | #编译好的elf在./build/bin/monitor 22 | #在开发板上运行 23 | ./monitor -c [配置文件路径] 24 | ``` 25 | -------------------------------------------------------------------------------- /monitor/video_capture/video_capture.h: -------------------------------------------------------------------------------- 1 | #ifndef VIDEO_CAPTRUE_MODULE_H_ 2 | #define VIDEO_CAPTURE_MODULE_H_ 3 | 4 | #include 5 | #include 6 | 7 | namespace nvr 8 | { 9 | 10 | class VideoCaptureModule : public rtc::RefCountInterface 11 | { 12 | public: 13 | 14 | virtual int32_t Initialize() = 0; 15 | 16 | virtual void Close() = 0; 17 | 18 | protected: 19 | ~VideoCaptureModule() override {} 20 | 21 | }; 22 | 23 | } // namespace nvr 24 | 25 | #endif -------------------------------------------------------------------------------- /conf/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "video": { 3 | "frame_rate": 25, 4 | "width": 1280, 5 | "height": 720, 6 | "codec_mode": "CBR", 7 | "codec_profile": 2, 8 | "codec_bitrate": 2048 9 | }, 10 | "detect": { 11 | "trigger_thresh": 1 12 | }, 13 | "record":{ 14 | "segment_duration":3600, 15 | "path":"/nfs/record", 16 | "use_md": true, 17 | "md_duration" : 60 18 | }, 19 | "rtmp":{ 20 | "url":"rtmp://127.0.0.1:1935/live/test" 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /monitor/video_process/osd.h: -------------------------------------------------------------------------------- 1 | // #ifndef OSD_H_ 2 | // #define OSD_H_ 3 | 4 | // #include 5 | // #include 6 | 7 | // namespace nvr 8 | // { 9 | // class OSD 10 | // { 11 | // public: 12 | // static OSD *Instance(); 13 | 14 | // ~OSD(); 15 | 16 | // int32_t Initialize(); 17 | 18 | // void close(); 19 | 20 | // private: 21 | // OSD(); 22 | 23 | // private: 24 | // SDL_PixelFormat *fmt_; 25 | // TTF_Font *font_; 26 | // bool init_; 27 | // }; 28 | // }; // namespace nvr 29 | 30 | // #endif -------------------------------------------------------------------------------- /monitor/live/rtmp_streamer.h: -------------------------------------------------------------------------------- 1 | #ifndef RTMP_STREAM_H_ 2 | #define RTMP_STREAM_H_ 3 | 4 | #include "live/streamer.h" 5 | 6 | #include 7 | 8 | namespace nvr 9 | { 10 | class RTMPStreamer : public Streamer 11 | { 12 | public: 13 | RTMPStreamer(); 14 | 15 | ~RTMPStreamer() override; 16 | 17 | int32_t Initialize(const std::string &u) override; 18 | 19 | void Close() override; 20 | 21 | int32_t WriteVideoFrame(const VideoFrame &frame) override; 22 | 23 | private: 24 | srs_rtmp_t rtmp_; 25 | bool init_; 26 | }; 27 | }; // namespace nvr 28 | 29 | #endif -------------------------------------------------------------------------------- /monitor/live/live.h: -------------------------------------------------------------------------------- 1 | #ifndef LIVE_MODULE_H_ 2 | #define LIVE_MODULE_H_ 3 | 4 | #include "video_codec/video_codec_define.h" 5 | #include "video/video_sink_interface.h" 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace nvr 13 | { 14 | class LiveModule : public rtc::RefCountInterface, public VideoSinkInterface 15 | { 16 | public: 17 | struct Params 18 | { 19 | std::string url; 20 | }; 21 | 22 | virtual int32_t Initialize(const Params ¶ms) = 0; 23 | 24 | virtual void Close() = 0; 25 | 26 | virtual void OnFrame(const VideoFrame &) override = 0; 27 | 28 | protected: 29 | ~LiveModule() override = default; 30 | }; 31 | }; // namespace nvr 32 | 33 | #endif -------------------------------------------------------------------------------- /monitor/record/mp4_muxer.h: -------------------------------------------------------------------------------- 1 | #ifndef MP4_MUXER_H_ 2 | #define MP4_MUXER_H_ 3 | 4 | #include "video_codec/video_codec_define.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace nvr 11 | { 12 | 13 | class MP4Muxer 14 | { 15 | public: 16 | MP4Muxer(); 17 | 18 | ~MP4Muxer(); 19 | 20 | int32_t Initialize(const std::string &filename, int width, int height, int frame_rate); 21 | 22 | int32_t WriteVideoFrame(const VideoFrame &frame); 23 | 24 | void Close(); 25 | private: 26 | int32_t WriteMetaData(); 27 | 28 | private: 29 | MP4FileHandle handle_; 30 | MP4TrackId track_; 31 | int width_; 32 | int height_; 33 | int frame_rate_; 34 | bool write_meta_; 35 | bool init_; 36 | 37 | }; 38 | } // namespace nvr 39 | #endif -------------------------------------------------------------------------------- /monitor/video_process/video_process.h: -------------------------------------------------------------------------------- 1 | #ifndef VIDEO_PROCESS_MODULE_H_ 2 | #define VIDEO_PROCESS_MODULE_H_ 3 | 4 | #include "video/video_sink_interface.h" 5 | 6 | #include 7 | #include 8 | 9 | namespace nvr 10 | { 11 | class VideoProcessModule : public rtc::RefCountInterface 12 | { 13 | public: 14 | struct Params 15 | { 16 | int32_t frame_rate; 17 | int32_t encode_width; 18 | int32_t encode_height; 19 | }; 20 | 21 | virtual int32_t Initialize(const Params ¶ms) = 0; 22 | 23 | virtual void Close() = 0; 24 | 25 | virtual void SetVideoSink(VideoSinkInterface *video_sink) = 0; 26 | 27 | protected: 28 | ~VideoProcessModule() override{}; 29 | }; 30 | }; // namespace nvr 31 | 32 | #endif -------------------------------------------------------------------------------- /monitor/live/rtmp.h: -------------------------------------------------------------------------------- 1 | #ifndef RTMP_H_ 2 | #define RTMP_H_ 3 | 4 | #include "live/live.h" 5 | #include "common/buffer.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace nvr 13 | { 14 | class RtmpLiveImpl : public LiveModule 15 | { 16 | public: 17 | static rtc::scoped_refptr Create(const Params ¶ms); 18 | 19 | int32_t Initialize(const Params ¶ms) override; 20 | 21 | void Close() override; 22 | 23 | void OnFrame(const VideoFrame &frame) override; 24 | 25 | protected: 26 | RtmpLiveImpl(); 27 | 28 | ~RtmpLiveImpl() override; 29 | 30 | private: 31 | Buffer<> buffer_; 32 | std::mutex mux_; 33 | std::condition_variable cond_; 34 | bool run_; 35 | std::unique_ptr thread_; 36 | bool init_; 37 | }; 38 | } // namespace nvr 39 | 40 | #endif -------------------------------------------------------------------------------- /monitor/video_codec/video_codec.h: -------------------------------------------------------------------------------- 1 | #ifndef VIDEO_CODEC_MODULE_H_ 2 | #define VIDEO_CODEC_MODULE_H_ 3 | 4 | #include "video/video_sink_interface.h" 5 | #include "video_codec/video_codec_define.h" 6 | 7 | #include 8 | #include 9 | 10 | namespace nvr 11 | { 12 | 13 | class VideoCodecModule : public rtc::RefCountInterface 14 | { 15 | public: 16 | struct Params 17 | { 18 | int32_t frame_rate; 19 | int32_t width; 20 | int32_t height; 21 | VideoCodecMode codec_mode; 22 | int32_t profile; 23 | int32_t bitrate; 24 | }; 25 | 26 | virtual int32_t Initialize(const Params ¶ms) = 0; 27 | 28 | virtual void Close() = 0; 29 | 30 | virtual void AddVideoSink(VideoSinkInterface *video_sink) = 0; 31 | 32 | virtual void ClearVideoSink() = 0; 33 | 34 | protected: 35 | ~VideoCodecModule() override {} 36 | }; 37 | }; // namespace nvr 38 | 39 | #endif -------------------------------------------------------------------------------- /monitor/common/system.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSTEM_H_ 2 | #define SYSTEM_H_ 3 | 4 | #include "global.h" 5 | 6 | #include 7 | 8 | namespace nvr 9 | { 10 | struct System 11 | { 12 | static int32_t InitMPP(); 13 | 14 | static void UnInitMPP(); 15 | 16 | static void InitLogger(); 17 | 18 | static inline int32_t Align(int num, int align = ALIGN) 19 | { 20 | return (num + align - 1) & ~(align - 1); 21 | } 22 | 23 | static int32_t CalcPicVbBlkSize(int width, int height, int align = ALIGN); 24 | 25 | static uint64_t GetSteadyMilliSeconds(); 26 | 27 | static int32_t VIBindVPSS(); 28 | 29 | static int32_t VIUnBindVPSS(); 30 | 31 | static int32_t VPSSBindVENC(); 32 | 33 | static int32_t VPSSUnBindVENC(); 34 | 35 | static int32_t CreateDir(const std::string &path); 36 | 37 | static std::string GetLocalTime(const std::string &format); 38 | }; 39 | } // namespace nvr 40 | #endif -------------------------------------------------------------------------------- /monitor/video_codec/video_codec_define.h: -------------------------------------------------------------------------------- 1 | #ifndef VIDEO_CODEC_DEFINE_H_ 2 | #define VIDEO_CODEC_DEFINE_H_ 3 | 4 | #include "video/video_frame.h" 5 | 6 | #include 7 | 8 | namespace nvr 9 | { 10 | 11 | enum VideoCodecMode 12 | { 13 | CBR = 0, 14 | VBR, 15 | AVBR 16 | }; 17 | 18 | struct H264Frame : public VideoFrame 19 | { 20 | enum NaluType 21 | { 22 | PSLICE = 1, 23 | ISLICE = 5, 24 | SEI = 6, 25 | SPS = 7, 26 | PPS = 8, 27 | }; 28 | 29 | ~H264Frame() override {} 30 | }; 31 | 32 | static VideoCodecMode StringToCodecMode(const std::string &str){ 33 | 34 | if (strcasecmp(str.c_str(), "CBR") == 0) 35 | return CBR; 36 | 37 | if (strcasecmp(str.c_str(), "VBR") == 0) 38 | return VBR; 39 | 40 | if (strcasecmp(str.c_str(), "AVBR") == 0) 41 | return AVBR; 42 | 43 | return CBR; 44 | } 45 | 46 | }; // namespace nvr 47 | #endif -------------------------------------------------------------------------------- /monitor/video_detect/video_detect.h: -------------------------------------------------------------------------------- 1 | #ifndef VIDEO_DETECT_MODULE_H_ 2 | #define VIDEO_DETECT_MODULE_H_ 3 | 4 | #include "video/video_sink_interface.h" 5 | #include "video/video_frame.h" 6 | 7 | #include 8 | #include 9 | 10 | namespace nvr 11 | { 12 | class DetectListener 13 | { 14 | public: 15 | virtual ~DetectListener() {} 16 | virtual void OnTrigger(int32_t num) = 0; 17 | }; 18 | 19 | class VideoDetectModule : public rtc::RefCountInterface, public VideoSinkInterface 20 | { 21 | public: 22 | struct Params 23 | { 24 | int32_t trigger_thresh; 25 | }; 26 | 27 | virtual int32_t Initialize(const Params ¶ms) = 0; 28 | 29 | virtual void Close() = 0; 30 | 31 | virtual void OnFrame(const VIDEO_FRAME_INFO_S &frame) = 0; 32 | 33 | virtual void AddListener(DetectListener *listener) = 0; 34 | 35 | protected: 36 | ~VideoDetectModule() override {} 37 | }; 38 | }; // namespace nvr 39 | 40 | #endif -------------------------------------------------------------------------------- /monitor/video_capture/video_capture_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef VIDEO_CAPTURE_IMPL_H_ 2 | #define VIDEO_CAPTURE_IMPL_H_ 3 | 4 | #include "video_capture/video_capture.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace nvr 11 | { 12 | class VideoCaptureImpl : public VideoCaptureModule 13 | { 14 | public: 15 | static rtc::scoped_refptr Create(); 16 | 17 | int32_t Initialize() override; 18 | 19 | void Close() override; 20 | 21 | protected: 22 | ~VideoCaptureImpl() override; 23 | 24 | VideoCaptureImpl(); 25 | 26 | private: 27 | int32_t StartMIPI(); 28 | 29 | int32_t InitISP(); 30 | 31 | void UnInitISP(); 32 | 33 | void StartISP(); 34 | 35 | void StopISP(); 36 | 37 | int32_t StartVI(); 38 | 39 | void StopVI(); 40 | 41 | int32_t StartVIChn(); 42 | 43 | void StopVIChn(); 44 | 45 | private: 46 | std::unique_ptr thread_; 47 | bool init_; 48 | }; 49 | } // namespace nvr 50 | 51 | #endif -------------------------------------------------------------------------------- /monitor/record/record.h: -------------------------------------------------------------------------------- 1 | #ifndef RECORD_MODULE_H_ 2 | #define RECORD_MODULE_H_ 3 | 4 | #include "video_codec/video_codec_define.h" 5 | #include "video/video_sink_interface.h" 6 | #include "video_detect/video_detect.h" 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace nvr 14 | { 15 | class RecordModule : public rtc::RefCountInterface, public VideoSinkInterface, public DetectListener 16 | { 17 | public: 18 | struct Params 19 | { 20 | int frame_rate; 21 | int width; 22 | int height; 23 | std::string path; 24 | int segment_duration; 25 | bool use_md; 26 | int md_duration; 27 | }; 28 | virtual int32_t Initialize(const Params ¶ms) = 0; 29 | 30 | virtual void Close() = 0; 31 | 32 | virtual void OnFrame(const VideoFrame &) override = 0; 33 | 34 | virtual void OnTrigger(int32_t num) override = 0; 35 | 36 | protected: 37 | virtual ~RecordModule() override = default; 38 | }; 39 | } // namespace nvr 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /monitor/live/streamer.h: -------------------------------------------------------------------------------- 1 | #ifndef STREAMER_H_ 2 | #define STREAMER_H_ 3 | 4 | #include "video_codec/video_codec_define.h" 5 | 6 | #include 7 | 8 | namespace nvr 9 | { 10 | class Streamer 11 | { 12 | public: 13 | virtual ~Streamer() {} 14 | 15 | virtual int32_t Initialize(const std::string &url, 16 | int32_t width, 17 | int32_t height, 18 | int32_t frame_rate, 19 | const std::string &sps, 20 | const std::string &pps) { return 0; } 21 | 22 | virtual int32_t Initialize(const std::string &url, 23 | int32_t width, 24 | int32_t height, 25 | int32_t frame_rate) { return 0; } 26 | 27 | virtual int32_t Initialize(const std::string &url) { return 0; } 28 | 29 | virtual void Close() = 0; 30 | 31 | virtual int32_t WriteVideoFrame(const VideoFrame &frame) = 0; 32 | }; 33 | } // namespace nvr 34 | 35 | #endif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 linmin(admin@linmin.xyz) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /monitor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(common) 2 | add_subdirectory(video_capture) 3 | add_subdirectory(video_process) 4 | add_subdirectory(video_detect) 5 | add_subdirectory(video_codec) 6 | add_subdirectory(live) 7 | add_subdirectory(record) 8 | 9 | add_executable(monitor 10 | main.cpp 11 | ) 12 | 13 | add_dependencies(monitor 14 | common 15 | video_capture 16 | video_process 17 | video_detect 18 | video_codec 19 | live 20 | record 21 | ) 22 | 23 | 24 | target_link_libraries(monitor 25 | #hisi 26 | libmpi.so 27 | libive.so 28 | libmd.so 29 | libVoiceEngine.so 30 | libupvqe.so 31 | libdnvqe.so 32 | lib_hiae.so 33 | libisp.so 34 | libsns_imx290.so 35 | lib_hiae.so 36 | lib_hiawb.so 37 | lib_hiaf.so 38 | lib_hidefog.so 39 | pthread 40 | dl 41 | m 42 | #thirdparty 43 | libeasylogger.a 44 | libmp4v2.a 45 | libjsoncpp.a 46 | ${PROJECT_BINARY_DIR}/lib/srs_librtmp.a 47 | #self 48 | common 49 | video_capture 50 | video_process 51 | video_detect 52 | video_codec 53 | live 54 | record 55 | ) 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /monitor/video_codec/video_codec_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef VIDEO_CODEC_IMPL_H_ 2 | #define VIDEO_CODEC_IMPL_H_ 3 | 4 | #include "video_codec/video_codec.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace nvr 12 | { 13 | 14 | class VideoCodecImpl : public VideoCodecModule 15 | { 16 | public: 17 | static rtc::scoped_refptr Create(const Params ¶ms); 18 | 19 | int32_t Initialize(const Params ¶ms) override; 20 | 21 | void Close() override; 22 | 23 | void AddVideoSink(VideoSinkInterface *video_sink) override; 24 | 25 | void ClearVideoSink() override; 26 | 27 | protected: 28 | VideoCodecImpl(); 29 | 30 | ~VideoCodecImpl() override; 31 | 32 | private: 33 | int32_t StartVENCChn(const Params ¶ms); 34 | 35 | void StopVENCChn(); 36 | 37 | void StartGetStreamThread(const Params ¶ms); 38 | 39 | void StopGetStreamThread(); 40 | 41 | private: 42 | std::mutex mux_; 43 | bool run_; 44 | std::unique_ptr thread_; 45 | std::vector *> video_sinks_; 46 | bool init_; 47 | }; 48 | }; // namespace nvr 49 | 50 | #endif -------------------------------------------------------------------------------- /monitor/record/mp4_record.h: -------------------------------------------------------------------------------- 1 | #ifndef MP4_RECORD_H_ 2 | #define MP4_RECORD_H_ 3 | 4 | #include "record/record.h" 5 | #include "common/buffer.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace nvr 14 | { 15 | class MP4RecordImpl : public RecordModule 16 | { 17 | public: 18 | static rtc::scoped_refptr Create(const Params ¶ms); 19 | 20 | int32_t Initialize(const Params ¶ms) override; 21 | 22 | void Close() override; 23 | 24 | void OnFrame(const VideoFrame &) override; 25 | 26 | void OnTrigger(int32_t num) override; 27 | 28 | protected: 29 | MP4RecordImpl(); 30 | 31 | ~MP4RecordImpl() override; 32 | 33 | private: 34 | void RecordThread(); 35 | bool RecordNeedToQuit(); 36 | bool RecordNeedToSegment(uint64_t start_time); 37 | 38 | private: 39 | std::mutex mux_; 40 | std::condition_variable cond_; 41 | Buffer<> buffer_; 42 | Params params_; 43 | std::atomic end_time_; 44 | bool run_; 45 | std::unique_ptr thread_; 46 | bool init_; 47 | }; 48 | 49 | } // namespace nvr 50 | 51 | #endif -------------------------------------------------------------------------------- /monitor/video_detect/video_detect_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef VIDEO_DETECT_IMPL_H_ 2 | #define VIDEO_DETECT_IMPL_H_ 3 | 4 | #include "video_detect/video_detect.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace nvr 12 | { 13 | 14 | class VideoDetectImpl : public VideoDetectModule 15 | { 16 | public: 17 | static rtc::scoped_refptr Create(const Params ¶ms); 18 | 19 | int32_t Initialize(const Params ¶ms) override; 20 | 21 | void Close() override; 22 | 23 | void OnFrame(const VIDEO_FRAME_INFO_S &frame) override; 24 | 25 | void AddListener(DetectListener *listener) override; 26 | 27 | protected: 28 | VideoDetectImpl(); 29 | 30 | ~VideoDetectImpl() override; 31 | 32 | private: 33 | int32_t StartMD(); 34 | 35 | void StopMD(); 36 | 37 | int32_t AllocMemory(); 38 | 39 | void FreeMemory(); 40 | 41 | int32_t IVEDMAImage(const VIDEO_FRAME_INFO_S &frame_info, const IVE_DST_IMAGE_S &dst_image, HI_BOOL instant); 42 | 43 | private: 44 | std::mutex mux_; 45 | IVE_SRC_IMAGE_S src_image_[2]; 46 | IVE_DST_MEM_INFO_S dst_mem_info_; 47 | int32_t trigger_thresh_; 48 | DetectListener *listener_; 49 | bool first_frame_; 50 | int index_; 51 | bool init_; 52 | }; 53 | }; // namespace nvr 54 | 55 | #endif -------------------------------------------------------------------------------- /monitor/video_process/video_process_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef VIDEO_PROCESS_IMPL_H_ 2 | #define VIDEO_PROCESS_IMPL_H_ 3 | 4 | #include "video_process/video_process.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace nvr 11 | { 12 | class VideoProcessImpl : public VideoProcessModule 13 | { 14 | public: 15 | static rtc::scoped_refptr Create(const Params ¶ms); 16 | 17 | int32_t Initialize(const Params ¶ms) override; 18 | 19 | void Close() override; 20 | 21 | void SetVideoSink(VideoSinkInterface *video_sink) override; 22 | 23 | protected: 24 | VideoProcessImpl(); 25 | 26 | ~VideoProcessImpl() override; 27 | 28 | private: 29 | int32_t StartVPSSGroup(const Params ¶ms); 30 | 31 | void StopVPSSGroup(); 32 | 33 | int32_t StartVPSSEncodeChn(const Params ¶ms); 34 | 35 | void StopVPSSEncodeChn(); 36 | 37 | int32_t StartVPSSDetectChn(const Params ¶ms); 38 | 39 | void StopVPSSDetectChn(); 40 | 41 | void StartProcessThread(const Params ¶ms); 42 | 43 | void StopProcessThread(); 44 | 45 | private: 46 | std::mutex mux_; 47 | bool run_; 48 | std::unique_ptr thread_; 49 | VideoSinkInterface *video_sink_; 50 | bool init_; 51 | }; 52 | } // namespace nvr 53 | 54 | #endif -------------------------------------------------------------------------------- /monitor/common/res_code.h: -------------------------------------------------------------------------------- 1 | #ifndef RES_CODE_H_ 2 | #define RES_CODE_H_ 3 | 4 | #include 5 | 6 | enum err_code 7 | { 8 | KSuccess = 0x0, 9 | KDupInitialize = 0x1, 10 | KMPPError = 0x3, 11 | KVIChnError = 0x4, 12 | KThirdPartyError = 0x5, 13 | KUnInitialize = 0x6, 14 | KSystemError = 0x7 15 | }; 16 | 17 | class NVRErrorCategory : public std::error_category 18 | { 19 | const char *name() const noexcept override 20 | { 21 | return "nvr"; 22 | } 23 | std::string message(int i) const override 24 | { 25 | switch (static_cast(i)) 26 | { 27 | case err_code::KSuccess: 28 | return "success"; 29 | case err_code::KDupInitialize: 30 | return "duplicate initialize"; 31 | case err_code::KMPPError: 32 | return "hisi mpp error"; 33 | case err_code::KThirdPartyError: 34 | return "thirdparty library error"; 35 | case err_code::KUnInitialize: 36 | return "not initialize"; 37 | case err_code::KSystemError: 38 | return "system error"; 39 | default: 40 | return "unknow"; 41 | } 42 | } 43 | }; 44 | 45 | namespace std 46 | { 47 | template <> 48 | struct is_error_code_enum : std::true_type 49 | { 50 | }; 51 | } // namespace std 52 | 53 | template 54 | struct is_error_code_enum : std::false_type 55 | { 56 | }; 57 | 58 | static NVRErrorCategory nvr_error_category; 59 | 60 | inline std::error_code 61 | make_error_code(err_code code) noexcept 62 | { 63 | return {static_cast(code), nvr_error_category}; 64 | } 65 | 66 | #endif -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | #配置交叉编译 4 | set(CMAKE_SYSTEM_NAME Linux) 5 | set(CMAKE_C_COMPILER arm-hisiv500-linux-gcc) 6 | SET(CMAKE_CXX_COMPILER arm-hisiv500-linux-g++) 7 | 8 | project(hisi_monitor 9 | VERSION 1.0.0 10 | LANGUAGES CXX) 11 | 12 | set(CMAKE_CXX_STANDARD 11) 13 | set(CMAKE_SKIP_RPATH true) 14 | set(CMAKE_BUILD_TYPE "Debug") 15 | 16 | #如果在选项中加入 -DALL_STATIC=1 使用静态gcc库以及静态g++库进行链接 17 | 18 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++") 19 | message(STATUS "project will link against gcc-static g++-static") 20 | 21 | 22 | #-fPIC 23 | set(CMAKE_POSITION_INDEPENDENT_CODE true) 24 | 25 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 26 | set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) 27 | 28 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=arm926ej-s -w -mno-unaligned-access -fno-aggressive-loop-optimizations -ffunction-sections -fdata-sections -Dhi3516ev100 -DSENSOR_TYPE=SONY_IMX290_MIPI_1080P_30FPS -DHI_RELEASE -DHI_XXXX -DISP_V2 -DHI_ACODEC_TYPE_INNER") 29 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcpu=arm926ej-s -w -mno-unaligned-access -fno-aggressive-loop-optimizations -ffunction-sections -fdata-sections -Dhi3516ev100 -DSENSOR_TYPE=SONY_IMX290_MIPI_1080P_30FPS -DHI_RELEASE -DHI_XXXX -DISP_V2 -DHI_ACODEC_TYPE_INNER") 30 | 31 | # -D__CMAKE_FILE__='\"$(notdir $(abspath $<))\"' 32 | include_directories( 33 | ${PROJECT_BINARY_DIR}/include 34 | ${PROJECT_SOURCE_DIR}/monitor 35 | ) 36 | 37 | link_directories( 38 | ${PROJECT_BINARY_DIR}/lib 39 | ) 40 | 41 | include(3rdparty.cmake) 42 | 43 | add_compile_options(-include global.h) 44 | 45 | add_subdirectory(monitor) 46 | 47 | -------------------------------------------------------------------------------- /monitor/common/config.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H_ 2 | #define CONFIG_H_ 3 | 4 | #include 5 | #include "video_codec/video_codec_define.h" 6 | 7 | namespace nvr 8 | { 9 | struct Config 10 | { 11 | struct Video 12 | { 13 | Video() 14 | { 15 | frame_rate = 25; 16 | width = 1280; 17 | height = 720; 18 | codec_mode = CBR; 19 | codec_profile = 0; 20 | codec_bitrate = 2000; 21 | } 22 | 23 | int32_t frame_rate; 24 | int32_t width; 25 | int32_t height; 26 | VideoCodecMode codec_mode; 27 | int32_t codec_profile; 28 | int32_t codec_bitrate; 29 | }; 30 | 31 | struct Detect 32 | { 33 | Detect() 34 | { 35 | trigger_thresh = 1; 36 | } 37 | int32_t trigger_thresh; 38 | }; 39 | struct Record 40 | { 41 | Record() 42 | { 43 | segment_duration = 3600; //second 44 | path = "/app/record"; 45 | use_md = true; 46 | md_duration = 60; //second 47 | }; 48 | 49 | int32_t segment_duration; 50 | std::string path; 51 | bool use_md; 52 | int32_t md_duration; 53 | }; 54 | 55 | struct Rtmp 56 | { 57 | Rtmp() 58 | { 59 | url = "rtmp://127.0.0.1:1935/live/monitor"; 60 | } 61 | 62 | std::string url; 63 | }; 64 | 65 | Video video; 66 | Detect detect; 67 | Rtmp rtmp; 68 | Record record; 69 | 70 | static Config *Instance() 71 | { 72 | static Config *instance = new Config; 73 | return instance; 74 | } 75 | 76 | int32_t ReadConfigFile(const std::string &config_file); 77 | 78 | 79 | }; 80 | } // namespace nvr 81 | 82 | #endif -------------------------------------------------------------------------------- /monitor/live/rtmp_streamer.cpp: -------------------------------------------------------------------------------- 1 | #include "live/rtmp_streamer.h" 2 | #include "common/res_code.h" 3 | 4 | namespace nvr 5 | { 6 | 7 | RTMPStreamer::RTMPStreamer() : rtmp_(nullptr), 8 | init_(false) 9 | { 10 | } 11 | 12 | RTMPStreamer::~RTMPStreamer() 13 | { 14 | Close(); 15 | } 16 | 17 | int32_t RTMPStreamer::Initialize(const std::string &url) 18 | { 19 | if (init_) 20 | return static_cast(KDupInitialize); 21 | 22 | rtmp_ = srs_rtmp_create(url.c_str()); 23 | if (srs_rtmp_handshake(rtmp_) != 0) 24 | { 25 | log_e("srs_rtmp_handshake failed"); 26 | return static_cast(KThirdPartyError); 27 | } 28 | 29 | if (srs_rtmp_connect_app(rtmp_) != 0) 30 | { 31 | log_e("srs_rtmp_connect_app failed"); 32 | return static_cast(KThirdPartyError); 33 | } 34 | 35 | if (srs_rtmp_publish_stream(rtmp_) != 0) 36 | { 37 | log_e("srs_rtmp_publish_stream failed"); 38 | return static_cast(KThirdPartyError); 39 | } 40 | 41 | init_ = true; 42 | 43 | return static_cast(KSuccess); 44 | } 45 | 46 | int32_t RTMPStreamer::WriteVideoFrame(const VideoFrame &frame) 47 | { 48 | #define ERROR_H264_DROP_BEFORE_SPS_PPS 3043 49 | #define ERROR_H264_DUPLICATED_SPS 3044 50 | #define ERROR_H264_DUPLICATED_PPS 3045 51 | if (!init_) 52 | return static_cast(KUnInitialize); 53 | 54 | int32_t ret; 55 | ret = srs_h264_write_raw_frames(rtmp_, (char *)frame.data, frame.len, frame.ts / 1000, frame.ts / 1000); 56 | if (ret != 0) 57 | { 58 | if (ret != ERROR_H264_DROP_BEFORE_SPS_PPS && 59 | ret != ERROR_H264_DUPLICATED_SPS && 60 | ret != ERROR_H264_DUPLICATED_PPS) 61 | { 62 | log_w("srs_h264_write_raw_frames failed,code %d", ret); 63 | return static_cast(KThirdPartyError); 64 | } 65 | } 66 | return static_cast(KSuccess); 67 | } 68 | 69 | void RTMPStreamer::Close() 70 | { 71 | if (!init_) 72 | return; 73 | srs_rtmp_destroy(rtmp_); 74 | init_ = false; 75 | } 76 | 77 | } // namespace nvr 78 | -------------------------------------------------------------------------------- /monitor/video_process/osd.cpp: -------------------------------------------------------------------------------- 1 | // #include "osd.h" 2 | 3 | // #include "common/config.h" 4 | // #include "common/res_code.h" 5 | 6 | // namespace nvr 7 | // { 8 | // OSD *OSD::Instance() 9 | // { 10 | // static OSD *instance = new OSD; 11 | // return instance; 12 | // } 13 | 14 | // OSD::~OSD() 15 | // { 16 | // } 17 | 18 | // OSD::OSD() : fmt_(nullptr), 19 | // font_(nullptr), 20 | // init_(false) 21 | // { 22 | // } 23 | 24 | // int32_t OSD::Initialize() 25 | // { 26 | // if (init_) 27 | // return static_cast(KDupInitialize); 28 | 29 | // if (TTF_Init() < 0) 30 | // { 31 | // log_e("TTF_Init failed"); 32 | // return static_cast(KThirdPartyError); 33 | // } 34 | 35 | // font_ = TTF_OpenFont(Config::Instance()->system.font_path.c_str(), Config::Instance()->system.font_size); 36 | // if (NULL == font_) 37 | // { 38 | // log_e("TTF_OpenFont failed"); 39 | // return static_cast(KThirdPartyError); 40 | // } 41 | 42 | // SDL_Color color = {0x0, 0x0, 0x0, 0x00}; 43 | // fmt_ = (SDL_PixelFormat *)malloc(sizeof(SDL_PixelFormat)); 44 | // memset(fmt_, 0, sizeof(SDL_PixelFormat)); 45 | // fmt_->BitsPerPixel = 16; 46 | // fmt_->BytesPerPixel = 1; 47 | // fmt_->Rmask = 0x7C00; 48 | // fmt_->Gmask = 0x03E0; 49 | // fmt_->Bmask = 0x001f; 50 | // fmt_->Amask = 0x8000; 51 | // // fmt_->format = SDL_PIXELFORMAT_ARGB1555; 52 | 53 | // std::string temp = "test"; 54 | // SDL_Surface *sdl_textsurface = TTF_RenderUTF8_Solid(font_, temp.c_str(), color); 55 | // // SDL_Surface *sdl_tmpsurface = SDL_CreateRGBSurface(SDL_SWSURFACE, sdl_textsurface->w, sdl_textsurface->h, 16, 0x7C00, 0x03E0, 0x001f, 0x8000); //ARGB1555 56 | // // SDL_Surface *sdl_tmpsurface = SDL_CreateRGBSurface(SDL_SWSURFACE, sdl_textsurface->w, sdl_textsurface->h, 16,0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); 57 | // // SDL_Rect bounds; 58 | // // bounds.x = 0; 59 | // // bounds.y = 0; 60 | // // bounds.w = sdl_textsurface->w; 61 | // // bounds.h = sdl_textsurface->h; 62 | // // SDL_LowerBlit(sdl_textsurface, &bounds, sdl_tmpsurface, &bounds); 63 | // SDL_SaveBMP(sdl_textsurface,"1.bmp"); 64 | // SDL_FreeSurface(sdl_textsurface); 65 | // // SDL_FreeSurface(sdl_tmpsurface); 66 | 67 | 68 | // init_ = true; 69 | 70 | // return static_cast(KSuccess); 71 | // } 72 | // } // namespace nvr -------------------------------------------------------------------------------- /monitor/common/buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef BUFFER_H_ 2 | #define BUFFER_H_ 3 | namespace nvr 4 | { 5 | template 6 | struct default_block_allocator_malloc_free 7 | { 8 | enum 9 | { 10 | requested_size = BlockSize 11 | }; 12 | 13 | static uint8_t *ordered_malloc() 14 | { 15 | return (uint8_t *)malloc(requested_size); 16 | } 17 | 18 | static void ordered_free(uint8_t *block) 19 | { 20 | free(block); 21 | } 22 | }; 23 | 24 | typedef default_block_allocator_malloc_free default_allocator; 25 | 26 | template //max 512K 27 | class Buffer 28 | { 29 | public: 30 | typedef BlockAllocator allocator; 31 | Buffer() 32 | { 33 | data_ = allocator::ordered_malloc(); 34 | start_pos_ = 0; 35 | end_pos_ = 0; 36 | } 37 | 38 | inline bool Append(uint8_t *data, uint32_t len) 39 | { 40 | if (FreeSpace() < len) 41 | return false; 42 | 43 | if (allocator::requested_size - end_pos_ < len) 44 | { 45 | uint32_t size = Size(); 46 | memmove(data_, data_ + start_pos_, size); 47 | start_pos_ = 0; 48 | end_pos_ = size; 49 | } 50 | memcpy(data_ + end_pos_, data, len); 51 | end_pos_ += len; 52 | return true; 53 | } 54 | 55 | inline bool Get(uint8_t *buf, uint32_t size) 56 | { 57 | if (Size() < size) 58 | return false; 59 | 60 | memcpy(buf, data_ + start_pos_, size); 61 | start_pos_ += size; 62 | return true; 63 | } 64 | inline uint32_t Size() const 65 | { 66 | return end_pos_ - start_pos_; 67 | } 68 | 69 | inline uint32_t FreeSpace() const 70 | { 71 | return allocator::requested_size - Size(); 72 | } 73 | 74 | inline uint8_t *GetCurrentPos() 75 | { 76 | return data_ + start_pos_; 77 | } 78 | 79 | inline bool Consume(uint32_t size) 80 | { 81 | if (Size() < size) 82 | return false; 83 | start_pos_ += size; 84 | return true; 85 | } 86 | 87 | inline void Clear() 88 | { 89 | start_pos_ = 0; 90 | end_pos_ = 0; 91 | } 92 | 93 | virtual ~Buffer() 94 | { 95 | allocator::ordered_free(data_); 96 | start_pos_ = 0; 97 | end_pos_ = 0; 98 | } 99 | 100 | private: 101 | uint8_t *data_; 102 | uint32_t start_pos_; 103 | uint32_t end_pos_; 104 | }; 105 | 106 | }; // namespace nvr 107 | 108 | #endif -------------------------------------------------------------------------------- /monitor/record/mp4_muxer.cpp: -------------------------------------------------------------------------------- 1 | #include "record/mp4_muxer.h" 2 | #include "common/res_code.h" 3 | 4 | namespace nvr 5 | { 6 | 7 | int32_t MP4Muxer::Initialize(const std::string &filename, int width, int height, int frame_rate) 8 | { 9 | if (init_) 10 | return static_cast(KDupInitialize); 11 | 12 | handle_ = MP4Create(filename.c_str()); 13 | if (handle_ == MP4_INVALID_FILE_HANDLE) 14 | { 15 | log_e("MP4Create failed"); 16 | return static_cast(KThirdPartyError); 17 | } 18 | 19 | width_ = width; 20 | height_ = height; 21 | frame_rate_ = frame_rate; 22 | 23 | init_ = true; 24 | 25 | return static_cast(KSuccess); 26 | } 27 | 28 | int32_t MP4Muxer::WriteVideoFrame(const VideoFrame &frame) 29 | { 30 | if (!init_) 31 | return static_cast(KUnInitialize); 32 | 33 | int32_t ret; 34 | 35 | if (!write_meta_ && frame.type == H264Frame::NaluType::SPS) 36 | { 37 | 38 | if (!MP4SetTimeScale(handle_, 900000)) 39 | { 40 | log_e("MP4SetTimeScale failed"); 41 | return static_cast(KThirdPartyError); 42 | } 43 | 44 | track_ = MP4AddH264VideoTrack(handle_, 900000, 900000 / frame_rate_, width_, height_, frame.data[5], frame.data[6], frame.data[7], 3); 45 | if (track_ == MP4_INVALID_TRACK_ID) 46 | { 47 | log_e("MP4AddH264VideoTrack failed"); 48 | return static_cast(KThirdPartyError); 49 | } 50 | 51 | write_meta_ = true; 52 | } 53 | 54 | if (write_meta_) 55 | { 56 | switch (frame.type) 57 | { 58 | case H264Frame::NaluType::SPS: 59 | MP4AddH264SequenceParameterSet(handle_, track_, &frame.data[4], frame.len - 4); 60 | break; 61 | 62 | case H264Frame::NaluType::PPS: 63 | case H264Frame::NaluType::SEI: 64 | MP4AddH264PictureParameterSet(handle_, track_, &frame.data[4], frame.len - 4); 65 | break; 66 | case H264Frame::NaluType::ISLICE: 67 | case H264Frame::NaluType::PSLICE: 68 | { 69 | uint32_t len = frame.len - 4; 70 | frame.data[0] = (len >> 24) & 0xff; 71 | frame.data[1] = (len >> 16) & 0xff; 72 | frame.data[2] = (len >> 8) & 0xff; 73 | frame.data[3] = len & 0xff; 74 | 75 | ret = MP4WriteSample(handle_, track_, frame.data, frame.len, MP4_INVALID_DURATION); 76 | if (!ret) 77 | { 78 | log_e("MP4WriteSample failed"); 79 | return static_cast(KThirdPartyError); 80 | } 81 | break; 82 | } 83 | 84 | default: 85 | log_w("unknow h264 frame type:%d", frame.type); 86 | break; 87 | } 88 | } 89 | 90 | return static_cast(KSuccess); 91 | } 92 | 93 | void MP4Muxer::Close() 94 | { 95 | if (!init_) 96 | return; 97 | 98 | MP4Close(handle_); 99 | handle_ = MP4_INVALID_FILE_HANDLE; 100 | track_ = MP4_INVALID_TRACK_ID; 101 | width_ = 0; 102 | height_ = 0; 103 | frame_rate_ = 0; 104 | write_meta_ = false; 105 | 106 | init_ = false; 107 | } 108 | 109 | MP4Muxer::MP4Muxer() : handle_(MP4_INVALID_FILE_HANDLE), 110 | track_(MP4_INVALID_TRACK_ID), 111 | width_(0), 112 | height_(0), 113 | frame_rate_(0), 114 | write_meta_(false), 115 | init_(false) 116 | { 117 | } 118 | 119 | MP4Muxer::~MP4Muxer() 120 | { 121 | Close(); 122 | } 123 | }; // namespace nvr -------------------------------------------------------------------------------- /monitor/global.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //stl 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | //system 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | //logger 24 | #include 25 | //hisi sdk 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | 63 | #define NVR_CHECK(condition) \ 64 | while (!(condition)) \ 65 | { \ 66 | log_e("failed when checking %s", #condition); \ 67 | exit(-1); \ 68 | } 69 | 70 | #define CHACK_ERROR(a) \ 71 | if (KSuccess != a) \ 72 | { \ 73 | log_e("error:%s", make_error_code(a).message().c_str()); \ 74 | return static_cast(a); \ 75 | } 76 | #define PRINT_FFMPEG_ERROR(a) \ 77 | do \ 78 | { \ 79 | char buf[1024]; \ 80 | av_strerror(a, buf, 1024); \ 81 | log_e("%s", buf); \ 82 | } while (0) 83 | 84 | #define PIC_WIDTH 1920 //mx290图像宽 85 | #define PIC_HEIGHT 1080 //mx290图像长 86 | #define FRAME_RATE 30 //mx290源帧率 87 | #define PIXEL_FORMAT PIXEL_FORMAT_YUV_SEMIPLANAR_420 //使用YUV420P 88 | #define PIC_SIZE PIC_HD1080 //1080P采样 89 | #define ALIGN 64 //默认内存对齐大小 90 | #define VB_POOLS_NUM 128 //缓冲池数量 91 | #define VB_MEM_BLK_NUM 5 //内存块数量(3516A100V内存不足,系统无法使用1080P) 92 | #define DETECT_WIDTH 720 //检测通道宽度 93 | #define DETECT_HEIGHT 480 //检测通道高度 94 | #define DETECT_MEM_BLK_NUM 1 //检测模块内存块数 95 | #define RECORD_DIR_FORMAT "%Y_%m_%d" //录制目录名称(日期格式) 96 | #define RECORD_FILE_FORMAT "%H_%M_%S" //录制文件名称(日期格式) 97 | #define BUFFER_LEN 524288 //缓存大小 98 | 99 | #define NVR_ISP_DEV 0 //ISP设备 100 | #define NVR_VI_DEV 0 //VI设备 101 | #define NVR_VI_CHN 0 //VI通道 102 | #define NVR_VPSS_GRP 0 //VPSS组 103 | #define NVR_VPSS_ENCODE_CHN 1 //VPSS编码通道 104 | #define NVR_VPSS_DETECT_CHN 2 //VPSS检测通道 105 | #define NVR_VENC_CHN 0 //VENC通道 106 | #define NVR_MD_CHN 0 //MD通道 107 | #define NVR_VDA_CHN 0 //VDA通道 108 | 109 | // arm-hisiv500-linux-g++不支持 110 | // template 111 | // T GLOBAL; -------------------------------------------------------------------------------- /monitor/live/rtmp.cpp: -------------------------------------------------------------------------------- 1 | #include "live/rtmp.h" 2 | #include "common/res_code.h" 3 | #include "live/rtmp_streamer.h" 4 | 5 | #include 6 | 7 | namespace nvr 8 | { 9 | 10 | rtc::scoped_refptr RtmpLiveImpl::Create(const Params ¶ms) 11 | { 12 | err_code code; 13 | 14 | rtc::scoped_refptr implemention = new rtc::RefCountedObject(); 15 | 16 | code = static_cast(implemention->Initialize(params)); 17 | 18 | if (KSuccess != code) 19 | { 20 | log_e("error:%s", make_error_code(code).message().c_str()); 21 | return nullptr; 22 | } 23 | 24 | return implemention; 25 | } 26 | 27 | int32_t RtmpLiveImpl::Initialize(const Params ¶ms) 28 | { 29 | if (init_) 30 | return static_cast(KDupInitialize); 31 | 32 | run_ = true; 33 | thread_ = std::unique_ptr(new std::thread([this, params]() { 34 | err_code code; 35 | RTMPStreamer rtmp_streamer; 36 | VideoFrame frame; 37 | bool wait_sps; 38 | 39 | bool init = false; 40 | 41 | uint8_t *temp_buf = (uint8_t *)malloc(BUFFER_LEN); 42 | if (!temp_buf) 43 | { 44 | log_e("malloc buffer failed"); 45 | return; 46 | } 47 | 48 | while (run_) 49 | { 50 | if (!init) 51 | { 52 | wait_sps = true; 53 | code = static_cast(rtmp_streamer.Initialize(params.url)); 54 | if (KSuccess != code) 55 | { 56 | log_e("error:%s", make_error_code(code).message().c_str()); 57 | return; 58 | } 59 | init = true; 60 | } 61 | { 62 | std::unique_lock lock(mux_); 63 | if (buffer_.Get((uint8_t *)&frame, sizeof(frame))) 64 | { 65 | memcpy(temp_buf, buffer_.GetCurrentPos(), frame.len); 66 | frame.data = temp_buf; 67 | if (!buffer_.Consume(frame.len)) 68 | { 69 | log_e("consme data from buffer failed,rest data not enough"); 70 | return; 71 | } 72 | } 73 | else if (run_) 74 | { 75 | cond_.wait(lock); 76 | continue; 77 | } 78 | } 79 | 80 | if (frame.type == H264Frame::NaluType::SPS) 81 | wait_sps = false; 82 | 83 | if (init && !wait_sps) 84 | { 85 | code = static_cast(rtmp_streamer.WriteVideoFrame(frame)); 86 | if (KSuccess != code) 87 | { 88 | log_w("rtmp connection break,try to reconnect..."); 89 | rtmp_streamer.Close(); 90 | init = false; 91 | } 92 | } 93 | } 94 | 95 | rtmp_streamer.Close(); 96 | free(temp_buf); 97 | })); 98 | 99 | init_ = true; 100 | return static_cast(KSuccess); 101 | } 102 | 103 | void RtmpLiveImpl::OnFrame(const VideoFrame &frame) 104 | { 105 | if (!init_) 106 | return; 107 | 108 | mux_.lock(); 109 | 110 | if (buffer_.FreeSpace() < sizeof(frame) + frame.len) 111 | { 112 | mux_.unlock(); 113 | return; 114 | } 115 | buffer_.Append((uint8_t *)&frame, sizeof(frame)); 116 | buffer_.Append(frame.data, frame.len); 117 | cond_.notify_one(); 118 | mux_.unlock(); 119 | } 120 | 121 | void RtmpLiveImpl::Close() 122 | { 123 | if (!init_) 124 | return; 125 | 126 | run_ = false; 127 | cond_.notify_all(); 128 | thread_->join(); 129 | thread_.reset(); 130 | thread_ = nullptr; 131 | buffer_.Clear(); 132 | init_ = false; 133 | } 134 | 135 | RtmpLiveImpl::RtmpLiveImpl() : run_(false), 136 | thread_(nullptr), 137 | init_(false) 138 | { 139 | } 140 | 141 | RtmpLiveImpl::~RtmpLiveImpl() 142 | { 143 | Close(); 144 | } 145 | }; // namespace nvr -------------------------------------------------------------------------------- /monitor/common/config.cpp: -------------------------------------------------------------------------------- 1 | #include "common/config.h" 2 | #include "common/res_code.h" 3 | #include "video_codec/video_codec_define.h" 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace nvr 10 | { 11 | 12 | int32_t Config::ReadConfigFile(const std::string &config_file) 13 | { 14 | std::ifstream ifs(config_file, std::ios::binary); 15 | if (!ifs.is_open()) 16 | { 17 | log_e("open config file %s failed", config_file.c_str()); 18 | return static_cast(KSystemError); 19 | } 20 | 21 | Json::Reader reader(Json::Features::strictMode()); 22 | Json::Value root; 23 | 24 | if (!reader.parse(ifs, root)) 25 | { 26 | log_e("parse config file failed,not json format"); 27 | return static_cast(KSystemError); 28 | } 29 | 30 | if (!root.isMember("video") || 31 | !root["video"].isObject()) 32 | { 33 | log_e("parse video config failed"); 34 | return static_cast(KSystemError); 35 | } 36 | 37 | Json::Value video = root["video"]; 38 | if (!video.isMember("frame_rate") || 39 | !video["frame_rate"].isInt() || 40 | !video.isMember("width") || 41 | !video["width"].isInt() || 42 | !video.isMember("height") || 43 | !video["height"].isInt() || 44 | !video.isMember("codec_mode") || 45 | !video["codec_mode"].isString() || 46 | !video.isMember("codec_profile") || 47 | !video["codec_profile"].isInt() || 48 | !video.isMember("codec_bitrate") || 49 | !video["codec_bitrate"].isInt()) 50 | { 51 | log_e("parse video config failed"); 52 | return static_cast(KSystemError); 53 | } 54 | 55 | if (!root.isMember("detect") || 56 | !root["detect"].isObject()) 57 | { 58 | log_e("parse detect config failed"); 59 | return static_cast(KSystemError); 60 | } 61 | 62 | Json::Value detect = root["detect"]; 63 | if (!detect.isMember("trigger_thresh") || 64 | !detect["trigger_thresh"].isInt()) 65 | { 66 | log_e("parse detect config failed"); 67 | return static_cast(KSystemError); 68 | } 69 | 70 | if (!root.isMember("record") || 71 | !root["record"].isObject()) 72 | { 73 | log_e("parse record config failed"); 74 | return static_cast(KSystemError); 75 | } 76 | 77 | Json::Value record = root["record"]; 78 | if (!record.isMember("segment_duration") || 79 | !record["segment_duration"].isInt() || 80 | !record.isMember("path") || 81 | !record["path"].isString() || 82 | !record.isMember("use_md") || 83 | !record["use_md"].isBool() || 84 | !record.isMember("md_duration") || 85 | !record["md_duration"].isInt()) 86 | { 87 | log_e("parse record config failed"); 88 | return static_cast(KSystemError); 89 | } 90 | 91 | if (!root.isMember("rtmp") || 92 | !root["rtmp"].isObject()) 93 | { 94 | log_e("parse rtmp config failed"); 95 | return static_cast(KSystemError); 96 | } 97 | 98 | Json::Value rtmp = root["rtmp"]; 99 | if (!rtmp.isMember("url") || 100 | !rtmp["url"].isString()) 101 | { 102 | log_e("parse rtmp config failed"); 103 | return static_cast(KSystemError); 104 | } 105 | 106 | //video 107 | this->video.frame_rate = video["frame_rate"].asInt(); 108 | this->video.width = video["width"].asInt(); 109 | this->video.height = video["height"].asInt(); 110 | this->video.codec_mode = StringToCodecMode(video["codec_mode"].asString()); 111 | this->video.codec_profile = video["codec_profile"].asInt(); 112 | //detect 113 | this->detect.trigger_thresh = detect["trigger_thresh"].asInt(); 114 | //record 115 | this->record.segment_duration =record["segment_duration"].asInt(); 116 | this->record.path = record["path"].asString(); 117 | this->record.use_md = record["use_md"].asBool(); 118 | this->record.md_duration = record["md_duration"].asInt(); 119 | //rtmp 120 | this->rtmp.url = rtmp["url"].asString(); 121 | 122 | return static_cast(KSuccess); 123 | } 124 | 125 | } // namespace nvr -------------------------------------------------------------------------------- /3rdparty.cmake: -------------------------------------------------------------------------------- 1 | include(ExternalProject) 2 | 3 | # set(COMPLIE_ARGS "-mcpu=arm926ej-s -w -mno-unaligned-access -fno-aggressive-loop-optimizations -ffunction-sections -fdata-sections") 4 | # set(FAST_COMPLIE_OPTION -j4) 5 | 6 | # #libav 7 | # ExternalProject_Add(libav 8 | # URL https://github.com/lam2003/monitor_3rdparty/raw/master/libav-12.3.tar.gz 9 | # DOWNLOAD_NAME libav-12.3.tar.gz 10 | # SOURCE_DIR libav 11 | # CONFIGURE_COMMAND cd ${PROJECT_BINARY_DIR}/libav && ./configure --arch=arm --cross-prefix=arm-hisiv500-linux- --enable-static --disable-shared --enable-cross-compile --target_os=linux --prefix=${PROJECT_BINARY_DIR}/libav/build --extra-cflags=${COMPLIE_ARGS} 12 | # BUILD_IN_SOURCE 1 13 | # BUILD_COMMAND make ${FAST_COMPLIE_OPTION} 14 | # INSTALL_COMMAND make install && cp ${PROJECT_BINARY_DIR}/libav/build/include ${PROJECT_BINARY_DIR} -rf && cp ${PROJECT_BINARY_DIR}/libav/build/lib ${PROJECT_BINARY_DIR} -rf 15 | # ) 16 | #jsoncpp 17 | # ExternalProject_Add(jsoncpp 18 | # URL https://github.com/lam2003/monitor_3rdparty/raw/master/jsoncpp-0.10.7.zip 19 | # DOWNLOAD_NAME jsoncpp-0.10.7.zip 20 | # SOURCE_DIR jsoncpp 21 | # CONFIGURE_COMMAND cd ${PROJECT_BINARY_DIR}/jsoncpp && cmake . -DCMAKE_SYSTEM_NAME=Linux -DCMAKE_C_COMPILER=arm-hisiv500-linux-gcc -DCMAKE_CXX_COMPILER=arm-hisiv500-linux-g++ -DJSONCPP_WITH_TESTS=OFF -DJSONCPP_WITH_POST_BUILD_UNITTEST=OFF -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/jsoncpp/build 22 | # BUILD_IN_SOURCE 1 23 | # BUILD_COMMAND make ${FAST_COMPLIE_OPTION} 24 | # INSTALL_COMMAND make install && cp ${PROJECT_BINARY_DIR}/jsoncpp/build/include ${PROJECT_BINARY_DIR} -rf && cp ${PROJECT_BINARY_DIR}/jsoncpp/build/lib ${PROJECT_BINARY_DIR} -rf 25 | # ) 26 | #easyloggrt 27 | # ExternalProject_Add(EasyLogger 28 | # URL https://github.com/lam2003/monitor_3rdparty/raw/master/EasyLogger.tar.gz 29 | # DOWNLOAD_NAME EasyLogger.tar.gz 30 | # SOURCE_DIR EasyLogger 31 | # CONFIGURE_COMMAND cd ${PROJECT_BINARY_DIR}/EasyLogger && cmake . -DCMAKE_SYSTEM_NAME=Linux -DCMAKE_C_COMPILER=arm-hisiv500-linux-gcc -DCMAKE_CXX_COMPILER=arm-hisiv500-linux-g++ -DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/EasyLogger/build 32 | # BUILD_IN_SOURCE 1 33 | # BUILD_COMMAND make ${FAST_COMPLIE_OPTION} 34 | # INSTALL_COMMAND make install && cp ${PROJECT_BINARY_DIR}/EasyLogger/build/include ${PROJECT_BINARY_DIR} -rf && cp ${PROJECT_BINARY_DIR}/EasyLogger/build/lib ${PROJECT_BINARY_DIR} -rf 35 | # ) 36 | #hisi sdk 37 | # ExternalProject_Add(hisi_sdk 38 | # URL https://github.com/lam2003/monitor_3rdparty/raw/master/hisi_sdk.tar.gz 39 | # DOWNLOAD_NAME hisi_sdk.tar.gz 40 | # SOURCE_DIR hisi_sdk 41 | # CONFIGURE_COMMAND "" 42 | # BUILD_IN_SOURCE 1 43 | # BUILD_COMMAND "" 44 | # INSTALL_COMMAND cp ${PROJECT_BINARY_DIR}/hisi_sdk/include ${PROJECT_BINARY_DIR} -rf && cp ${PROJECT_BINARY_DIR}/hisi_sdk/lib ${PROJECT_BINARY_DIR} -rf 45 | # ) 46 | 47 | 48 | # #freetype 49 | # ExternalProject_Add(freetype 50 | # URL https://github.com/lam2003/monitor_3rdparty/raw/master/freetype-2.10.0.tar.gz 51 | # DOWNLOAD_NAME freetype-2.10.0.tar.gz 52 | # SOURCE_DIR freetype 53 | # CONFIGURE_COMMAND cd ${PROJECT_BINARY_DIR}/freetype && ./configure --host=arm-hisiv500-linux --disable-shared --enable-freetype-config --prefix=${PROJECT_BINARY_DIR}/freetype/build CFLAGS=${COMPLIE_ARGS} CXXFLAGS=${COMPLIE_ARGS} 54 | # BUILD_IN_SOURCE 1 55 | # BUILD_COMMAND make ${FAST_COMPLIE_OPTION} 56 | # INSTALL_COMMAND make install && cp ${PROJECT_BINARY_DIR}/freetype/build/include ${PROJECT_BINARY_DIR} -rf && cp ${PROJECT_BINARY_DIR}/freetype/build/lib ${PROJECT_BINARY_DIR} -rf 57 | # ) 58 | #sdl2 59 | # ExternalProject_Add(SDL2 60 | # URL https://github.com/lam2003/monitor_3rdparty/raw/master/SDL2-2.0.9.tar.gz 61 | # DOWNLOAD_NAME SDL2-2.0.9.tar.gz 62 | # SOURCE_DIR SDL2 63 | # CONFIGURE_COMMAND cd ${PROJECT_BINARY_DIR}/SDL2 && ./configure --host=arm-hisiv500-linux --disable-shared --prefix=${PROJECT_BINARY_DIR}/SDL2/build -build=i386 --disable-video-wayland --disable-video-wayland-qt-touch --disable-pulseaudio --disable-video-dummy --disable-arts --disable-esd --disable-alsa --disable-video-x11 --enable-joystick --enable-input-tslib --enable-video-directfb --disable-video-mir CFLAGS=${COMPLIE_ARGS} CXXFLAGS=${COMPLIE_ARGS} 64 | # BUILD_IN_SOURCE 1 65 | # BUILD_COMMAND make ${FAST_COMPLIE_OPTION} 66 | # INSTALL_COMMAND make install && cp ${PROJECT_BINARY_DIR}/SDL2/build/include ${PROJECT_BINARY_DIR} -rf && cp ${PROJECT_BINARY_DIR}/SDL2/build/lib ${PROJECT_BINARY_DIR} -rf 67 | # ) 68 | #sdl2_ttf 69 | # ExternalProject_Add(SDL2_ttf 70 | # DEPENDS freetype SDL2 71 | # URL https://github.com/lam2003/monitor_3rdparty/raw/master/SDL2_ttf-2.0.15.tar.gz 72 | # DOWNLOAD_NAME SDL2_ttf-2.0.15.tar.gz 73 | # SOURCE_DIR SDL2_ttf 74 | # CONFIGURE_COMMAND cd ${PROJECT_BINARY_DIR}/SDL2_ttf && export FT2_CONFIG=${PROJECT_BINARY_DIR}/freetype/build/bin/freetype-config && export SDL2_CONFIG=${PROJECT_BINARY_DIR}/SDL2/build/bin/sdl2-config && export PKG_CONFIG_PATH=${PROJECT_BINARY_DIR}/lib/pkgconfig && ./configure --host=arm-hisiv500-linux --prefix=${PROJECT_BINARY_DIR}/SDL2_ttf/build --disable-shared CFLAGS=${COMPLIE_ARGS} CXXFLAGS=${COMPLIE_ARGS} 75 | # BUILD_IN_SOURCE 1 76 | # BUILD_COMMAND make ${FAST_COMPLIE_OPTION} 77 | # INSTALL_COMMAND make install && cp ${PROJECT_BINARY_DIR}/SDL2_ttf/build/include ${PROJECT_BINARY_DIR} -rf && cp ${PROJECT_BINARY_DIR}/SDL2_ttf/build/lib ${PROJECT_BINARY_DIR} -rf 78 | # ) 79 | 80 | 81 | ExternalProject_Add(thirdparty 82 | URL https://github.com/lam2003/monitor_3rdparty/raw/master/thirdparty.tar.gz 83 | DOWNLOAD_NAME thirdparty.tar.gz 84 | SOURCE_DIR thirdparty 85 | CONFIGURE_COMMAND "" 86 | BUILD_IN_SOURCE 1 87 | BUILD_COMMAND "" 88 | INSTALL_COMMAND cp ${PROJECT_BINARY_DIR}/thirdparty/include ${PROJECT_BINARY_DIR} -rf && cp ${PROJECT_BINARY_DIR}/thirdparty/lib ${PROJECT_BINARY_DIR} -rf && cp ${PROJECT_BINARY_DIR}/thirdparty/base ${PROJECT_BINARY_DIR}/include/ -rf 89 | ) -------------------------------------------------------------------------------- /monitor/record/mp4_record.cpp: -------------------------------------------------------------------------------- 1 | #include "record/mp4_record.h" 2 | #include "record/mp4_muxer.h" 3 | #include "common/res_code.h" 4 | #include "common/system.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace nvr 11 | { 12 | 13 | rtc::scoped_refptr MP4RecordImpl::Create(const Params ¶ms) 14 | { 15 | err_code code; 16 | 17 | rtc::scoped_refptr implemention = new rtc::RefCountedObject(); 18 | 19 | code = static_cast(implemention->Initialize(params)); 20 | 21 | if (KSuccess != code) 22 | { 23 | log_e("error:%s", make_error_code(code).message().c_str()); 24 | return nullptr; 25 | } 26 | 27 | return implemention; 28 | } 29 | 30 | bool MP4RecordImpl::RecordNeedToQuit() 31 | { 32 | 33 | if (params_.use_md && System::GetSteadyMilliSeconds() >= end_time_) 34 | return true; 35 | return false; 36 | } 37 | 38 | bool MP4RecordImpl::RecordNeedToSegment(uint64_t start_time) 39 | { 40 | if (System::GetSteadyMilliSeconds() > start_time + (params_.segment_duration * 1000)) 41 | return true; 42 | return false; 43 | } 44 | 45 | void MP4RecordImpl::OnTrigger(int32_t num) 46 | { 47 | end_time_ = System::GetSteadyMilliSeconds() + (params_.md_duration * 1000); 48 | } 49 | 50 | void MP4RecordImpl::RecordThread() 51 | { 52 | } 53 | 54 | int32_t MP4RecordImpl::Initialize(const Params ¶ms) 55 | { 56 | if (init_) 57 | return static_cast(KDupInitialize); 58 | 59 | params_ = params; 60 | run_ = true; 61 | thread_ = std::unique_ptr(new std::thread([this]() { 62 | err_code code; 63 | MP4Muxer muxer; 64 | VideoFrame frame; 65 | uint64_t now; 66 | uint64_t start_time; 67 | bool wait_sps; 68 | 69 | bool init = false; 70 | uint8_t *temp_buf = (uint8_t *)malloc(BUFFER_LEN); 71 | if (!temp_buf) 72 | { 73 | log_e("malloc buffer failed"); 74 | return; 75 | } 76 | 77 | now = System::GetSteadyMilliSeconds(); 78 | while (run_ && RecordNeedToQuit()) 79 | usleep(500000); //500ms 80 | 81 | while (run_) 82 | { 83 | if (!init) 84 | { 85 | std::string path; 86 | { 87 | //创建文件夹,按日期创建 88 | std::ostringstream oss; 89 | oss << params_.path << '/' << System::GetLocalTime(RECORD_DIR_FORMAT); 90 | path = oss.str(); 91 | code = static_cast(System::CreateDir(path)); 92 | if (KSuccess != code) 93 | return; 94 | } 95 | std::ostringstream oss; 96 | oss << path << '/' << "record_" << System::GetLocalTime(RECORD_FILE_FORMAT) << ".mp4"; 97 | code = static_cast(muxer.Initialize(oss.str().c_str(), params_.width, params_.height, params_.frame_rate)); 98 | if (KSuccess != code) 99 | { 100 | log_e("error:%s", make_error_code(code).message().c_str()); 101 | return; 102 | } 103 | 104 | mux_.lock(); 105 | buffer_.Clear(); 106 | mux_.unlock(); 107 | 108 | start_time = System::GetSteadyMilliSeconds(); 109 | wait_sps = true; 110 | init = true; 111 | } 112 | 113 | { 114 | std::unique_lock lock(mux_); 115 | if (buffer_.Get((uint8_t *)&frame, sizeof(frame))) 116 | { 117 | memcpy(temp_buf, buffer_.GetCurrentPos(), frame.len); 118 | frame.data = temp_buf; 119 | if (!buffer_.Consume(frame.len)) 120 | { 121 | log_e("consme data from buffer failed,rest data not enough"); 122 | return; 123 | } 124 | } 125 | else if (run_) 126 | { 127 | cond_.wait(lock); 128 | continue; 129 | } 130 | } 131 | 132 | if (frame.type == H264Frame::NaluType::SPS) 133 | wait_sps = false; 134 | 135 | if (!wait_sps) 136 | { 137 | code = static_cast(muxer.WriteVideoFrame(frame)); 138 | if (KSuccess != code) 139 | { 140 | log_e("error:%s", make_error_code(code).message().c_str()); 141 | return; 142 | } 143 | } 144 | 145 | if (RecordNeedToQuit()) 146 | { 147 | muxer.Close(); 148 | init = false; 149 | while (run_ && RecordNeedToQuit()) 150 | usleep(500000); //500ms 151 | } 152 | else if (RecordNeedToSegment(start_time)) 153 | { 154 | muxer.Close(); 155 | init = false; 156 | } 157 | } 158 | muxer.Close(); 159 | free(temp_buf); 160 | })); 161 | 162 | init_ = true; 163 | return static_cast(KSuccess); 164 | } 165 | 166 | void MP4RecordImpl::OnFrame(const VideoFrame &frame) 167 | { 168 | if (!init_) 169 | return; 170 | 171 | mux_.lock(); 172 | if (buffer_.FreeSpace() < sizeof(frame) + frame.len) 173 | { 174 | mux_.unlock(); 175 | return; 176 | } 177 | 178 | buffer_.Append((uint8_t *)&frame, sizeof(frame)); 179 | buffer_.Append(frame.data, frame.len); 180 | cond_.notify_one(); 181 | mux_.unlock(); 182 | } 183 | 184 | void MP4RecordImpl::Close() 185 | { 186 | if (!init_) 187 | return; 188 | 189 | run_ = false; 190 | cond_.notify_all(); 191 | thread_->join(); 192 | thread_.reset(); 193 | thread_ = nullptr; 194 | 195 | init_ = false; 196 | } 197 | 198 | MP4RecordImpl::MP4RecordImpl() : end_time_(0), 199 | run_(false), 200 | thread_(nullptr), 201 | init_(false) 202 | { 203 | } 204 | 205 | MP4RecordImpl::~MP4RecordImpl() 206 | { 207 | Close(); 208 | } 209 | }; // namespace nvr -------------------------------------------------------------------------------- /monitor/main.cpp: -------------------------------------------------------------------------------- 1 | #include "common/system.h" 2 | #include "common/res_code.h" 3 | #include "common/config.h" 4 | #include "video_capture/video_capture_impl.h" 5 | #include "video_process/video_process_impl.h" 6 | #include "video_detect/video_detect_impl.h" 7 | #include "video_codec/video_codec_impl.h" 8 | #include "live/rtmp.h" 9 | #include "record/mp4_record.h" 10 | 11 | using namespace nvr; 12 | 13 | static const char *KOpts = "c:"; 14 | struct option KLongOpts[] = { 15 | {"config", 1, NULL, 'c'}, 16 | {0, 0, 0, 0}}; 17 | 18 | static bool KRun = true; 19 | 20 | void signal_handler(int signo) 21 | { 22 | if (signo == SIGINT) 23 | { 24 | log_w("recevice SIGINT,quit process"); 25 | KRun = false; 26 | } 27 | else if (signo == SIGTERM) 28 | { 29 | log_w("recevice SIGTERM,quit process"); 30 | KRun = false; 31 | } 32 | else if (signo == SIGPIPE) 33 | { 34 | log_w("recevice SIGPIPE"); 35 | } 36 | } 37 | 38 | int main(int argc, char **argv) 39 | { 40 | err_code code; 41 | uint64_t start_time, end_time; 42 | 43 | //初始化日志系统 44 | System::InitLogger(); 45 | 46 | //初始化信号处理函数 47 | signal(SIGINT, signal_handler); 48 | signal(SIGPIPE, signal_handler); 49 | signal(SIGTERM, signal_handler); 50 | 51 | //读取配置文件 52 | int opt; 53 | while ((opt = getopt_long(argc, argv, KOpts, KLongOpts, NULL)) != -1) 54 | { 55 | switch (opt) 56 | { 57 | case 'c': 58 | { 59 | log_w("using config file %s", optarg); 60 | code = static_cast(Config::Instance()->ReadConfigFile(optarg)); 61 | CHACK_ERROR(code) 62 | break; 63 | } 64 | } 65 | } 66 | 67 | //初始化海思sdk 68 | log_i("initializing mpp..."); 69 | 70 | code = static_cast(System::InitMPP()); 71 | CHACK_ERROR(code) 72 | 73 | //初始化视频采集模块 74 | log_i("initializing video capture..."); 75 | 76 | rtc::scoped_refptr video_capture_module = VideoCaptureImpl::Create(); 77 | NVR_CHECK(NULL != video_capture_module) 78 | 79 | //初始化视频处理模块 80 | log_i("initializing video process..."); 81 | 82 | rtc::scoped_refptr video_process_module = VideoProcessImpl::Create({Config::Instance()->video.frame_rate, 83 | Config::Instance()->video.width, 84 | Config::Instance()->video.height}); 85 | NVR_CHECK(NULL != video_process_module) 86 | 87 | log_i("binding video capture and video process..."); 88 | code = static_cast(System::VIBindVPSS()); 89 | CHACK_ERROR(code) 90 | 91 | //初始化运动侦测模块 92 | log_i("initializing video detect..."); 93 | rtc::scoped_refptr video_detect_module = VideoDetectImpl::Create({Config::Instance()->detect.trigger_thresh}); 94 | NVR_CHECK(NULL != video_process_module) 95 | 96 | log_i("attach video detect to video process..."); 97 | video_process_module->SetVideoSink(video_detect_module); 98 | 99 | //初始化视频编码模块 100 | log_i("initializing video encode..."); 101 | rtc::scoped_refptr video_codec_module = VideoCodecImpl::Create({Config::Instance()->video.frame_rate, 102 | Config::Instance()->video.width, 103 | Config::Instance()->video.height, 104 | Config::Instance()->video.codec_mode, 105 | Config::Instance()->video.codec_profile, 106 | Config::Instance()->video.codec_bitrate}); 107 | NVR_CHECK(NULL != video_codec_module); 108 | 109 | log_i("binding video process and video encode..."); 110 | code = static_cast(System::VPSSBindVENC()); 111 | CHACK_ERROR(code) 112 | 113 | // 初始化直播 114 | log_i("initializing live..."); 115 | rtc::scoped_refptr live_module = RtmpLiveImpl::Create({Config::Instance()->rtmp.url}); 116 | NVR_CHECK(NULL != live_module); 117 | 118 | log_i("attach live to video encode..."); 119 | video_codec_module->AddVideoSink(live_module); 120 | 121 | log_i("initializing record..."); 122 | rtc::scoped_refptr record_module = MP4RecordImpl::Create({Config::Instance()->video.frame_rate, 123 | Config::Instance()->video.width, 124 | Config::Instance()->video.height, 125 | Config::Instance()->record.path, 126 | Config::Instance()->record.segment_duration, 127 | Config::Instance()->record.use_md, 128 | Config::Instance()->record.md_duration}); 129 | NVR_CHECK(NULL != record_module); 130 | 131 | log_i("attach record to video encode..."); 132 | video_codec_module->AddVideoSink(record_module); 133 | 134 | log_i("attact record to video detect..."); 135 | video_detect_module->AddListener(record_module); 136 | 137 | while (KRun) 138 | sleep(1000); 139 | 140 | log_i("detch record and video detect..."); 141 | video_detect_module->AddListener(nullptr); 142 | 143 | log_i("detch live/record and video encode..."); 144 | video_codec_module->ClearVideoSink(); 145 | 146 | log_i("closing record..."); 147 | record_module->Close(); 148 | 149 | log_i("closing live..."); 150 | live_module->Close(); 151 | 152 | log_i("unbinding video process and video encode..."); 153 | System::VPSSUnBindVENC(); 154 | 155 | log_i("closing video encode..."); 156 | video_codec_module->Close(); 157 | 158 | log_i("detach video detect and video process..."); 159 | video_process_module->SetVideoSink(nullptr); 160 | 161 | log_i("closing video detect..."); 162 | video_process_module->Close(); 163 | 164 | log_i("unbinding video capture and video process..."); 165 | System::VIUnBindVPSS(); 166 | 167 | log_i("closing video process..."); 168 | video_process_module->Close(); 169 | 170 | log_i("closing video capture..."); 171 | video_capture_module->Close(); 172 | 173 | log_i("closing mpp..."); 174 | System::UnInitMPP(); 175 | 176 | return 0; 177 | } -------------------------------------------------------------------------------- /monitor/common/system.cpp: -------------------------------------------------------------------------------- 1 | #include "common/system.h" 2 | #include "common/res_code.h" 3 | 4 | #include 5 | 6 | namespace nvr 7 | { 8 | 9 | int32_t System::InitMPP() 10 | { 11 | int32_t ret; 12 | 13 | VB_CONF_S vb_cfg; 14 | memset(&vb_cfg, 0, sizeof(VB_CONF_S)); 15 | vb_cfg.u32MaxPoolCnt = VB_POOLS_NUM; 16 | vb_cfg.astCommPool[0].u32BlkSize = CalcPicVbBlkSize(PIC_WIDTH, PIC_HEIGHT); 17 | vb_cfg.astCommPool[0].u32BlkCnt = VB_MEM_BLK_NUM; 18 | vb_cfg.astCommPool[1].u32BlkSize = CalcPicVbBlkSize(DETECT_WIDTH, DETECT_HEIGHT); 19 | vb_cfg.astCommPool[1].u32BlkCnt = DETECT_MEM_BLK_NUM; 20 | 21 | ret = HI_MPI_SYS_Exit(); 22 | if (HI_SUCCESS != ret) 23 | log_e("HI_MPI_SYS_Exit failed,code %#x", ret); 24 | 25 | ret = HI_MPI_VB_Exit(); 26 | if (HI_SUCCESS != ret) 27 | log_e("HI_MPI_VB_Exit failed,code %#x", ret); 28 | 29 | ret = HI_MPI_VB_SetConf(&vb_cfg); 30 | if (HI_SUCCESS != ret) 31 | { 32 | log_e("HI_MPI_VB_SetConf failed,code %#x", ret); 33 | return static_cast(KMPPError); 34 | } 35 | 36 | ret = HI_MPI_VB_Init(); 37 | if (HI_SUCCESS != ret) 38 | { 39 | log_e("HI_MPI_VB_Init failed,code %#x", ret); 40 | return static_cast(KMPPError); 41 | } 42 | 43 | MPP_SYS_CONF_S sys_conf; 44 | memset(&sys_conf, 0, sizeof(sys_conf)); 45 | sys_conf.u32AlignWidth = ALIGN; 46 | 47 | ret = HI_MPI_SYS_SetConf(&sys_conf); 48 | if (HI_SUCCESS != ret) 49 | { 50 | log_e("HI_MPI_SYS_SetConf failed,code %#x", ret); 51 | return static_cast(KMPPError); 52 | } 53 | 54 | ret = HI_MPI_SYS_Init(); 55 | if (HI_SUCCESS != ret) 56 | { 57 | log_e("HI_MPI_SYS_Init failed,code %#x", ret); 58 | return static_cast(KMPPError); 59 | } 60 | 61 | return static_cast(KSuccess); 62 | } 63 | 64 | void System::UnInitMPP() 65 | { 66 | int32_t ret; 67 | 68 | ret = HI_MPI_SYS_Exit(); 69 | if (HI_SUCCESS != ret) 70 | log_e("HI_MPI_SYS_Exit failed,code %#x", ret); 71 | 72 | ret = HI_MPI_VB_Exit(); 73 | if (HI_SUCCESS != ret) 74 | log_e("HI_MPI_VB_Exit failed,code %#x", ret); 75 | } 76 | 77 | void System::InitLogger() 78 | { 79 | setbuf(stdout, NULL); 80 | elog_init(); 81 | elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_ALL); 82 | elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_ALL & ~ELOG_FMT_FUNC); 83 | elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_T_INFO | ELOG_FMT_TIME); 84 | elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_T_INFO | ELOG_FMT_TIME); 85 | elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_ALL & ~ELOG_FMT_FUNC); 86 | elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_ALL & ~ELOG_FMT_FUNC); 87 | elog_set_text_color_enabled(true); 88 | elog_start(); 89 | } 90 | 91 | int32_t System::CalcPicVbBlkSize(int width, int height, int align) 92 | { 93 | int32_t vb_pic_header_size; 94 | int32_t align_width = Align(width, align); 95 | int32_t align_height = Align(height, align); 96 | VB_PIC_HEADER_SIZE(width, height, PIXEL_FORMAT, vb_pic_header_size); 97 | return vb_pic_header_size + ((align_width * align_height) * 3 >> 1); 98 | } 99 | 100 | uint64_t System::GetSteadyMilliSeconds() 101 | { 102 | using namespace std::chrono; 103 | auto now = steady_clock::now(); 104 | auto now_since_epoch = now.time_since_epoch(); 105 | return duration_cast(now_since_epoch).count(); 106 | } 107 | 108 | int32_t System::VIUnBindVPSS() 109 | { 110 | int32_t ret; 111 | 112 | MPP_CHN_S src_chn; 113 | src_chn.enModId = HI_ID_VIU; 114 | src_chn.s32DevId = NVR_VI_DEV; 115 | src_chn.s32ChnId = NVR_VI_CHN; 116 | 117 | MPP_CHN_S dest_chn; 118 | dest_chn.enModId = HI_ID_VPSS; 119 | dest_chn.s32DevId = NVR_VPSS_GRP; 120 | dest_chn.s32ChnId = 0; 121 | 122 | ret = HI_MPI_SYS_UnBind(&src_chn, &dest_chn); 123 | if (HI_SUCCESS != ret) 124 | { 125 | log_e("HI_MPI_SYS_UnBind failed,code %#x", ret); 126 | return static_cast(KMPPError); 127 | } 128 | 129 | return static_cast(KSuccess); 130 | } 131 | 132 | int32_t System::VIBindVPSS() 133 | { 134 | int32_t ret; 135 | 136 | MPP_CHN_S src_chn; 137 | src_chn.enModId = HI_ID_VIU; 138 | src_chn.s32DevId = NVR_VI_DEV; 139 | src_chn.s32ChnId = NVR_VI_CHN; 140 | 141 | MPP_CHN_S dest_chn; 142 | dest_chn.enModId = HI_ID_VPSS; 143 | dest_chn.s32DevId = NVR_VPSS_GRP; 144 | dest_chn.s32ChnId = 0; 145 | 146 | ret = HI_MPI_SYS_Bind(&src_chn, &dest_chn); 147 | if (HI_SUCCESS != ret) 148 | { 149 | log_e("HI_MPI_SYS_Bind failed,code %#x", ret); 150 | return static_cast(KMPPError); 151 | } 152 | 153 | return static_cast(KSuccess); 154 | } 155 | 156 | int32_t System::VPSSUnBindVENC() 157 | { 158 | int32_t ret; 159 | 160 | MPP_CHN_S src_chn; 161 | src_chn.enModId = HI_ID_VPSS; 162 | src_chn.s32DevId = NVR_VPSS_GRP; 163 | src_chn.s32ChnId = NVR_VPSS_ENCODE_CHN; 164 | 165 | MPP_CHN_S dest_chn; 166 | dest_chn.enModId = HI_ID_VENC; 167 | dest_chn.s32DevId = 0; 168 | dest_chn.s32ChnId = NVR_VENC_CHN; 169 | 170 | ret = HI_MPI_SYS_UnBind(&src_chn, &dest_chn); 171 | if (HI_SUCCESS != ret) 172 | { 173 | log_e("HI_MPI_SYS_UnBind failed,code %#x", ret); 174 | return static_cast(KMPPError); 175 | } 176 | 177 | return static_cast(KSuccess); 178 | } 179 | 180 | int32_t System::VPSSBindVENC() 181 | { 182 | int32_t ret; 183 | 184 | MPP_CHN_S src_chn; 185 | src_chn.enModId = HI_ID_VPSS; 186 | src_chn.s32DevId = NVR_VPSS_GRP; 187 | src_chn.s32ChnId = NVR_VPSS_ENCODE_CHN; 188 | 189 | MPP_CHN_S dest_chn; 190 | dest_chn.enModId = HI_ID_VENC; 191 | dest_chn.s32DevId = 0; 192 | dest_chn.s32ChnId = NVR_VENC_CHN; 193 | 194 | ret = HI_MPI_SYS_Bind(&src_chn, &dest_chn); 195 | if (HI_SUCCESS != ret) 196 | { 197 | log_e("HI_MPI_SYS_Bind failed,code %#x", ret); 198 | return static_cast(KMPPError); 199 | } 200 | 201 | return static_cast(KSuccess); 202 | } 203 | 204 | int32_t System::CreateDir(const std::string &path) 205 | { 206 | size_t pos = 0; 207 | while (true) 208 | { 209 | pos = path.find_first_of('/', pos); 210 | std::string sub_str = path.substr(0, pos); 211 | if (sub_str != "" && access(sub_str.c_str(), F_OK) != 0) 212 | { 213 | log_w("create dir %s", sub_str.c_str()); 214 | if (mkdir(sub_str.c_str(), 0777) != 0) 215 | { 216 | log_e("mkdir failed,%s", strerror(errno)); 217 | return static_cast(KSystemError); 218 | } 219 | } 220 | if (pos == std::string::npos) 221 | break; 222 | pos++; 223 | } 224 | 225 | return static_cast(KSuccess); 226 | } 227 | 228 | std::string System::GetLocalTime(const std::string &format) 229 | { 230 | time_t t = time(nullptr); 231 | char buf[256]; 232 | strftime(buf, sizeof(buf), format.c_str(), localtime(&t)); 233 | return std::string(buf, strlen(buf)); 234 | } 235 | 236 | } // namespace nvr 237 | -------------------------------------------------------------------------------- /monitor/video_detect/video_detect_impl.cpp: -------------------------------------------------------------------------------- 1 | #include "video_detect/video_detect_impl.h" 2 | #include "common/res_code.h" 3 | #include "common/system.h" 4 | 5 | #include 6 | 7 | namespace nvr 8 | { 9 | rtc::scoped_refptr VideoDetectImpl::Create(const Params ¶ms) 10 | { 11 | err_code code; 12 | 13 | rtc::scoped_refptr implemention = new rtc::RefCountedObject(); 14 | 15 | code = static_cast(implemention->Initialize(params)); 16 | 17 | if (KSuccess != code) 18 | { 19 | log_e("error:%s", make_error_code(code).message().c_str()); 20 | return nullptr; 21 | } 22 | 23 | return implemention; 24 | } 25 | 26 | int32_t VideoDetectImpl::StartMD() 27 | { 28 | int32_t ret; 29 | 30 | ret = HI_IVS_MD_Init(); 31 | if (HI_SUCCESS != ret) 32 | { 33 | log_e("HI_IVS_MD_Init failed,code %#x", ret); 34 | return static_cast(KMPPError); 35 | } 36 | MD_ATTR_S attr; 37 | 38 | attr.enAlgMode = MD_ALG_MODE_BG; 39 | attr.enSadMode = IVE_SAD_MODE_MB_4X4; 40 | attr.enSadOutCtrl = IVE_SAD_OUT_CTRL_THRESH; 41 | attr.u16SadThr = 200; 42 | attr.u16Width = DETECT_WIDTH; 43 | attr.u16Height = DETECT_HEIGHT; 44 | attr.stAddCtrl.u0q16X = 32768; 45 | attr.stAddCtrl.u0q16Y = 32768; 46 | attr.stCclCtrl.enMode = IVE_CCL_MODE_4C; 47 | attr.stCclCtrl.u16InitAreaThr = 16; 48 | attr.stCclCtrl.u16Step = 4; 49 | 50 | ret = HI_IVS_MD_CreateChn(NVR_MD_CHN, &attr); 51 | if (HI_SUCCESS != ret) 52 | { 53 | log_e("HI_IVS_MD_CreateChn failed,code %#x", ret); 54 | return static_cast(KMPPError); 55 | } 56 | return static_cast(KSuccess); 57 | } 58 | 59 | void VideoDetectImpl::StopMD() 60 | { 61 | int32_t ret; 62 | 63 | ret = HI_IVS_MD_DestroyChn(NVR_MD_CHN); 64 | if (HI_SUCCESS != ret && HI_ERR_IVE_NOTREADY != ret) 65 | log_e("HI_IVS_MD_DestroyChn failed,code %#x", ret); 66 | 67 | ret = HI_IVS_MD_Exit(); 68 | if (HI_SUCCESS != ret) 69 | log_e("HI_IVS_MD_Exit failed,code %#x", ret); 70 | } 71 | 72 | int32_t VideoDetectImpl::IVEDMAImage(const VIDEO_FRAME_INFO_S &frame_info, const IVE_DST_IMAGE_S &dst_image, HI_BOOL instant) 73 | { 74 | int32_t ret; 75 | 76 | IVE_HANDLE handle; 77 | IVE_SRC_DATA_S src_data; 78 | IVE_DST_DATA_S dst_data; 79 | IVE_DMA_CTRL_S dma_ctrl = {IVE_DMA_MODE_DIRECT_COPY, 0}; 80 | HI_BOOL finish = HI_FALSE; 81 | 82 | //fill src 83 | src_data.pu8VirAddr = (HI_U8 *)frame_info.stVFrame.pVirAddr[0]; 84 | src_data.u32PhyAddr = frame_info.stVFrame.u32PhyAddr[0]; 85 | src_data.u16Width = (HI_U16)frame_info.stVFrame.u32Width; 86 | src_data.u16Height = (HI_U16)frame_info.stVFrame.u32Height; 87 | src_data.u16Stride = (HI_U16)frame_info.stVFrame.u32Stride[0]; 88 | 89 | //fill dst 90 | dst_data.pu8VirAddr = dst_image.pu8VirAddr[0]; 91 | dst_data.u32PhyAddr = dst_image.u32PhyAddr[0]; 92 | dst_data.u16Width = dst_image.u16Width; 93 | dst_data.u16Height = dst_image.u16Height; 94 | dst_data.u16Stride = dst_image.u16Stride[0]; 95 | 96 | ret = HI_MPI_IVE_DMA(&handle, &src_data, &dst_data, &dma_ctrl, instant); 97 | if (HI_SUCCESS != ret) 98 | { 99 | log_e("HI_MPI_IVE_DMA failed,code %#x", ret); 100 | return static_cast(KMPPError); 101 | } 102 | 103 | if (HI_TRUE == instant) 104 | { 105 | ret = HI_MPI_IVE_Query(handle, &finish, HI_TRUE); 106 | while (!finish && HI_ERR_IVE_QUERY_TIMEOUT == ret) 107 | { 108 | usleep(100); 109 | ret = HI_MPI_IVE_Query(handle, &finish, HI_TRUE); 110 | } 111 | if (HI_SUCCESS != ret) 112 | { 113 | log_e("HI_MPI_IVE_Query failed,code %#x", ret); 114 | return static_cast(KMPPError); 115 | } 116 | } 117 | 118 | return static_cast(KSuccess); 119 | } 120 | 121 | int32_t VideoDetectImpl::AllocMemory() 122 | { 123 | int32_t ret; 124 | for (int i = 0; i < 2; i++) 125 | { 126 | memset(&src_image_[i], 0, sizeof(src_image_[i])); 127 | src_image_[i].enType = IVE_IMAGE_TYPE_U8C1; 128 | src_image_[i].u16Width = DETECT_WIDTH; 129 | src_image_[i].u16Height = DETECT_HEIGHT; 130 | src_image_[i].u16Stride[0] = System::Align(DETECT_WIDTH, 16); 131 | ret = HI_MPI_SYS_MmzAlloc(&src_image_[i].u32PhyAddr[0], (void **)&src_image_[i].pu8VirAddr[0], NULL, HI_NULL, src_image_[i].u16Stride[0] * DETECT_HEIGHT); 132 | if (HI_SUCCESS != ret) 133 | { 134 | log_e("HI_MPI_SYS_MmzAlloc failed,code %#x,ret"); 135 | return static_cast(KMPPError); 136 | } 137 | } 138 | 139 | memset(&dst_mem_info_, 0, sizeof(dst_mem_info_)); 140 | dst_mem_info_.u32Size = sizeof(IVE_CCBLOB_S); 141 | ret = HI_MPI_SYS_MmzAlloc(&dst_mem_info_.u32PhyAddr, (void **)&dst_mem_info_.pu8VirAddr, NULL, HI_NULL, dst_mem_info_.u32Size); 142 | if (HI_SUCCESS != ret) 143 | { 144 | log_e("HI_MPI_SYS_MmzAlloc failed,code %#x,ret"); 145 | return static_cast(KMPPError); 146 | } 147 | 148 | return static_cast(KSuccess); 149 | } 150 | 151 | void VideoDetectImpl::FreeMemory() 152 | { 153 | int32_t ret; 154 | ret = HI_MPI_SYS_MmzFree(dst_mem_info_.u32PhyAddr, dst_mem_info_.pu8VirAddr); 155 | if (HI_SUCCESS != ret) 156 | log_e("HI_MPI_SYS_MmzFree failed,code %#x", ret); 157 | 158 | for (int i = 0; i < 2; i++) 159 | { 160 | ret = HI_MPI_SYS_MmzFree(src_image_[i].u32PhyAddr[0], src_image_[i].pu8VirAddr[0]); 161 | if (HI_SUCCESS != ret) 162 | log_e("HI_MPI_SYS_MmzFree failed,code %#x", ret); 163 | } 164 | } 165 | 166 | void VideoDetectImpl::OnFrame(const VIDEO_FRAME_INFO_S &frame) 167 | { 168 | if (!init_) 169 | return; 170 | 171 | int32_t ret; 172 | IVE_CCBLOB_S *ccbloc; 173 | 174 | if (first_frame_) 175 | { 176 | if (KSuccess != static_cast(IVEDMAImage(frame, src_image_[index_], HI_TRUE))) 177 | { 178 | log_e("ive dma image failed"); 179 | return; 180 | } 181 | index_ = 1 - index_; 182 | first_frame_ = false; 183 | return; 184 | } 185 | else 186 | { 187 | if (KSuccess != static_cast(IVEDMAImage(frame, src_image_[index_], HI_TRUE))) 188 | { 189 | log_e("ive dma image failed"); 190 | return; 191 | } 192 | } 193 | 194 | ret = HI_IVS_MD_Process(NVR_MD_CHN, &src_image_[index_], &src_image_[1 - index_], nullptr, &dst_mem_info_); 195 | if (HI_SUCCESS != ret) 196 | { 197 | log_e("HI_IVS_MD_Process failed,code %#x", ret); 198 | return; 199 | } 200 | 201 | ccbloc = (IVE_CCBLOB_S *)(dst_mem_info_.pu8VirAddr); 202 | 203 | log_d("move objs num:%d,trigger thresh:%d", ccbloc->u8RegionNum, trigger_thresh_); 204 | mux_.lock(); 205 | if (ccbloc->u8RegionNum >= trigger_thresh_ && listener_) 206 | listener_->OnTrigger(ccbloc->u8RegionNum); 207 | mux_.unlock(); 208 | 209 | index_ = 1 - index_; 210 | } 211 | 212 | int32_t VideoDetectImpl::Initialize(const Params ¶ms) 213 | { 214 | if (init_) 215 | return static_cast(KDupInitialize); 216 | 217 | err_code code; 218 | 219 | code = static_cast(StartMD()); 220 | if (KSuccess != code) 221 | return code; 222 | 223 | code = static_cast(AllocMemory()); 224 | if (KSuccess != code) 225 | return code; 226 | 227 | trigger_thresh_ = params.trigger_thresh; 228 | 229 | init_ = true; 230 | 231 | return static_cast(KSuccess); 232 | } 233 | 234 | void VideoDetectImpl::Close() 235 | { 236 | if (!init_) 237 | return; 238 | 239 | FreeMemory(); 240 | 241 | StopMD(); 242 | 243 | trigger_thresh_ = 0; 244 | listener_ = nullptr; 245 | first_frame_ = true; 246 | index_ = 0; 247 | init_ = false; 248 | } 249 | 250 | VideoDetectImpl::~VideoDetectImpl() 251 | { 252 | Close(); 253 | } 254 | VideoDetectImpl::VideoDetectImpl() : trigger_thresh_(0), 255 | listener_(nullptr), 256 | first_frame_(true), 257 | index_(0), 258 | init_(false) 259 | { 260 | } 261 | 262 | void VideoDetectImpl::AddListener(DetectListener *listener) 263 | { 264 | mux_.lock(); 265 | listener_ = listener; 266 | mux_.unlock(); 267 | } 268 | } // namespace nvr -------------------------------------------------------------------------------- /monitor/video_process/video_process_impl.cpp: -------------------------------------------------------------------------------- 1 | #include "video_process_impl.h" 2 | #include "common/res_code.h" 3 | 4 | #include 5 | 6 | namespace nvr 7 | { 8 | 9 | rtc::scoped_refptr VideoProcessImpl::Create(const Params ¶ms) 10 | { 11 | err_code code; 12 | 13 | rtc::scoped_refptr implemention(new rtc::RefCountedObject()); 14 | 15 | code = static_cast(implemention->Initialize(params)); 16 | 17 | if (KSuccess != code) 18 | { 19 | log_e("error:%s", make_error_code(code).message().c_str()); 20 | return nullptr; 21 | } 22 | 23 | return implemention; 24 | } 25 | 26 | VideoProcessImpl::VideoProcessImpl() : run_(false), 27 | thread_(nullptr), 28 | video_sink_(nullptr), 29 | init_(false) 30 | { 31 | } 32 | 33 | VideoProcessImpl::~VideoProcessImpl() 34 | { 35 | Close(); 36 | } 37 | 38 | int32_t VideoProcessImpl::StartVPSSGroup(const Params ¶ms) 39 | { 40 | int32_t ret; 41 | 42 | VPSS_GRP_ATTR_S grp_attr; 43 | memset(&grp_attr, 0, sizeof(grp_attr)); 44 | 45 | grp_attr.u32MaxW = PIC_WIDTH; 46 | grp_attr.u32MaxH = PIC_HEIGHT; 47 | grp_attr.bIeEn = HI_FALSE; 48 | grp_attr.bNrEn = HI_TRUE; 49 | grp_attr.bHistEn = HI_FALSE; 50 | grp_attr.bDciEn = HI_FALSE; 51 | grp_attr.enDieMode = VPSS_DIE_MODE_NODIE; 52 | grp_attr.enPixFmt = PIXEL_FORMAT; 53 | grp_attr.bSharpenEn = HI_FALSE; 54 | 55 | ret = HI_MPI_VPSS_CreateGrp(NVR_VPSS_GRP, &grp_attr); 56 | if (HI_SUCCESS != ret) 57 | { 58 | log_e("HI_MPI_VPSS_CreateGrp failed,code %#x", ret); 59 | return static_cast(KMPPError); 60 | } 61 | 62 | ret = HI_MPI_VPSS_StartGrp(NVR_VPSS_GRP); 63 | if (HI_SUCCESS != ret) 64 | { 65 | log_e("HI_MPI_VPSS_StartGrp failed,code %#x", ret); 66 | return static_cast(KMPPError); 67 | } 68 | 69 | return static_cast(KSuccess); 70 | } 71 | 72 | void VideoProcessImpl::StopVPSSGroup() 73 | { 74 | int32_t ret; 75 | 76 | ret = HI_MPI_VPSS_StopGrp(NVR_VPSS_GRP); 77 | if (HI_SUCCESS != ret) 78 | log_e("HI_MPI_VPSS_StopGrp failed,code %#x", ret); 79 | 80 | ret = HI_MPI_VPSS_DestroyGrp(NVR_VPSS_GRP); 81 | if (HI_SUCCESS != ret) 82 | log_e("HI_MPI_VPSS_DestroyGrp failed,code %#x", ret); 83 | } 84 | 85 | int32_t VideoProcessImpl::StartVPSSEncodeChn(const Params ¶ms) 86 | { 87 | int32_t ret; 88 | 89 | VPSS_CHN_ATTR_S chn_attr; 90 | memset(&chn_attr, 0, sizeof(chn_attr)); 91 | chn_attr.s32SrcFrameRate = FRAME_RATE; 92 | chn_attr.s32DstFrameRate = params.frame_rate; 93 | 94 | ret = HI_MPI_VPSS_SetChnAttr(NVR_VPSS_GRP, NVR_VPSS_ENCODE_CHN, &chn_attr); 95 | if (HI_SUCCESS != ret) 96 | { 97 | log_e("HI_MPI_VPSS_SetChnAttr failed,code %#x", ret); 98 | return static_cast(KMPPError); 99 | } 100 | 101 | VPSS_CHN_MODE_S chn_mode; 102 | memset(&chn_mode, 0, sizeof(chn_mode)); 103 | chn_mode.enChnMode = VPSS_CHN_MODE_USER; 104 | chn_mode.bDouble = HI_FALSE; 105 | chn_mode.enPixelFormat = PIXEL_FORMAT; 106 | chn_mode.u32Width = params.encode_width; 107 | chn_mode.u32Height = params.encode_height; 108 | chn_mode.enCompressMode = COMPRESS_MODE_SEG; 109 | 110 | ret = HI_MPI_VPSS_SetChnMode(NVR_VPSS_GRP, NVR_VPSS_ENCODE_CHN, &chn_mode); 111 | if (HI_SUCCESS != ret) 112 | { 113 | log_e("HI_MPI_VPSS_SetChnMode failed,code %#x", ret); 114 | return static_cast(KMPPError); 115 | } 116 | 117 | ret = HI_MPI_VPSS_EnableChn(NVR_VPSS_GRP, NVR_VPSS_ENCODE_CHN); 118 | if (HI_SUCCESS != ret) 119 | { 120 | log_e("HI_MPI_VPSS_EnableChn failed,code %#x", ret); 121 | return static_cast(KMPPError); 122 | } 123 | 124 | return static_cast(KSuccess); 125 | } 126 | 127 | void VideoProcessImpl::StopVPSSEncodeChn() 128 | { 129 | int32_t ret; 130 | 131 | ret = HI_MPI_VPSS_DisableChn(NVR_VPSS_GRP, NVR_VPSS_ENCODE_CHN); 132 | if (HI_SUCCESS != ret) 133 | log_e("HI_MPI_VPSS_DisableChn failed,code %#x", ret); 134 | } 135 | 136 | int32_t VideoProcessImpl::StartVPSSDetectChn(const Params ¶ms) 137 | { 138 | int32_t ret; 139 | 140 | VPSS_CHN_ATTR_S chn_attr; 141 | memset(&chn_attr, 0, sizeof(chn_attr)); 142 | chn_attr.s32SrcFrameRate = FRAME_RATE; 143 | chn_attr.s32DstFrameRate = 5; 144 | 145 | ret = HI_MPI_VPSS_SetChnAttr(NVR_VPSS_GRP, NVR_VPSS_DETECT_CHN, &chn_attr); 146 | if (HI_SUCCESS != ret) 147 | { 148 | log_e("HI_MPI_VPSS_SetChnAttr failed,code %#x", ret); 149 | return static_cast(KMPPError); 150 | } 151 | 152 | VPSS_CHN_MODE_S chn_mode; 153 | memset(&chn_mode, 0, sizeof(chn_mode)); 154 | chn_mode.enChnMode = VPSS_CHN_MODE_USER; 155 | chn_mode.bDouble = HI_FALSE; 156 | chn_mode.enPixelFormat = PIXEL_FORMAT; 157 | chn_mode.u32Width = DETECT_WIDTH; 158 | chn_mode.u32Height = DETECT_HEIGHT; 159 | chn_mode.enCompressMode = COMPRESS_MODE_NONE; 160 | 161 | ret = HI_MPI_VPSS_SetChnMode(NVR_VPSS_GRP, NVR_VPSS_DETECT_CHN, &chn_mode); 162 | if (HI_SUCCESS != ret) 163 | { 164 | log_e("HI_MPI_VPSS_SetChnMode failed,code %#x", ret); 165 | return static_cast(KMPPError); 166 | } 167 | 168 | ret = HI_MPI_VPSS_EnableChn(NVR_VPSS_GRP, NVR_VPSS_DETECT_CHN); 169 | if (HI_SUCCESS != ret) 170 | { 171 | log_e("HI_MPI_VPSS_EnableChn failed,code %#x", ret); 172 | return static_cast(KMPPError); 173 | } 174 | 175 | return static_cast(KSuccess); 176 | } 177 | 178 | void VideoProcessImpl::StopVPSSDetectChn() 179 | { 180 | int32_t ret; 181 | ret = HI_MPI_VPSS_DisableChn(NVR_VPSS_GRP, NVR_VPSS_DETECT_CHN); 182 | if (HI_SUCCESS != ret) 183 | log_e("HI_MPI_VPSS_DisableChn failed,code %#x", ret); 184 | } 185 | 186 | void VideoProcessImpl::StartProcessThread(const Params ¶ms) 187 | { 188 | run_ = true; 189 | thread_ = std::unique_ptr(new std::thread([this]() { 190 | int32_t ret; 191 | VIDEO_FRAME_INFO_S frame_info; 192 | 193 | ret = HI_MPI_VPSS_SetDepth(NVR_VPSS_GRP, NVR_VPSS_DETECT_CHN, 1); 194 | if (HI_SUCCESS != ret) 195 | { 196 | log_e("HI_MPI_VPSS_SetDepth failed,code %#x", ret); 197 | return; 198 | } 199 | 200 | while (run_) 201 | { 202 | ret = HI_MPI_VPSS_GetChnFrame(NVR_VPSS_GRP, NVR_VPSS_DETECT_CHN, &frame_info, 500); //500ms 203 | if (HI_SUCCESS != ret && HI_ERR_VPSS_BUF_EMPTY != ret) 204 | { 205 | log_e("HI_MPI_VPSS_GetChnFrame failed,code %#x", ret); 206 | return; 207 | } 208 | 209 | if (HI_ERR_VPSS_BUF_EMPTY == ret) 210 | { 211 | log_w("HI_MPI_VPSS_GetChnFrame return HI_ERR_VPSS_BUF_EMPTY"); 212 | continue; 213 | } 214 | 215 | mux_.lock(); 216 | if (video_sink_) 217 | video_sink_->OnFrame(frame_info); 218 | mux_.unlock(); 219 | 220 | ret = HI_MPI_VPSS_ReleaseChnFrame(NVR_VPSS_GRP, NVR_VPSS_DETECT_CHN, &frame_info); 221 | if (HI_SUCCESS != ret) 222 | { 223 | log_e("HI_MPI_VPSS_ReleaseChnFrame failed,code %#x", ret); 224 | return; 225 | } 226 | } 227 | })); 228 | }; 229 | 230 | void VideoProcessImpl::StopProcessThread() 231 | { 232 | run_ = false; 233 | thread_->join(); 234 | thread_.reset(); 235 | thread_ = nullptr; 236 | } 237 | 238 | void VideoProcessImpl::SetVideoSink(VideoSinkInterface *video_sink) 239 | { 240 | std::unique_lock lock(mux_); 241 | video_sink_ = video_sink; 242 | } 243 | 244 | int32_t VideoProcessImpl::Initialize(const Params ¶ms) 245 | { 246 | if (init_) 247 | return static_cast(KDupInitialize); 248 | err_code code; 249 | 250 | code = static_cast(StartVPSSGroup(params)); 251 | if (KSuccess != code) 252 | return static_cast(code); 253 | 254 | code = static_cast(StartVPSSEncodeChn(params)); 255 | if (KSuccess != code) 256 | return static_cast(code); 257 | 258 | code = static_cast(StartVPSSDetectChn(params)); 259 | if (KSuccess != code) 260 | return static_cast(code); 261 | 262 | StartProcessThread(params); 263 | 264 | init_ = true; 265 | 266 | return static_cast(KSuccess); 267 | } 268 | 269 | void VideoProcessImpl::Close() 270 | { 271 | if (!init_) 272 | return; 273 | 274 | StopProcessThread(); 275 | 276 | StopVPSSDetectChn(); 277 | 278 | StopVPSSEncodeChn(); 279 | 280 | StopVPSSGroup(); 281 | 282 | video_sink_ = nullptr; 283 | 284 | init_ = false; 285 | } 286 | 287 | }; // namespace nvr 288 | -------------------------------------------------------------------------------- /monitor/video_codec/video_codec_impl.cpp: -------------------------------------------------------------------------------- 1 | #include "video_codec/video_codec_impl.h" 2 | #include "common/res_code.h" 3 | #include "common/system.h" 4 | 5 | #include 6 | 7 | #define PACKET_BUFFER_SIZE (256 * 1024) //256kB 8 | 9 | namespace nvr 10 | { 11 | 12 | rtc::scoped_refptr VideoCodecImpl::Create(const Params ¶ms) 13 | { 14 | err_code code; 15 | 16 | rtc::scoped_refptr implemention = new rtc::RefCountedObject(); 17 | 18 | code = static_cast(implemention->Initialize(params)); 19 | 20 | if (KSuccess != code) 21 | { 22 | log_e("error:%s", make_error_code(code).message().c_str()); 23 | return nullptr; 24 | } 25 | 26 | return implemention; 27 | } 28 | 29 | int32_t VideoCodecImpl::StartVENCChn(const Params ¶ms) 30 | { 31 | int32_t ret; 32 | 33 | VENC_CHN_ATTR_S chn_attr; 34 | memset(&chn_attr, 0, sizeof(chn_attr)); 35 | 36 | chn_attr.stVeAttr.enType = PT_H264; 37 | 38 | VENC_ATTR_H264_S h264_attr; 39 | memset(&h264_attr, 0, sizeof(h264_attr)); 40 | 41 | h264_attr.u32MaxPicWidth = PIC_WIDTH; 42 | h264_attr.u32MaxPicHeight = PIC_HEIGHT; 43 | h264_attr.u32PicWidth = params.width; 44 | h264_attr.u32PicHeight = params.height; 45 | h264_attr.u32BufSize = PIC_WIDTH * PIC_HEIGHT * 2; 46 | h264_attr.u32Profile = params.profile; 47 | h264_attr.bByFrame = HI_FALSE; 48 | 49 | memcpy(&chn_attr.stVeAttr.stAttrH264e, &h264_attr, sizeof(h264_attr)); 50 | if (params.codec_mode == CBR) 51 | { 52 | chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR; 53 | 54 | VENC_ATTR_H264_CBR_S h264_cbr; 55 | memset(&h264_cbr, 0, sizeof(h264_cbr)); 56 | 57 | h264_cbr.u32Gop = params.frame_rate; 58 | h264_cbr.u32StatTime = 1; 59 | h264_cbr.u32SrcFrmRate = params.frame_rate; 60 | h264_cbr.fr32DstFrmRate = params.frame_rate; 61 | h264_cbr.u32BitRate = params.bitrate; 62 | h264_cbr.u32FluctuateLevel = 1; 63 | 64 | memcpy(&chn_attr.stRcAttr.stAttrH264Cbr, &h264_cbr, sizeof(h264_cbr)); 65 | } 66 | else if (params.codec_mode == VBR) 67 | { 68 | chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264VBR; 69 | 70 | VENC_ATTR_H264_VBR_S h264_vbr; 71 | memset(&h264_vbr, 0, sizeof(h264_vbr)); 72 | 73 | h264_vbr.u32Gop = params.frame_rate; 74 | h264_vbr.u32StatTime = 1; 75 | h264_vbr.u32SrcFrmRate = params.frame_rate; 76 | h264_vbr.fr32DstFrmRate = params.frame_rate; 77 | h264_vbr.u32MinQp = 10; 78 | h264_vbr.u32MinIQp = 10; 79 | h264_vbr.u32MaxQp = 40; 80 | h264_vbr.u32MaxBitRate = params.bitrate; 81 | 82 | memcpy(&chn_attr.stRcAttr.stAttrH264Vbr, &h264_vbr, sizeof(h264_vbr)); 83 | } 84 | else if (params.codec_mode == AVBR) 85 | { 86 | chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264AVBR; 87 | 88 | VENC_ATTR_H264_AVBR_S h264_avbr; 89 | memset(&h264_avbr, 0, sizeof(h264_avbr)); 90 | 91 | h264_avbr.u32Gop = params.frame_rate; 92 | h264_avbr.u32StatTime = 1; 93 | h264_avbr.u32SrcFrmRate = params.frame_rate; 94 | h264_avbr.fr32DstFrmRate = params.frame_rate; 95 | h264_avbr.u32MaxBitRate = params.bitrate; 96 | 97 | memcpy(&chn_attr.stRcAttr.stAttrH264AVbr, &h264_avbr, sizeof(h264_avbr)); 98 | } 99 | else 100 | { 101 | log_e("unsupport codec mode:%d", static_cast(params.codec_mode)); 102 | return static_cast(KMPPError); 103 | } 104 | 105 | chn_attr.stGopAttr.enGopMode = VENC_GOPMODE_NORMALP; 106 | chn_attr.stGopAttr.stNormalP.s32IPQpDelta = 0; 107 | 108 | ret = HI_MPI_VENC_CreateChn(NVR_VENC_CHN, &chn_attr); 109 | if (HI_SUCCESS != ret) 110 | { 111 | log_e("HI_MPI_VENC_CreateChn failed,code %#x", ret); 112 | return static_cast(KMPPError); 113 | } 114 | 115 | ret = HI_MPI_VENC_StartRecvPic(NVR_VENC_CHN); 116 | if (HI_SUCCESS != ret) 117 | { 118 | log_e("HI_MPI_VENC_StartRecvPic failed,code %#x", ret); 119 | return static_cast(KMPPError); 120 | } 121 | 122 | return static_cast(KSuccess); 123 | } 124 | 125 | void VideoCodecImpl::StopVENCChn() 126 | { 127 | int32_t ret; 128 | 129 | ret = HI_MPI_VENC_StopRecvPic(NVR_VENC_CHN); 130 | if (HI_SUCCESS != ret) 131 | log_e("HI_MPI_VENC_StopRecvPic failed,code %#x", ret); 132 | 133 | ret = HI_MPI_VENC_DestroyChn(NVR_VENC_CHN); 134 | if (HI_SUCCESS != ret) 135 | log_e("HI_MPI_VENC_DestroyChn failed,code %#x", ret); 136 | } 137 | 138 | void VideoCodecImpl::StartGetStreamThread(const Params ¶ms) 139 | { 140 | run_ = true; 141 | thread_ = std::unique_ptr(new std::thread([this, params]() { 142 | int32_t ret; 143 | 144 | VENC_STREAM_S stream; 145 | VENC_CHN_STAT_S chn_stat; 146 | 147 | int32_t fd = HI_MPI_VENC_GetFd(NVR_VENC_CHN); 148 | if (fd < 0) 149 | { 150 | log_e("HI_MPI_VENC_GetFd failed"); 151 | return; 152 | } 153 | 154 | fd_set fds; 155 | timeval tv; 156 | 157 | void *packet_buf = malloc(PACKET_BUFFER_SIZE); 158 | uint32_t packet_buf_size = PACKET_BUFFER_SIZE; 159 | if (!packet_buf) 160 | { 161 | log_e("malloc packet buffer failed"); 162 | return; 163 | } 164 | 165 | while (run_) 166 | { 167 | FD_ZERO(&fds); 168 | FD_SET(fd, &fds); 169 | 170 | tv.tv_sec = 1; 171 | tv.tv_usec = 0; 172 | 173 | ret = select(fd + 1, &fds, NULL, NULL, &tv); 174 | if (ret < 0) 175 | { 176 | log_e("select failed"); 177 | return; 178 | } 179 | 180 | if (ret == 0) 181 | continue; 182 | 183 | if (FD_ISSET(fd, &fds)) 184 | { 185 | memset(&stream, 0, sizeof(stream)); 186 | memset(&chn_stat, 0, sizeof(chn_stat)); 187 | ret = HI_MPI_VENC_Query(NVR_VENC_CHN, &chn_stat); 188 | if (HI_SUCCESS != ret) 189 | { 190 | log_e("HI_MPI_VENC_Query failed,code %#x", ret); 191 | return; 192 | } 193 | 194 | if (!chn_stat.u32CurPacks) 195 | { 196 | log_w("current frame is null"); 197 | return; 198 | } 199 | 200 | if (sizeof(VENC_PACK_S) * chn_stat.u32CurPacks > packet_buf_size) 201 | { 202 | free(packet_buf); 203 | packet_buf = malloc(sizeof(VENC_PACK_S) * chn_stat.u32CurPacks); 204 | if (!packet_buf) 205 | { 206 | log_e("malloc packet buffer failed"); 207 | return; 208 | } 209 | packet_buf_size = sizeof(VENC_PACK_S) * chn_stat.u32CurPacks; 210 | } 211 | stream.pstPack = (VENC_PACK_S *)packet_buf; 212 | stream.u32PackCount = chn_stat.u32CurPacks; 213 | 214 | ret = HI_MPI_VENC_GetStream(NVR_VENC_CHN, &stream, HI_TRUE); 215 | if (HI_SUCCESS != ret) 216 | { 217 | log_e("HI_MPI_VENC_GetStream failed,code %#x", ret); 218 | return; 219 | } 220 | 221 | for (uint32_t i = 0; i < stream.u32PackCount; i++) 222 | { 223 | 224 | H264Frame frame; 225 | frame.type = static_cast(stream.pstPack[i].DataType.enH264EType); 226 | frame.data = stream.pstPack[i].pu8Addr; 227 | frame.len = stream.pstPack[i].u32Len; 228 | frame.ts = stream.pstPack[i].u64PTS; 229 | for (size_t j = 0; j < video_sinks_.size(); j++) 230 | video_sinks_[j]->OnFrame(frame); 231 | } 232 | 233 | ret = HI_MPI_VENC_ReleaseStream(NVR_VENC_CHN, &stream); 234 | if (HI_SUCCESS != ret) 235 | { 236 | log_e("HI_MPI_VENC_ReleaseStream failed,code %#x", ret); 237 | return; 238 | } 239 | } 240 | } 241 | free(packet_buf); 242 | })); 243 | } 244 | 245 | void VideoCodecImpl::StopGetStreamThread() 246 | { 247 | run_ = false; 248 | thread_->join(); 249 | thread_.reset(); 250 | thread_ = nullptr; 251 | } 252 | 253 | int32_t VideoCodecImpl::Initialize(const Params ¶ms) 254 | { 255 | if (init_) 256 | return static_cast(KDupInitialize); 257 | 258 | err_code code; 259 | 260 | code = static_cast(StartVENCChn(params)); 261 | if (KSuccess != code) 262 | return static_cast(code); 263 | 264 | StartGetStreamThread(params); 265 | 266 | init_ = true; 267 | 268 | return static_cast(KSuccess); 269 | } 270 | void VideoCodecImpl::AddVideoSink(VideoSinkInterface *video_sink) 271 | { 272 | std::unique_lock lock(mux_); 273 | video_sinks_.push_back(video_sink); 274 | } 275 | 276 | void VideoCodecImpl::ClearVideoSink() 277 | { 278 | std::unique_lock lock(mux_); 279 | video_sinks_.clear(); 280 | } 281 | 282 | void VideoCodecImpl::Close() 283 | { 284 | if (!init_) 285 | return; 286 | 287 | StopGetStreamThread(); 288 | 289 | StopVENCChn(); 290 | 291 | video_sinks_.clear(); 292 | init_ = false; 293 | } 294 | 295 | VideoCodecImpl::VideoCodecImpl() : run_(false), 296 | thread_(nullptr), 297 | init_(false) 298 | { 299 | } 300 | 301 | VideoCodecImpl::~VideoCodecImpl() 302 | { 303 | Close(); 304 | } 305 | 306 | }; // namespace nvr -------------------------------------------------------------------------------- /monitor/video_capture/video_capture_impl.cpp: -------------------------------------------------------------------------------- 1 | #include "video_capture/video_capture_impl.h" 2 | #include "common/res_code.h" 3 | 4 | #include 5 | 6 | static combo_dev_attr_t COMBO_DEV_ATTR = 7 | { 8 | .devno = 0, 9 | .input_mode = INPUT_MODE_LVDS, 10 | {.lvds_attr = 11 | { 12 | .img_size = {PIC_WIDTH, PIC_HEIGHT}, 13 | .raw_data_type = RAW_DATA_12BIT, 14 | .wdr_mode = HI_WDR_MODE_NONE, 15 | 16 | .sync_mode = LVDS_SYNC_MODE_SAV, 17 | .vsync_type = {LVDS_VSYNC_NORMAL, 0, 0}, 18 | .fid_type = {LVDS_FID_NONE, HI_FALSE}, 19 | 20 | .data_endian = LVDS_ENDIAN_BIG, 21 | .sync_code_endian = LVDS_ENDIAN_BIG, 22 | .lane_id = {0, 1, 2, 3}, 23 | 24 | .sync_code = 25 | { 26 | {{0xab0, 0xb60, 0x800, 0x9d0}, 27 | {0xab0, 0xb60, 0x800, 0x9d0}, 28 | {0xab0, 0xb60, 0x800, 0x9d0}, 29 | {0xab0, 0xb60, 0x800, 0x9d0}}, 30 | {{0xab0, 0xb60, 0x800, 0x9d0}, 31 | {0xab0, 0xb60, 0x800, 0x9d0}, 32 | {0xab0, 0xb60, 0x800, 0x9d0}, 33 | {0xab0, 0xb60, 0x800, 0x9d0}}, 34 | {{0xab0, 0xb60, 0x800, 0x9d0}, 35 | {0xab0, 0xb60, 0x800, 0x9d0}, 36 | {0xab0, 0xb60, 0x800, 0x9d0}, 37 | {0xab0, 0xb60, 0x800, 0x9d0}}, 38 | {{0xab0, 0xb60, 0x800, 0x9d0}, 39 | {0xab0, 0xb60, 0x800, 0x9d0}, 40 | {0xab0, 0xb60, 0x800, 0x9d0}, 41 | {0xab0, 0xb60, 0x800, 0x9d0}}}}}}; 42 | 43 | static ISP_PUB_ATTR_S ISP_PUB_ATTR = { 44 | 45 | .stWndRect = { 46 | .s32X = 0, 47 | .s32Y = 0, 48 | .u32Width = PIC_WIDTH, 49 | .u32Height = PIC_HEIGHT, 50 | }, 51 | .f32FrameRate = FRAME_RATE, 52 | .enBayer = BAYER_GBRG}; 53 | 54 | static VI_DEV_ATTR_S VI_DEV_ATTR = { 55 | 56 | .enIntfMode = VI_MODE_LVDS, 57 | 58 | .enWorkMode = VI_WORK_MODE_1Multiplex, 59 | 60 | .au32CompMask = {0xFFF00000, 0x0}, 61 | 62 | .enScanMode = VI_SCAN_PROGRESSIVE, 63 | 64 | .s32AdChnId = {-1, -1, -1, -1}, 65 | 66 | .enDataSeq = VI_INPUT_DATA_YUYV, 67 | 68 | .stSynCfg = { 69 | .enVsync = VI_VSYNC_PULSE, 70 | .enVsyncNeg = VI_VSYNC_NEG_LOW, 71 | .enHsync = VI_HSYNC_VALID_SINGNAL, 72 | .enHsyncNeg = VI_HSYNC_NEG_HIGH, 73 | .enVsyncValid = VI_VSYNC_VALID_SINGAL, 74 | .enVsyncValidNeg = VI_VSYNC_VALID_NEG_HIGH, 75 | 76 | .stTimingBlank = { 77 | .u32HsyncHfb = 0, 78 | .u32HsyncAct = 1280, 79 | .u32HsyncHbb = 0, 80 | 81 | .u32VsyncVfb = 0, 82 | .u32VsyncVact = 720, 83 | .u32VsyncVbb = 0, 84 | 85 | .u32VsyncVbfb = 0, 86 | .u32VsyncVbact = 0, 87 | .u32VsyncVbbb = 0}}, 88 | 89 | .enDataPath = VI_PATH_ISP, 90 | 91 | .enInputDataType = VI_DATA_TYPE_RGB, 92 | 93 | .bDataRev = HI_FALSE, 94 | 95 | .stDevRect = {.s32X = 0, .s32Y = 0, .u32Width = PIC_WIDTH, .u32Height = PIC_HEIGHT}}; 96 | 97 | static VI_CHN_ATTR_S VI_CHN_ATTR = { 98 | .stCapRect = {.s32X = 0, .s32Y = 0, .u32Width = PIC_WIDTH, .u32Height = PIC_HEIGHT}, 99 | .stDestSize = {.u32Width = PIC_WIDTH, .u32Height = PIC_HEIGHT}, 100 | .enCapSel = VI_CAPSEL_BOTH, 101 | .enPixFormat = PIXEL_FORMAT, 102 | .enCompressMode = COMPRESS_MODE_NONE, 103 | .bMirror = HI_FALSE, 104 | .bFlip = HI_FALSE, 105 | .s32SrcFrameRate = FRAME_RATE, 106 | .s32DstFrameRate = FRAME_RATE}; 107 | 108 | namespace nvr 109 | { 110 | rtc::scoped_refptr VideoCaptureImpl::Create() 111 | { 112 | err_code code; 113 | 114 | rtc::scoped_refptr implemention(new rtc::RefCountedObject()); 115 | 116 | code = static_cast(implemention->Initialize()); 117 | 118 | if (KSuccess != code) 119 | { 120 | log_e("error:%s", make_error_code(code).message().c_str()); 121 | return nullptr; 122 | } 123 | 124 | return implemention; 125 | } 126 | 127 | int32_t VideoCaptureImpl::StartMIPI() 128 | { 129 | //��ʼ��mipi(Mobile Idustry Processor Interface) 130 | int32_t fd = open("/dev/hi_mipi", O_RDWR); 131 | if (fd < 0) 132 | { 133 | log_e("open hisi mipi device failed,%s", strerror(errno)); 134 | return static_cast(KMPPError); 135 | } 136 | 137 | //��ʼ����mipi 138 | ioctl(fd, HI_MIPI_RESET_MIPI, &COMBO_DEV_ATTR.devno); 139 | 140 | //��ʼ���ô����� 141 | ioctl(fd, HI_MIPI_RESET_SENSOR, &COMBO_DEV_ATTR.devno); 142 | 143 | //����mipi 144 | if (ioctl(fd, HI_MIPI_SET_DEV_ATTR, &COMBO_DEV_ATTR)) 145 | { 146 | log_e("configure mipi failed,%s", strerror(errno)); 147 | return static_cast(KMPPError); 148 | } 149 | 150 | usleep(10000); //10ms 151 | 152 | //��������mipi 153 | ioctl(fd, HI_MIPI_UNRESET_MIPI, &COMBO_DEV_ATTR.devno); 154 | 155 | //�������ô����� 156 | ioctl(fd, HI_MIPI_UNRESET_SENSOR, &COMBO_DEV_ATTR.devno); 157 | 158 | ::close(fd); 159 | 160 | return static_cast(KSuccess); 161 | } 162 | 163 | int32_t VideoCaptureImpl::InitISP() 164 | { 165 | int32_t ret; 166 | 167 | ret = sensor_register_callback(); 168 | if (HI_SUCCESS != ret) 169 | { 170 | log_e("sensor_register_callback failed,code %#x", ret); 171 | return static_cast(KMPPError); 172 | } 173 | 174 | ALG_LIB_S alg_lib; 175 | memset(&alg_lib, 0, sizeof(alg_lib)); 176 | 177 | alg_lib.s32Id = 0; 178 | strncpy(alg_lib.acLibName, HI_AE_LIB_NAME, 20); 179 | ret = HI_MPI_AE_Register(NVR_ISP_DEV, &alg_lib); 180 | if (HI_SUCCESS != ret) 181 | { 182 | log_e("HI_MPI_AE_Register failed,code %#x", ret); 183 | return static_cast(KMPPError); 184 | } 185 | 186 | alg_lib.s32Id = 0; 187 | strncpy(alg_lib.acLibName, HI_AWB_LIB_NAME, 20); 188 | ret = HI_MPI_AWB_Register(NVR_ISP_DEV, &alg_lib); 189 | if (HI_SUCCESS != ret) 190 | { 191 | log_e("HI_MPI_AWB_Register failed,code %#x", ret); 192 | return static_cast(KMPPError); 193 | } 194 | 195 | alg_lib.s32Id = 0; 196 | strncpy(alg_lib.acLibName, HI_AF_LIB_NAME, 20); 197 | ret = HI_MPI_AF_Register(NVR_ISP_DEV, &alg_lib); 198 | if (HI_SUCCESS != ret) 199 | { 200 | log_e("HI_MPI_AF_Register failed,code %#x", ret); 201 | return static_cast(KMPPError); 202 | } 203 | 204 | ret = HI_MPI_ISP_MemInit(NVR_ISP_DEV); 205 | if (HI_SUCCESS != ret) 206 | { 207 | log_e("HI_MPI_ISP_Init failed,code %#x", ret); 208 | return static_cast(KMPPError); 209 | } 210 | 211 | ISP_WDR_MODE_S wdr_mode; 212 | memset(&wdr_mode, 0, sizeof(wdr_mode)); 213 | wdr_mode.enWDRMode = WDR_MODE_NONE; 214 | ret = HI_MPI_ISP_SetWDRMode(NVR_ISP_DEV, &wdr_mode); 215 | if (HI_SUCCESS != ret) 216 | { 217 | log_e("HI_MPI_ISP_SetWDRMode failed,code %#x", ret); 218 | return static_cast(KMPPError); 219 | } 220 | 221 | ret = HI_MPI_ISP_SetPubAttr(NVR_ISP_DEV, &ISP_PUB_ATTR); 222 | if (HI_SUCCESS != ret) 223 | { 224 | log_e("HI_MPI_ISP_SetPubAttr failed,code %#x", ret); 225 | return static_cast(KMPPError); 226 | } 227 | 228 | ret = HI_MPI_ISP_Init(NVR_ISP_DEV); 229 | if (HI_SUCCESS != ret) 230 | { 231 | log_e("HI_MPI_ISP_Init failed,code %#x", ret); 232 | return static_cast(KMPPError); 233 | } 234 | 235 | return static_cast(KSuccess); 236 | }; 237 | 238 | void VideoCaptureImpl::UnInitISP() 239 | { 240 | int32_t ret; 241 | 242 | ALG_LIB_S alg_lib; 243 | memset(&alg_lib, 0, sizeof(alg_lib)); 244 | 245 | alg_lib.s32Id = 0; 246 | strncpy(alg_lib.acLibName, HI_AF_LIB_NAME, 20); 247 | ret = HI_MPI_AF_UnRegister(NVR_ISP_DEV, &alg_lib); 248 | if (HI_SUCCESS != ret) 249 | log_e("HI_MPI_AF_UnRegister failed,code %#x", ret); 250 | 251 | alg_lib.s32Id = 0; 252 | strncpy(alg_lib.acLibName, HI_AWB_LIB_NAME, 20); 253 | ret = HI_MPI_AWB_UnRegister(NVR_ISP_DEV, &alg_lib); 254 | if (HI_SUCCESS != ret) 255 | log_e("HI_MPI_AWB_UnRegister failed,code %#x", ret); 256 | 257 | alg_lib.s32Id = 0; 258 | strncpy(alg_lib.acLibName, HI_AE_LIB_NAME, 20); 259 | ret = HI_MPI_AE_UnRegister(NVR_ISP_DEV, &alg_lib); 260 | if (HI_SUCCESS != ret) 261 | log_e("HI_MPI_AE_UnRegister failed,code %#x", ret); 262 | 263 | ret = sensor_unregister_callback(); 264 | if (HI_SUCCESS != ret) 265 | log_e("sensor_unregister_callback failed,code %#x", ret); 266 | } 267 | 268 | void VideoCaptureImpl::StartISP() 269 | { 270 | thread_ = std::unique_ptr(new std::thread([this]() { 271 | int32_t ret; 272 | ret = HI_MPI_ISP_Run(NVR_ISP_DEV); 273 | if (HI_SUCCESS != ret) 274 | log_e("HI_MPI_ISP_Run failed,code %#x", ret); 275 | })); 276 | 277 | usleep(10000); //10ms 278 | } 279 | 280 | void VideoCaptureImpl::StopISP() 281 | { 282 | int32_t ret; 283 | 284 | ret = HI_MPI_ISP_Exit(NVR_ISP_DEV); 285 | if (HI_SUCCESS != ret) 286 | log_e("HI_MPI_ISP_Exit failed,code %#x", ret); 287 | 288 | thread_->join(); 289 | thread_.reset(); 290 | thread_ = nullptr; 291 | } 292 | 293 | int32_t VideoCaptureImpl::StartVI() 294 | { 295 | int32_t ret; 296 | 297 | ISP_WDR_MODE_S wdr_mode; 298 | wdr_mode.enWDRMode = WDR_MODE_NONE; 299 | 300 | ret = HI_MPI_ISP_GetWDRMode(NVR_ISP_DEV, &wdr_mode); 301 | if (HI_SUCCESS != ret) 302 | { 303 | log_e("HI_MPI_ISP_GetWDRMode failed,code %#x", ret); 304 | return static_cast(KMPPError); 305 | } 306 | 307 | ret = HI_MPI_VI_SetDevAttr(NVR_VI_DEV, &VI_DEV_ATTR); 308 | if (HI_SUCCESS != ret) 309 | { 310 | log_e("HI_MPI_VI_SetDevAttr failed,code %#x", ret); 311 | return static_cast(KMPPError); 312 | } 313 | 314 | VI_WDR_ATTR_S wdr_attr; 315 | memset(&wdr_attr, 0, sizeof(wdr_attr)); 316 | wdr_attr.enWDRMode = wdr_mode.enWDRMode; 317 | wdr_attr.bCompress = HI_FALSE; 318 | 319 | ret = HI_MPI_VI_SetWDRAttr(NVR_VI_DEV, &wdr_attr); 320 | if (HI_SUCCESS != ret) 321 | { 322 | log_e("HI_MPI_VI_SetWDRAttr failed,code %#x", ret); 323 | return static_cast(KMPPError); 324 | } 325 | 326 | ret = HI_MPI_VI_EnableDev(NVR_VI_DEV); 327 | if (HI_SUCCESS != ret) 328 | { 329 | log_e("HI_MPI_VI_EnableDev failed,code %#x", ret); 330 | return static_cast(KMPPError); 331 | } 332 | 333 | return static_cast(KSuccess); 334 | }; 335 | 336 | void VideoCaptureImpl::StopVI() 337 | { 338 | int32_t ret; 339 | 340 | ret = HI_MPI_VI_DisableDev(NVR_VI_DEV); 341 | if (HI_SUCCESS != ret) 342 | log_e("HI_MPI_VI_DisableDev failed,code %#x", ret); 343 | }; 344 | 345 | int32_t VideoCaptureImpl::StartVIChn() 346 | { 347 | int32_t ret; 348 | 349 | ret = HI_MPI_VI_SetChnAttr(NVR_VI_CHN, &VI_CHN_ATTR); 350 | if (HI_SUCCESS != ret) 351 | { 352 | log_e("HI_MPI_VI_SetChnAttr failed,code %#x", ret); 353 | return static_cast(KMPPError); 354 | } 355 | 356 | ret = HI_MPI_VI_EnableChn(NVR_VI_CHN); 357 | if (HI_SUCCESS != ret) 358 | { 359 | log_e("HI_MPI_VI_EnableChn failed,code %#x", ret); 360 | return static_cast(KMPPError); 361 | } 362 | 363 | return static_cast(KSuccess); 364 | }; 365 | 366 | void VideoCaptureImpl::StopVIChn() 367 | { 368 | int32_t ret; 369 | 370 | ret = HI_MPI_VI_DisableChn(NVR_VI_CHN); 371 | if (HI_SUCCESS != ret) 372 | log_e("HI_MPI_VI_DisableChn failed,code %#x", ret); 373 | } 374 | 375 | int32_t VideoCaptureImpl::Initialize() 376 | { 377 | if (init_) 378 | return static_cast(KDupInitialize); 379 | 380 | err_code code; 381 | 382 | code = static_cast(StartMIPI()); 383 | if (KSuccess != code) 384 | return code; 385 | 386 | code = static_cast(InitISP()); 387 | if (KSuccess != code) 388 | return code; 389 | 390 | StartISP(); 391 | 392 | code = static_cast(StartVI()); 393 | if (KSuccess != code) 394 | return code; 395 | 396 | code = static_cast(StartVIChn()); 397 | if (KSuccess != code) 398 | return code; 399 | 400 | init_ = true; 401 | 402 | return static_cast(KSuccess); 403 | } 404 | 405 | void VideoCaptureImpl::Close() 406 | { 407 | if (!init_) 408 | return; 409 | 410 | StopVIChn(); 411 | 412 | StopVI(); 413 | 414 | StopISP(); 415 | 416 | UnInitISP(); 417 | 418 | init_ = false; 419 | } 420 | 421 | VideoCaptureImpl::VideoCaptureImpl() : thread_(nullptr), 422 | init_(false) 423 | { 424 | } 425 | 426 | VideoCaptureImpl::~VideoCaptureImpl() 427 | { 428 | Close(); 429 | } 430 | }; // namespace nvr --------------------------------------------------------------------------------