第三章 音视频-FFmpeg对应AVFrame解码处理思路和用途

第三章 音视频-FFmpeg对应AVFrame解码处理思路和用途

第一章 音视频-FFmpeg解码流程和对应结构参数意
第二章 音视频-FFmpeg对应解析格式说明
第三章 音视频-FFmpeg对应AVFrame解码处理思路和用途
第四章 音视频-FFmpeg实现播放器思维
第五章 音视频-FFmpeg实现播放器解封装、读AVPacket包
第六章 音视频-FFmpeg实现播放器解码和对应数据处理

音视频解码

ffmpeg解码是把AVPacket的压缩包解码成AVFrame的数据结构体,下面通用音视频解码方法:

// This does not quite work like avcodec_decode_audio4/avcodec_decode_video2.
// There is the following difference: if you got a frame, you must call
// it again with pkt=NULL. pkt==NULL is treated differently from pkt->size==0
// (pkt==NULL means get more output, pkt->size==0 is a flush/drain packet)
static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt)
{
    int ret;

    *got_frame = 0;

    if (pkt) {
        ret = avcodec_send_packet(avctx, pkt);
        // In particular, we don't expect AVERROR(EAGAIN), because we read all
        // decoded frames with avcodec_receive_frame() until done.
        if (ret < 0 && ret != AVERROR_EOF)
            return ret;
    }

    ret = avcodec_receive_frame(avctx, frame);
    if (ret < 0 && ret != AVERROR(EAGAIN))
        return ret;
    if (ret >= 0)
        *got_frame = 1;

    return 0;
}

AVFrame视频帧格式处理

要判断 AVFrame 是否是 YUV420P 格式,可以通过检查帧的像素格式(format 字段)是否为 AV_PIX_FMT_YUV420P。示例代码如下:

AVFrame *frame; // 假设为已经解码的 AVFrame

if (frame->format == AV_PIX_FMT_YUV420P) {
} else {
}

如果格式不是AV_PIX_FMT_YUV420P可以进行转换处理,可以用sws进行转换,也可以用libYUV进行转换,libYUV的效率更加高。

为什么要转换YUV420P?

正常有可能ai有要求;也可能编码是时候要h264等编码格式要求;渲染要求也是可能,要进行格式转换,如做播放器;也可以硬编码由GPU来转换,如做播放器。

AVFrame音频帧格式处理

音频解码出来是pcm的格式,可能单通道,和对应格式位数、采样率,要转换你想要格式和采样率等就需要用到重采样。重采样是将音频数据从一种采样率、位深度或通道布局转换为另一种的过程。在 FFmpeg 中,可以使用 swr_convert() 函数来进行音频重采样。

下面是一个简单的示例代码,演示如何使用 swr_convert() 函数对 AVFrame 进行重采样:

#include <libswresample/swresample.h>

AVFrame *in_frame;  // 输入帧
AVFrame *out_frame; // 输出帧

// 初始化重采样上下文
SwrContext *swr_ctx = swr_alloc();
av_opt_set_int(swr_ctx, "in_channel_layout",    in_frame->channel_layout, 0);
av_opt_set_int(swr_ctx, "in_sample_rate",       in_frame->sample_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", in_frame->format, 0);
av_opt_set_int(swr_ctx, "out_channel_layout",    out_frame->channel_layout, 0);
av_opt_set_int(swr_ctx, "out_sample_rate",       out_frame->sample_rate, 0);
av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", out_frame->format, 0);
swr_init(swr_ctx);

// 计算转换后的输出数据大小
int out_samples = av_rescale_rnd(swr_get_delay(swr_ctx, in_frame->sample_rate) + in_frame->nb_samples,
                                 out_frame->sample_rate, in_frame->sample_rate, AV_ROUND_UP);

// 分配输出帧数据
av_frame_get_buffer(out_frame, 0);

// 进行重采样
int ret = swr_convert(swr_ctx, out_frame->data, out_samples,
                      (const uint8_t **)in_frame->data, in_frame->nb_samples);

if (ret < 0) {
    fprintf(stderr, "Error while converting\n");
}

// 释放重采样上下文
swr_free(&swr_ctx);

这个示例代码中,首先初始化了重采样上下文(SwrContext),然后根据输入帧和输出帧的参数配置了重采样的参数。接着计算了转换后的输出数据大小,并为输出帧分配了足够的内存空间。最后调用 swr_convert() 函数进行重采样,将输入帧的数据转换为输出帧的数据。
AVSampleFormat格式可以根据第二章,对应系统使用对应支持格式才可以播放对应pcm的音频数据。
在这里插入图片描述

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

baoyu45585

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值