<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      逆天Qt/在嵌入式板子上同時播放4路8K視頻/硬解碼GPU繪制/RK3588性能太兇殘

      說來也奇怪,最近RK3588的用戶扎堆,近期連續(xù)遠(yuǎn)程了七八個板子都是3588,有firefly的,有野火魯班貓的,有正點(diǎn)原子的等,總體都大差不差,通過各種性能對比測試,魯班貓性能更突出。在我們普通的PC機(jī)器電腦,播放一個8K,直接GPU干滿,除非顯卡強(qiáng)勁,普通的顯卡一般就只能支撐1路265格式的8K播放,以為這就是極限了,沒想到在小小的嵌入式板子上,播放8K也是這么的流暢,不愧是專有的RKMPP硬解方案,這還不是極限,開了4路8K,居然也行,絕對的震驚,顛覆了我的認(rèn)知,這才幾百塊的核心板,這么兇殘嗎?

      Snipaste_2025-07-22_15-20-18

      Snipaste_2025-07-23_15-38-28

      Snipaste_2025-07-23_15-39-40

      下面是一個使用純 Qt 和 FFmpeg 實(shí)現(xiàn) Rockchip MPP (RKMPP) 硬件解碼的示例代碼。這個示例展示了如何初始化 FFmpeg 并使用 RKMPP 進(jìn)行硬件解碼。

      準(zhǔn)備工作

      1. 確保已安裝 FFmpeg 并啟用了 RKMPP 支持
      2. 確保 Qt 開發(fā)環(huán)境已配置好
      3. 需要在 Rockchip 平臺上運(yùn)行(如 RK3399, RK3588 等)

      完整代碼實(shí)現(xiàn)

      #include <QCoreApplication>
      #include <QDebug>
      #include <QImage>
      #include <QFile>
      
      extern "C" {
      #include <libavcodec/avcodec.h>
      #include <libavformat/avformat.h>
      #include <libavutil/imgutils.h>
      #include <libavutil/opt.h>
      #include <libavutil/hwcontext.h>
      #include <libavutil/hwcontext_drm.h>
      }
      
      class RKMPPDecoder {
      public:
          RKMPPDecoder() : fmt_ctx(nullptr), video_dec_ctx(nullptr), hw_device_ctx(nullptr) {}
          ~RKMPPDecoder() { cleanup(); }
      
          bool init(const QString &filePath) {
              // 注冊所有 FFmpeg 組件
              avformat_network_init();
              avdevice_register_all();
      
              // 打開輸入文件
              if (avformat_open_input(&fmt_ctx, filePath.toUtf8().constData(), nullptr, nullptr) < 0) {
                  qWarning() << "Could not open source file" << filePath;
                  return false;
              }
      
              // 獲取流信息
              if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) {
                  qWarning() << "Could not find stream information";
                  return false;
              }
      
              // 查找視頻流
              int ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
              if (ret < 0) {
                  qWarning() << "Could not find video stream in input file";
                  return false;
              }
              video_stream_idx = ret;
              AVStream *video_stream = fmt_ctx->streams[video_stream_idx];
      
              // 查找硬件解碼器
              const AVCodec *decoder = nullptr;
              if (video_stream->codecpar->codec_id == AV_CODEC_ID_H264) {
                  decoder = avcodec_find_decoder_by_name("h264_rkmpp");
              } else if (video_stream->codecpar->codec_id == AV_CODEC_ID_HEVC) {
                  decoder = avcodec_find_decoder_by_name("hevc_rkmpp");
              } else if (video_stream->codecpar->codec_id == AV_CODEC_ID_VP9) {
                  decoder = avcodec_find_decoder_by_name("vp9_rkmpp");
              }
      
              if (!decoder) {
                  qWarning() << "Failed to find RKMPP decoder for codec" << avcodec_get_name(video_stream->codecpar->codec_id);
                  return false;
              }
      
              // 創(chuàng)建解碼器上下文
              video_dec_ctx = avcodec_alloc_context3(decoder);
              if (!video_dec_ctx) {
                  qWarning() << "Failed to allocate decoder context";
                  return false;
              }
      
              // 復(fù)制流參數(shù)到解碼器上下文
              if (avcodec_parameters_to_context(video_dec_ctx, video_stream->codecpar) < 0) {
                  qWarning() << "Failed to copy codec parameters to decoder context";
                  return false;
              }
      
              // 設(shè)置硬件加速
              if (initHardware() < 0) {
                  qWarning() << "Failed to initialize hardware decoder";
                  return false;
              }
      
              // 打開解碼器
              if (avcodec_open2(video_dec_ctx, decoder, nullptr) < 0) {
                  qWarning() << "Failed to open codec";
                  return false;
              }
      
              return true;
          }
      
          void decodeFrames() {
              AVPacket *pkt = av_packet_alloc();
              AVFrame *frame = av_frame_alloc();
              AVFrame *sw_frame = av_frame_alloc();
              int ret = 0;
      
              if (!pkt || !frame || !sw_frame) {
                  qWarning() << "Failed to allocate packet or frame";
                  goto end;
              }
      
              // 讀取并解碼幀
              while (av_read_frame(fmt_ctx, pkt) >= 0) {
                  if (pkt->stream_index == video_stream_idx) {
                      ret = avcodec_send_packet(video_dec_ctx, pkt);
                      if (ret < 0) {
                          qWarning() << "Error sending packet to decoder";
                          continue;
                      }
      
                      while (ret >= 0) {
                          ret = avcodec_receive_frame(video_dec_ctx, frame);
                          if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                              break;
                          } else if (ret < 0) {
                              qWarning() << "Error during decoding";
                              break;
                          }
      
                          // 處理硬件幀
                          if (frame->format == AV_PIX_FMT_DRM_PRIME) {
                              // 從硬件幀獲取 DRM 描述符
                              AVDRMFrameDescriptor *drm_desc = (AVDRMFrameDescriptor *)frame->data[0];
                              
                              // 這里可以添加處理 DRM 幀的代碼
                              // 例如使用 Qt 的 EGL 或直接渲染到屏幕
                              
                              qDebug() << "Got DRM PRIME frame, width:" << frame->width << "height:" << frame->height;
                          } else {
                              // 如果不是硬件幀,可能是軟件回退
                              qDebug() << "Got software frame, format:" << frame->format;
                          }
      
                          av_frame_unref(frame);
                      }
                  }
                  av_packet_unref(pkt);
              }
      
          end:
              av_packet_free(&pkt);
              av_frame_free(&frame);
              av_frame_free(&sw_frame);
          }
      
      private:
          int initHardware() {
              int ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_DRM, nullptr, nullptr, 0);
              if (ret < 0) {
                  qWarning() << "Failed to create DRM HW device context";
                  return ret;
              }
      
              video_dec_ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
              if (!video_dec_ctx->hw_device_ctx) {
                  qWarning() << "Failed to reference HW device context";
                  return -1;
              }
      
              // 設(shè)置像素格式為 DRM PRIME
              video_dec_ctx->pix_fmt = AV_PIX_FMT_DRM_PRIME;
              video_dec_ctx->get_format = get_hw_format;
      
              return 0;
          }
      
          static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *pix_fmts) {
              const enum AVPixelFormat *p;
              
              for (p = pix_fmts; *p != -1; p++) {
                  if (*p == AV_PIX_FMT_DRM_PRIME) {
                      return *p;
                  }
              }
              
              qWarning() << "Failed to get HW surface format";
              return AV_PIX_FMT_NONE;
          }
      
          void cleanup() {
              if (video_dec_ctx) {
                  avcodec_free_context(&video_dec_ctx);
                  video_dec_ctx = nullptr;
              }
              if (fmt_ctx) {
                  avformat_close_input(&fmt_ctx);
                  fmt_ctx = nullptr;
              }
              if (hw_device_ctx) {
                  av_buffer_unref(&hw_device_ctx);
                  hw_device_ctx = nullptr;
              }
          }
      
          AVFormatContext *fmt_ctx;
          AVCodecContext *video_dec_ctx;
          AVBufferRef *hw_device_ctx;
          int video_stream_idx;
      };
      
      int main(int argc, char *argv[]) {
          QCoreApplication a(argc, argv);
      
          if (argc < 2) {
              qWarning() << "Usage: " << argv[0] << " <input file>";
              return -1;
          }
      
          RKMPPDecoder decoder;
          if (!decoder.init(argv[1])) {
              return -1;
          }
      
          qDebug() << "Starting decoding...";
          decoder.decodeFrames();
          qDebug() << "Decoding finished";
      
          return a.exec();
      }
      

      代碼說明

      1. 初始化部分:

        • 使用 avformat_open_input 打開輸入文件
        • 查找視頻流并確定合適的 RKMPP 解碼器 (h264_rkmpp, hevc_rkmpp 或 vp9_rkmpp)
        • 初始化硬件解碼上下文
      2. 硬件加速設(shè)置:

        • 使用 av_hwdevice_ctx_create 創(chuàng)建 DRM 硬件設(shè)備上下文
        • 設(shè)置像素格式為 AV_PIX_FMT_DRM_PRIME
        • 實(shí)現(xiàn) get_hw_format 回調(diào)函數(shù)
      3. 解碼循環(huán):

        • 使用 av_read_frame 讀取數(shù)據(jù)包
        • 使用 avcodec_send_packetavcodec_receive_frame 進(jìn)行解碼
        • 處理返回的 DRM PRIME 幀
      4. 資源清理:

        • 在析構(gòu)函數(shù)中釋放所有 FFmpeg 資源

      編譯說明

      在 Rockchip 平臺上編譯此代碼時,需要鏈接以下庫:

      • libavcodec
      • libavformat
      • libavutil
      • libavdevice

      典型的編譯命令:

      g++ -o rkmpp_decoder rkmpp_decoder.cpp \
          -I/usr/include/qt \
          -I/usr/include/qt/QtCore \
          -lQt5Core \
          -lavcodec -lavformat -lavutil -lavdevice
      

      注意事項(xiàng)

      1. 此代碼需要在 Rockchip 平臺上運(yùn)行,且系統(tǒng)已正確配置 RKMPP 驅(qū)動和 FFmpeg 支持
      2. 解碼后的幀是 DRM PRIME 格式,需要額外的代碼來渲染或轉(zhuǎn)換為 Qt 可用的格式
      3. 實(shí)際應(yīng)用中可能需要添加更多的錯誤處理和狀態(tài)檢查

      如果需要將解碼后的幀顯示在 Qt 窗口中,可以考慮使用 Qt 的 EGL 或 OpenGL 集成來直接渲染 DRM PRIME 幀,或者將幀轉(zhuǎn)換為 RGB 格式后使用 QImage/QPixmap 顯示。

      posted @ 2025-07-24 11:33  飛揚(yáng)青云  閱讀(241)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 精品国精品无码自拍自在线| 日韩精品久久久肉伦网站| 亚洲一品道一区二区三区| 男女激情一区二区三区| 国产久爱免费精品视频| 亚洲国产午夜福利精品| 欧美一区二区三区成人久久片| 国产成人综合亚洲欧美日韩 | 久久精品国产熟女亚洲av| 亚洲av无码国产在丝袜线观看| 最近中文字幕完整版2019| 好硬好湿好爽好深视频| 日本一卡2卡3卡四卡精品网站| 中文字幕无码免费久久| 欧洲中文字幕国产精品| 国产成人亚洲无码淙合青草| 久久99九九精品久久久久蜜桃| 国产精品国产三级国产午| 舒城县| 日本黄色一区二区三区四区 | 精品国产中文字幕av| 国产精品亚洲综合色区丝瓜| 91精品久久久久久无码人妻| 久久久久久久久久久免费精品| 国产精品沙发午睡系列990531| 性色av不卡一区二区三区 | 老司机午夜精品视频资源| 最近中文字幕免费手机版| 无码国产精品一区二区VR老人| 精品国产一区二区亚洲人| 国产精品一区二区香蕉| 少妇撒尿一区二区在线视频| 福利一区二区在线播放| 国产边摸边吃奶边叫做激情视频| 成年午夜免费韩国做受视频| 久久精品国产精品亚洲综合| 成人精品视频一区二区三区 | 九九久久自然熟的香蕉图片| 国产乱码精品一区二区三区中文| 成人看的污污超级黄网站免费 | 亚洲一级特黄大片一级特黄|