小白想变强 2020-04-19 13:57 采纳率: 0%
浏览 1141

ffmpeg 硬编码时avcodec_encode_video2返回错误码-11(Resource temporarily unavailable)

用ffmpeg将bmp文件序列编码为h264,使用软编码器AV_CODEC_ID_H264时
程序可以正常运行,换成硬编码器h264_nvenc后,程序有时可以正常运行,但有时会报错,错误现象为:
编码生成的h264文件大小为0KB,avcodec_encode_video2()函数返回错误码-11,使用av_strerror显示错误码映射为“Resource temporarily unavailable”。
换成新的API(avcodec_send_frame和avcodec_receive_packet)后,已经返回-11。程序如下:

#include<stdio.h>
#include<iostream>
#include<afx.h>
using namespace std;
extern"C"
{
#include <libavcodec\avcodec.h>  
#include <libavformat\avformat.h>
#include <libswscale\swscale.h>
#include <libavutil\pixfmt.h>
#include <libavutil\imgutils.h>
#include <libavutil/opt.h>
#include "libavutil/time.h"
}
#define bmpImagePath "F:/laboratory/holiday/bmp2H264/image_bmp1/%03d.bmp" //bmp图像路径
#define H264FilePath "F:/laboratory/holiday/bmp2H264/h264/text.h264"     //H264文件输出路径
const int image_number = 100; //bmp图片数量
int main()
{
    CFile file[image_number + 1000];
    BYTE *szTxt[image_number + 1000];
    int nWidth = 0;
    int nHeight = 0;
    int nDataLen = 0;
    int nLen;
    CString csFileName;
    for (int fileI = 1; fileI <= image_number; fileI++)
    {
        csFileName.Format(bmpImagePath, fileI);
        file[fileI - 1].Open(csFileName, CFile::modeRead | CFile::typeBinary);
        nLen = file[fileI - 1].GetLength();

        szTxt[fileI - 1] = new BYTE[nLen];
        file[fileI - 1].Read(szTxt[fileI - 1], nLen);
        file[fileI - 1].Close();

        BITMAPFILEHEADER bmpFHeader;
        BITMAPINFOHEADER bmpIHeader;
        memcpy(&bmpFHeader, szTxt[fileI - 1], sizeof(BITMAPFILEHEADER));
        int nHeadLen = bmpFHeader.bfOffBits - sizeof(BITMAPFILEHEADER);
        memcpy(&bmpIHeader, szTxt[fileI - 1] + sizeof(BITMAPFILEHEADER), nHeadLen);
        nWidth = bmpIHeader.biWidth;
        nHeight = bmpIHeader.biHeight;
        szTxt[fileI - 1] += bmpFHeader.bfOffBits;
        nDataLen = nLen - bmpFHeader.bfOffBits;
        cout << "fileI:" << fileI << endl;
    }

    av_register_all();
    avcodec_register_all();
    AVFrame *m_pRGBFrame = new AVFrame[1];  //RGB帧数据  
    AVFrame *m_pYUVFrame = new AVFrame[1];;  //YUV帧数据
    AVCodecContext *c = NULL;
    //AVCodecContext *in_c = NULL;
    AVCodec *pCodecH264 = NULL; //编码器
    uint8_t * yuv_buff = NULL;//

                              //查找h264编码器
                              //pCodecH264 = avcodec_find_encoder(AV_CODEC_ID_H264); //软编码器
    pCodecH264 = avcodec_find_encoder_by_name("h264_nvenc"); //硬编码器
    if (!pCodecH264)
    {
        fprintf(stderr, "h264 codec not found\n");
        exit(1);
    }

    c = avcodec_alloc_context3(pCodecH264);
    if (!c) {
        throw exception("avcodec_alloc_context3 failed!");
    }

    c->bit_rate = 3000000;// put sample parameters 
                          //c->bit_rate = 2500000;// put sample parameters
    c->width = nWidth;
    c->height = nHeight;

    AVRational rate;
    rate.num = 1;
    rate.den = 25;
    c->time_base = rate;//(AVRational){1,25};
    c->gop_size = 10; // emit one intra frame every ten frames 
    c->max_b_frames = 1;
    c->thread_count = 1;
    c->pix_fmt = AV_PIX_FMT_YUV420P;//PIX_FMT_RGB24;


    if (avcodec_open2(c, pCodecH264, NULL)<0)   //打开编码器
        TRACE("不能打开编码库");

    int size = c->width * c->height;

    yuv_buff = (uint8_t *)malloc((size * 3) / 2); // size for YUV 420 


    uint8_t * rgb_buff = new uint8_t[nDataLen]; //将rgb图像数据填充rgb帧

                                                //图象编码
                                                //int outbuf_size = 100000000;
    int outbuf_size = nWidth * nHeight * 3;
    uint8_t * outbuf = (uint8_t*)malloc(outbuf_size);
    int u_size = 0;
    FILE *f = NULL;
    char * filename = H264FilePath;
    f = fopen(filename, "wb");
    if (!f)
    {
        TRACE("could not open %s\n", filename);
        exit(1);
    }

    //初始化SwsContext
    SwsContext * scxt = sws_getContext(c->width, c->height, AV_PIX_FMT_BGR24, c->width, c->height, AV_PIX_FMT_YUV420P, SWS_POINT, NULL, NULL, NULL);

    AVPacket avpkt;

    //AVFrame *pTFrame=new AVFrame
    int num = 0;
    long long int vpts = 0;

    for (int i = 0; i< image_number; ++i)
    {

        int index = i;
        memcpy(rgb_buff, szTxt[index], nDataLen);

        avpicture_fill((AVPicture*)m_pRGBFrame, (uint8_t*)rgb_buff, AV_PIX_FMT_RGB24, nWidth, nHeight);

        //将YUV buffer 填充YUV Frame
        avpicture_fill((AVPicture*)m_pYUVFrame, (uint8_t*)yuv_buff, AV_PIX_FMT_YUV420P, nWidth, nHeight);

        // 翻转RGB图像
        m_pRGBFrame->data[0] += m_pRGBFrame->linesize[0] * (nHeight - 1);
        m_pRGBFrame->linesize[0] *= -1;
        m_pRGBFrame->data[1] += m_pRGBFrame->linesize[1] * (nHeight / 2 - 1);
        m_pRGBFrame->linesize[1] *= -1;
        m_pRGBFrame->data[2] += m_pRGBFrame->linesize[2] * (nHeight / 2 - 1);
        m_pRGBFrame->linesize[2] *= -1;


        //将RGB转化为YUV
        sws_scale(scxt, m_pRGBFrame->data, m_pRGBFrame->linesize, 0, c->height, m_pYUVFrame->data, m_pYUVFrame->linesize);
        int got_packet_ptr = 0;
        av_init_packet(&avpkt);
        avpkt.data = outbuf;
        avpkt.size = outbuf_size;
        //m_pYUVFrame->pts = vpts;
        /*u_size = avcodec_send_frame(c, m_pYUVFrame);
        if (u_size != 0)
        {
            char errorbuf[1024] = { 0 };
            av_strerror(u_size, errorbuf, sizeof(errorbuf));
            cout << "error number:" << u_size << "avcodec_send_frame error:" << errorbuf << endl;
        }
        u_size = avcodec_receive_packet(c, &avpkt);
        if (u_size != 0)
        {
            char errorbuf[1024] = { 0 };
            av_strerror(u_size, errorbuf, sizeof(errorbuf));
            cout << "error number:"<< u_size << " avcodec_receive_packet error:" << errorbuf << endl;
        }*/
        u_size = avcodec_encode_video2(c, &avpkt, m_pYUVFrame, &got_packet_ptr);
        if (u_size != 0)
        {
            char errorbuf[1024] = { 0 };
            av_strerror(u_size, errorbuf, sizeof(errorbuf));
            cout << "error number:" << u_size << "avcodec_encode_video2 error:" << errorbuf << endl;
        }
        m_pYUVFrame->pts++;
        //cout << "encode frame" << index + 1 << " successfully!" << endl;
        cout << "u_size:" << u_size << endl;
        if (u_size == 0)
        {
            cout << "encode frame" << index + 1 << " successfully!" << endl;
            cout << "*************" << ++num << "************" << endl;
            fwrite(avpkt.data, 1, avpkt.size, f);
        }
        //vpts++;
        else
        {
            avcodec_send_packet(c, &avpkt);
        }
    }
    cout << "nWidth" << nWidth << endl;
    cout << "nHeight" << nHeight << endl;
    fclose(f);
    delete[]m_pRGBFrame;
    delete[]m_pYUVFrame;
    delete[]rgb_buff;
    free(outbuf);
    free(yuv_buff);
    avcodec_close(c);
    av_free(c);
    //avcodec_free_context(&c);
    system("pause");

    return 0;
}

错误结果截图如下:
图片说明

  • 写回答

1条回答 默认 最新

  • xiaogang2567 2022-08-14 11:03
    关注

    avcodec_send_packet返回AVERROR(EAGAIN)表示当前还无法接受新的packet,还有frame没有取出来
    需要把未接收的packet先缓存起来

    if (ret == AVERROR(EAGAIN)) {
        pkt_pending = true;
        if (pkt != &pending_pkt)
            av_packet_move_ref(&pending_pkt, pkt);
    } 
    
    
    
    评论

报告相同问题?

悬赏问题

  • ¥15 用三极管设计—个共射极放大电路
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示