【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码(三)

简介: 【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码

【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码(二)https://developer.aliyun.com/article/1467277


7.2 YUV和RGB在视频数据处理中的应用

YUV和RGB是两种不同的颜色空间。RGB是基于颜色光的三原色(红、绿、蓝)来描述颜色的,每个像素的颜色由这三种颜色的强度组合而成。而YUV则是将颜色信息分为亮度信息(Y)和色度信息(UV),这种方式更接近人眼对颜色的感知方式,因此在视频编码和传输中更常用。

在处理视频数据时,可能需要根据具体的需求和环境,选择合适的颜色模型。例如,如果你的显示设备或者渲染库可以直接处理YUV格式的数据,那么你可以直接从AVFrame中取出YUV数据进行显示,无需进行任何转换。然而,许多常见的显示设备和渲染库(例如,SDL、OpenGL)通常只能处理RGB格式的数据。在这种情况下,你需要将YUV数据转换为RGB数据才能进行显示。

在C++中,我们可以使用FFmpeg提供的swscale库来进行这种转换。以下是一个简单的示例:

// 创建一个swsContext,用于YUV到RGB的转换
struct SwsContext* sws_ctx = sws_getContext(width, height, AV_PIX_FMT_YUV420P,
                                            width, height, AV_PIX_FMT_RGB24,
                                            SWS_BILINEAR, NULL, NULL, NULL);
if (!sws_ctx) {
    // 错误处理
}
// 创建一个AVFrame,用于存储RGB数据
AVFrame* rgb_frame = av_frame_alloc();
if (!rgb_frame) {
    // 错误处理
}
rgb_frame->format = AV_PIX_FMT_RGB24;
rgb_frame->width = width;
rgb_frame->height = height;
// 分配RGB数据的内存
int ret = av_frame_get_buffer(rgb_frame, 0);
if (ret < 0) {
    // 错误处理
}
// 将YUV数据转换为RGB数据
sws_scale(sws_ctx, yuv_frame->data, yuv_frame->linesize, 0, height,
          rgb_frame->data, rgb_frame->linesize);
// 此时,rgb_frame中存储的就是RGB数据,可以直接用于显示

在这个示例中,我们首先创建了一个swsContext,用于YUV到RGB的转换。然后,我们创建了一个AVFrame,用于存储RGB数据,并分配了相应的内存。最后,我们使用sws_scale函数将YUV数据转换为RGB数据。此时,rgb_frame中存储的就是RGB数据,可以直接用于显示。

7.3 视频数据的最小单位:帧

在视频中,帧(Frame)是最小的独立单位,每一帧都代表了一个独立的图像。在处理视频数据时,我们通常需要处理一系列的视频帧,每一帧都是一个独立的YUV或RGB图像。

在FFmpeg中,每一帧的数据被存储在一个AVFrame结构体中。AVFrame结构体包含了帧的数据以及一些元数据,例如,帧的宽度和高度、时间戳(PTS和DTS)等。你可以通过AVFrame的成员变量来访问这些数据和元数据。

在处理视频帧时,我们通常需要遍历每一帧,对每一帧进行相应的处理。以下是一个简单的示例:

// 创建一个AVFrame,用于存储解码后的帧
AVFrame* frame = av_frame_alloc();
if (!frame) {
    // 错误处理
}
// 循环读取和解码帧
while (1) {
    // 读取一帧
    int ret = av_read_frame(format_ctx, &pkt);
    if (ret < 0) {
        // 错误处理
    }
    // 判断是否是我们需要的视频流
    if (pkt.stream_index == video_stream_index) {
        // 解码帧
       
 ret = avcodec_send_packet(codec_ctx, &pkt);
        if (ret < 0) {
            // 错误处理
        }
        while (ret >= 0) {
            ret = avcodec_receive_frame(codec_ctx, frame);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                break;
            } else if (ret < 0) {
                // 错误处理
            }
            // 此时,frame中存储的就是解码后的帧,可以进行相应的处理
            // 例如,你可以将帧的数据转换为RGB格式,然后显示出来
        }
    }
    // 释放pkt
    av_packet_unref(&pkt);
}
// 释放frame
av_frame_free(&frame);

