FFmpeg-- c++实现:pcm和yuv编码

文章目录

      • 流程
        • 音频
        • 视频
      • api
      • 核心代码
        • audioencoder.h
        • audioencoder.cpp
        • videoencoder.h
        • videoencoder.cpp

pcm和yuv编码为aac和h264,封装为c++的AudioEncoder类和VideoEncoder类

流程

音频
  • 初始化音频参数
    int InitAAC(int channels, int sample_rate, int bit_rate);

  • 音频编码,pts需要转化为编码时的pts, 发送帧frame, 获取 packet
    AVPacket *Encode(AVFrame *farme, int stream_index, int64_t pts, int64_t time_base);

  • 获取一帧数据通道号的采样点
    int GetFrameSize()

  • 获取编码器需要的采样格式
    int GetSampleFormat()

  • 释放资源
    void DeInit();

视频
  • 初始化视频参数
    int InitH264(int width, int height, int fps, int bit_rate);

  • 视频编码,pts需要转化为编码时的pts, 需要初始化AVFrame结构体,发送帧frame, 获取 packet
    AVPacket *Encode(AVFrame *farme, int stream_index, int64_t pts, int64_t time_base);

  • 释放资源
    void DeInit();

api

  • 用于初始化一个AVFrame结构体,包括设置AVFrame中的各项参数,不需要重新分配buffer,需要传入一个指向AVFrame结构体的指针
int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],const uint8_t *src,enum AVPixelFormat pix_fmt, int width, int height, int align);

核心代码

