文章目录




博客简介 . FFMPEG 音视频流 获取流程



FFMPEG 音视频流 AVStream ( 结构体 ) 获取流程 :



① 获取音视频流信息 :​ ​avformat_find_stream_info ( )​ , 在 ​​【Android FFMPEG 开发】FFMPEG 初始化 ( 网络初始化 | 打开音视频 | 查找音视频流 )​​ 博客中 , FFMPEG 初始化完毕后 , 获取了音视频流 , 本博客中讲解获取该音视频流对应的编解码器 , 从获取该音视频流开始 ;

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);



② 音视频流数量 :​ 获取的音视频流信息存储在 ​AVFormatContext *formatContext​ 结构体中 , nb_streams 元素的值就是音视频流的个数 ;

//音视频流的个数
formatContext->nb_streams



③ 音视频流 :​ ​AVFormatContext *formatContext​ 结构体中的 音视频流数组元素 ​AVStream **streams​ 元素 , 通过数组下标可以获取指定位置索引的音视频流 ;

//取出一个媒体流 ( 视频流 / 音频流 )
AVStream *stream = formatContext->streams[i];




I . FFMPEG 获取音视频流信息 ( AVFormatContext 结构体 )



1 . 获取音视频流信息 :​ ​avformat_find_stream_info ( )​ , 在 ​​【Android FFMPEG 开发】FFMPEG 初始化 ( 网络初始化 | 打开音视频 | 查找音视频流 )​​ 博客中 , FFMPEG 初始化完毕后 , 获取了音视频流 , 本博客中讲解获取该音视频流对应的编解码器 , 从获取该音视频流开始 ;



2 . 信息存放载体 :​ 调用 ​avformat_find_stream_info ( )​ 方法 , 获取音视频流信息存储在 ​AVFormatContext *formatContext​ 结构体中 ; 可以通过 formatContext->结构体元素 获取相应的 FFMPEG 数据 ;




II . FFMPEG 获取 音视频流 数量



1 . 结构体元素 :​ 音视频流数量信息存储在 ​AVFormatContext *formatContext​ 结构体中 的 ​unsigned int nb_streams​ 元素中 ;

/**
* Number of elements in AVFormatContext.streams.
*
* Set by avformat_new_stream(), must not be modified by any other code.
*/
unsigned int nb_streams;



2 . 获取示例 :​ 调用 ​AVFormatContext *formatContext​ 结构体指针的 “->” 运算符获取其结构体中的元素值 ;

//stream_count 是音视频流数量
int stream_count = formatContext->nb_streams;




III . FFMPEG 获取音视频流



1 . 音视频流结构体 AVStream :​ 音视频流在 FFMPEG 中被定义成了结构体 , typedef struct AVStream , 该结构体定义在了 avformat.h 中 ;

/**
* Stream structure.
* New fields can be added to the end with minor version bumps.
* Removal, reordering and changes to existing fields require a major
* version bump.
* sizeof(AVStream) must not be used outside libav*.
*/
typedef struct AVStream {
...
} AVStream



2 . 结构体元素 :​ 音视频流结构体 AVStream 存储在 ​AVFormatContext *formatContext​ 结构体中 的 ​AVStream **streams​ 元素中 , 这是一个 AVStream 结构体指针数组 ;

/**
* A list of all streams in the file. New streams are created with
* avformat_new_stream().
*
* - demuxing: streams are created by libavformat in avformat_open_input().
* If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also
* appear in av_read_frame().
* - muxing: streams are created by the user before avformat_write_header().
*
* Freed by libavformat in avformat_free_context().
*/
AVStream **streams;



2 . 使用 AVStream ** 数组下标获取音视频流 :



① 获取 AVStream **streams 数组 :​ 调用 ​AVFormatContext *formatContext​ 结构体指针的 “->” 运算符获取其结构体中的 AVStream **streams 元素值 ;

② 获取 AVStream *stream 音视频流 :​ 再使用数组下标获取指定索引的 AVStream * 音视频流 ;

③ 常用使用场景 :​ 一般是在 for 循环中遍历解析音视频流 ;

//formatContext->nb_streams 是 音频流 / 视频流 个数 ;
// 循环解析 视频流 / 音频流 , 一般是两个 , 一个视频流 , 一个音频流
for(int i = 0; i < formatContext->nb_streams; i ++){

//取出一个媒体流 ( 视频流 / 音频流 )
AVStream *stream = formatContext->streams[i];

}