Firefly Open Source Community

Title: RV1126 frame reading CPU usage [Print This Page]

Author: emreharbutoglu    Time: 3/24/2023 16:49
Title: RV1126 frame reading CPU usage
Last edited by emreharbutoglu In 3/24/2023 16:50 Editor

Hi, I am using the firmware above. I wrote a C++ code that reads frames from a USB camera with ffmpeg library. But the problem is CPU usage. The process is consuming CPU around between %50-60. This is too much for a frame reading task. What should I do for this?

  1. #include <iostream>
  2. #include <chrono>
  3. #include <cstddef>
  4. #include <unistd.h>
  5. #include <string.h>

  6. extern "C" {
  7. #include <libavformat/avformat.h>
  8. #include <libavcodec/avcodec.h>
  9. #include <libavdevice/avdevice.h>
  10. #include <libavutil/avutil.h>
  11. #include <libavutil/pixdesc.h>
  12. #include <libswscale/swscale.h>
  13. }

  14. #include "opencv2/opencv.hpp"
  15. #include "zmq.hpp"
  16. #include "nlohmann/json.hpp"

  17. #include <opencv2/highgui.hpp>

  18. using json = nlohmann::json;

  19. #define WIDTH (640)
  20. #define HEIGHT (480)
  21. #define VIDM_COEFF (7)

  22. void int2array(u_char* output_array, uint64_t num, uint8_t digit);
  23. void combine_arrays(u_char* main_array, int id_size, int data_size, u_char* array_1, u_char* array_2);

  24. int main(){
  25.     std::ifstream cfg_file("config.json");
  26.     json cfg = json::parse(cfg_file);

  27.     zmq::context_t ctx;
  28.     zmq::socket_t publisher(ctx, ZMQ_PUB);
  29.     publisher.bind("ipc:///frames_socket.ipc");
  30.     const char* infile = "/dev/video25";

  31.     // initialize FFmpeg library
  32.     avcodec_register_all();
  33.     avdevice_register_all();
  34.     av_register_all();
  35. //  av_log_set_level(AV_LOG_DEBUG);

  36.     AVInputFormat *inputFormat =av_find_input_format("v4l2");
  37.     AVDictionary *options = NULL;
  38.     av_dict_set(&options, "input_format", "mjpeg", 0);
  39.     av_dict_set(&options, "framerate", "15", 0);
  40.     av_dict_set(&options, "aspect", "4:3", 0);
  41.     av_dict_set(&options, "video_size", "640x480", 0);

  42.     //AVFormatContext *pAVFormatContext = NULL;

  43.     int ret;

  44.     // open input file context
  45.     AVFormatContext* inctx = nullptr;
  46.     ret = avformat_open_input(&inctx, infile, inputFormat, &options);
  47.     if (ret < 0) {
  48.         std::cerr << "fail to avforamt_open_input(\"" << infile << "\"): ret=" << ret;
  49.         return 2;
  50.     }
  51.     // retrive input stream information
  52.     ret = avformat_find_stream_info(inctx, nullptr);
  53.     if (ret < 0) {
  54.         std::cerr << "fail to avformat_find_stream_info: ret=" << ret;
  55.         return 2;
  56.     }

  57.     // find primary video stream
  58.     AVCodec* vcodec = nullptr;
  59.     ret = av_find_best_stream(inctx, AVMEDIA_TYPE_VIDEO, -1, -1, &vcodec, 0);
  60.     if (ret < 0) {
  61.         std::cerr << "fail to av_find_best_stream: ret=" << ret;
  62.         return 2;
  63.     }
  64.     const int vstrm_idx = ret;
  65.     AVStream* vstrm = inctx->streams[vstrm_idx];

  66.     // open video decoder context
  67.     ret = avcodec_open2(vstrm->codec, vcodec, nullptr);
  68.     if (ret < 0) {
  69.         std::cerr << "fail to avcodec_open2: ret=" << ret;
  70.         return 2;
  71.     }

  72.     const int dst_width = vstrm->codec->width;
  73.     const int dst_height = vstrm->codec->height;
  74.     const AVPixelFormat dst_pix_fmt = AV_PIX_FMT_BGR24;
  75.     SwsContext* swsctx = sws_getCachedContext(
  76.         nullptr, vstrm->codec->width, vstrm->codec->height, vstrm->codec->pix_fmt,
  77.         dst_width, dst_height, dst_pix_fmt, SWS_BICUBIC, nullptr, nullptr, nullptr);
  78.     if (!swsctx) {
  79.         std::cerr << "fail to sws_getCachedContext";
  80.         return 2;
  81.     }

  82.     AVFrame* frame = av_frame_alloc();
  83.     std::vector<uint8_t> framebuf(avpicture_get_size(dst_pix_fmt, dst_width, dst_height));
  84.     avpicture_fill(reinterpret_cast<AVPicture*>(frame), framebuf.data(), dst_pix_fmt, dst_width, dst_height);

  85.     AVFrame* decframe = av_frame_alloc();
  86.     bool end_of_stream = false;
  87.     int got_pic = 0;
  88.     AVPacket pkt;

  89.     auto rpm = std::chrono::high_resolution_clock::now();
  90.     uint16_t fps_counter = 0;

  91.     do {
  92.         if ((std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - rpm)).count() >= 1000000) {
  93.             std::cout << "FPS_COUNTER: " << fps_counter << std::endl;
  94.             rpm = std::chrono::high_resolution_clock::now();
  95.             fps_counter = 0;
  96.         }
  97.         auto fps_time_start = std::chrono::high_resolution_clock::now();
  98.         usleep(50000); //35000 for cam
  99.         //while(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - fps_time_start).count() <= 100000);
  100.         if (!end_of_stream) {
  101.             ret = av_read_frame(inctx, &pkt);
  102.             if (ret < 0 && ret != AVERROR_EOF) {
  103.                 std::cerr << "fail to av_read_frame: ret=" << ret;
  104.                 return 2;
  105.             }
  106.             if (ret == 0 && pkt.stream_index != vstrm_idx)
  107.                 goto next_packet;
  108.             end_of_stream = (ret == AVERROR_EOF);
  109.         }
  110.         if (end_of_stream) {
  111.             // null packet for bumping process
  112.             av_init_packet(&pkt);
  113.             pkt.data = nullptr;
  114.             pkt.size = 0;
  115.         }
  116.         // decode video frame
  117.         avcodec_decode_video2(vstrm->codec, decframe, &got_pic, &pkt);
  118.         if (!got_pic) {
  119.             goto next_packet;
  120.         }
  121.         // convert frame to OpenCV matrix
  122.         sws_scale(swsctx, decframe->data, decframe->linesize, 0, decframe->height, frame->data, frame->linesize);
  123.         
  124.         {
  125.         cv::Mat image(dst_height, dst_width, CV_8UC3, framebuf.data(), frame->linesize[0]);
  126.         //cv::imwrite("frame_test.png", image);
  127.         //cv::resize(image, image, cv::Size(640, 640), cv::INTER_LINEAR);
  128.       
  129.         //auto fps_duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - fps_time_start);
  130.         //
  131.         //std::cout << "fps_duration" << 1000000/fps_duration.count() << std::endl;
  132.         
  133.         uint64_t frame_id = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
  134.         u_char b_frame_id[16];
  135.         int2array(b_frame_id, frame_id, 16);
  136.         auto pub_time_start = std::chrono::high_resolution_clock::now();
  137.         u_char main_array[16+image.total()*image.elemSize()];
  138.         combine_arrays(main_array, 16, image.total()*image.elemSize(), b_frame_id, image.data);
  139.         zmq::message_t msg(main_array, 16+image.total()*image.elemSize());
  140.         //zmq::message_t msg_frame_id(b_frame_id, 16);
  141.         //zmq::message_t msg_frame(image.data, image.total()*image.elemSize());
  142.         //publisher.send(msg_frame_id, zmq::send_flags::sndmore);
  143.         //publisher.send(msg_frame, zmq::send_flags::none);
  144.         publisher.send(msg, zmq::send_flags::none);

  145.         auto pub_duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - pub_time_start);
  146.         auto fps_duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - fps_time_start);
  147.         std::cout << "ZMQ publish took: " << pub_duration.count() << " microseconds " << 1000000/fps_duration.count() << " fps" << std::endl;
  148.         time_t now = time(0);
  149.         fps_counter++;
  150.         std::cout << "[INFO] Frame Published, frame_id: " << frame_id << ", datetime: " << std::ctime(&now);   
  151.         }
  152.       
  153. next_packet:
  154.         av_free_packet(&pkt);
  155.     } while (!end_of_stream || got_pic);
  156.     av_frame_free(&decframe);
  157.     av_frame_free(&frame);
  158.     avcodec_close(vstrm->codec);
  159.     avformat_close_input(&inctx);
  160.     return 0;  
  161. }

  162. void combine_arrays(u_char* main_array, int id_size, int data_size, u_char* array_1, u_char* array_2){
  163.     for(int i = 0; i < id_size; i++){
  164.         main_array[i] = array_1[i];
  165.     }
  166.     for(int i = 0; i < data_size; i++){
  167.         main_array[i+16] = array_2[i];
  168.     }
  169. }

  170. void int2array(u_char* output_array, uint64_t num, uint8_t digit){
  171.     for (int i = digit-1-3; i >= 0; i--)
  172.         {
  173.             output_array[i] = (num % 10);
  174.             num /= 10;
  175.         }
  176.         output_array[13] = '=';
  177.         output_array[14] = '=';
  178.         output_array[15] = '=';
  179. }
Copy the code

Also I have found a solution but it's CPU usage around between %20-30. I executing a shell command that reads frames with ffmpeg command. Not an effective solution.
My goal is reducing the CPU usage to between %5-10.


tchip_askquestions

out.zip

987 Bytes, Down times: 0


Author: emreharbutoglu    Time: 3/24/2023 16:49
BTW FPS is 15




Welcome Firefly Open Source Community (https://bbs.t-firefly.com/) Powered by Discuz! X3.1