audioencoder.h
#ifndef AUDIOENCODER_H
#define AUDIOENCODER_Hextern "C"
{
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
}
class AudioEncoder
{
public:AudioEncoder();~AudioEncoder();int InitAAC(int channels, int sample_rate, int bit_rate);
//    int InitMP3(/*int channels, int sample_rate, int bit_rate*/);void DeInit();  // 释放资源AVPacket *Encode(AVFrame *farme, int stream_index, int64_t pts, int64_t time_base);int GetFrameSize(); // 获取一帧数据 每个通道需要多少个采样点int GetSampleFormat();  // 编码器需要的采样格式
private:int channels_ = 2;int sample_rate_ = 44100;int bit_rate_ = 128*1024;int64_t pts_ = 0;AVCodecContext * codec_ctx_ = NULL;
};#endif // AUDIOENCODER_H
audioencoder.cpp
#include "audioencoder.h"AudioEncoder::AudioEncoder()
{}AudioEncoder::~AudioEncoder()
{if(codec_ctx_) {DeInit();}
}int AudioEncoder::InitAAC(int channels, int sample_rate, int bit_rate)
{channels_ = channels;sample_rate_ = sample_rate;bit_rate_ = bit_rate;AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AAC);if(!codec) {printf("avcodec_find_encoder AV_CODEC_ID_AAC failed\n");return -1;}codec_ctx_ = avcodec_alloc_context3(codec);if(!codec_ctx_) {printf("avcodec_alloc_context3 AV_CODEC_ID_AAC failed\n");return -1;}codec_ctx_->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;codec_ctx_->bit_rate = bit_rate_;codec_ctx_->sample_rate = sample_rate_;codec_ctx_->sample_fmt = AV_SAMPLE_FMT_FLTP;codec_ctx_->channels = channels_;codec_ctx_->channel_layout = av_get_default_channel_layout(codec_ctx_->channels);int ret = avcodec_open2(codec_ctx_, NULL, NULL);if(ret != 0) {char errbuf[1024] = {0};av_strerror(ret, errbuf, sizeof(errbuf) - 1);printf("avcodec_open2 failed:%s\n", errbuf);return -1;}printf("InitAAC success\n");return 0;
}void AudioEncoder::DeInit()
{if(codec_ctx_) {avcodec_free_context(&codec_ctx_);  // codec_ctx_被设置为NULL
//        codec_ctx_ = NULL;  // 不需要再写}
}AVPacket *AudioEncoder::Encode(AVFrame *frame, int stream_index, int64_t pts, int64_t time_base)
{if(!codec_ctx_) {printf("codec_ctx_ null\n");return NULL;}pts = av_rescale_q(pts, AVRational{1, (int)time_base}, codec_ctx_->time_base);if(frame) {frame->pts = pts;}int ret = avcodec_send_frame(codec_ctx_, frame);if(ret != 0) {char errbuf[1024] = {0};av_strerror(ret, errbuf, sizeof(errbuf) - 1);printf("avcodec_send_frame failed:%s\n", errbuf);return NULL;}AVPacket *packet = av_packet_alloc();ret = avcodec_receive_packet(codec_ctx_, packet);if(ret != 0) {char errbuf[1024] = {0};av_strerror(ret, errbuf, sizeof(errbuf) - 1);printf("avcodec_receive_packet failed:%s\n", errbuf);av_packet_free(&packet);return NULL;}packet->stream_index = stream_index;return packet;
}int AudioEncoder::GetFrameSize()
{if(codec_ctx_)return codec_ctx_->frame_size;return 0;
}int AudioEncoder::GetSampleFormat()
{if(codec_ctx_)return codec_ctx_->sample_fmt;return -1;  // AV_SAMPLE_FMT_NONE
}
videoencoder.h
#ifndef VIDEOENCODER_H
#define VIDEOENCODER_H
extern "C"
{
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
}class VideoEncoder
{
public:VideoEncoder();~VideoEncoder();int InitH264(int width, int height, int fps, int bit_rate);void DeInit();AVPacket *Encode(uint8_t *yuv_data, int yuv_size,int stream_index, int64_t pts, int64_t time_base);private:int width_ = 0;int height_ = 0;int fps_ = 25;int bit_rate_ = 500*1024;int64_t pts_ = 0;AVCodecContext * codec_ctx_ = NULL;AVFrame *frame_ = NULL;
};#endif // VIDEOENCODER_H
videoencoder.cpp
#include "videoencoder.h"
extern "C"
{
#include "libavutil/imgutils.h"
}
VideoEncoder::VideoEncoder()
{}VideoEncoder::~VideoEncoder()
{if(codec_ctx_) {DeInit();}
}int VideoEncoder::InitH264(int width, int height, int fps, int bit_rate)
{width_ = width;height_ = height;fps_ = fps;bit_rate_ = bit_rate;AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264);if(!codec) {printf("avcodec_find_encoder AV_CODEC_ID_H264 failed\n");return -1;}codec_ctx_ = avcodec_alloc_context3(codec);if(!codec_ctx_) {printf("avcodec_alloc_context3 AV_CODEC_ID_H264 failed\n");return -1;}codec_ctx_->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;codec_ctx_->bit_rate = bit_rate_;codec_ctx_->width = width_;codec_ctx_->height = height_;codec_ctx_->framerate = {fps_, 1};codec_ctx_->time_base = {1, 1000000};   // 单位为微妙codec_ctx_->gop_size = fps_;codec_ctx_->max_b_frames = 0;codec_ctx_->pix_fmt = AV_PIX_FMT_YUV420P;int ret = avcodec_open2(codec_ctx_, NULL, NULL);if(ret != 0) {char errbuf[1024] = {0};av_strerror(ret, errbuf, sizeof(errbuf) - 1);printf("avcodec_open2 failed:%s\n", errbuf);return -1;}frame_ = av_frame_alloc();if(!frame_) {printf("av_frame_alloc failed\n");return -1;}frame_->width = width_;frame_->height = height_;frame_->format = codec_ctx_->pix_fmt;printf("Inith264 success\n");return 0;
}void VideoEncoder::DeInit()
{if(codec_ctx_) {avcodec_free_context(&codec_ctx_);}if(frame_) {av_frame_free(&frame_);}
}AVPacket *VideoEncoder::Encode(uint8_t *yuv_data, int yuv_size, int stream_index, int64_t pts, int64_t time_base)
{if(!codec_ctx_) {printf("codec_ctx_ null\n");return NULL;}int ret = 0;pts = av_rescale_q(pts, AVRational{1, (int)time_base}, codec_ctx_->time_base);frame_->pts = pts;if(yuv_data) {//该函数用于初始化一个AVFrame结构体,包括设置AVFrame中的各项参数,不需要重新分配buffer//使用该函数需要传入一个指向AVFrame结构体的指针int ret_size = av_image_fill_arrays(frame_->data, frame_->linesize,yuv_data, (AVPixelFormat)frame_->format,frame_->width, frame_->height, 1);if(ret_size != yuv_size) {printf("ret_size:%d != yuv_size:%d -> failed\n", ret_size, yuv_size);return NULL;}ret = avcodec_send_frame(codec_ctx_, frame_);} else {ret = avcodec_send_frame(codec_ctx_, NULL);}if(ret != 0) {char errbuf[1024] = {0};av_strerror(ret, errbuf, sizeof(errbuf) - 1);printf("avcodec_send_frame failed:%s\n", errbuf);return NULL;}AVPacket *packet = av_packet_alloc();ret = avcodec_receive_packet(codec_ctx_, packet);if(ret != 0) {char errbuf[1024] = {0};av_strerror(ret, errbuf, sizeof(errbuf) - 1);printf("avcodec_receive_packet failed:%s\n", errbuf);av_packet_free(&packet);return NULL;}packet->stream_index = stream_index;return packet;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/755825.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

KVM安装-kvm彻底卸载-docker安装Webvirtmgr

KVM安装和使用 一、安装 检测硬件是否支持KVM需要硬件的支持,使用命令查看硬件是否支持KVM。如果结果中有vmx(Intel)或svm(AMD)字样,就说明CPU的支持的 egrep ‘(vmx|svm)’ /proc/cpuinfo关闭selinux将 /etc/sysconfig/selinux 中的 SELinux=enforcing 修改为 SELinux=d…

AI预测福彩3D第13弹【2024年3月19日预测--第3套算法重新开始计算第2次测试】

今天咱们继续对第3套算法进行第2次测试,第3套算法加入了012路的权重。废话不多说了,直接上结果吧~ 最终,经过研判分析,2024年3月19日福彩3D的七码预测结果如下: 百位:0 1 3 4 2 7 9(6换9&#x…

LCR144翻转二叉树(力扣简单题,Java,递归+非递归)

目录 题目描述: 递归代码1: 递归代码2: 非递归代码(层次遍历): 题目描述: 给定一棵二叉树的根节点 root,请左右翻转这棵二叉树,并返回其根节点。 示例 1:…

synchronized锁升级的过程

在Java中,锁的状态分为四种,分别是无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态 无锁 当一个线程第一次访问一个对象的同步块时,"JVM会在对象头中设置该线程的Thread ID,并将对象头的状态位设置为“偏向锁”。这个过…

mysql 主从复制、读写分离、高可用

MySQL 的主从复制、读写分离和高可用性是数据库架构中常见的概念,它们旨在提高数据库的可靠性、性能和可扩展性。下面我将分别解释这三个概念: 1. MySQL 主从复制 主从复制 是 MySQL 中的一个功能,允许数据从一个 MySQL 数据库服务器&#…

如何在iOS系统抓取log

前言:因为作者目前工作领域和苹果智能家居有关,然后发现一些bug其实是apple sdk原生code的问题,所以需要给apple提radar单,就需要抓ios端Log充当证据给apple看,其实ios抓log非常简单,大家感兴趣可以学习下哦…

VS2022 配置QT5.9.9

QT安装 下载地址:https://download.qt.io/archive/qt/ 下载安装后进行配置 无法运行 rc.exe 下载VS2022 官网下载 配置 1.扩展-管理扩展-下载Qt Visual Studio Tools 安装 2.安装完成后,打开vs2022,点击扩展,会发现多出了QT VS Tools,点…

网页的制作

1.格式 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>中文测试。。。。</title> </head> <body> 这里是测试body测试内容。。。 </body> </ht…

爱恩斯坦棋小游戏使用C语言+ege/easyx实现

目录 1、游戏介绍和规则 2、需要用到的头文件 3、这里我也配上一个ege和easyx的下载链接吧&#xff0c;应该下一个就可以 4、运行结果部分展示 5、需要用到的图片要放在代码同一文件夹下 6、代码地址&#xff08;里面有需要用到的图片&#xff09; 1、游戏介绍和规则 规则如…

leetcode 647 回文子串

1. 暴力解法 class Solution:def countSubstrings(self, s: str) -> int:res 0for i in range(len(s)):for j in range(i1,len(s)1):seq s[i:j]rev seq[::-1]if seq rev:res res 1return res 2. 动态规划 class Solution:def countSubstrings(self, s: str) -> i…

简单介绍注册波兰公司的基本条件

波兰&#xff0c;一个位于中欧的国家&#xff0c;具有丰富的历史文化和资源&#xff0c;同时也拥有稳定的政治和经济环境。在这里&#xff0c;注册公司不仅有助于您拓展业务&#xff0c;还能享受到优惠的税收政策和良好的投资环境。下面&#xff0c;我们将详细介绍注册波兰公司…

代码随想录算法训练营第五十一天 | 力扣 309. 买卖股票的最佳时机含冷冻期,714. 买卖股票的最佳时机含手续费

题目链接&#xff1a;309. 买卖股票的最佳时机含冷冻期 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int maxProfit(vector<int>& prices) {int n prices.size();if (n 0) return 0;vector<vector<int>> dp(n, vector<int>…

Footprint Analytics 强势入局 AI 推出全新投研工具

作者&#xff1a;lesleyfootprint.network 3 月 15 日&#xff0c;链上数据平台 Footprint Analytics 宣布入局 AI&#xff0c;推出了旗下首款 AI 投研工具—— Pea.AI。 作为专门服务于区块链行业的 AI 平台&#xff0c;Pea.AI 旨在提升加密资产投资领域的数据流动性和知识…

镭速,企业传输大文件都在用的udp文件传输工具

在当今快速变化的数字世界中&#xff0c;文件传输工具已成为企业运营不可或缺的一部分。尤其是面对大文件传输的需求&#xff0c;传统的TCP协议由于其设计上的局限性&#xff0c;往往无法满足企业对高速、稳定传输的需求。这时&#xff0c;UDP文件传输工具以其独特的优势走进了…

你知道吗?腾讯云服务器61元一年,2024又降价了

腾讯云服务器多少钱一年&#xff1f;61元一年起。2024年最新腾讯云服务器优惠价格表&#xff0c;腾讯云轻量2核2G3M服务器61元一年、2核2G4M服务器99元一年可买三年、2核4G5M服务器165元一年、3年756元、轻量4核8M12M服务器646元15个月、4核16G10M配置32元1个月、312元一年、8核…

自注意力机制的理解

一、自注意力要解决什么问题 循环神经网络由于信息传递的容量以及梯度消失问题&#xff0c;只能建立短距离依赖关系。为了建立长距离的依赖关系&#xff0c;可以增加网络的层数或者使用全连接网络。但是全连接网络无法处理变长的输入序列&#xff0c;另外&#xff0c;不同的输…

数字签名的理解和使用方法java

数字签名是一种加密算法&#xff0c;用于确保电子文档或信息的完整性、认证和不可抵赖性。它使用公钥密码学的原理&#xff0c;在发送方使用私钥对文件进行加密生成签名&#xff0c;接收方使用对应的公钥对签名进行解密验证。如果签名验证成功&#xff0c;就可以确认文件未被篡…

MySQL最实用面试题(2024-3-14持续更新中)

MySQL篇面试题 一、介绍 ​ 这是由小龙同学自己总结领悟的mysql面试题的解析&#xff0c;也是面试宝典 二、题目 1.数据库三大范式&#xff1a; –作用&#xff1a; ​ 使表结构清晰&#xff0c;减少数据冗余&#xff08;简单讲就是重复&#xff09;&#xff0c;提高查询…

pandas无法读取/保存xls格式的excel的解决办法

文章目录 一、读取报错* 问题1* 解决办法1二、保存报错* 问题1* 解决办法1* 问题2* 解决办法2一、读取报错 * 问题1 使用 pandas 读取 .xls 后缀的 excel 报错: Traceback (most recent call last):File "D:\PycharmProjects\tools\my_project\start.py", line 1…

朋友圈运营小秘诀,让你事半功倍!

朋友圈已成为了现代社交的重要平台&#xff0c;如何在朋友圈中进行有效的运营&#xff0c;吸引更多的关注和互动&#xff0c;成为了许多人关注的焦点。 今天&#xff0c;我将分享一些朋友圈运营的小秘诀&#xff0c;帮助你事半功倍&#xff0c;让你的朋友圈更具吸引力&#xf…