雷神simplest

it2022-05-05  119

写在前面

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

看了雷神的小学期视频课,在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 * leixiaohua1020@126.com * 中国传媒大学/数字电视技术 * 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 ][s]\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][s]\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 ] s\n", info, if_temp->name); if_temp=if_temp->next; } //Output while (of_temp != NULL){ sprintf(info, "%s[Out] s\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 s\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[s]\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; }

最新回复(0)