ffplay.c函数结构简单分析

ffmpeg ffplay.c 源码分析一:ffplay 框架分析,主要数据结构分析 ffplay.c是FFmpeg源码⾃带的播放器,调⽤FFmpeg和SDL API实现⼀个⾮常有⽤的播放器。例如哔哩哔哩著名开源项⽬ijkplayer也是基于ffplay.c进⾏⼆次开发。ffplay实现了播放器的主体功能,掌握其原理对于我们独⽴开发播放器⾮常有帮助。2.1.1 初始化packet queue。2.1.2 初始化frame queue。2.1.4 创建数据读取线程。1 ffplay.c的意义。1 ffplay.c的意义。2.1.3初始化clock。2.1 播放器初始化。 阅读详情

注:最近学习FFmpeg代码,好记性不如烂笔头,不过雷神已经写过了相关的文章,故转载之,虽然有部分结构与ffmpeg-3.2.2的不太一样,但绝大部分还是适用的。(致敬 雷神)

附:原文《ffplay.c函数结构简单分析(画图)》


FFplay是FFmpeg项目提供的播放器示例。尽管FFplay只是一个简单的播放器示例,它的源代码的量也是不少的。之前看代码,主要是集中于某一个“点”进行研究,而没有从总体结构上进行分析。本文就打算弥补之前学习的不足,从总体结构上分析一下FFplay的源代码,画图理一下它的结构。其中还有诸多不足,以后有机会慢慢完善。
说明一下自己画的结构图的规则:图中仅画出了比较重要的函数之间的调用关系。粉红色的函数是FFmpeg编解码类库(libavcodec,libavformat等)的API。紫色的函数是SDL的API。其他不算很重要的函数就不再列出了。
在看ffplay.c的代码之前,最好先看一下简单的代码了解FFmpeg播放一个视频的核心代码:

100行代码实现最简单的基于FFMPEG+SDL的视频播放器

最简单的基于FFmpeg+SDL的音频播放器


总体结构图

FFplay的总体函数调用结构图如下图所示。


上图所示本是一张高清大图。但是页面显示不下。因此上传了一份:
http://my.youkuaiyun.com/leixiaohua1020/album/detail/1788077

上面地址的那张图保存下来的话就是一张清晰的图片了。

下文对主要函数分别解析。


main()

main()是FFplay的主函数。
调用了如下函数
av_register_all():注册所有编码器和解码器。
show_banner():打印输出FFmpeg版本信息(编译时间,编译选项,类库信息等)。
parse_options():解析输入的命令。
SDL_Init():SDL初始化。
stream_open ():打开输入媒体。
event_loop():处理各种消息,不停地循环下去。


下图红框中的内容即为show_banner()的输出结果。
 


parse_options()

parse_options()解析全部输入选项。即将输入命令“ffplay -f h264 test.264”中的“-f”这样的命令解析出来。其函数调用结构如下图所示。需要注意的是,FFplay(ffplay.c)的parse_options()和FFmpeg(ffmpeg.c)中的parse_options()实际上是一样的。因此本部分的内容和《 ffmpeg.c函数结构简单分析(画图) 》中的parse_options()有很多重复的地方。
 
