当前位置: 首页 > article >正文

RK3568使用C++和FFmpeg进行视频流,并使用自带GPU加速

在RK3568平台上使用C++和FFmpeg进行视频流处理时,可以利用GPU加速解码。RK3568芯片集成了Mali-G52 GPU,支持硬件加速的视频解码。以下是一个基本的示例,展示如何使用FFmpeg和RK3568的GPU加速来拉取视频流。

1. 安装FFmpeg和RKMPP

首先,确保你已经安装了FFmpeg和RKMPP(Rockchip Media Process Platform)。RKMPP是Rockchip提供的用于硬件加速的库。

sudo apt-get update
sudo apt-get install ffmpeg
sudo apt-get install librkmpp-dev

2. 编写C++代码

以下是一个简单的C++代码示例,展示如何使用FFmpeg和RKMPP来拉取视频流并进行硬件加速解码。

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/hwcontext.h>
#include <libavutil/error.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#include <libswscale/swscale.h>
}

#include <iostream>
#include <stdexcept>

#define HARDWARE_DEVICE_TYPE AV_HWDEVICE_TYPE_DRM

void handle_error(int errnum) {
    char errbuf[AV_ERROR_MAX_STRING_SIZE];
    av_strerror(errnum, errbuf, sizeof(errbuf));
    throw std::runtime_error(errbuf);
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <input_url>" << std::endl;
        return 1;
    }

    const char* input_url = argv[1];

    av_register_all();
    avformat_network_init();

    AVFormatContext* format_ctx = avformat_alloc_context();
    if (!format_ctx) {
        std::cerr << "Could not allocate format context" << std::endl;
        return 1;
    }

    if (avformat_open_input(&format_ctx, input_url, nullptr, nullptr) < 0) {
        std::cerr << "Could not open input " << input_url << std::endl;
        return 1;
    }

    if (avformat_find_stream_info(format_ctx, nullptr) < 0) {
        std::cerr << "Could not find stream information" << std::endl;
        return 1;
    }

    int video_stream_index = -1;
    for (unsigned int i = 0; i < format_ctx->nb_streams; i++) {
        if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            video_stream_index = i;
            break;
        }
    }

    if (video_stream_index == -1) {
        std::cerr << "Could not find video stream" << std::endl;
        return 1;
    }

    AVCodecParameters* codec_params = format_ctx->streams[video_stream_index]->codecpar;
    const AVCodec* codec = avcodec_find_decoder(codec_params->codec_id);
    if (!codec) {
        std::cerr << "Unsupported codec" << std::endl;
        return 1;
    }

    AVCodecContext* codec_ctx = avcodec_alloc_context3(codec);
    if (!codec_ctx) {
        std::cerr << "Could not allocate codec context" << std::endl;
        return 1;
    }

    if (avcodec_parameters_to_context(codec_ctx, codec_params) < 0) {
        std::cerr << "Could not copy codec parameters to context" << std::endl;
        return 1;
    }

    AVBufferRef* hw_device_ctx = nullptr;
    if (av_hwdevice_ctx_create(&hw_device_ctx, HARDWARE_DEVICE_TYPE, nullptr, nullptr, 0) < 0) {
        std::cerr << "Could not create hardware device context" << std::endl;
        return 1;
    }

    codec_ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);

    if (avcodec_open2(codec_ctx, codec, nullptr) < 0) {
        std::cerr << "Could not open codec" << std::endl;
        return 1;
    }

    AVFrame* frame = av_frame_alloc();
    AVFrame* sw_frame = av_frame_alloc();
    if (!frame || !sw_frame) {
        std::cerr << "Could not allocate frames" << std::endl;
        return 1;
    }

    AVPacket packet;
    while (av_read_frame(format_ctx, &packet) >= 0) {
        if (packet.stream_index == video_stream_index) {
            if (avcodec_send_packet(codec_ctx, &packet) < 0) {
                std::cerr << "Error sending packet for decoding" << std::endl;
                break;
            }

            while (avcodec_receive_frame(codec_ctx, frame) >= 0) {
                if (frame->format == AV_PIX_FMT_DRM_PRIME) {
                    if (av_hwframe_transfer_data(sw_frame, frame, 0) < 0) {
                        std::cerr << "Error transferring data to software frame" << std::endl;
                        break;
                    }
                    // Process sw_frame here
                    std::cout << "Frame decoded: " << sw_frame->width << "x" << sw_frame->height << std::endl;
                }
            }
        }
        av_packet_unref(&packet);
    }

    av_frame_free(&frame);
    av_frame_free(&sw_frame);
    avcodec_free_context(&codec_ctx);
    avformat_close_input(&format_ctx);
    av_buffer_unref(&hw_device_ctx);

    return 0;
}

3. 编译代码

此处代码仅作参考,建议使用cmake搭建工程后编译测试


http://www.kler.cn/a/539758.html

相关文章:

  • IDEA+DeepSeek让Java开发起飞
  • ZooKeeper 的典型应用场景:从概念到实践
  • 智能化食品安全管理:AI视频监控在大型商场的技术方案
  • Java ArrayList 扩容机制详解
  • 【Java基础】序列化、反序列化和不可变类
  • 【实用教程】在 Android Studio 中连接 MuMu 模拟器
  • 寒假2.7
  • Springboot原理(面试高频)
  • Linux | 自动化构建 —— make / Makefile
  • 导航守卫router.beforeEach
  • 设计模式.
  • F#语言的物联网
  • Linux0号进程的静态创建
  • 如何在 Vue 中使用 mixins?
  • HTML之CSS定位、浮动、盒子模型
  • Spring AI 介绍
  • 【设计模式】【行为型模式】策略模式(Strategy)
  • windows下搭建tftp服务器+网络启动Linux
  • 苹果可折叠iPad:2028年的科技盛宴?
  • 30~32.ppt
  • 计算机网络面经
  • 实验7 路由器之间IPsec VPN配置
  • UE学习日志#25、26 C++笔记#11 智能指针
  • Gemini 2.0模型更新:谷歌最新AI大模型全面开启智能时代
  • java数据结构_二叉树_5.3 (几道例题搞定二叉树的遍历)
  • BMC开发技术栈指南