我是靠谱客的博主 背后唇彩,最近开发中收集的这篇文章主要介绍使用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所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部