FFmpeg 音视频解封装

1.简介

解封装:如下图所示,就是将FLV、MKV、MP4等文件解封装为视频H.264或H.265压缩数据,音频MP3或AAC的压缩数据,下图为常用的基本操作。

2.流程

下图是解封装的基本流程图。

2.1 在使用FFmpeg API之前,需要先注册API,然后才能使用API。当然,新版本的库不需要再调用下面的方法。

    av_register_all()

2.2 构建AVFormatContext

声明输入的封装结构体,通过输入文件或者流地址作为封装结构的句柄。韩国电视台的流地址rtmp://mobliestream.c3tv.com:554/live/goodtv.sdp。

    AVFormatContext* inputFmtCtx = nullptr;
    const char* inputUrl = "rtmp://mobliestream.c3tv.com:554/live/goodtv.sdp";

    ///打开输入的流,获取数据 begin
    int ret = avformat_open_input(&inputFmtCtx, inputUrl, NULL, NULL);

2.3 查找音视频流信息,通过下面的接口与AVFormatContext中建立输入文件对应的流信息。

	//查找;
	if (avformat_find_stream_info(inputFmtCtx, NULL) < 0)
	{
		printf("Couldn't find stream information.\n");
		return false;
	}

2.4 读取音视频流,采用av_read_frame来读取数据包,读出来的数据存储在AVPacket中,确定其为音频、视频、字幕数据,最后解码,或者存储。

	AVPacket* pkt = NULL;
	pkt = av_packet_alloc();

	while (av_read_frame(inputFmtCtx, pkt) >= 0)
	{
		//获取数据包

		//.....解码或者存储

		//重置
		av_packet_unref(pkt);
	}

上述代码所示,通过循环调用av_read_frame()读取到pkt包,然后可以进行解码或者存储数据,如果读取的数据结束,则退出循环,开始指向结束操作。

2.5 执行结束后关闭输入文件,释放资源。

	//关闭
	avformat_close_input(&inputFmtCtx);

	//释放资源
	av_packet_free(&pkt);

3.源码

int main()
{
    //av_register_all();
    avformat_network_init();

    AVDictionary* options = NULL;

    av_dict_set(&options, "buffer_size", "1024000", 0);
    av_dict_set(&options, "max_delay", "500000", 0);
    av_dict_set(&options, "stimeout", "2000000", 0);
    av_dict_set(&options, "rtsp_transport", "tcp", 0);

    AVFormatContext* inputFmtCtx = nullptr;
    const char* inputUrl = "rtmp://mobliestream.c3tv.com:554/live/goodtv.sdp";

    ///打开输入的流,获取数据 begin
    int ret = avformat_open_input(&inputFmtCtx, inputUrl, NULL, NULL);
    if (ret != 0)
    {
        printf("Couldn't open input stream.\n");
        return -1;
    }

    int vIndex = -1;
    int aIndex = -1;

    //查找;
    if (avformat_find_stream_info(inputFmtCtx, NULL) < 0)
    {
        printf("Couldn't find stream information.\n");
        return false;
    }

    AVPacket* pkt = NULL;
    pkt = av_packet_alloc();


    while (av_read_frame(inputFmtCtx, pkt) >= 0)
    {
        //获取数据包

        //.....解码或者存储

        //重置
        av_packet_unref(pkt);
    }


    //关闭
    avformat_close_input(&inputFmtCtx);

    //释放资源
    av_packet_free(&pkt);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/wzz953200463/article/details/125791661