FFmepg--视频编码流程--yuv编码为h264

2024-03-15 21:12

本文主要是介绍FFmepg--视频编码流程--yuv编码为h264,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

      • 基本概念
      • 流程
      • api
      • 核心代码

基本概念

YUV格式:是一种颜色编码方式,YUV分别为三个分量:‘Y’是明亮度,也就是灰度值;‘U’和‘V’是色度
YUV格式的分类:

  • planar的YUV格式:先存储planar的Y像素点,在依次存储U和V像素点
  • packed的YUV格式:交叉存储YUV像素点

YUV流的采样方式:

  • YUV4:4:4:表示一个Y分量对应一组UV分量。
  • YUV4:2:2:表示两个Y分量共用一组UV分量。
  • YUV4:2:0:表示四个Y分量共用一组UV分量。

流程

请添加图片描述

api

  • int av_frame_get_buffer(AVFrame *frame, int align);
    为⾳频或视频数据分配新的buffer,使用完成后,需要将引用计数-1

  • int av_image_alloc(uint8_t *pointers[4], int linesizes[4], int w, int h, enum AVPixelFormat pix_fmt,int align):
    按照指定的宽、高、像素格式来分配图像内存,第一个参数为Frame的数据

  • int av_frame_make_writable(AVFrame *frame):

  • 检查AVFrame->data是否可写

  • int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align):
    计算1帧数据的大小,参数为像素格式、图像宽、图像⾼,字节对齐方式

  • av_image_fill_arrays: 存储⼀帧像素数据存储到AVFrame对应的data buffer

核心代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include <libavcodec/avcodec.h>
#include <libavutil/time.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>int64_t get_time()
{return av_gettime_relative() / 1000;  // 换算成毫秒
}
static int encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,FILE *outfile)
{int ret;/* send the frame to the encoder */ret = avcodec_send_frame(enc_ctx, frame);if (ret < 0){return -1;}while (ret >= 0){ret = avcodec_receive_packet(enc_ctx, pkt);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;} else if (ret < 0) {return -1;}fwrite(pkt->data, 1, pkt->size, outfile);}return 0;
}int main(int argc, char **argv)
{char *in_yuv_file = NULL;char *out_h264_file = NULL;FILE *infile = NULL;FILE *outfile = NULL;const char *codec_name = NULL;const AVCodec *codec = NULL;AVCodecContext *codec_ctx= NULL;AVFrame *frame = NULL;AVPacket *pkt = NULL;int ret = 0;in_yuv_file = argv[1];      // 输入YUV文件out_h264_file = argv[2];codec_name = argv[3];/* 查找指定的编码器 */codec = avcodec_find_encoder_by_name(codec_name);if (!codec) {fprintf(stderr, "Codec '%s' not found\n", codec_name);exit(1);}codec_ctx = avcodec_alloc_context3(codec);if (!codec_ctx) {fprintf(stderr, "Could not allocate video codec context\n");exit(1);}/* 设置分辨率*/codec_ctx->width = 1280;codec_ctx->height = 720;/* 设置time base */codec_ctx->time_base = (AVRational){1, 25};codec_ctx->framerate = (AVRational){25, 1};/* 设置I帧间隔* 如果frame->pict_type设置为AV_PICTURE_TYPE_I, 则忽略gop_size的设置,一直当做I帧进行编码*/codec_ctx->gop_size = 25;   // I帧间隔codec_ctx->max_b_frames = 2; // 如果不想包含B帧则设置为0codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;//if (codec->id == AV_CODEC_ID_H264) {// 相关的参数可以参考libx264.c的 AVOption optionsav_opt_set(codec_ctx->priv_data, "preset", "medium", 0);av_opt_set(codec_ctx->priv_data, "profile", "main", 0);av_opt_set(codec_ctx->priv_data, "tune","zerolatency",0);}/** 设置编码器参数*//* 设置bitrate */codec_ctx->bit_rate = 3000000;/* 将codec_ctx和codec进行绑定 */avcodec_open2(codec_ctx, codec, NULL);// 打开输入和输出文件infile = fopen(in_yuv_file, "rb");outfile = fopen(out_h264_file, "wb");// 分配pkt和framepkt = av_packet_alloc();frame = av_frame_alloc();// 为frame分配bufferframe->format = codec_ctx->pix_fmt;frame->width  = codec_ctx->width;frame->height = codec_ctx->height;ret = av_frame_get_buffer(frame, 0);// 计算出每一帧的数据 像素格式 * 宽 * 高// 1382400int frame_bytes = av_image_get_buffer_size(frame->format, frame->width,frame->height, 1);uint8_t *yuv_buf = (uint8_t *)malloc(frame_bytes);// 作用int64_t begin_time = get_time();int64_t end_time = begin_time;int64_t all_begin_time = get_time();int64_t all_end_time = all_begin_time;int64_t pts = 0;printf("start enode\n");for (;;) {memset(yuv_buf, 0, frame_bytes);size_t read_bytes = fread(yuv_buf, 1, frame_bytes, infile);ret = av_frame_make_writable(frame);int need_size = av_image_fill_arrays(frame->data, frame->linesize, yuv_buf,frame->format,frame->width, frame->height, 1);pts += 40;// 设置pts 计算frame->pts = pts;       // 使用采样率作为pts的单位,具体换算成秒 pts*1/采样率begin_time = get_time();encode(codec_ctx, frame, pkt, outfile);end_time = get_time();printf("encode time:%lldms\n", end_time - begin_time);}/* 冲刷编码器 */encode(codec_ctx, NULL, pkt, outfile);all_end_time = get_time();printf("all encode time:%lldms\n", all_end_time - all_begin_time);// 关闭文件fclose(infile);fclose(outfile);// 释放内存if(yuv_buf) {free(yuv_buf);}av_frame_free(&frame);av_packet_free(&pkt);avcodec_free_context(&codec_ctx);printf("main finish, please enter Enter and exit\n");getchar();return 0;
}

