ffmpeg播放器实现详解 - 视频显示

本文详细解析ffmpeg播放器ffplay中视频帧的渲染显示过程,从渲染环境搭建、视频帧渲染到项目源码编译和验证。通过使用sdl库完成视频帧的渲染,介绍如何在ffmpeg解码后将视频帧显示在窗口上。同时,文章指出可能遇到的音频设备和视频设备初始化问题及其解决方案,并提供源码清单。
摘要由CSDN通过智能技术生成

ffplay是ffmpeg源码中一个自带的开源播放器实例,同时支持本地视频文件的播放以及在线流媒体播放,功能非常强大。

FFplay: FFplay is a very simple and portable media player using the FFmpeg libraries and the SDL library. It is mostly used as a testbed for the various FFmpeg APIs.

ffplay中的代码充分调用了ffmpeg中的函数库,因此,想学习ffmpeg的使用,或基于ffmpeg开发一个自己的播放器,ffplay都是一个很好的切入点。

由于ffmpeg本身的开发文档比较少,且ffplay播放器源码的实现相对复杂,除了基础的ffmpeg组件调用外,还包含视频帧的渲染、音频帧的播放、音视频同步策略及线程调度等问题。

因此,这里我们以ffmpeg官网推荐的一个ffplay播放器简化版本的开发例程为基础,在此基础上循序渐进由浅入深,最终探讨实现一个视频播放器的完整逻辑。

在上篇文章中介绍了如果搭建一个基于ffmpeg的播放器框架

本文在上篇文章的基础上,继续讨论如何将ffmpeg解码出的视频帧进行渲染显示

1、视频帧渲染

上篇文章中介绍了如何基于ffmpeg搭建一个视频播放器框架,运行程序后可以看到,除了生成几张图片外,程序好像什么也做不了。

这是因为ffmpeg通过其封装的api及组件,为我们屏蔽了不同视频封装格式及编码格式的差异,以统一的api接口提供给开发者使用,开发者不需要了解每种编码方式及封装方式具体的技术细节,只需要调用ffmpeg提供的api就可以完成解封装和解码的操作了。

至于视频帧的渲染及音频帧的播放,ffmpeg就无能为力了,因此需要借助类似sdl库等其他第三方组件来完成。

这里讲述如何使用sdl库完成视频帧的渲染,sdl在底层封装了opengl图形库,sdl提供的api简化了opengl的绘图操作,为开发者提供了很多便利的操作,当然,你也可以采用其他系统支持的图形库来绘制视频帧。

1.1 渲染环境搭建

一个视频帧在显示前,需要准备一个用于显示视频的窗口对象,以及附着在窗口上的画布对象

创建SDL窗口,并指定图像尺寸及像素个数

// 创建SDL窗口,并指定图像尺寸
screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);

创建画布对象

// 创建画布对象
bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height, SDL_YV12_OVERLAY, screen);

1.2 视频帧渲染

在窗口和画布对象创建完成后,就可以开始视频帧的渲染显示了。

在对画布对象操作前,需要对其加线程锁保护,避免其他线程对画布中的内容进行竞争性访问(后面的内容很快会涉及到多线程环境的开发)。对线程操作不熟悉的同学可以了解一下在多线程环境下,多个线程对临界区资源的竞争性访问与线程同步操作。

SDL_LockYUVOverlay(bmp);//locks the overlay for direct access to pixel data

向画布注入解码后的视频帧

sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pict.data, pict.linesize);

在画布对象的视频帧填充操作完成后,释放sdl线程锁。

//Unlocks a previously locked overlay. An overlay must be unlocked before it can be displayed
SDL_UnlockYUVOverlay(bmp);

对视频帧的渲染

SDL_DisplayYUVOverlay(bmp, &rect);//图像渲染

可以看到,由于借助了sdl封装的api绘图接口,视频帧的渲染还是非常容易的,如果直接采用opengl绘图,绘制过程会相对复杂些,例程主要的目的是为了介绍ffmpeg的使用,因此,这里采用sdl简化了渲染流程。

1.3 项目源码编译

本例程和上篇文章中用到的编译方法完全一样

tutorial02: tutorial02.c
	gcc -o tutorial02 -g3 tutorial02.c -I${FFMPEG_INCLUDE} -I${SDL_INCLUDE}  \
	-L${FFMPEG_LIB} -lavut
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FFmpeg是一个开源的跨平台音视频处理工具,也可以用来实现播放器功能。通过使用FFmpeg库,可以实现音视频的解码、编码、封装、解封装等功能,从而实现播放器的各种操作。 要实现一个基本的播放器,可以按照以下步骤进行: 1. 打开音视频文件:使用FFmpeg的avformat_open_input函数打开音视频文件,获取音视频流的信息。 2. 解码音视频流:使用FFmpeg的avcodec_send_packet和avcodec_receive_frame函数对音视频流进行解码,得到解码后的音频帧和视频帧。 3. 音视频同步:根据音频帧和视频帧的时间戳,进行音视频的同步。可以使用音频帧的播放时长和视频帧的播放时长来确定音视频的同步策略。例如,根据音频帧的播放时长来更新音频时钟,并根据音频时钟来确定视频帧的播放时间。 4. 显示视频帧:将解码后的视频帧进行渲染,显示在屏幕上。 5. 播放音频帧:将解码后的音频帧通过音频设备进行播放。 需要注意的是,以上只是一个简单的播放器实现的基本步骤,实际的播放器还需要处理音视频的同步、缓冲、错误处理等问题。此外,FFmpeg还提供了丰富的功能和接口,可以根据具体需求进行更复杂的播放器功能实现。 引用\[1\]中提到了解封装的过程,解封装是将输入的封装格式的数据分离成音频流压缩编码数据和视频流压缩编码数据的过程。在播放器中,可以使用FFmpeg的avformat_open_input函数打开封装格式的音视频文件,并通过解封装操作获取音频流和视频流的数据。 引用\[2\]中提到了音视频的同步过程,根据音频帧和视频帧的播放时长来确定音视频的同步策略。在播放器中,可以使用音频帧的播放时长和视频帧的播放时长来进行音视频的同步操作。 引用\[3\]中提到了音视频帧的显示播放时间和同步状态的维持问题。在播放器中,可以根据音频帧和视频帧的显示播放时间来确定何时播放哪一帧,并根据实际情况进行同步状态的维持。 综上所述,通过使用FFmpeg库,可以实现一个基本的播放器,并根据具体需求进行更复杂的功能扩展。 #### 引用[.reference_title] - *1* *2* [FFmpeg —— 18.FFmpeg简易播放器实现——音视频播放(含音视频同步)](https://blog.csdn.net/guoyunfei123/article/details/106041992)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [ffmpeg播放器实现详解 - 视频同步控制](https://blog.csdn.net/chanlp129/article/details/125471964)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值