1.导入编译好的FFmpeg库文件以及头文件

笔者使用的是静态库,静态库存放路径是:src/main/cpp/ffmpeg/libs/armeabi-v7a

导入的静态库:

  • libavcodec.a
  • libavfilter.a
  • libavformat.a
  • libavutil.a
  • libswresample.a
  • libswscale.a

头文件路径:src/main/cpp/ffmpeg/include

2.配置CMakeLists.txt配置文件

cmake_minimum_required(VERSION 3.18.1)project("msplayer")# ffmpeg的路径
set(FFMPEG ${CMAKE_SOURCE_DIR}/ffmpeg)
# rtmp的路径
set(RTMP ${CMAKE_SOURCE_DIR}/rtmp)
# 导入ffmpeg的头文件
include_directories(${FFMPEG}/include)#ffmpeg库指定
set(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -L${FFMPEG}/libs/${CMAKE_ANDROID_ARCH_ABI}")
#rtmp库指定
set(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -L${RTMP}/libs/${CMAKE_ANDROID_ARCH_ABI}")# 批量导入 源文件
file(GLOB src_files *.cpp)add_library(msplayerSHARED${src_files})find_library(log-liblog)target_link_libraries(msplayer# 忽略顺序的方式,导入-Wl,--start-groupavcodec avfilter avformat avutil swresample swscale-Wl,--end-groupz   #libz.so 是FFMpeg 额外需要的库文件rtmpandroid  #ANativeWindow 用来渲染画面OpenSLES  #OpenSLES 用来播放PCM格式的音频${log-lib})

3.视频解封装

void MSPlayer::prepare_() {/*avFormatContext 视频格式上下文 */avFormatContext = avformat_alloc_context();/*这个参数用于设置额外信息*/AVDictionary *dictionary = nullptr;av_dict_set(&dictionary, "timeout", "5000000", 0);// 单位微妙/**data_source 视频文件绝对地址 或者rtmp推流地址*/int r = avformat_open_input(&avFormatContext, data_source, nullptr, &dictionary);/*释放字典,用完必须释放*/av_dict_free(&dictionary);if (r) {if (helper) {/**视频地址或者url异常*/helper->onError(MS_THREAD_CHILD, FFMPEG_CAN_NOT_OPEN_URL);}avformat_close_input(&avFormatContext);return;}/** 查找媒体中的音视频流的信息*/r = avformat_find_stream_info(avFormatContext, nullptr);if (r < 0) {if (helper) {  /**未发现音视频流*/helper->onError(MS_THREAD_CHILD, FFMPEG_CAN_NOT_FIND_STREAMS);}avformat_close_input(&avFormatContext);return;}/**得到视频长度*/this->duration = avFormatContext->duration / AV_TIME_BASE;/*编解码上下文*/AVCodecContext *codecContext = nullptr;/*遍历视频流:一个音频流一个视频流*/for (int i = 0; i < avFormatContext->nb_streams; ++i) {/*获取媒体流(视频 or 音频)*/AVStream *stream = avFormatContext->streams[i];/**  从流中获取参数(宽高 等等)后面的解码器需要用到*  */AVCodecParameters *parameters = stream->codecpar;/*可以拿到视频宽高*/int width = parameters->width;int height = parameters->height;/*得到编解码器*/AVCodec *codec = avcodec_find_decoder(parameters->codec_id);if (!codec) {if (helper) {helper->onError(MS_THREAD_CHILD, FFMPEG_FIND_DECODER_FAIL);}avformat_close_input(&avFormatContext);return;}/*得到解码器上下文*/codecContext = avcodec_alloc_context3(codec);if (!codecContext) {if (helper) {/**得到解码器失败*/helper->onError(MS_THREAD_CHILD, FFMPEG_FIND_DECODER_FAIL);}/*释放此上下文codecContext就行,codec内部会自动释放 */avcodec_free_context(&codecContext);avformat_close_input(&avFormatContext);return;}/***  将parameters 初始化codecContext*/r = avcodec_parameters_to_context(codecContext, parameters);if (r < 0) {if (helper) {/*初始化codecContext 失败*/helper->onError(MS_THREAD_CHILD, FFMPEG_ALLOC_CODEC_CONTEXT_FAIL);}/*释放此上下文 codecContext就行,codec内部会自动释放 */avcodec_free_context(&codecContext);avformat_close_input(&avFormatContext);return;}/*打开解码器*/r = avcodec_open2(codecContext, codec, nullptr);if (r) {if (helper) {/*打开解码器失败*/helper->onError(MS_THREAD_CHILD, FFMPEG_OPEN_DECODER_FAIL);}avcodec_free_context(&codecContext);avformat_close_input(&avFormatContext);return;}AVRational time_base = stream->time_base;/*通过流类型创建对应的通道进行进行解码操作*/if (parameters->codec_type == AVMediaType::AVMEDIA_TYPE_AUDIO) {/*初始化音频通道对象*/audio_channel = new AudioChannel(i, codecContext, time_base);} else if (parameters->codec_type == AVMediaType::AVMEDIA_TYPE_VIDEO) {/*视频独有的fps值*/AVRational fps_rational = stream->avg_frame_rate;int fps = av_q2d(fps_rational);/*初始化视频通道*/video_channel = new VideoChannel(i, codecContext, time_base, fps);}}if (!audio_channel && !video_channel) {if (helper) {helper->onError(MS_THREAD_CHILD, FFMPEG_NOMEDIA);}if (codecContext) {/**释放此上下文 codecContext 不用管codec*/avcodec_free_context(&codecContext);}avformat_close_input(&avFormatContext);return;}/*prepare success*/if (helper) {helper->onPrepared(MS_THREAD_CHILD);}
}

解封状流程:

  • avformat_alloc_context() 创建avFormatContext 视频格式上下文
  • avformat_open_input() 打开视频资源
  • avformat_find_stream_info() 查找视频中的流信息
  • avFormatContext->streams[i] 得到音频或者视频流信息
  • stream->codecpar 从流中得到解码器的参数信息(也就是视频参数信息)
  • avcodec_find_decoder 通过参数中的codec_id 找到解码器AVCodec
  • avcodec_alloc_context3(codec) 得到解码器上下文 AVCodecContext
  • avcodec_parameters_to_context 初始化解码器上下文
  • avcodec_open2 打开解码器

上面就完成了FFmpeg对视频文件的解封装的操作

Android FFmpeg视频播放器一解封装相关推荐

  1. Android FFmpeg视频播放器三 音频封装格式解码播放

    Android FFmpeg视频播放器一解封装 Android Android FFmpeg视频播放器二 视频封装格式解码播放 视频解封装之后就会得到音频流和视频流,解封状得到的数据是AVPackag ...

  2. 《Android FFmpeg 播放器开发梳理》第一章 播放器初始化与解复用流程

    <Android FFmpeg 播放器开发梳理>: 第零章 基础公共类的封装 播放器初始化与解复用流程 这一章,我们来讲解播放器解复用(从文件中读取数据包)的流程.在讲解播放器的读数据包流 ...

  3. Android本地视频播放器开发--NDK编译FFmpeg

    在Android本地视频播放器开发中的搜索本地视频章节中,我们能够搜索本地视频并且显示每个视频的图片.标题.时间长度,当然如果需要添加其他的例如视频的长度和宽度可以使用Video类中的方法,既然我们获 ...

  4. 实现在Android本地视频播放器开发

    在Android本地视频播放器开发中的搜索本地视频章节中,我们能够搜索本地视频并且显示每个视频的图片.标题.时间长度,当然如果需要添加其他的例如视频的长度和宽度可以使用Video类中的方法,既然我们获 ...

  5. Android本地视频播放器开发--视频解码

    在上一章Android本地视频播放器开发--SDL编译编译中编译出sdl的支持库,当时我们使用的2.0,但是有些api被更改了,所以在以下的使用者中我们使用SDL1.3的库,这个库我会传上源码以及编译 ...

  6. android 编译 sdl,SDL编译 - Android本地视频播放器开发_Linux编程_Linux公社-Linux系统门户网站...

    在上一章  Android本地视频播放器开发--ffmpeg解码视频文件中的音频(2)[http://www.linuxidc.com/Linux/2013-06/85955p5.htm]中使用Ope ...

  7. 05.视频播放器内核切换封装

    05.视频播放器内核切换封装 目录介绍 01.视频播放器内核封装需求 02.播放器内核架构图 03.如何兼容不同内核播放器 04.看一下ijk的内核实现类 05.看一下exo的内核实现类 06.如何创 ...

  8. Android 自定义视频播放器

    由于录像之后,原先选用的腾讯VOD点播播放器显示出来竖屏都变横屏了,虽然选中了现在的腾讯VOD点播,还是把Android视频播放器了解了一番. Android自定义视频播放器有以下三种: 一.Medi ...

  9. Android本地视频播放器开发--SDL编译

    在上一章 Android本地视频播放器开发--ffmpeg解码视频文件中的音频(2)中使用OpenSL ES来播放视频的声音,遗留的问题是声音的不同步,由于视频实现部分也要同步,而且音视频也要同步,所 ...

  10. Android本地视频播放器开发 - 搜索本地视频(1)

    这一章的主要内容是搜索手机本地视频,添加到ListView列表里,每一个表项含有这个视频的缩略图,视频的播放时间,视频的标题,在搜索本地视频(1)中我们先制作搜索功能.   Video.java--视 ...

最新文章

  1. Spring Cloud 2020: Hystrix不生效怪我咯
  2. 关于CSS3圆角矩形的一些学习探讨
  3. 解决OutOfMemoryError: unable to create new native thread问题
  4. 一文读懂RPA与BPM的区别和联系
  5. 图像处理随笔——颜色空间
  6. 2013Esri全球用户大会之ArcGIS for ServerPortal for ArcGIS
  7. HBase 源码解析
  8. linux每天定时开关机,如何实现ubuntu每天定时关机
  9. 流畅的python mobi_流畅的Python中文pdf_Python教程
  10. SpringBoot构建电商基础秒杀项目
  11. SolidWorks打开step.文件显示模板无效的解决办法
  12. 红米note3双网通丨标注:2015617_官方线刷包_救砖包_解账户锁
  13. 关于QQ登录出现非官方应用 错误码100044的解决办法
  14. mysql无法打开excel_关于Navicat将Excel数据导入到MySQL中出现无法打开文件错误
  15. 经典神经网络模型整理
  16. 【 Kotlin 脚本编程Kotlin Scripting 】Linux Shell 脚本与Kotlin Scripting
  17. OUC课程评价小程序(测试报告)
  18. C# Aliyun OSS 获取Bucket列表异常:无法发送具有此谓词类型的内容正文
  19. 什么是Use Case?
  20. #ifdef __cplusplus 倒底是什么意思?

热门文章

  1. 常用文件的mime和mimetype的对应关系
  2. ns手柄pc驱动_支持amiibo和体感!switch游戏手柄莱仕达天弓NS体验
  3. close函数 qt_QT中关闭应用程序和窗口的函数(quit(),exit()以及close()的区别)
  4. 台式机和计算机有什么区别,笔记本电脑和台式电脑有什么区别
  5. 微软梁念坚:六个新潮流推动IT行业发展
  6. 大数据分析项目实例:Hadoop数据分析应用场景
  7. 中芯国际三季度营业收入创新高;德州仪器与德赛西威签署合作备忘录 | 全球TMT...
  8. DSP内核结构中的 D L S M
  9. Flutter-图表显示charts_flutter
  10. Pytorch实现EfficientNet