这篇关于FFmepg--视频编码流程--yuv编码为h264的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/813273

相关文章

Python使用自带的base64库进行base64编码和解码

《Python使用自带的base64库进行base64编码和解码》在Python中,处理数据的编码和解码是数据传输和存储中非常普遍的需求,其中,Base64是一种常用的编码方案,本文我将详细介绍如何使... 目录引言使用python的base64库进行编码和解码编码函数解码函数Base64编码的应用场景注意

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

Spring AI ectorStore的使用流程

《SpringAIectorStore的使用流程》SpringAI中的VectorStore是一种用于存储和检索高维向量数据的数据库或存储解决方案,它在AI应用中发挥着至关重要的作用,本文给大家介... 目录一、VectorStore的基本概念二、VectorStore的核心接口三、VectorStore的

python之流程控制语句match-case详解

《python之流程控制语句match-case详解》:本文主要介绍python之流程控制语句match-case使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录match-case 语法详解与实战一、基础值匹配(类似 switch-case)二、数据结构解构匹

VSCode中C/C++编码乱码问题的两种解决方法

《VSCode中C/C++编码乱码问题的两种解决方法》在中国地区,Windows系统中的cmd和PowerShell默认编码是GBK,但VSCode默认使用UTF-8编码,这种编码不一致会导致在VSC... 目录问题方法一:通过 Code Runner 插件调整编码配置步骤方法二:在 PowerShell

在VSCode中本地运行DeepSeek的流程步骤

《在VSCode中本地运行DeepSeek的流程步骤》本文详细介绍了如何在本地VSCode中安装和配置Ollama和CodeGPT,以使用DeepSeek进行AI编码辅助,无需依赖云服务,需要的朋友可... 目录步骤 1:在 VSCode 中安装 Ollama 和 CodeGPT安装Ollama下载Olla

Python如何实现读取csv文件时忽略文件的编码格式

《Python如何实现读取csv文件时忽略文件的编码格式》我们再日常读取csv文件的时候经常会发现csv文件的格式有多种,所以这篇文章为大家介绍了Python如何实现读取csv文件时忽略文件的编码格式... 目录1、背景介绍2、库的安装3、核心代码4、完整代码1、背景介绍我们再日常读取csv文件的时候经常

linux环境openssl、openssh升级流程

《linux环境openssl、openssh升级流程》该文章详细介绍了在Ubuntu22.04系统上升级OpenSSL和OpenSSH的方法,首先,升级OpenSSL的步骤包括下载最新版本、安装编译... 目录一.升级openssl1.官网下载最新版openssl2.安装编译环境3.下载后解压安装4.备份

C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)

《C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)》本文主要介绍了C#集成DeepSeek模型实现AI私有化的方法,包括搭建基础环境,如安装Ollama和下载DeepS... 目录前言搭建基础环境1、安装 Ollama2、下载 DeepSeek R1 模型客户端 ChatBo