我是靠谱客的博主 背后唇彩,最近开发中收集的这篇文章主要介绍使用C++ 封装一个FFmpeg通用性Muxer和Encoder组件-2 AV_Encoder,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
编码器的主要作用
源码github
1 初始化编码器
2 编码
3 获取每一帧数据
4 返回相关的参数
AudioEncoder 类的定义( 视频的逻辑差不多 相对于的注解就写了一部分)
av_rescale_q () 时间基转换函数 不同时间基之间的转换
#include <vector>
extern "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 *frame, int stream_index, int64_t pts, int64_t time_base);
int Encode(AVFrame *farme, int stream_index, int64_t pts, int64_t time_base,
std::vector<AVPacket *> &packets);
int GetFrameSize(); // 获取一帧数据 每个通道需要多少个采样点
int GetSampleFormat(); // 编码器需要的采样格式
AVCodecContext *GetCodecContext();
int GetChannels();
int GetSampleRate();
private:
int channels_ = 2;
int sample_rate_ = 44100;
int bit_rate_ = 128*1024;
int64_t pts_ = 0;
AVCodecContext * codec_ctx_ = NULL;
};
音频编码器的实现
#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 failedn");
return -1;
}
codec_ctx_ = avcodec_alloc_context3(codec);
if(!codec_ctx_) {
printf("avcodec_alloc_context3 AV_CODEC_ID_AAC failedn");
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:%sn", errbuf);
return -1;
}
printf("InitAAC successn");
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_ nulln");
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:%sn", 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("aac avcodec_receive_packet failed:%sn", errbuf);
av_packet_free(&packet);
return NULL;
}
packet->stream_index = stream_index;
return packet;
}
//
int AudioEncoder::Encode(AVFrame *frame, int stream_index, int64_t pts, int64_t time_base,
std::vector<AVPacket *> &packets)
{
if(!codec_ctx_) {
printf("codec_ctx_ nulln");
return NULL;
}
// 通过time_base转换函数 获得pts
pts = av_rescale_q(pts, AVRational{1, (int)time_base}, codec_ctx_->time_base);
if(frame) {
//设置对应的pts
frame->pts = pts;
}
// frame 送入编码器
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:%sn", errbuf);
return NULL;
}
// 从编码器中获取 编码出的packet
while(1)
{
AVPacket *packet = av_packet_alloc();
ret = avcodec_receive_packet(codec_ctx_, packet);
packet->stream_index = stream_index;
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
ret = 0;
av_packet_free(&packet);
break;
} else if (ret < 0) {
char errbuf[1024] = {0};
av_strerror(ret, errbuf, sizeof(errbuf) - 1);
printf("aac avcodec_receive_packet failed:%sn", errbuf);
av_packet_free(&packet);
ret = -1;
}
printf("AAC pts:%lldn", packet->pts);
//编码的文件存入动态数组中
packets.push_back(packet);
}
return ret;
}
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
}
AVCodecContext *AudioEncoder::GetCodecContext()
{
return codec_ctx_;
}
int AudioEncoder::GetChannels()
{
if(codec_ctx_)
return codec_ctx_->channels;
return -1;
}
int AudioEncoder::GetSampleRate()
{
if(codec_ctx_)
return codec_ctx_->sample_rate;
return -1;
}
最后
以上就是背后唇彩为你收集整理的使用C++ 封装一个FFmpeg通用性Muxer和Encoder组件-2 AV_Encoder的全部内容,希望文章能够帮你解决使用C++ 封装一个FFmpeg通用性Muxer和Encoder组件-2 AV_Encoder所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复