3

理解ffmpeg - 轩脉刃

 1 year ago
source link: https://www.cnblogs.com/yjf512/p/17536124.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

ffmpeg是一个完整的、跨平台的音频和视频录制、转换和流媒体解决方案。

它的官网:https://ffmpeg.org/

这里有一份中文的文档:https://ffmpeg.p2hp.com/

ffmpeg提供了什么?

在centos上,可以通过yum进行安装:

yum install epel-release

rpm -Uvh https://download1.rpmfusion.org/free/el/rpmfusion-free-release-7.noarch.rpm

yum install ffmpeg ffmpeg-devel


按照上述命令安装完ffmpeg-devel后,会在 /usr/lib64/ 路径找到对应的库

  • libavcodec.so
  • libavutil.so

ffmpeg安装完以后会有三个工具:

  • ffmpeg 用于在格式之间转换多媒体文件的命令行工具
  • ffplay 基于SDL和FFmpeg库的简单媒体播放器
  • ffprobe 一个简单的多媒体流分析器

ffmpeg还提供一系列的库,能提供开发者进行编码开发。

  • libavutil 是一个包含用于简化变成的函数的库,包括随机数生成器、数据结构、数学例程、核心多媒体实用程序等等。
  • libavcodec 是一个包含音频/视频编解码器的解码器和编码器的库。
  • libavformat 是一个包含用于多媒体容器格式的复用器和复用器的库
  • libavdevice 是一个包含输入和输出设备的库,用于从许多常见的多媒体输入/输出软件框架中抓取和渲染,包括Video4Linux, Video4Linux2, VfW和ALSA。
  • libavfilter 是一个包含媒体过滤器的库。
  • libswscacle 是一个执行高度优化的图像播放和色彩空间/像素格式转换操作的库。
  • libswresample 是一个执行高度优化的音频重采样、重矩阵化和样本格式转换操作的库。

ffmpeg是开源的,源码可以直接

git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg

FFmpeg主要是使用C语言编写的,由于FFmpeg需要对音频和视频进行底层处理,包括解码、编码、封装、解封装等操作,因此选择C语言是非常合适的,因为它可以提供对底层操作系统和硬件的直接访问。

libavutil

FFmpeg的Libavutil库提供了许多方法和功能,用于在多媒体处理中进行通用的实用工具和基本功能。以下是一些常见的Libavutil库提供的方法和功能:

  1. 内存管理:
    • av_malloc()av_mallocz():动态分配内存。
    • av_free():释放先前分配的内存。
    • av_memcpy_backptr():从后向前拷贝内存。
    • av_fast_malloc():快速分配内存。
  2. 字符串操作:
    • av_strstart()av_stristart():检查字符串的前缀。
    • av_stristr():在字符串中查找子字符串,忽略大小写。
    • av_get_token():从输入字符串中提取标记。
    • av_strcasecmp()av_strncasecmp():比较字符串,忽略大小写。
  3. 时间和时钟:
    • av_gettime():获取当前时间戳。
    • av_gettime_relative():获取相对时间戳。
    • av_usleep():微秒级延迟。
  4. 数学和整数操作:
    • av_clipl_int32()av_clipf():对整数和浮点数进行范围限制。
    • av_log2():计算以2为底的对数。
    • av_gcd():计算最大公约数。
    • av_rescale_q():按比例转换数值。
  5. 字节操作:
    • av_be2ne16()av_be2ne32():将大端字节序转换为本地字节序。
    • av_memcpy_backptr():从后向前拷贝字节。
  6. 字节流处理:
    • avio_* 系列函数:用于读写字节流,如打开、关闭、读取和写入文件。

这只是一小部分Libavutil库提供的方法和功能列表。Libavutil还提供了许多其他有用的函数,用于处理时间戳、计算时间间隔、处理字节流、颜色空间转换等等。

更多方法见:http://ffmpeg.org/doxygen/trunk/group__lavu.html#details

libavcodec