parse_options()调用了如下函数:
parse_option():解析一个输入选项。具体的解析步骤不再赘述。parse_options()会循环调用parse_option()直到所有选项解析完毕。FFmpeg的每一个选项信息存储在一个OptionDef结构体中。定义如下:
[cpp]  view plain  copy
  1. typedef struct OptionDef {  
  2.     const char *name;  
  3.     int flags;  
  4. #define HAS_ARG    0x0001  
  5. #define OPT_BOOL   0x0002  
  6. #define OPT_EXPERT 0x0004  
  7. #define OPT_STRING 0x0008  
  8. #define OPT_VIDEO  0x0010  
  9. #define OPT_AUDIO  0x0020  
  10. #define OPT_INT    0x0080  
  11. #define OPT_FLOAT  0x0100  
  12. #define OPT_SUBTITLE 0x0200  
  13. #define OPT_INT64  0x0400  
  14. #define OPT_EXIT   0x0800  
  15. #define OPT_DATA   0x1000  
  16. #define OPT_PERFILE  0x2000     /* the option is per-file (currently ffmpeg-only).  
  17.          implied by OPT_OFFSET or OPT_SPEC */  
  18. #define OPT_OFFSET 0x4000       /* option is specified as an offset in a passed optctx */  
  19. #define OPT_SPEC   0x8000       /* option is to be stored in an array of SpecifierOpt.  
  20.          Implies OPT_OFFSET. Next element after the offset is  
  21.          an int containing element count in the array. */  
  22. #define OPT_TIME  0x10000  
  23. #define OPT_DOUBLE 0x20000  
  24.      union {  
  25.         void *dst_ptr;  
  26.         int (*func_arg)(void *, const char *, const char *);  
  27.         size_t off;  
  28.     } u;  
  29.     const char *help;  
  30.     const char *argname;  
  31. } OptionDef;  

