雷神simplest_ffmpeg_player解析(二)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/asd501823206/article/details/96430793

写在前面

学习雷神的博客,向雷神致敬~

看了雷神的小学期视频课,在Github上下载了simplest_ffmpeg_player的代码,为代码加上了注释,作为留存。

2019.07.18

前置知识点
simplest_ffmpeg_helloworld.cpp注释


知识点

URLProtocol

在这里插入图片描述

其中 url_protocols[]protocol_list.c

static const URLProtocol * const url_protocols[] = {
    &ff_async_protocol,
    &ff_cache_protocol,
    &ff_concat_protocol,
    &ff_crypto_protocol,
    &ff_data_protocol,
    &ff_ffrtmphttp_protocol,
    &ff_file_protocol,
    &ff_ftp_protocol,
    &ff_gopher_protocol,
    &ff_hls_protocol,
    &ff_http_protocol,
    &ff_httpproxy_protocol,
    &ff_icecast_protocol,
    &ff_mmsh_protocol,
    &ff_mmst_protocol,
    &ff_md5_protocol,
    &ff_pipe_protocol,
    &ff_prompeg_protocol,
    &ff_rtmp_protocol,
    &ff_rtmpt_protocol,
    &ff_rtp_protocol,
    &ff_srtp_protocol,
    &ff_subfile_protocol,
    &ff_tee_protocol,
    &ff_tcp_protocol,
    &ff_udp_protocol,
    &ff_udplite_protocol,
    &ff_unix_protocol,
    NULL };
xxx_register_all

请参考FFmpeg源码(一)梦开始的地方——av_register_all(),包含av_register_all()、avcodec_register_all()及avfilter_register_all()的源码分析。


simplest_ffmpeg_helloworld.cpp
/**
 * 最简单的FFmpeg Helloworld程序
 * Simplest FFmpeg HelloWorld
 *
 * 雷霄骅 Lei Xiaohua
 * [email protected]
 * 中国传媒大学/数字电视技术
 * Communication University of China / Digital TV Technology
 * http://blog.csdn.net/leixiaohua1020
 *
 * 
 * 本程序是基于FFmpeg函数的最简单的程序。它可以打印出FFmpeg类库的下列信息:
 * Protocol:  FFmpeg类库支持的协议
 * AVFormat:  FFmpeg类库支持的封装格式
 * AVCodec:   FFmpeg类库支持的编解码器
 * AVFilter:  FFmpeg类库支持的滤镜
 * Configure: FFmpeg类库的配置信息
 * 
 * This is the simplest program based on FFmpeg API. It can show following 
 * informations about FFmpeg library:
 * Protocol:  Protocols supported by FFmpeg.
 * AVFormat:  Container format supported by FFmpeg.
 * AVCodec:   Encoder/Decoder supported by FFmpeg.
 * AVFilter:  Filters supported by FFmpeg.
 * Configure: configure information of FFmpeg.
 *
 */

#include <stdio.h>

#define __STDC_CONSTANT_MACROS

#ifdef _WIN32
//Windows
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#ifdef __cplusplus
};
#endif
#endif

//FIX
struct URLProtocol;
/**
 * Protocol Support Information
 * 协议支持信息(输入协议&&输出协议)
 */
char * urlprotocolinfo(){
	
	char *info=(char *)malloc(40000);

	// 将指定内存的前n个字节设置为特定的值
	memset(info,0,40000);

    // 注册复用器,编码器等(参考https://blog.csdn.net/asd501823206/article/details/96377773)
	av_register_all();

	struct URLProtocol *pup = NULL;
	//Input
	struct URLProtocol **p_temp = &pup;

	/**
	 * libavformat->protocolos.c
	
     * const char *avio_enum_protocols(void **opaque, int output)
     * {
     *     const URLProtocol **p = *opaque;
     *
     *     p = p ? p + 1 : url_protocols;
     *     *opaque = p;
     *     if (!*p) {
     *         *opaque = NULL;
     *         return NULL;
     *     }
     *     if ((output && (*p)->url_write) || (!output && (*p)->url_read))
     *         return (*p)->name;
     *     return avio_enum_protocols(opaque, output);
     * }
     *
     * Iterate through names of available protocols.
     * 迭代可用协议的名称。
     *
     * Parameters
     *      opaque	A private pointer representing current protocol. It must be a pointer to NULL on first iteration and will be updated by successive calls to avio_enum_protocols.
     *      opaque  表示当前协议的私有指针。 它必须是第一次迭代时指向NULL的指针,并将通过连续调用avio_enum_protocols进行更新。
     *
     *      output	If set to 1, iterate over output protocols, otherwise over input protocols.
     *      output  如果设置为1,则迭代输出协议,否则迭代输入协议。
     * Returns
     *      A static string containing the name of current protocol or NULL
     *      包含当前协议名称或NULL的静态字符串
     */
	avio_enum_protocols((void **)p_temp, 0);
	while ((*p_temp) != NULL){
		sprintf(info, "%s[In ][%10s]\n", info, avio_enum_protocols((void **)p_temp, 0));
	}
	pup = NULL;
	//Output
	avio_enum_protocols((void **)p_temp, 1);
	while ((*p_temp) != NULL){
		sprintf(info, "%s[Out][%10s]\n", info, avio_enum_protocols((void **)p_temp, 1));
	}

	return info;
}

