Hi Guys
Hope this helps other people. I have managed to get an rtsp stream on my pico MAX using the following. The next step is to add the RKNN infering but I dont have enough C skills so if anyone can build on this or add, please go ahead.
I could be wrong but this is the closest i have come so far.
I suggest first doing the RKNN tutorial and making a basic cc program first to understand the build script.
First you need to buildroot and add :
ffmpeg
jpeglib
Then build a new image for you pico. I have only done this on the Pico Max.
Then i used the RKNN Model Inference tutorial and build my own C program.
Here is a copy of the CmakeLists.txt
Code: Select all
cmake_minimum_required(VERSION 3.4.1)
project(apex)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,--allow-shlib-undefined")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wl,--allow-shlib-undefined")
# install target and libraries
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/apex_${CMAKE_SYSTEM_NAME})
set(CMAKE_SKIP_INSTALL_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
# rknn api
set(RKNN_API_PATH ${CMAKE_SOURCE_DIR}/../../../runtime/RV1106/${CMAKE_SYSTEM_NAME}/librknn_api)
set(RKNN_RT_LIB ${RKNN_API_PATH}/armhf/librknnmrt.so)
include_directories(${RKNN_API_PATH}/include)
include_directories(${CMAKE_SOURCE_DIR}/../../3rdparty)
include_directories(/home/Projects/luckfox/luckfox-pico/sysdrv/source/buildroot/buildroot-2023.02.6/output/host/arm-buildroot-linux-uclibcgnueabihf/sysroot/usr/include)
link_directories(/home/Projects/luckfox/luckfox-pico/sysdrv/source/buildroot/buildroot-2023.02.6/output/host/arm-buildroot-linux-uclibcgnueabihf/sysroot/usr/lib)
# Apex
include_directories(${CMAKE_SOURCE_DIR}/include)
add_executable(apex
src/main.cc
src/postprocess.cc
)
target_link_libraries(apex avformat avcodec avutil jpeg
${RKNN_RT_LIB}
)
# install target and libraries
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/apex_${CMAKE_SYSTEM_NAME})
install(TARGETS apex DESTINATION ./)
install(PROGRAMS ${RKNN_RT_LIB} DESTINATION lib)
install(DIRECTORY model DESTINATION ./)
And here is a copy of my .cc file.
Code: Select all
#include "rknn_api.h"
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <vector>
#include <iostream>
#include <filesystem>
#include <string>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include <jpeglib.h>
extern "C"{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}
// #define STB_IMAGE_IMPLEMENTATION
// #include "stb/stb_image.h"
// #define STB_IMAGE_RESIZE_IMPLEMENTATION
// #include <stb/stb_image_resize.h>
// #include "postprocess.h"
// #define PERF_WITH_POST 1
//Using Hikvision Camera
#define RTSP_URL "rtsp://xxx:xxx@10.0.0.86:554/Streaming/Channels/102"
/*-------------------------------------------
Main Functions
-------------------------------------------*/
int main() {
av_register_all();
// Initialize network components (needed for RTSP)
avformat_network_init();
AVFormatContext *formatContext = avformat_alloc_context();
// Open the RTSP stream
if (avformat_open_input(&formatContext, RTSP_URL, NULL, NULL) != 0) {
fprintf(stderr, "Error opening RTSP stream\n");
return 1;
}
// Find stream information
if (avformat_find_stream_info(formatContext, NULL) < 0) {
fprintf(stderr, "Error finding stream information\n");
avformat_close_input(&formatContext);
avformat_network_deinit();
return 1;
}
// Find the first video stream
int videoStreamIndex = -1;
for (int i = 0; i < formatContext->nb_streams; i++) {
if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStreamIndex = i;
break;
}
}
if (videoStreamIndex == -1) {
fprintf(stderr, "Error finding video stream\n");
avformat_close_input(&formatContext);
avformat_network_deinit();
return 1;
}
AVCodecContext *codecContext = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(codecContext, formatContext->streams[videoStreamIndex]->codecpar);
AVCodec *codec = avcodec_find_decoder(codecContext->codec_id);
if (!codec) {
fprintf(stderr, "Error finding codec\n");
avcodec_free_context(&codecContext);
avformat_close_input(&formatContext);
avformat_network_deinit();
return 1;
}
if (avcodec_open2(codecContext, codec, NULL) < 0) {
fprintf(stderr, "Error opening codec\n");
avcodec_free_context(&codecContext);
avformat_close_input(&formatContext);
avformat_network_deinit();
return 1;
}
AVPacket packet;
av_init_packet(&packet);
AVFrame *frame = av_frame_alloc();
printf("Ready to receive frames...\n");
while (av_read_frame(formatContext, &packet) >= 0) {
if (packet.stream_index == videoStreamIndex) {
// Decode video frame
if (avcodec_send_packet(codecContext, &packet) == 0) {
while (avcodec_receive_frame(codecContext, frame) == 0) {
// Print frame information
printf("Received frame: width=%d, height=%d\n", frame->width, frame->height);
// Save the frame to an image file (you can implement this function)
//save_frame_to_image(frame->data[0], frame->linesize[0] * frame->height, frame->width, frame->height);
// Sleep for a short duration (adjust as needed)
usleep(10000); // 10ms
}
}
}
av_packet_unref(&packet);
}
printf("Finished receiving frames...\n");
av_frame_free(&frame);
avcodec_free_context(&codecContext);
avformat_close_input(&formatContext);
// Clean up
avformat_network_deinit();
return 0;
}
Hope this helps someone
Thanks
Robby