在这个示例中,我们首先创建了一个AVFrame,用于存储解码后的帧。然后,我们进入一个循环,不断地读取和解码帧。对于每一帧,我们首先判断它是否是我们需要的视频流,如果是,我们就进行解码,并对解码后的帧进行相应的处理。最后,我们释放了pkt和frame。

这就是视频数据的采集和处理的基本过程。在下一章中,我们将讨论音频数据的采集和处理。

8. 音频数据的采集和处理

在本章中,我们将深入探讨音频数据的采集和处理过程。我们将从音频数据的采集开始,然后讨论PCM(Pulse Code Modulation,脉冲编码调制)在音频数据处理中的应用,最后我们将探讨音频数据的最小单位:样本。

8.1 音频数据的采集过程

音频数据的采集过程可以分为以下几个步骤:

  1. 音频采集设备(如麦克风)首先将声音(这是一种模拟信号)转换为电信号。
  2. 通过模数转换器(ADC,Analog-to-Digital Converter)将电信号转换为数字信号。这个数字信号就是 PCM 数据。

下图展示了音频采集的过程:

在这个过程中,声音信号会被样本化(sampling),量化(quantization),并编码(encoding):

  • 样本化是指在一定的时间间隔内测量信号的振幅。样本化的频率(即每秒的样本数)通常被称为采样率(sample rate)。常见的采样率包括 44.1 kHz(CD 质量)和 48 kHz(DVD 质量)。
  • 量化是指将每个样本的振幅值映射到一个有限的集合。量化的精度(即振幅值的可能数)通常被称为位深(bit depth)。常见的位深包括 16 位(CD 质量)和 24 位(高分辨率音频)。
  • 编码是指将量化后的样本值转换为二进制数据。

这个过程会生成 PCM 数据,这是一种原始的、未压缩的音频数据格式。

8.2 PCM在音频数据处理中的应用

在音频数据处理中,PCM(Pulse Code Modulation,脉冲编码调制)是一种常用的音频数据格式。PCM 是一种未经过压缩的原始音频数据格式。在 PCM 中,音频信号被分为一系列的样本,每个样本代表了在一个特定时间点的音频信号的振幅。

在 FFmpeg 中,解码后的音频数据通常被存储为 PCM 数据。AVFrame 中的数据指针指向的就是这些 PCM 数据。你可以直接从 AVFrame 中取出这些数据,并将其转换为适合你的音频播放设备的格式(例如,float 数组)。

在处理 PCM 数据时,你需要知道以下的参数:

  • 样本大小:这决定了每个样本的位数。例如,如果样本大小为 16 位,那么你需要每 16 位取出一个样本。
  • 样本格式:这决定了样本的表示方式。例如,样本可以是有符号的整数、无符号的整数、浮点数等。
  • 声道布局:这决定了多声道音频中各个声道的顺序。例如,对于立体声音频,声道布局可以是左声道在前,右声道在后,也可以是右声道在前,左声道在后。
  • 声道数:这决定了每个立体声样本中包含的声道数。例如,对于立体声音频,声道数为 2。

你需要根据这些参数,正确地从 AVFrame 的数据指针中取出样本,并将样本转换为适合你的音频播放设备的格式。例如,如果你的音频播放设备需要 float 格式的数据,你可能需要将样本从原始的 PCM 格式转换为 float 格式。

8.3 音频数据的最小单位:样本

在音频数据中,样本(Sample)是最小的独立单位。在 PCM 中,音频信号被分为一系列的样本,每个样本代表了在一个特定时间点的音频信号的振幅。样本的数量、大小和格式都会影响音频的质量和特性。

样本的数量,也就是采样率,决定了音频的频率响应。根据奈奎斯特定理,采样率必须至少是音频信号最高频率的两倍,才能无失真地重建音频信号。因此,对于人耳能听到的最高频率(大约 20 kHz),CD 的采样率为 44.1 kHz,这是足够的。

样本的大小,也就是位深,决定了音频的动态范围。位深越大,动态范围越大,音频信号的细节就越丰富。例如,16 位的位深可以提供大约 96 dB 的动态范围,而 24 位的位深可以提供大约 144 dB 的动态范围。