FFmpeg的libavcodec库是用于音频和视频编解码的核心库。它提供了丰富的方法和功能,用于处理不同编解码器的音视频数据。以下是一些常见的libavcodec库提供的方法和功能:

  1. 编解码器操作:
    • avcodec_find_encoder()avcodec_find_decoder():查找编码器和解码器。
    • avcodec_open2()avcodec_close():打开和关闭编码器和解码器。
    • avcodec_parameters_to_context():将编码器参数转换为编码器上下文。
  2. 编码器和解码器参数设置:
    • avcodec_parameters_alloc()avcodec_parameters_free():分配和释放编码器参数对象。
    • avcodec_parameters_copy():复制编码器参数。
    • avcodec_parameters_from_context():从编码器上下文中获取编码器参数。
  3. 编码和解码:
    • avcodec_send_packet():发送数据包给编码器或解码器。
    • avcodec_receive_frame():接收解码器输出的帧。
    • avcodec_encode_video2()avcodec_encode_audio2():编码视频和音频数据。
    • avcodec_decode_video2()avcodec_decode_audio4():解码视频和音频数据。
  4. 视频和音频帧操作:
    • av_frame_alloc()av_frame_free():分配和释放帧对象。
    • av_frame_get_best_effort_timestamp():获取最佳时间戳。
    • av_frame_copy()av_frame_copy_props():复制帧数据和属性。
  5. 编解码器参数查询:
    • av_codec_get_name():获取编解码器名称。
    • av_codec_get_tag2():获取编解码器的四字节标签。
  6. 错误处理和信息获取:
    • av_strerror():获取错误消息字符串。
    • avcodec_error_to_string():将错误代码转换为字符串。
    • avcodec_get_name():获取编解码器的名称。
    • avcodec_get_type():获取编解码器的类型。

这只是一小部分libavcodec库提供的方法和功能列表。libavcodec库还提供了更多用于处理音视频编解码的功能,如设置编码参数、处理编码器的选项、帧格式转换等。

更多方法见:http://ffmpeg.org/doxygen/trunk/group__libavc.html

libavformat

FFmpeg的libavformat库提供了用于音视频封装和解封装的方法和功能。它支持多种音视频容器格式,如AVI、MP4、MKV等。以下是一些常见的libavformat库提供的方法和功能:

  1. 格式上下文操作:
    • avformat_open_input()avformat_close_input():打开和关闭媒体文件。
    • avformat_find_stream_info():获取媒体文件的流信息。
    • avformat_alloc_context()avformat_free_context():分配和释放格式上下文。
  2. 流操作:
    • av_find_best_stream():查找最佳的音视频流。
    • av_read_frame():读取音视频帧。
    • av_seek_frame():在媒体文件中进行帧级别的跳转。
    • av_write_frame():写入音视频帧。
  3. 封装格式操作:
    • avformat_write_header()avformat_write_trailer():写入封装格式的头部和尾部。
    • avio_open()avio_close():打开和关闭封装格式的IO上下文。
  4. 流信息获取:
    • avformat_new_stream():创建新的音视频流。
    • av_stream_get_end_pts():获取流的结束时间戳。
    • av_stream_get_r_frame_rate():获取流的帧率。
  5. 格式参数设置和获取:
    • avformat_alloc_output_context2():分配输出格式上下文。
    • avformat_alloc_output_context2():获取输入格式上下文的参数。
  6. 时间基和时间戳处理:
    • av_rescale_q():按比例转换时间戳。
    • av_guess_frame_rate():猜测帧率。
  7. 错误处理和信息获取:
    • av_strerror():获取错误消息字符串。
    • avformat_version():获取libavformat库的版本号。
    • av_dump_format():输出媒体文件的格式信息。

这只是一小部分libavformat库提供的方法和功能列表。libavformat库还提供了更多用于音视频封装和解封装的功能,如元数据操作、时间码处理、流选择、封装格式的选项设置等。

更多方法见:http://ffmpeg.org/doxygen/trunk/group__libavf.html

libavdevice

