ffmpeg编码器使用

1、设置编码格式:

AVCodecID codec_id = AV_CODEC_ID_H264;

2、打开编码器

视频编码器可以分为软件编码器、cuvid编码器、 qsv编码器,由于硬件编码器效率高,所以优先打开硬件编码器,具体实现如下(三个编码器打开函数查看最后的补充内容)。

//打开视频编码器
bool VideoEncoder::openVideoEncoder(const AVCodecID &codec_id)
{
    bool isSucceed = false;
    bool isHardWareEncoderOpened = false;

    //尝试打开cuvid编码器器
    isHardWareEncoderOpened = openHardEncoder_Cuvid(codec_id);

    //cuvid打开失败了 继续尝试 qsv
    if (!isHardWareEncoderOpened)
        isHardWareEncoderOpened = openHardEncoder_Qsv(codec_id);

    //尝试打开硬件解码器失败了 改用软解码
    if (!isHardWareEncoderOpened)
        isSucceed = openSoftEncoder(codec_id);
    else
        isSucceed = true;
    return isSucceed;
}

3、进行编码

		int ret = avcodec_send_frame(pCodecCtx, picture);
        if (ret != 0)
        {
            char buff[128]={0};
            av_strerror(ret, buff, 128);
            fprintf(stderr, "Error sending a frame for encoding! (%s)\n", buff);
            continue;
        }
        while (0 == avcodec_receive_packet(pCodecCtx, &pkt))
        {
            bool isKeyFrame = pkt.flags & AV_PKT_FLAG_KEY; //判断是否关键帧
            T_NALU_TYPE naluType = T_NALU_H264;
            VideoFramePtr framePtr = std::make_shared<VideoFrame>(); //创建VideoFrame类型的智能指针         
            framePtr->setNalu(pkt.data + 4, pkt.size - 4, naluType);  //剔除4个字节的起始码
            RtpSenderManager->sendVideo(framePtr, node.time);       //发送数据
        }
        av_packet_unref(&pkt);
        av_free(node.buffer);

补充:

  1. 打开软编码器函数
bool VideoEncoder::openSoftEncoder(const AVCodecID &codec_id)
{
    bool isSucceed = false;
    fprintf(stderr,"open software encoder... \n");
    pCodec = avcodec_find_encoder(codec_id);
    if (pCodec == nullptr)
    {
        fprintf(stderr, "Codec not found.\n");
        isSucceed = false;
    }
    else
    {
        pCodecCtx = avcodec_alloc_context3(pCodec);
        pCodecCtx->thread_count = 8;
        AVDictionary *param = setEncoderParam(codec_id);
        ///打开解码器
        if (avcodec_open2(pCodecCtx, pCodec, &param) < 0)
        {
            avcodec_close(pCodecCtx);
            avcodec_free_context(&pCodecCtx);
            pCodecCtx = nullptr;
            isSucceed = false;
            fprintf(stderr,"Could not open codec.\n");
        }
        else
            isSucceed = true;
    }
    return isSucceed;
}
  1. 打开硬件编码器(intel)

bool VideoEncoder::openHardEncoder_Qsv(const AVCodecID &codec_id)
{
    bool isSucceed = false;

    fprintf(stderr,"open hardware encoder cuvid...\n");

    //查找硬件解码器
    char hardWareDecoderName[32] = {0};

    if (AV_CODEC_ID_H264 == codec_id)
        sprintf(hardWareDecoderName, "h264_qsv");
    else if (AV_CODEC_ID_HEVC == codec_id)
        sprintf(hardWareDecoderName, "hevc_qsv");

    if (strlen(hardWareDecoderName) > 0)
    {
        pCodec = avcodec_find_encoder_by_name(hardWareDecoderName);
        if (pCodec != NULL)
        {
            pCodecCtx = avcodec_alloc_context3(pCodec);
            AVDictionary *param = setEncoderParam(codec_id);

            if (avcodec_open2(pCodecCtx, pCodec, &param) < 0) //打开解码器
            {
                avcodec_close(pCodecCtx);
                avcodec_free_context(&pCodecCtx);
                pCodecCtx = nullptr;
                isSucceed = false;
                fprintf(stderr,"Could not open codec %s\n",hardWareDecoderName);
            }
            else
            {
                isSucceed = true;
                fprintf(stderr,"open codec %s succeed! %d %d\n",hardWareDecoderName,pCodec->id,pCodecCtx->codec_id);
            }
        }
        else
            fprintf(stderr,"Codec %s not found.\n",hardWareDecoderName);
    }
    return isSucceed;
}
  1. 打开硬件编码器(英伟达)
bool VideoEncoder::openHardEncoder_Cuvid(const AVCodecID &codec_id)
{
    bool isSucceed = false;

    fprintf(stderr,"open hardware encoder cuvid...\n");

    ///查找硬件解码器
    char hardWareDecoderName[32] = {0};

    if (AV_CODEC_ID_H264 == codec_id)
        sprintf(hardWareDecoderName, "h264_nvenc");
    else if (AV_CODEC_ID_HEVC == codec_id)
        sprintf(hardWareDecoderName, "hevc_nvenc");

    if (strlen(hardWareDecoderName) > 0)
    {
        pCodec = avcodec_find_encoder_by_name(hardWareDecoderName);
        if (pCodec != nullptr)
        {
            pCodecCtx = avcodec_alloc_context3(pCodec);
            AVDictionary *param = setEncoderParam(codec_id);
           
            if (avcodec_open2(pCodecCtx, pCodec, &param) < 0) //打开解码器
            {
                avcodec_close(pCodecCtx);
                avcodec_free_context(&pCodecCtx);
                pCodecCtx = nullptr;
                isSucceed = false;

                fprintf(stderr,"Could not open codec %s\n",hardWareDecoderName);
            }
            else
            {
                isSucceed = true;
                fprintf(stderr,"open codec %s succeed! %d %d\n",hardWareDecoderName,pCodec->id,pCodecCtx->codec_id);
            }
        }
        else
            fprintf(stderr,"Codec %s not found.\n",hardWareDecoderName);
    }
    return isSucceed;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值