文章实时采集(编码h264还是一样使用ffmpeg_encode技术交流讨论(一))

优采云 发布时间: 2021-09-03 06:06

  文章实时采集(编码h264还是一样使用ffmpeg_encode技术交流讨论(一))

  采集屏幕图像之前介绍过,转换为YUV420p。传送门

  YUV420p数据为原创图片数据,100张1920x1080图片总大小达到300M。太可怕了!可见这种方式直接写入文件是行不通的。因此,我们需要先将其编码为h264,然后再将其写入文件。至于什么是h264,之前已经介绍过了,这里就不介绍了。

  废话不多说,直接看正文。

  编码h264还是一样使用ffmpeg,方法如下:

  1.打开编码器

      AVCodecContext* pCodecCtx;    AVCodec* pCodec;

    uint8_t* picture_buf;

    AVFrame* picture;

  bool H264Encoder::openEncoder()

{

    int size;

    int in_w = mWidth;

    int in_h = mHeight;//宽高

    //查找h264编码器

    pCodec = avcodec_find_encoder(AV_CODEC_ID_H264);

    if(!pCodec)

    {

      fprintf(stderr, "h264 codec not found

");

      exit(1);

    }

    pCodecCtx = avcodec_alloc_context3(pCodec);

    pCodecCtx->codec_id = AV_CODEC_ID_H264;

    pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;

    pCodecCtx->pix_fmt = PIX_FMT_YUV420P;

    pCodecCtx->width = in_w;

    pCodecCtx->height = in_h;

    pCodecCtx->time_base.num = 1;

    pCodecCtx->time_base.den = 15;//帧率(既一秒钟多少张图片)

    pCodecCtx->bit_rate = mBitRate; //比特率(调节这个大小可以改变编码后视频的质量)

    pCodecCtx->gop_size=12;

    // some formats want stream headers to be separate

    if (pCodecCtx->flags & AVFMT_GLOBALHEADER)

        pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;

    // Set Option

    AVDictionary *param = 0;

    //H.264

    //av_dict_set(&param, "preset", "slow", 0);

    av_dict_set(&param, "preset", "superfast", 0);

    av_dict_set(&param, "tune", "zerolatency", 0);  //实现实时编码

    pCodec = avcodec_find_encoder(pCodecCtx->codec_id);

    if (!pCodec){

      printf("Can not find video encoder! 没有找到合适的编码器!

");

      return false;

    }

    if (avcodec_open2(pCodecCtx, pCodec,&param) pix_fmt, pCodecCtx->width, pCodecCtx->height); //计算需要用到的数据大小

    picture_buf = (uint8_t *)av_malloc(size); //分配空间

    avpicture_fill((AVPicture *)picture, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);

    return true;

}

  2.coding

  编码前的数据必须是Yuv420p格式。我们已经获得了这样的数据。使用 avcodec_encode_video2 实现编码:

  picture->data[0] = node.buffer;     // 亮度Y            

picture->data[1] = node.buffer + y_size;  // U

picture->data[2] = node.buffer + y_size*5/4; // V

int got_picture=0;

//编码

int ret = avcodec_encode_video2(pCodecCtx, &pkt,picture, &got_picture);

if (got_picture==1)            

{

//   bool isKeyFrame = pkt.flags & AV_PKT_FLAG_KEY; //判断是否关键帧

     int w = fwrite(pkt.data,1,pkt.size,h264Fp); //写入文件中 (h264的裸数据 直接写入文件 也可以播放  因为这里包含H264关键帧)

}

  最近时间比较少,代码就不多解释了,直接看完整项目。

  完整的项目下载链接:

  最终生成的out.h264可以直接用普通播放器打开播放。

  保存的文件比以前小了数百倍!

  注意:由于h264没有时间戳,只有帧率,这里设置为15。但是,我们采集桌面时,采集每秒不到15帧,所以玩的时候速度玩家开会快很多是正常的。

  了解音视频技术,欢迎访问

  欢迎加入QQ群121376426进行音视频技术交流与讨论

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线