/**
 * AVFormat Support Information
 *
 * 获取所有复用器、解复用器并打印
 */
char * avformatinfo(){

	char *info=(char *)malloc(40000);
	memset(info,0,40000);

	av_register_all();

    /**
     * libavformat->format.c中
     *
     * // head of registered input format linked list
     * static AVInputFormat* first_iformat = NULL;
     *
     * AVInputFormat *av_iformat_next(const AVInputFormat *f)
     * {
     *     if (f)
     *         return f->next;
     *     else
     *         return first_iformat;
     * }
     *
     * 当传入为null时,返回所有注册的复用器的第一个。in&out逻辑相同
     *
     * 循环调用next,打印出format->name
     */
	AVInputFormat *if_temp = av_iformat_next(NULL);
	AVOutputFormat *of_temp = av_oformat_next(NULL);
	//Input
	while(if_temp!=NULL){
		sprintf(info, "%s[In ] %10s\n", info, if_temp->name);
		if_temp=if_temp->next;
	}
	//Output
	while (of_temp != NULL){
		sprintf(info, "%s[Out] %10s\n", info, of_temp->name);
		of_temp = of_temp->next;
	}
	return info;
}

/**
 * AVCodec Support Information
 *
 * static AVCodec *first_avcodec = NULL;
 *
 * AVCodec *av_codec_next(const AVCodec *c)
 * {
 *     if (c)
 *         return c->next;
 *     else
 *         return first_avcodec;
 * }
 *
 * 当传入为null时,返回所有注册的编解码器的第一个
 */
char * avcodecinfo()
{
	char *info=(char *)malloc(40000);
	memset(info,0,40000);

	av_register_all();

	AVCodec *c_temp = av_codec_next(NULL);

    // 循环取下一个AVCodec
	while(c_temp!=NULL){
	    // 解码/编码
		if (c_temp->decode!=NULL){
			sprintf(info, "%s[Dec]", info);
		}
		else{
			sprintf(info, "%s[Enc]", info);
		}
		// Type:视频、音频、字幕
		switch (c_temp->type){
		case AVMEDIA_TYPE_VIDEO:
			sprintf(info, "%s[Video]", info);
			break;
		case AVMEDIA_TYPE_AUDIO:
			sprintf(info, "%s[Audio]", info);
			break;
		default:
			sprintf(info, "%s[Other]", info);
			break;
		}

        // name
		sprintf(info, "%s %10s\n", info, c_temp->name);

		c_temp=c_temp->next;
	}
	return info;
}

/**
 * AVFilter Support Information
 */
char * avfilterinfo()
{
	char *info=(char *)malloc(40000);
	memset(info,0,40000);

    /**
     * 详细注册信息请查看https://blog.csdn.net/asd501823206/article/details/96377773
     */
	avfilter_register_all();

    /**
     * libavfilter->avfilter.c
     *
     * static AVFilter *first_filter;
     *
     * const AVFilter *avfilter_next(const AVFilter *prev)
     * {
     *     return prev ? prev->next : first_filter;
     * }
     *
     * 循环打印出filter->name
     */
	AVFilter *f_temp = (AVFilter *)avfilter_next(NULL);
	
	while (f_temp != NULL){
		sprintf(info, "%s[%15s]\n", info, f_temp->name);
		f_temp=f_temp->next;
	}
	return info;
}

/**
 * Configuration Information
 *
 * Return the libavcodec build-time configuration. 构建时的配置信息
 */
char * configurationinfo()
{
	char *info=(char *)malloc(40000);
	memset(info,0,40000);

    // 注册复用器,编码器等(参考https://blog.csdn.net/asd501823206/article/details/96377773)
	av_register_all();

	sprintf(info, "%s\n", avcodec_configuration());

	return info;
}

/**
 * 每个函数(除了avfilterinfo)都调用了av_register_all(),av_register_all()里的ff_thread_once保证了register_all只会被调用一次
 */
int main(int argc, char* argv[])
{
	char *infostr=NULL;
	infostr=configurationinfo();
	printf("\n<<Configuration>>\n%s",infostr);
	free(infostr);

	infostr=urlprotocolinfo();
	printf("\n<<URLProtocol>>\n%s",infostr);
	free(infostr);

	infostr=avformatinfo();
	printf("\n<<AVFormat>>\n%s",infostr);
	free(infostr);

	infostr=avcodecinfo();
	printf("\n<<AVCodec>>\n%s",infostr);
	free(infostr);

	infostr=avfilterinfo();
	printf("\n<<AVFilter>>\n%s",infostr);
	free(infostr);

	return 0;
}

猜你喜欢

转载自blog.csdn.net/asd501823206/article/details/96430793
今日推荐