1、av_register_all()
av_register_all() 是 FFmpeg 库中的一个函数,它已经在 FFmpeg 4.0 版本中被弃用。这个函数在旧版本的 FFmpeg 中用于注册所有可用的音视频封装器(demuxer)和解码器(decoder),以便在处理音视频文件时可以正确地识别和处理各种格式。
在较新的 FFmpeg 版本中,这个函数已经被废弃,取而代之的是自动注册机制。现在,当你使用 FFmpeg 库时,它会自动注册可用的封装器和解码器,而无需显式调用 av_register_all()。
因此,在使用较新版本的 FFmpeg 时,你无需调用 av_register_all() 函数。只需使用 FFmpeg 库中的其他函数和结构来处理音视频文件即可。
2、avformat_network_init()
avformat_network_init() 是 FFmpeg 库中的一个函数,用于初始化网络协议。在某些情况下,当你需要通过网络访问音视频资源时,你可能需要调用这个函数来确保网络协议的正确初始化。
该函数位于 libavformat/network.h 头文件中。调用 avformat_network_init() 函数会初始化 FFmpeg 库中使用的网络协议,以便可以使用诸如 HTTP、RTMP、RTSP 等网络协议来访问远程音视频资源。
以下是示例代码,展示了如何使用 avformat_network_init() 函数:
#include <libavformat/avformat.h>
int main() {
// 初始化网络协议
avformat_network_init();
// 其他音视频处理操作
...
// 清理资源
avformat_network_deinit();
return 0;
}
在上述示例中,我们首先调用 avformat_network_init() 来初始化网络协议。然后,在这个函数之后,你可以进行其他音视频处理操作。最后,使用 avformat_network_deinit() 清理相关资源。
3、avformat_open_input()
avformat_open_input() 是 FFmpeg 库中的一个函数,用于打开音视频文件或网络流以进行读取操作。
函数原型如下:
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);
参数说明:
- ps:指向 AVFormatContext 指针的指针。函数将分配并填充一个 AVFormatContext 结构体,用于表示打开的音视频文件或网络流的上下文信息。
- url:要打开的音视频文件或网络流的路径或 URL。
- fmt:可选参数,用于指定强制使用的输入格式。通常可以将其设置为 NULL,让 FFmpeg 自动检测输入格式。
- options:可选参数,用于传递额外的选项。可以使用 AVDictionary 结构体来设置各种选项,比如设置输入缓冲区大小等。
返回值为一个非负整数,表示函数的执行结果。如果返回值小于0,则表示打开输入失败,可以通过返回值查看错误码。
以下是示例代码,展示了如何使用 avformat_open_input() 函数:
#include <libavformat/avformat.h>
int main() {
AVFormatContext *formatContext = NULL;
// 打开音视频文件或网络流
int ret = avformat_open_input(&formatContext, "test01.mp4", NULL, NULL);
if (ret < 0) {
// 打开失败,处理错误
return ret;
}
// 在这里进行其他音视频处理操作
// 关闭输入文件或网络流
avformat_close_input(&formatContext);
return 0;
}
在上述示例中,我们首先声明了一个 AVFormatContext 指针 formatContext。然后,调用 avformat_open_input() 函数来打开名为 input.mp4 的音视频文件。如果打开成功,将返回一个非负值;否则,将返回一个负数,表示打开失败。在这之后,你可以进行其他的音视频处理操作。最后,使用 avformat_close_input() 函数关闭输入文件或网络流,并释放相关资源。
这只是 avformat_open_input() 函数的基本用法。在实际使用中,你可能需要根据需要设置更多的选项、处理错误以及对音视频流进行解码等操作。
4、avformat_find_stream_info()
avformat_find_stream_info() 是 FFmpeg 库中的一个函数,用于获取音视频流的相关信息。
函数原型如下:
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
参数说明:
- ic:指向 AVFormatContext 结构体的指针,表示打开的音视频文件或网络流的上下文信息。
- options:可选参数,用于传递额外的选项。可以使用 AVDictionary 结构体来设置各种选项。
返回值为一个非负整数,表示函数的执行结果。如果返回值小于0,则表示获取流信息失败,可以通过返回值查看错误码。
以下是示例代码,展示了如何使用 avformat_find_stream_info() 函数:
#include <libavformat/avformat.h>
int main() {
AVFormatContext *formatContext = NULL;
// 打开音视频文件或网络流
int ret = avformat_open_input(&formatContext, "test01.mp4", NULL, NULL);
if (ret < 0) {
// 打开失败,处理错误
return ret;
}
// 获取音视频流的相关信息
ret = avformat_find_stream_info(formatContext, NULL);
if (ret < 0) {
// 获取信息失败,处理错误
avformat_close_input(&formatContext);
return ret;
}
// 在这里可以访问音视频流的相关信息
// 关闭输入文件或网络流
avformat_close_input(&formatContext);
return 0;
}
在上述示例中,我们首先调用 avformat_open_input() 函数来打开名为 input.mp4 的音视频文件。如果打开成功,将返回一个非负值;否则,将返回一个负数,表示打开失败。然后,我们调用 avformat_find_stream_info() 函数来获取音视频流的相关信息。如果获取成功,将返回一个非负值;否则,将返回一个负数,表示获取信息失败。在获取成功后,你可以访问 AVFormatContext 结构体中的成员来获取音视频流的详细信息,比如流的数量、流的类型、时长等。最后,使用 avformat_close_input() 函数关闭输入文件或网络流,并释放相关资源。
注意: 获取流信息是一个耗时的操作,可能需要一些时间。在实际使用中,你可能还需要对流进行解码、选择特定的音视频流等操作。
5、av_find_best_stream()
av_find_best_stream() 是 FFmpeg 库中的一个函数,用于查找最佳的音视频流。
函数原型如下:
int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, int wanted_stream_nb, int related_stream, AVCodec **decoder_ret, int flags);
参数说明:
- ic:指向 AVFormatContext 结构体的指针,表示打开的音视频文件或网络流的上下文信息。
- type:希望获取的流的类型,可以是 AVMEDIA_TYPE_AUDIO、AVMEDIA_TYPE_VIDEO 或 AVMEDIA_TYPE_SUBTITLE。
- wanted_stream_nb:期望获取的流的索引号。如果为负值,则表示不关心具体的索引号,只需获取符合类型要求的最佳流。
- related_stream:关联流的索引号。在某些情况下,需要提供关联的流索引号来帮助确定最佳流。
- decoder_ret:指向 AVCodec 指针的指针,用于返回找到的解码器。
- flags:附加选项,可以设置为 AVFMT_FIND_STREAM_INFO_DISCARD, AVFMT_FIND_STREAM_INFO_NOBLOCK 或 AVFMT_FIND_STREAM_INFO_NOBSF。
返回值为非负整数,表示找到的最佳流的索引号。如果返回值小于0,则表示未找到符合要求的流。
以下是示例代码,展示了如何使用 av_find_best_stream() 函数:
#include <libavformat/avformat.h>
int main() {
AVFormatContext *formatContext = NULL;
int audioStreamIndex = -1;
int videoStreamIndex = -1;
// 打开音视频文件或网络流
int ret = avformat_open_input(&formatContext, "test01.mp4", NULL, NULL);
if (ret < 0) {
// 打开失败,处理错误
return ret;
}
// 获取音频流和视频流的索引号
audioStreamIndex = av_find_best_stream(formatContext, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
videoStreamIndex = av_find_best_stream(formatContext, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
// 在这里可以使用音频流和视频流进行处理
// 关闭输入文件或网络流
avformat_close_input(&formatContext);
return 0;
}
在上述示例中,我们首先调用 avformat_open_input() 函数来打开名为 input.mp4 的音视频文件。然后,我们使用 av_find_best_stream() 函数分别查找最佳的音频流和视频流。通过指定 AVMEDIA_TYPE_AUDIO 和 AVMEDIA_TYPE_VIDEO,我们可以获取符合类型要求的最佳流的索引号。在这之后,你可以使用获取到的音频流和视频流进行相应的处理。最后,使用 avformat_close_input() 函数关闭输入文件或网络流,并释放相关资源。
av_find_best_stream() 函数会根据流的相关属性(例如编解码器参数、时长等)来选择最佳的流。你可以根据需要对返回的流进行进一步的处理,例如解码等操作。
6、AVFormatContext
AVFormatContext 是 FFmpeg 库中的一个结构体,用于表示音视频文件或网络流的上下文信息。
AVFormatContext 结构体包含了许多成员变量,用于存储和管理音视频文件或网络流的相关信息,例如文件格式、音视频流、编解码器参数、时长、元数据等。以下是 AVFormatContext 结构体的一些重要成员变量:
- AVInputFormat *iformat:指向 AVInputFormat 结构体的指针,表示输入的文件格式。通常在打开输入文件或网络流时由 FFmpeg 自动检测并填充。
- AVIOContext *pb:指向 AVIOContext 结构体的指针,用于读取输入文件或网络流的数据。它提供了访问输入数据的方法,包括本地文件、网络协议等。
- unsigned int nb_streams:表示音视频流的数量。
- AVStream **streams:指向 AVStream 指针数组的指针,用于存储音视频流的信息。每个 AVStream 结构体表示一个音视频流,包含了该流的相关参数和信息。
- AVDictionary *metadata:指向 AVDictionary 结构体的指针,用于存储音视频文件或网络流的元数据信息,例如标题、作者、描述等。
- int duration:表示音视频文件或网络流的总时长,以微秒为单位。
- AVCodecParameters *codecpar:指向 AVCodecParameters 结构体的指针,用于存储音视频流的编解码器参数,例如编码格式、采样率、分辨率等。
- AVDictionary *metadata:指向 AVDictionary 结构体的指针,用于存储音视频文件或网络流的元数据信息,例如标题、作者、描述等。
- AVFormatContext 结构体还包含其他一些成员变量,用于存储和管理音视频文件或网络流的更多信息。
以下是示例代码,展示了如何使用 AVFormatContext 结构体:
#include <libavformat/avformat.h>
int main() {
AVFormatContext *formatContext = NULL;
// 打开音视频文件或网络流
int ret = avformat_open_input(&formatContext, "test01.mp4", NULL, NULL);
if (ret < 0) {
// 打开失败,处理错误
return ret;
}
// 在这里可以访问 formatContext 的成员变量,如 nb_streams, duration, metadata 等
// 关闭输入文件或网络流
avformat_close_input(&formatContext);
return 0;
}
在上述示例中,我们声明了一个 AVFormatContext 结构体指针 formatContext,通过调用 avformat_open_input() 函数来打开名为 input.mp4 的音视频文件。如果打开成功,将返回一个非负值;否则,将返回一个负数,表示打开失败。在打开成功后,你可以访问 formatContext 的成员变量,如 nb_streams、duration、metadata 等,以获取音视频文件或网络流的相关信息。最后,使用 avformat_close_input() 函数关闭输入文件或网络流,并释放相关资源。
AVFormatContext 结构体是 FFmpeg 库中非常重要的一个结构体,用于管理和操作音视频文件或网络流的上下文信息。在使用 FFmpeg 进行音视频处理时,经常需要使用到 AVFormatContext 结构体来获取和操作音视频相关的信息和参数。
7、AVStream
AVStream 是 FFmpeg 库中的一个结构体,用于表示音视频流的相关信息。
每个 AVStream 结构体对应一个音频流、视频流或字幕流,包含了该流的各种参数和信息,例如流的索引号、编解码器参数、时长、帧率、采样率等。
以下是 AVStream 结构体的一些重要成员变量:
- int index:表示流的索引号,用于唯一标识一个流。
- AVCodecParameters *codecpar:指向 AVCodecParameters 结构体的指针,用于存储该流的编解码器参数,例如编码格式、采样率、分辨率等。
- int64_t duration:表示该流的时长,以时间基(time base)为单位。可以通过除以时间基的分子和分母来转换为秒数。
- AVRational time_base:表示时间基。用于将时长和时间戳(timestamp)转换为实际的时间值。
- int64_t start_time:表示该流的起始时间,以时间基为单位。
- AVDictionary *metadata:指向 AVDictionary 结构体的指针,用于存储该流的元数据信息,例如标题、作者、描述等。
- AVRational avg_frame_rate:表示该流的平均帧率。
- AVPacketList *first_dts:指向 AVPacketList 结构体的指针,表示该流的第一个解码时间戳(decode timestamp)。
- int disposition:表示该流的附加信息,例如是否为默认流、是否包含字幕等。
- int discard:表示是否丢弃该流。
- struct AVCodecParserContext *parser:指向 AVCodecParserContext 结构体的指针,用于解析该流的数据。
- struct AVCodecContext *codec:指向 AVCodecContext 结构体的指针,表示该流的编解码器上下文。
- void *priv_data:指向私有数据的指针,用于存储特定于流的自定义数据。
以上仅列举了 AVStream 结构体的一部分成员变量。你可以通过访问 AVStream 的成员变量来获取和操作音视频流的相关信息。
以下是示例代码,展示了如何使用 AVStream 结构体:
#include <libavformat/avformat.h>
int main() {
AVFormatContext *formatContext = NULL;
// 打开音视频文件或网络流
int ret = avformat_open_input(&formatContext, "input.mp4", NULL, NULL);
if (ret < 0) {
// 打开失败,处理错误
return ret;
}
// 获取第一个音频流
int audioStreamIndex = av_find_best_stream(formatContext, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
if (audioStreamIndex < 0) {
// 未找到音频流,处理错误
avformat_close_input(&formatContext);
return audioStreamIndex;
}
// 获取音频流的信息
AVStream *audioStream = formatContext->streams[audioStreamIndex];
AVRational timeBase = audioStream->time_base;
int64_t duration = audioStream->duration;
// 在这里可以访问 audioStream 的其他成员变量
// 关闭输入文件或网络流
avformat_close_input(&formatContext);
return 0;
}
在上述示例中,我们首先调用 avformat_open_input() 函数来打开名为 input.mp4 的音视频文件。然后,使用 av_find_best_stream() 函数查找最佳的音频流,并获取其索引号。通过访问 formatContext->streams[audioStreamIndex],我们可以获取音频流的 AVStream 结构体。在这之后,你可以访问 audioStream 的成员变量,如 time_base、duration 等,以获取音频流的相关信息。最后,使用 avformat_close_input() 函数关闭输入文件或网络流,并释放相关资源。
AVStream 结构体是 FFmpeg 库中用于表示音视频流的重要数据结构之一。在使用 FFmpeg 进行音视频处理时,你需要使用 AVStream 结构体来获取和操作音视频流的参数和信息,例如编码器参数、时长、帧率等。
8、AVPacket
AVPacket 是 FFmpeg 库中的一个结构体,用于表示音视频数据包。
音视频数据在文件或网络流中以数据包的形式存在,每个数据包包含了一帧音频或视频数据。AVPacket 结构体用于存储和传递这些数据包,其中包含了数据和与之相关的元信息。
以下是 AVPacket 结构体的一些重要成员变量:
- int64_t pts:表示数据包的显示时间戳(Presentation Timestamp),即数据包应该在播放时显示的时间。
- int64_t dts:表示数据包的解码时间戳(Decode Timestamp),即数据包在解码时使用的时间。
- uint8_t *data:指向数据包的数据缓冲区的指针。
- int size:表示数据包的数据大小(字节数)。
- int stream_index:表示数据包所属的流的索引号。
- int flags:表示数据包的标志位,用于指示数据包的特殊属性。
- AVDictionary *metadata:指向 AVDictionary 结构体的指针,用于存储数据包的元数据信息。
- int duration:表示数据包的持续时间,以时间基(time base)为单位。
- AVRational pts:表示数据包的显示时间戳的时间基。
- AVRational dts:表示数据包的解码时间戳的时间基。
- void *priv:指向私有数据的指针,用于存储特定于数据包的自定义数据。
以上仅列举了 AVPacket 结构体的一部分成员变量。你可以通过访问 AVPacket 的成员变量来获取和操作音视频数据包的相关信息。
以下是示例代码,展示了如何使用 AVPacket 结构体:
#include <libavformat/avformat.h>
int main() {
AVFormatContext *formatContext = NULL;
// 打开音视频文件或网络流
int ret = avformat_open_input(&formatContext, "input.mp4", NULL, NULL);
if (ret < 0) {
// 打开失败,处理错误
return ret;
}
// 获取第一个视频流
int videoStreamIndex = av_find_best_stream(formatContext, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (videoStreamIndex < 0) {
// 未找到视频流,处理错误
avformat_close_input(&formatContext);
return videoStreamIndex;
}
// 读取视频数据包
AVPacket packet;
while (av_read_frame(formatContext, &packet) >= 0) {
if (packet.stream_index == videoStreamIndex) {
// 处理视频数据包
// 在这里可以访问 packet 的成员变量,如 pts, dts, data, size 等
}
// 释放数据包的资源
av_packet_unref(&packet);
}
// 关闭输入文件或网络流
avformat_close_input(&formatContext);
return 0;
}
在上述示例中,我们首先调用 avformat_open_input() 函数来打开名为 input.mp4 的音视频文件。然后,使用 av_find_best_stream() 函数查找最佳的视频流,并获取其索引号。接下来,通过调用 av_read_frame() 函数循环读取数据包,判断数据包的流索引是否与视频流索引相匹配,如果匹配则表示读取到了视频数据包。在处理视频数据包时,你可以访问 packet 的成员变量,如 pts、dts、data、size 等,以获取数据包的相关信息。最后,使用 av_packet_unref() 函数释放数据包的资源。需要注意的是,av_packet_unref() 函数将会自动释放数据包的数据缓冲区,你无需手动释放。
9、av_read_frame
av_read_frame() 是 FFmpeg 库中的一个函数,用于从媒体文件或网络流中读取音视频数据包。
函数原型如下:
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
- AVFormatContext *s:指向 AVFormatContext 结构体的指针,表示打开的媒体文件或网络流的上下文。
- AVPacket *pkt:指向 AVPacket 结构体的指针,用于存储读取到的音视频数据包。
函数返回值为非负整数表示读取成功,返回值为负数表示读取失败或遇到了文件结束等错误情况。
av_read_frame() 函数的作用是读取媒体文件或网络流中的下一个音视频数据包,并将其存储在提供的 AVPacket 结构体中。每次调用该函数,它将会从输入流中读取一个数据包,并将数据包的相关信息填充到 pkt 中。
你可以在循环中多次调用 av_read_frame() 函数,以逐个读取媒体文件中的所有音视频数据包。读取的数据包可以根据 pkt->stream_index 来判断属于哪个流(音频、视频或字幕流)。然后,你可以根据需要处理和解码这些数据包,比如进行播放、转码、分析等操作。
以下是示例代码,展示了如何使用 av_read_frame() 函数读取音视频数据包:
#include <libavformat/avformat.h>
int main() {
AVFormatContext *formatContext = NULL;
// 打开音视频文件或网络流
int ret = avformat_open_input(&formatContext, "input.mp4", NULL, NULL);
if (ret < 0) {
// 打开失败,处理错误
return ret;
}
// 循环读取音视频数据包
AVPacket packet;
while (av_read_frame(formatContext, &packet) >= 0) {
// 处理音视频数据包
// 在这里可以访问 packet 的成员变量,如 stream_index, pts, dts, data, size 等
// 释放数据包的资源
av_packet_unref(&packet);
}
// 关闭输入文件或网络流
avformat_close_input(&formatContext);
return 0;
}
在上述示例中,我们首先调用 avformat_open_input() 函数来打开名为 input.mp4 的音视频文件。然后,通过循环调用 av_read_frame() 函数来读取音视频数据包。在处理数据包时,你可以访问 packet 的成员变量,如 stream_index、pts、dts、data、size 等,以获取数据包的相关信息。最后,使用 av_packet_unref() 函数释放数据包的资源。
av_read_frame() 函数会按照数据包在文件中的顺序读取数据,因此读取到的数据包可能是音频、视频或字幕流的任意一个。你可以根据 stream_index 判断数据包属于哪个流,并根据需要进行进一步处理。另外,当读取到文件结束时,av_read_frame() 函数将返回负值,表示读取结束。你可以通过检查返回值来判断是否读取完整个文件。
10、ffmpeg解封装实例
#include <iostream>
#include <chrono>
#include <thread>
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libavutil/channel_layout.h> // 用户音频声道布局
#include <libavutil/mathematics.h> // 用于数学相关操作
#include <libavutil/timestamp.h> // 用于时间戳操作
#include <libavformat/avformat.h> // 用于封装与解封装操作
#include <libswscale/swscale.h> // 用于缩放、转换颜色格式操作
#include <libswresample/swresample.h> // 用于进行音频采样率操作
#include <libswresample/swresample.h>
#include <libswscale/swscale.h>
#include <libavutil/avutil.h>
#include <libavutil/opt.h> // 设置操作选项操作
}
static double r2d(AVRational r)
{
return r.den == 0 ? 0 : (double)r.num / (double)r.den;
}
void PrintError(const std::string& message, int error)
{
char buf[1024] = { 0 };
av_strerror(error, buf, sizeof(buf) - 1);
std::cout << message << ": " << buf << std::endl;
}
int main()
{
constexpr char file_path[] = "1.flv"; // 地址
//初始化封装库
av_register_all();
//初始化网络库 (可以打开rtsp rtmp http 协议的流媒体视频)
avformat_network_init();
// 参数设置
AVDictionary *opts = nullptr;
// 设置rtsp流已tcp协议打开
av_dict_set(&opts, "max_delay", "500", 0);
// 解封装上下文
AVFormatContext *fmt_ctx = nullptr;
int ret = avformat_open_input(
&fmt_ctx,
file_path,
0, // 自动选择解封装器
&opts // 参数设置,比如rtsp的延迟时间
);
if (ret != 0)
{
PrintError("Could not find stream information", ret);
return -1;
}
// 获取流信息
ret = avformat_find_stream_info(fmt_ctx, 0);
// 总时长 ms
int total_ms = fmt_ctx->duration / (AV_TIME_BASE / 1000);
std::cout << "total_ms = " << total_ms << std::endl;
// 打印视频流详细信息
av_dump_format(fmt_ctx, 0, file_path, 0);
// 音视频索引, 读取时区分音视频
int video_stream_idx = 0;
int audio_stream_idx = 1;
// 获取音视频流信息
for (int i = 0; i < fmt_ctx->nb_streams; i++)
{
AVStream *as = fmt_ctx->streams[i];
std::cout << "codec_id = " << as->codecpar->codec_id << std::endl;
std::cout << "format = " << as->codecpar->format << std::endl;
// 音频
if (as->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
{
audio_stream_idx = i;
std::cout << "audio info: " << std::endl;
std::cout << "sample_rate = " << as->codecpar->sample_rate << std::endl;
std::cout << "channels = " << as->codecpar->channels << std::endl;
std::cout << "frame_size = " << as->codecpar->frame_size << std::endl;
}
else if (as->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) //视频 AVMEDIA_TYPE_VIDEO
{
video_stream_idx = i;
std::cout << i << "video info: " << std::endl;
std::cout << "width=" << as->codecpar->width << std::endl;
std::cout << "height=" << as->codecpar->height << std::endl;
//帧率 fps 分数转换
std::cout<<"video fps = " << r2d(as->avg_frame_rate) << std::endl;
}
}
AVPacket *pkt = av_packet_alloc();
for(;;)
{
int ret = av_read_frame(fmt_ctx, pkt);
if (ret != 0)
{
// int ms = 300;
// av_seek_frame(fmt_ctx, video_stream_idx, 0, )
av_seek_frame(fmt_ctx, video_stream_idx, 0, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME);
break;
}
std::cout << "AVPacket size: " << pkt->size << std::endl;
// 显示时间
std::cout << "AVPacket pts: " << pkt->pts << std::endl;
//转换为毫秒,方便做音视频同步
std::cout << "pkt->pts ms = " << pkt->pts * (r2d(fmt_ctx->streams[pkt->stream_index]->time_base) * 1000) << std::endl;
// 解码时间
std::cout << "AVPacket dts: " << pkt->dts << std::endl;
if (pkt->stream_index == video_stream_idx)
{
std::cout << "==========video=========" << std::endl;
}
else if (pkt->stream_index == audio_stream_idx)
{
std::cout << "==========audio=========" << std::endl;
}
// 释放,引用计数-1 为0释放空间
av_packet_unref(pkt);
}
av_packet_free(&pkt);
if (fmt_ctx)
{
//释放封装上下文,并且把fmt_ctx置0
avformat_close_input(&fmt_ctx);
}
getchar();
return 0;
}
作者:小熊维尼的曲奇饼干
来源:写Bug那些事
原文:https://mp.weixin.qq.com/s/82PKhlAEO_frT9NJSLoGew
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。