wordpress4.0 中文深圳專業(yè)seo
本專欄主要是提供一種國產(chǎn)化圖像識別的解決方案,專欄中實(shí)現(xiàn)了YOLOv5/v8在國產(chǎn)化芯片上的使用部署,并可以實(shí)現(xiàn)網(wǎng)頁端實(shí)時(shí)查看。根據(jù)自己的具體需求可以直接產(chǎn)品化部署使用。
B站配套視頻:https://www.bilibili.com/video/BV1or421T74f
前言
在實(shí)際生產(chǎn)過程中,有很多時(shí)候不光是通過網(wǎng)絡(luò)獲取rtsp視頻流,通常會(huì)采用在板子上插上USB攝像頭獲取畫面。
今天我將向搭建演示該如何通過USB獲取畫面后推流出RTSP視頻流。
本課程相關(guān)代碼以開源在V8的項(xiàng)目中,有開源鏈接的朋友可以重新拉取一下代碼。
前期準(zhǔn)備
首先我們需要確定一下基本原理,usb的獲取和推流到rtsp是這里面存在編碼不一致的問題。
通常我們會(huì)采用opencv獲取usb攝像頭的畫面然后進(jìn)行推理,這時(shí)候圖像是RGB編碼的。
而推流到RTSP中就變成了YUV編碼,那自然就會(huì)想到RK3588的固有能力,硬件編碼器MPP。
那RTSP的推流我們就選擇官方推薦的ZLMediakit來實(shí)現(xiàn)。正題結(jié)構(gòu)如下所示:
下載和編譯zlmediakit、mpp
代碼講解查看視頻 https://www.bilibili.com/video/BV1or421T74f](https://www.bilibili.com/video/BV1or421T74f
cd ZLMediaKit
git submodule init
git submodule update
cmake . -B build && cmake --build build -j4
cd ../mpp
cmake . -B build && cmake --build build -j4
cp ./submodules/mpp/build/utils/libutils.a libs/
cp ./submodules/ZLMediaKit/release/linux/Debug/libmk_api.so libs/
源碼核心部分
int process_video_file(rknn_app_context_t *ctx, const char *video_path)
{// 讀取視頻cv::VideoCapture cap(video_path);if (!cap.isOpened()){printf("Failed to open video file: %s", video_path);}// 獲取視頻尺寸、幀率int cap_width = cap.get(cv::CAP_PROP_FRAME_WIDTH);int cap_height = cap.get(cv::CAP_PROP_FRAME_HEIGHT);int fps = cap.get(cv::CAP_PROP_FPS);ctx->media = mk_media_create("__defaultVhost__", ctx->push_path_first.c_str(), ctx->push_path_second.c_str(), 0, 0, 0);codec_args v_args = {0};mk_track v_track = mk_track_create(MKCodecH264, &v_args);mk_media_init_track(ctx->media, v_track);mk_media_init_complete(ctx->media);mk_media_set_on_regist(ctx->media, on_mk_media_source_regist_func, ctx);// 初始化編碼器MppEncoder *mpp_encoder = new MppEncoder();MppEncoderParams enc_params;memset(&enc_params, 0, sizeof(MppEncoderParams));enc_params.width = cap_width;enc_params.height = cap_height;enc_params.fmt = MPP_FMT_YUV420SP;enc_params.type = MPP_VIDEO_CodingAVC;mpp_encoder->Init(enc_params, ctx);ctx->encoder = mpp_encoder;// mpp編碼配置void *mpp_frame = NULL;int mpp_frame_fd = 0;void *mpp_frame_addr = NULL;int enc_data_size;int frame_index = 0;int ret = 0;// 畫面cv::Mat img;while (true){// 讀取視頻幀cap >> img;if (img.empty()){printf("Video end.");break;}frame_index++;// 結(jié)束計(jì)時(shí)auto end_time = std::chrono::high_resolution_clock::now();// 將當(dāng)前時(shí)間點(diǎn)轉(zhuǎn)換為毫秒級別的時(shí)間戳auto millis = std::chrono::time_point_cast<std::chrono::milliseconds>(end_time).time_since_epoch().count();mpp_frame = ctx->encoder->GetInputFrameBuffer();mpp_frame_fd = ctx->encoder->GetInputFrameBufferFd(mpp_frame);mpp_frame_addr = ctx->encoder->GetInputFrameBufferAddr(mpp_frame);rga_buffer_t src = wrapbuffer_fd(mpp_frame_fd, cap_width, cap_height, RK_FORMAT_YCbCr_420_SP);int enc_buf_size = ctx->encoder->GetFrameSize();char *enc_data = (char *)malloc(enc_buf_size);rga_buffer_t rgb_img = wrapbuffer_virtualaddr((void *)img.data, cap_width, cap_height, RK_FORMAT_BGR_888);// 將RGB圖像復(fù)制到src中imcopy(rgb_img, src);if (frame_index == 1){enc_data_size = ctx->encoder->GetHeader(enc_data, enc_buf_size);}// 內(nèi)存初始化memset(enc_data, 0, enc_buf_size);enc_data_size = ctx->encoder->Encode(mpp_frame, enc_data, enc_buf_size);ret = mk_media_input_h264(ctx->media, enc_data, enc_data_size, millis, millis);if (ret != 1){printf("mk_media_input_frame failed\n");}}cap.release();
}
代碼講解查看視頻https://www.bilibili.com/video/BV1or421T74f