FFmpeg的libavdevice库提供了与音视频设备交互的方法和功能。它允许您进行音频和视频的采集和播放,并提供了与设备的交互接口。以下是一些常见的libavdevice库提供的方法和功能:

  1. 设备操作:
    • avdevice_register_all():注册所有可用的设备。
    • avdevice_list_devices():列出可用的音视频设备。
    • avdevice_get_input_list():获取输入设备列表。
    • avdevice_get_output_list():获取输出设备列表。
    • avdevice_open()avdevice_close():打开和关闭设备。
  2. 设备参数设置:
    • avdevice_capabilities_create()avdevice_capabilities_free():创建和释放设备参数对象。
    • avdevice_list_input_sources()avdevice_list_output_sinks():列出输入源和输出接口。
    • avdevice_list_formats():列出设备支持的音视频格式。
  3. 设备采集和播放:
    • avdevice_read_packet():从设备读取音视频包。
    • avdevice_write_packet():向设备写入音视频包。
  4. 错误处理和信息获取:
    • av_strerror():获取错误消息字符串。
    • avdevice_version():获取libavdevice库的版本号。

更多方法见:http://ffmpeg.org/doxygen/trunk/group__lavd.html

libavfilter

FFmpeg的libavfilter库提供了音视频滤镜处理的方法和功能。它允许您对音视频数据进行各种滤镜和效果的处理,如裁剪、缩放、旋转、色彩调整等。以下是一些常见的libavfilter库提供的方法和功能:

  1. 滤镜图处理:
    • avfilter_register_all():注册所有可用的滤镜。
    • avfilter_graph_alloc()avfilter_graph_free():创建和释放滤镜图。
    • avfilter_graph_parse2():解析滤镜图的字符串描述。
  2. 滤镜操作:
    • avfilter_get_by_name():通过名称获取滤镜。
    • avfilter_graph_create_filter():创建滤镜实例。
    • avfilter_init_str():初始化滤镜参数。
  3. 输入输出处理:
    • av_buffersrc_add_frame():向输入缓冲区添加帧数据。
    • av_buffersink_get_frame():从输出缓冲区获取帧数据。
  4. 滤镜参数设置和查询:
    • avfilter_inout_alloc()avfilter_inout_free():创建和释放输入输出结构。
    • avfilter_graph_config():配置滤镜图。
  5. 错误处理和信息获取:
    • av_strerror():获取错误消息字符串。
    • avfilter_version():获取libavfilter库的版本号。

libswscale

FFmpeg的libswscale库提供了图像缩放和颜色空间转换的方法和功能。它用于对视频帧进行大小调整、像素格式转换和色彩空间转换等操作。以下是一些常见的libswscale库提供的方法和功能:

  1. 缩放和图像处理:
    • sws_getContext()sws_freeContext():创建和释放图像缩放上下文。
    • sws_scale():缩放和转换图像。
    • sws_setColorspaceDetails():设置颜色空间细节。
  2. 图像参数获取和设置:
    • sws_getCachedContext()sws_getContext():获取和设置图像缩放上下文的缓存。
  3. 颜色空间转换:
    • sws_convertPalette8ToPacked32():将8位调色板转换为32位色彩。
    • sws_setColorspaceDetails():设置颜色空间细节。
  4. 错误处理和信息获取:
    • sws_strerror():获取错误消息字符串。
    • swscale_version():获取libswscale库的版本号。

libswresample

FFmpeg的libswresample库提供了音频重采样和格式转换的方法和功能。它用于对音频数据进行采样率、通道布局和样本格式的转换。以下是一些常见的libswresample库提供的方法和功能:

  1. 上下文和重采样操作:
    • swr_alloc()swr_free():创建和释放音频重采样上下文。
    • swr_init():初始化音频重采样上下文。
    • swr_convert():进行音频重采样。
  2. 参数设置和查询:
    • swr_config_frame():设置输入/输出音频帧的参数。
    • swr_set_compensation():设置音频重采样补偿。
  3. 输入/输出音频帧处理:
    • swr_alloc_set_opts():设置输入/输出音频帧的参数并创建音频重采样上下文。
    • swr_convert_frame():进行音频重采样并输出音频帧。
  4. 延迟处理:
    • swr_get_delay():获取重采样的延迟。
    • swr_inject_silence():注入静音样本。
  5. 错误处理和信息获取:
    • swresample_strerror():获取错误消息字符串。
    • swresample_version():获取libswresample库的版本号。

