第三章 音视频-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的音频数据。