样本的格式,例如有符号的整数、无符号的整数、浮点数等,决定了样本的表示方式。不同的样本格式可能需要不同的处理方式。

在处理音频数据时,理解样本的概念是非常重要的。只有正确地处理样本,才能正确地处理音频数据。

结语

FFmpeg在音视频处理中的重要性

FFmpeg是一个强大的音视频处理库,它提供了一套完整的工具和API,可以用来进行音视频的编解码、转码、流化等操作。在C/C++和嵌入式领域,FFmpeg是音视频处理的首选工具。

FFmpeg的强大之处在于它的灵活性和功能性。它支持大量的音视频编解码器,可以处理几乎所有的音视频格式。它的API设计得非常灵活,可以满足各种复杂的音视频处理需求。

在实际应用中,我们可以使用FFmpeg进行各种音视频处理任务,例如:

解码视频文件,获取原始的YUV数据

将YUV数据转换为RGB数据,以便在计算机屏幕上显示

解码音频文件,获取原始的PCM数据

将PCM数据转换为其他格式,以便在音频设备上播放

编码YUV或PCM数据,生成视频或音频文件

将一个音视频格式转换为另一个格式(转码)

将音视频数据流化,以便进行网络传输

在使用FFmpeg时,我们需要了解一些关键的概念和技术,例如YUV、PCM、I帧、P帧和B帧等。这些概念和技术是音视频处理的基础,理解它们对于有效地使用FFmpeg非常重要。

在我们的编程学习之旅中,理解是我们迈向更高层次的重要一步。然而,掌握新技能、新理念,始终需要时间和坚持。从心理学的角度看,学习往往伴随着不断的试错和调整,这就像是我们的大脑在逐渐优化其解决问题的“算法”。

这就是为什么当我们遇到错误,我们应该将其视为学习和进步的机会,而不仅仅是困扰。通过理解和解决这些问题,我们不仅可以修复当前的代码,更可以提升我们的编程能力,防止在未来的项目中犯相同的错误。

我鼓励大家积极参与进来,不断提升自己的编程技术。无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力。

目录
相关文章
|
1月前
|
算法 数据处理 开发者
FFmpeg库的使用与深度解析:解码音频流流程
FFmpeg库的使用与深度解析:解码音频流流程
36 0
|
1月前
|
存储 编解码 数据处理
【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码(二)
【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码
38 0
|
3月前
|
Linux 编译器 数据安全/隐私保护
Windows10 使用MSYS2和VS2019编译FFmpeg源代码-测试通过
FFmpeg作为一个流媒体的整体解决方案,在很多项目中都使用了它,如果我们也需要使用FFmpeg进行开发,很多时候我们需要将源码编译成动态库或者静态库,然后将库放入到我们的项目中,这样我们就能在我们的项目中使用FFmpeg提供的接口进行开发。关于FFmpeg的介绍这里就不过多说明。
76 0
|
7月前
|
C++ Windows
FFmpeg入门及编译 3
FFmpeg入门及编译
54 0
|
7月前
|
编解码 API 开发工具
FFmpeg入门及编译 1
FFmpeg入门及编译
97 0
|
24天前
|
开发工具
使用FFmpeg4.3.1的SDK官方开发包编译ffmpeg.c(二)
使用FFmpeg4.3.1的SDK官方开发包编译ffmpeg.c(二)
12 0
|
7月前
|
API C语言 C++
FFmpeg入门及编译 2
FFmpeg入门及编译
80 0
|
3月前
|
编解码 Ubuntu C++
WebAssembly01--web 编译FFmpeg(WebAssembly版)库
WebAssembly01--web 编译FFmpeg(WebAssembly版)库
21 0
|
3月前
|
存储 Ubuntu 开发工具
ffmpeg笔记(二)windows下和ubuntu-16.04下ffmpeg编译
ffmpeg笔记(二)windows下和ubuntu-16.04下ffmpeg编译
|
4月前
ffmpeg的下载、编译与安装
ffmpeg的下载、编译与安装
104 0