其中的重要字段:
name:用于存储选项的名称。例如“i”,“f”,“codec”等等。
flags:存储选项值的类型。例如:HAS_ARG(包含选项值),OPT_STRING(选项值为字符串类型),OPT_TIME(选项值为时间类型。
u:存储该选项的处理函数。
help:选项的说明信息。
FFmpeg使用一个名称为options,类型为OptionDef的数组存储所有的选项。有一部分通用选项存储在cmdutils_common_opts.h中。这些选项对于FFmpeg,FFplay以及FFprobe都试用。
cmdutils_common_opts.h内容如下:
[cpp]  view plain  copy
  1. { "L"          , OPT_EXIT, {(void*)show_license},      "show license" },  
  2.    { "h"          , OPT_EXIT, {(void*) show_help},         "show help", "topic" },  
  3.    { "?"          , OPT_EXIT, {(void*)show_help},         "show help", "topic" },  
  4.    { "help"       , OPT_EXIT, {(void*)show_help},         "show help", "topic" },  
  5.    { "-help"      , OPT_EXIT, {(void*)show_help},         "show help", "topic" },  
  6.    { "version"    , OPT_EXIT, {(void*)show_version},      "show version" },  
  7.    { "formats"    , OPT_EXIT, {(void*)show_formats  },    "show available formats" },  
  8.    { "codecs"     , OPT_EXIT, {(void*)show_codecs   },    "show available codecs" },  
  9.    { "decoders"   , OPT_EXIT, {(void*)show_decoders },    "show available decoders" },  
  10.    { "encoders"   , OPT_EXIT, {(void*)show_encoders },    "show available encoders" },  
  11.    { "bsfs"       , OPT_EXIT, {(void*)show_bsfs     },    "show available bit stream filters" },  
  12.    { "protocols"  , OPT_EXIT, {(void*)show_protocols},    "show available protocols" },  
  13.    { "filters"    , OPT_EXIT, {(void*)show_filters  },    "show available filters" },  
  14.    { "pix_fmts"   , OPT_EXIT, {(void*)show_pix_fmts },    "show available pixel formats" },  
  15.    { "layouts"    , OPT_EXIT, {(void*)show_layouts  },    "show standard channel layouts" },  
  16.    { "sample_fmts", OPT_EXIT, {(void*)show_sample_fmts }, "show available audio sample formats" },  
  17.    { "loglevel"   , HAS_ARG,  {(void*)opt_loglevel},      "set libav* logging level", "loglevel" },  
  18.    { "v",           HAS_ARG,  {(void*)opt_loglevel},      "set libav* logging level", "loglevel" },  
  19.    { "debug"      , HAS_ARG,  {(void*)opt_codec_debug},   "set debug flags", "flags" },  
  20.    { "fdebug"     , HAS_ARG,  {(void*)opt_codec_debug},   "set debug flags", "flags" },  
  21.    { "report"     , 0,        {(void*)opt_report}, "generate a report" },  
  22.    { "max_alloc"  , HAS_ARG,  {(void*) opt_max_alloc},     "set maximum size of a single allocated block", "bytes" },  
  23.    { "cpuflags"   , HAS_ARG | OPT_EXPERT, {(void*) opt_cpuflags}, "force specific cpu flags", "flags" },  

options数组的定义位于ffplay.c中,如下所示:
[cpp]  view plain  copy
  1. static const OptionDef options[] = {  
  2. #include "cmdutils_common_opts.h"//包含进来  
  3.     { "x", HAS_ARG, { (void*) opt_width }, "force displayed width", "width" },  
  4.     { "y", HAS_ARG, { (void*) opt_height }, "force displayed height", "height" },  
  5.     { "s", HAS_ARG | OPT_VIDEO, { (void*) opt_frame_size }, "set frame size (WxH or abbreviation)", "size" },  
  6.     { "fs", OPT_BOOL, { &is_full_screen }, "force full screen" },  
  7.     { "an", OPT_BOOL, { &audio_disable }, "disable audio" },  
  8.     { "vn", OPT_BOOL, { &video_disable }, "disable video" },  
  9.     { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_number" },  
  10.     { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_number" },  
  11.     { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_number" },  
  12.     { "ss", HAS_ARG, { (void*) opt_seek }, "seek to a given position in seconds", "pos" },  
  13.     { "t", HAS_ARG, { (void*) opt_duration }, "play  \"duration\" seconds of audio/video", "duration" },  
  14.     //选项众多,不再一一列出…  
  15. };  


选项众多,简单举几个例子:
强行设置设置屏幕的宽度选项(“-x”选项):
[cpp]  view plain  copy
  1. { "x", HAS_ARG, { (void*) opt_width }, "force displayed width", "width" }  
从代码中可以看出,“-x”选项包含选项值(HAS_ARG),选项处理函数是opt_width()。选项说明是"force displayed width"。opt_width()的内容如下:
[cpp]  view plain  copy
  1. static int opt_width(void *optctx, const char *opt, const char *arg)  
  2. {  
  3.     screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);  
  4.     return 0;  
  5. }  

可以看出其作用是解析输入的字符串为整数并赋值给全局变量screen_width。


全屏(“-fs”选项)
[cpp]  view plain  copy
  1. { "fs", OPT_BOOL, { &is_full_screen }, "force full screen" }  

从代码中可以看出,“-fs”选项包含布尔型选项值(OPT_BOOL),并绑定了全局变量is_full_screen。选项说明是"force full screen"。

SDL_Init()

SDL_Init()用于初始化SDL。FFplay中视频的显示和声音的播放都用到了SDL。

stream_open()

stream_open()的作用是打开输入的媒体。这个函数还是比较复杂的,包含了FFplay中各种线程的创建。它的函数调用结构如下图所示。
 
stream_open()调用了如下函数:
packet_queue_init():初始化各个PacketQueue(视频/音频/字幕)
read_thread():读取媒体信息线程。

read_thread()

read_thread()调用了如下函数:

avformat_open_input():打开媒体。
avformat_find_stream_info():获得媒体信息。
av_dump_format():输出媒体信息到控制台。
stream_component_open():分别打开视频/音频/字幕解码线程。
refresh_thread():视频刷新线程。
av_read_frame():获取一帧压缩编码数据(即一个AVPacket)。
packet_queue_put():根据压缩编码数据类型的不同(视频/音频/字幕),放到不同的PacketQueue中。



refresh_thread()

refresh_thread()调用了如下函数:

SDL_PushEvent(FF_REFRESH_EVENT):发送FF_REFRESH_EVENT的SDL_Event
av_usleep():每两次发送之间,间隔一段时间。

stream_component_open()

stream_component_open()用于打开视频/音频/字幕解码的线程。其函数调用关系如下图所示。


stream_component_open()调用了如下函数:
avcodec_find_decoder():获得解码器。
avcodec_open2():打开解码器。
audio_open():打开音频解码。
SDL_PauseAudio(0):SDL中播放音频的函数。
video_thread():创建视频解码线程。
subtitle_thread():创建字幕解码线程。
packet_queue_start():初始化PacketQueue。


audio_open()调用了如下函数
SDL_OpenAudio():SDL中打开音频设备的函数。注意它是根据SDL_AudioSpec参数打开音频设备。SDL_AudioSpec中的callback字段指定了音频播放的回调函数sdl_audio_callback()。当音频设备需要更多数据的时候,会调用该回调函数。因此该函数是会被反复调用的。


下面来看一下SDL_AudioSpec中指定的回调函数sdl_audio_callback()。
sdl_audio_callback()调用了如下函数
audio_decode_frame():解码音频数据。
update_sample_display():当不显示视频图像,而是显示音频波形的时候,调用此函数。


audio_decode_frame()调用了如下函数
packet_queue_get():获取音频压缩编码数据(一个AVPacket)。
avcodec_decode_audio4():解码音频压缩编码数据(得到一个AVFrame)。
swr_init():初始化libswresample中的SwrContext。libswresample用于音频采样采样数据(PCM)的转换。
swr_convert():转换音频采样率到适合系统播放的格式。
swr_free():释放SwrContext。


video_thread()调用了如下函数
avcodec_alloc_frame():初始化一个AVFrame。
get_video_frame():获取一个存储解码后数据的AVFrame。
queue_picture():


get_video_frame()调用了如下函数
packet_queue_get():获取视频压缩编码数据(一个AVPacket)。
avcodec_decode_video2():解码视频压缩编码数据(得到一个AVFrame)。


queue_picture()调用了如下函数
SDL_LockYUVOverlay():锁定一个SDL_Overlay。
sws_getCachedContext():初始化libswscale中的SwsContext。Libswscale用于图像的Raw格式数据(YUV,RGB)之间的转换。注意sws_getCachedContext()和sws_getContext()功能是一致的。
sws_scale():转换图像数据到适合系统播放的格式。
SDL_UnlockYUVOverlay():解锁一个SDL_Overlay。




subtitle_thread()调用了如下函数
packet_queue_get():获取字幕压缩编码数据(一个AVPacket)。

avcodec_decode_subtitle2():解码字幕压缩编码数据。

 

event_loop()

FFplay再打开媒体之后,便会进入event_loop()函数,永远不停的循环下去。该函数用于接收并处理各种各样的消息。有点像Windows的消息循环机制。
PS:该循环确实是无止尽的,其形式为如下
[cpp]  view plain  copy
  1. SDL_Event event;  
  2. for (;;) {  
  3.     SDL_WaitEvent(&event);  
  4.         switch (event.type) {  
  5.         case SDLK_ESCAPE:  
  6.         case SDLK_q:  
  7.                 do_exit(cur_stream);  
  8.                 break;  
  9.         case SDLK_f:  
  10.         …  
  11.         …  
  12.         }  
  13. }  


event_loop()函数调用关系如下所示。
 
根据event_loop()中SDL_WaitEvent()接收到的SDL_Event类型的不同,会调用不同的函数进行处理(从编程的角度来说就是一个switch()语法)。图中仅仅列举了几个例子:
SDLK_ESCAPE(按下“ESC”键):do_exit()。退出程序。
SDLK_f(按下“f”键):toggle_full_screen()。切换全屏显示。
SDLK_SPACE(按下“空格”键):toggle_pause()。切换“暂停”。
SDLK_DOWN(按下鼠标键):stream_seek()。跳转到指定的时间点播放。
SDL_VIDEORESIZE(窗口大小发生变化):SDL_SetVideoMode()。重新设置宽高。
FF_REFRESH_EVENT(视频刷新事件(自定义事件)):video_refresh()。刷新视频。


下面分析一下do_exit()函数。该函数用于退出程序。函数的调用关系如下图所示。
 
do_exit()函数调用了以下函数
stream_close():关闭打开的媒体。
SDL_Quit():关闭SDL。


stream_close()函数调用了以下函数
packet_queue_destroy():释放PacketQueue。
SDL_FreeYUVOverlay():释放SDL_Overlay。
sws_freeContext():释放SwsContext。


下面重点分析video_refresh()函数。该函数用于将图像显示到显示器上。函数的调用关系如下图所示。
 
video_refresh()函数调用了以下函数
video_display():显示像素数据到屏幕上。
show_status:这算不上是一个函数,但是是一个独立的功能模块,因此列了出来。该部分打印输出播放的状态至屏幕上。如下图所示。
 
video_display()函数调用了以下函数
video_open():初始化的时候调用,打开播放窗口。
video_audio_display():显示音频波形图(或者频谱图)的时候调用。里面包含了不少画图操作。
video_image_display():显示视频画面的时候调用。


video_open()函数调用了以下函数
SDL_SetVideoMode():设置SDL_Surface(即SDL最基础的黑色的框)的大小等信息。
SDL_WM_SetCaption():设置SDL_Surface对应窗口的标题文字。


video_audio_display()函数调用了以下函数
SDL_MapRGB():获得指定(R,G,B)以及SDL_PixelFormat的颜色数值。例如获得黑色的值,作为背景。(R,G,B)为(0x00,0x00,0x00)。
fill_rectangle():将指定颜色显示到屏幕上。
SDL_UpdateRect():更新屏幕。


video_image_display()函数调用了以下函数
calculate_display_rect():计算显示画面的位置。当拉伸了SDL的窗口的时候,可以让其中的视频保持纵横比。
SDL_DisplayYUVOverlay():显示画面至屏幕。


使用egypt+graphviz分析ffplay的函数调用关系图 在《Ffplay视频播放流程》文章中我给出了一个ffplay的函数调用关系图,在分析代码上会有不小的帮助。那么本文就详细的描述如何从源码中一步步的得到我们想要的函数调用关系图。 前置条件 下载ffmpeg源码 安装graphviz:sudo>http://www.gson.org/egypt/ 编译整个ffmepg 我采用的是默认配置+直接编译的方式,即./configure &&> 阅读详情

相关推荐

ijkPlayer源码分析 PacketQueue分析

前言 本文介绍PacketQueue,相对于FrameQueue来说比较简单,可以类比Android中的MessageQueue。 PacketQueue总体介绍 单向链表结构。first_pkt、last_pkt,是链表的起点和终点结点;recycle_pkt链表用于节点复用; 是一个多线程安全队列,靠等待唤醒机制保证线程安全; 当遇到flush_pkt时,serial加1自增,标志着流序列变化,区分是否是连续的流; typedef struct MyAVPacketList { AVPack

baiiu 952

音视频中的PTS和DTS及同步

说明:此页是所有索引的集合,从此出发,可以找到博客的所有链接。 网络相关索引:https://blog.csdn.net/knowledgebao/article/details/84626184 linux基础相关索引:https://blog.csdn.net/knowledgebao/article/details/84315842 GStreamer专栏索引:https://blog.csdn.net/knowledgebao/article/details/84621238 Gobject

lucky的专栏 972

Xilinx Vivado LDPC IP core,TSN IP core. 各种IP core

Xilinx Vivado LDPC IP core,TSN IP core. 各种IP core

qq_1432825237的博客 3991

ffplay.c函数结构简单分析(画图)

最近重温了一下FFplay的源代码。FFplay是FFmpeg项目提供的播放器示例。尽管FFplay只是一个简单的播放器示例,它的源代码的量也是不少的。之前看代码,主要是集中于某一个“点”进行研究,而没有从总体结构上进行分析。本文就打算弥补之前学习的不足,从总体结构上分析一下FFplay的源代码,画图理一下它的结构。其中还有诸多不足,以后有机会慢慢完善。

雷霄骅(leixiaohua1020)的专栏 3万+

别再搞混了!Vue3里xgplayer播放FLV视频与FLV直播流,配置到底差在哪?

本文详细解析了在Vue3项目中使用xgplayer播放FLV视频与FLV直播流的配置差异,帮助开发者避免常见错误。通过对比点播与直播的核心协议差异、插件选择及配置参数,提供实战代码示例和性能优化技巧,确保流畅播放体验。特别针对直播流场景,深入讲解专属配置和问题排查方法。

weixin_28687331的博客 150

Halcon图片拼接避坑指南:特征点匹配常见问题与解决方案

本文深入解析Halcon图片拼接中特征点匹配的常见问题与解决方案,涵盖特征点提取、匹配优化及变换模型选择等关键环节。针对工业视觉检测中的拼接错位、重影等问题,提供参数调优、图像预处理和算法选择等实战技巧,帮助开发者高效避坑并提升拼接精度。

weixin_28694169的博客 198

FFmpeg常用结构体、关键函数、ffplay.c分析

AVFormatContext是一个贯穿全局的数据结构,很多函数都要用它作为参数。FFmpeg代码中对这个数据结构的注释是format I/O context,此结构包含了一个视频流的格式内容。其中存有AVIputFormat(或AVOutputFormat,但是同一时间AVFormatContext内只能存在其中一个)、AVStream、AVPacket这几个重要的数据结构以及一些其他的相关信息,比如title、author、copyright等。

wangyongyao1989的博客 1714

SFF-8654接口引脚定义全解析:从SAS到U.2的高速硬件连接核心

在高速数据存储与传输领域,接口标准是连接主机与存储设备、确保信号完整性与协议互通性的物理基础。其核心原理在于通过精确定义的物理引脚和电气特性,承载不同的高速串行通信协议,如SAS和PCIe。这类高密度连接器的技术价值在于以紧凑的形态支持多协议兼容与高速率传输,满足了企业级存储、高性能计算对带宽和可靠性的苛刻要求。典型的应用场景包括服务器硬盘背板连接、NVMe U.2固态硬盘直连以及外部存储扩展。本文聚焦于SFF-8654(亦称Mini SAS HD)这一关键接口,深入剖析其引脚定义、信号分区(如高速数据通道

weixin_29188043的博客 710

ffplay c函数结构简单分析(画图)

ffplay c函数结构简单分析(画图)

hffgjh的博客 235

想发故障诊断论文?手把手教你用CWRU数据集复现第一个Baseline模型

本文提供了一份基于CWRU轴承数据集的故障诊断Baseline模型实战指南,手把手教你从数据准备到模型构建的全流程。通过详细的Python代码示例和学术级实验设计,帮助初学者快速复现第一个故障诊断模型,为发表高质量论文奠定基础。

weixin_28681255的博客 428

无人机多旋翼倾转动力测试系统-适用于(eVTOL开发、缩比模型测试、科研教育)

LY-QZ-F4多旋翼倾转动力测试系统是全球首款专为倾转四旋翼设计的多自由度动力测试平台,融合高精度传感、动态倾转模拟与智能工况分析,为下一代eVTOL技术提供全维度验证工具。采用航空级应变传感器(精度±0.1% FS),同步捕获推力、扭矩、俯仰/滚转力矩,动态误差<1%。同时测试电驱动系统(单轴最大150kW)与混合动力单元(增程式),支持高压(800V)平台。通过MET数据采集软件,控制采集一体化,定制化,实时观察上百个传感器数据,实时更改测试需求。可搭配六维姿态平台,温湿度舱、振动台等环境模拟设备。

weixin_49209795的博客 874

ffplay.c函数结构简单分析(绘图)

近期重温了一下FFplay的源码。FFplay是FFmpeg项目提供的播放器演示样例。虽然FFplay不过一个简单的播放器演示样例,它的源码的量也是不少的。之前看代码,主要是集中于某一个“点”进行研究,而没有从整体结构上进行分析。本文就打算弥补之前学习的不足,从整体结构上分析一下FFplay的源码,绘图理一下它的结构。当中还有诸多不足。以后有机会慢慢完好。说明一下自己画的结构图的规则:图中仅画...

weixin_30243533的博客 155

【项目实战】自动化测试软件VectorCAST介绍

VectorCAST是一款先进的自动化测试软件。VectorCAST是一款功能强大、易于使用的自动化测试软件。VectorCAST适用于各种嵌入式系统的测试。VectorCAST为嵌入式系统的测试提供了一种高效、可靠的解决方案。VectorCAST提供了一整套完整的测试工具,包括测试管理、代码覆盖、缺陷定位、报告生成等,以帮助开发人员提高测试效率,确保软件质量。VectorCAST支持。

奶爸的编程之路,也就一周冷个三天 2008

H264一些不错的网站

http://3ms.huawei.com/hi/blog/10004_2400173.html http://javapyer.iteye.com/blog/1989274 https://github.com/zhanghuicuc/ffmpeg_camera_streamer/blob/master/ffmpeg_camera_streamer/ffmpeg_camera

我想 我做 11万+

【华为OD机试真题】7、字符串筛选排序 | 机试真题+思路参考+代码解析(C++、Java、Py)

题目描述 >输入一个由N个大小写字母组成的字符串 按照ASCII码值从小到大进行排序 查找字符串中第K个最小ASCII码值的字母(k>=1) 输出该字母所在字符串中的位置索引(字符串的第一个位置索引为0) k如果大于字符串长度则输出最大ASCII码值的字母所在字符串的位置索引 如果有重复字母则输出字母的最小位置索引

KJ.JK 2267

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

FFplay源码分析-main

本系列 以 ffmpeg4.2 源码为准,下载地址:链接:百度网盘 提取码:g3k8 FFplay 源码分析系列以一条简单的命令开始,ffplay -i a.mp4。a.mp4下载链接:百度网盘,提取码:nl0s 。 这个系列主要目的是让读者看完这个系列之后能对 ffplay.c 的主干逻辑有清晰的了解。一些次要的功能,例如各种 ffplay 命令行中其他的命令参数**-filter** -vcodec等等。理解主干逻辑之后,自行断点debug即可了解 -filter -vcodec 等 命令参数实现。

u012117034的博客 1259

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

初来驾到——ffplay总体框架和核心数据结构分析

serial用于标记当前节点的播放序列号,主要用来区分是否是连续数据,每一次进行seek操作,都会使得serial做+1的操作,以区分不同的播放序列. 每次 seek 以后 以前的队列中的东西当然就不能用了呗 应该放弃的放弃 要free 的 free。ffplay中,视频,音频,字幕有各自的解码线程和播放线程,故ffplay中其实也存在着对应的三种frameQueue,每个队列都有一个读端和写端,读端位于播放线程,而写端自然而然在解码线程接受数据。AVFifo 是一个按字节存储数据的结构体。

qq_73143395的博客 1203

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

ffplay.c源码分析【2】

ffplay.c源码

m0_60259116的博客 321

ffplay.c学习-1-框架及数据结构

ffplay播放器学习 目录 ffplay.c的意义 FFplay框架分析 数据结构分析 struct VideoState 播放器封装 struct Clock 时钟封装 struct MyAVPacketList和PacketQueue队列 packet_queue_init() packet_queue_destroy() packet_queue_start() packet_queue_abort() packet_queue_put() packet_queue_get() packet

努力努力再努力L 431

ffplay.c源码分析【1】

ffplay.c源码分析【1】

m0_60259116的博客 588
上一篇: 音视频之路之开篇——视音频编解码技术零基础学习方法
下一篇: FFmpeg源代码结构
noahsun1024
博客等级 码龄10年 46粉丝 14原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值