如何读取一个mp4?

我现在有一个mp4文件,要读取这个文件应该怎么操作呢?

我是按照签名说的yum的方式安装ffmpeg-devel,它的

动态库地址为:/user/lib64/

header头文件地址为:/usr/include/ffmpeg/libavcodec/

在程序中直接引用就行

#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>

以下是一段读取互联网mp4的代码。

#include <iostream>

extern "C" 
{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
}

int main() {
    std::cout << "start read url mp4" << std::endl;
    
    // 做注册处理
	av_register_all();

    avformat_network_init();

	AVFormatContext *inputContext = NULL;
    // 打开一个url的信息
    std::string url = "https://demo.com/BigBuckBunny.mp4";
	int ret = avformat_open_input(&inputContext, url.c_str(), NULL, NULL);
    if ( ret != 0) {
    	// 打开文件失败,处理错误
        // 可以通过调用 av_strerror() 函数将错误码转换为可读的错误消息
        char errorStr[AV_ERROR_MAX_STRING_SIZE];
        av_strerror(ret, errorStr, sizeof(errorStr));
        printf("Failed to open input file: %s\n", errorStr);
        return ret;
	}

    ret = avformat_find_stream_info(inputContext, NULL);
    if (ret < 0) {
       char errorStr[AV_ERROR_MAX_STRING_SIZE];
        av_strerror(ret, errorStr, sizeof(errorStr));
        printf("Failed to avformat_find_stream_info file: %s\n", errorStr);
        return ret; 
    }

    // 输出AVFormatContent信息
    av_dump_format(inputContext, -1, url.c_str(), 0);

	for (int i = 0; i < inputContext->nb_streams; i++) {
    	AVStream *stream = inputContext->streams[i];
    	if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
        	// 处理音频流
    	}
    	else if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
        	// 处理视频流
    	}

      int64_t duration = stream->duration;
      std::cout << duration << std::endl;
	}

	avformat_close_input(&inputContext);

	std::cout << "ok" << std::endl;
	return 0;
}
start read url mp4
Input #-1, mov,mp4,m4a,3gp,3g2,mj2, from 'https://demo.com/BigBuckBunny.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isomavc1mp42
    creation_time   : 2010-01-10T08:29:06.000000Z
  Duration: 00:09:56.47, start: 0.000000, bitrate: 2119 kb/s
    Stream #-1:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
    Metadata:
      creation_time   : 2010-01-10T08:29:06.000000Z
      handler_name    : (C) 2007 Google Inc. v08.13.2007.
    Stream #-1:1(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1991 kb/s, 24 fps, 24 tbr, 24k tbn, 48 tbc (default)
    Metadata:
      creation_time   : 2010-01-10T08:29:06.000000Z
      handler_name    : (C) 2007 Google Inc. v08.13.2007.
26304512
14315000
ok

这里的关键的函数调用逻辑如下:

  • av_register_all 初始化ffmpeg库
  • avformat_network_init 初始化ffmpeg的网络访问,如果我们的输入文件是url,则需要初始化
  • avformat_open_input 打开音视频文件,这个时候并没有读取到这个音视频文件的信息
  • AVFormatContext 这个是非常重要的结构,表示音视频格式的上下文,一些重要字段
    • AVInputFormat:指向输入格式的指针,包含解封装函数等信息。
    • AVStream:指向音视频流的数组,每个流都有对应的索引。
    • nb_streams:音视频流的数量。
    • duration:音视频文件的总时长。
    • bit_rate:音视频文件的比特率。
    • metadata:元数据,包含了文件的附加信息,如标题、作者、描述等。
  • avformat_find_stream_info 获取音视频文件的流信息
  • av_dump_format 打印AVFormatContext的信息
  • av_strerror 将错误码转换为可读的错误消息字符串

Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK