Firefly Open Source Community

   Login   |   Register   |
New_Topic
Print Previous Topic Next Topic

[Linux] RV1126 frame reading CPU usage

21

Credits

0

Prestige

0

Contribution

new registration

Rank: 1

Credits
21

【Linux】 RV1126 frame reading CPU usage

Posted at 3/24/2023 16:49:32      View:2802 | Replies:2        Print      Only Author   [Copy Link] 1#
Problem description and steps to reproduce:
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.


out.zip

987 Bytes, Down times: 0

Reply

Use props Report

21

Credits

0

Prestige

0

Contribution

new registration

Rank: 1

Credits
21
Posted at 3/24/2023 16:49:33        Only Author  2#
BTW FPS is 15
Reply

Use props Report

131

Credits

0

Prestige

0

Contribution

registered members

Rank: 2

Credits
131
Posted at 6 day before        Only Author  3#
Um hocheffektive ICF ICF-ACC Zertifizierungsprüfung vorzubereiten, wissen Sie, Welches Gerät verwendbar ist? ICF ICF-ACC Dumps von Pass4Test sind die zuverlässigen Unterlagen. Die Unterlagen sind von IT-Eliten geschaffen. Die sind auch sehr seltene Unterlagen. Die Hitz-Rate der ICF ICF-ACC Dumps ist sehr hoch und die Durchlaufrate erreicht 100%, weil die IT-Eliten die Punkte der Prüfungsfragen sehr gut und alle möglichen Fragen in zukünftigen aktuellen Prüfungen sammeln. Glauben Sie nicht? Aber es ist wirklich. Sie können wissen nach der Nutzung.
Reply

Use props Report

You need to log in before you can reply Login | Register

This forum Credits Rules

Quick Reply Back to top Back to list