本篇项目地址,求star
https://github.com/979451341/Audio-and-video-learning-materials/tree/master/FFmpeg%E6%92%AD%E6%94%BE%E8%A7%86%E9%A2%91

首先FFmpeg是c语言写的,所以我们需要NDK的技术,然后我使用的NDK使用Cmake的,一开始就是说如何将FFmpeg导入项目,使用我的方法导入FFmpeg不用一分钟。

这个需要大家先在上面的代码地址里下载项目代码
因为FFmpeg这个基于android的so文件如何生成的我不写出来,我也是直接用别人文件,直接使用我项目里的就好了

1.FFmpeg简单的说明

多媒体视频处理工具FFmpeg有非常强大的功能包括视频采集功能、视频格式转换、视频抓图、给视频加水印等。

他的功能有7大部分完整

libavcodec:提供范围更广的编解码器的实现。

libavformat:实现流媒体协议,容器格式和基本的I/O访问。

libavutil:包括校验,解压缩和各种实用功能。

libavfilter:提供了一个平均改变解码音频和视频通过过滤器链。

libavdevice:提供抽象访问捕获和重放设备。

libswresample:实现音频混合和重采样程序。

libswscale:实现颜色转换和缩放程序。

2.环境配置

将下载的项目里jniLibs和cpp粘贴到自己创建的项目的main文件夹下

我还需要在app module的build.gradle添加代码,在defaultConfig里添加ndk支持的类型,还有给Cmake添加参数,在android下导入CMakeLists文件,例子代码如下:

  1. android {
  2. compileSdkVersion 26
  3. defaultConfig {
  4. applicationId "jonesx.videoplayer"
  5. minSdkVersion 19
  6. targetSdkVersion 26
  7. versionCode 1
  8. versionName "1.0"
  9. testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  10. ndk {
  11. abiFilters 'armeabi'
  12. }
  13. externalNativeBuild {
  14. cmake {
  15. arguments '-DANDROID_TOOLCHAIN=clang','-DANDROID_STL=gnustl_static'
  16. }
  17. }
  18. }
  19. buildTypes {
  20. release {
  21. minifyEnabled false
  22. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  23. }
  24. }
  25. externalNativeBuild {
  26. cmake {
  27. path "src/main/cpp/CMakeLists.txt"
  28. }
  29. }
  30. }

3.代码说明

首先就是能够使用cpp文件夹下的VideoPlayer的代码,那我们就需要创建一个VideoPlayer的java类

  1. public class VideoPlayer {
  2.  
  3. static {
  4. System.loadLibrary("VideoPlayer");
  5. }
  6.  
  7. public static native int play(Object surface);
  8. }

使用这个play函数,直接在SurfaceView的surfaceCreated函数里开启线程使用

  1. @Override
  2. public void surfaceCreated(SurfaceHolder holder) {
  3. new Thread(new Runnable() {
  4. @Override
  5. public void run() {
  6. VideoPlayer.play(surfaceHolder.getSurface());
  7. }
  8. }).start();
  9. }

那重点来了,说一说VideoPlayer用到了FFmpeg哪些东西

获取视频格式的环境,打开MP4文件

  1. AVFormatContext *pFormatCtx = avformat_alloc_context();
  2.  
  3. if (avformat_open_input(&pFormatCtx, file_name, NULL, NULL) != 0) {
  4.  
  5. LOGD("Couldn't open file:%s\n", file_name);
  6. return -1; // Couldn't open file
  7. }

查看是否有流,如果那就看是否有视频流

  1. if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
  2. LOGD("Couldn't find stream information.");
  3. return -1;
  4. }
  5.  
  6. int videoStream = -1, i;
  7. for (i = 0; i < pFormatCtx->nb_streams; i++) {
  8. if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO
  9. && videoStream < 0) {
  10. videoStream = i;
  11. }
  12. }
  13. if (videoStream == -1) {
  14. LOGD("Didn't find a video stream.");
  15. return -1; // Didn't find a video stream
  16. }

获得视频解码器环境,然后看这个解码器是否能够开启

  1. AVCodecContext *pCodecCtx = pFormatCtx->streams[videoStream]->codec;
  2.  
  3. // Find the decoder for the video stream
  4. AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
  5. if (pCodec == NULL) {
  6. LOGD("Codec not found.");
  7. return -1; // Codec not found
  8. }
  9.  
  10. if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
  11. LOGD("Could not open codec.");
  12. return -1; // Could not open codec
  13. }

通过surface获取目前手机屏幕给这个Surface的内存空间

  1. // 获取native window
  2. ANativeWindow *nativeWindow = ANativeWindow_fromSurface(env, surface);
  3.  
  4. // 获取视频宽高
  5. int videoWidth = pCodecCtx->width;
  6. int videoHeight = pCodecCtx->height;
  7.  
  8. // 设置native window的buffer大小,可自动拉伸
  9. ANativeWindow_setBuffersGeometry(nativeWindow, videoWidth, videoHeight,
  10. WINDOW_FORMAT_RGBA_8888);
  11. ANativeWindow_Buffer windowBuffer;
  12.  
  13. if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
  14. LOGD("Could not open codec.");
  15. return -1; // Could not open codec
  16. }

转格式

  1. struct SwsContext *sws_ctx = sws_getContext(pCodecCtx->width,
  2. pCodecCtx->height,
  3. pCodecCtx->pix_fmt,
  4. pCodecCtx->width,
  5. pCodecCtx->height,
  6. AV_PIX_FMT_RGBA,
  7. SWS_BILINEAR,
  8. NULL,
  9. NULL,
  10. NULL);

首先这个解码是在一个循环里,然后解码,和之前一样一帧一帧的解码,但是如果一帧太大那就下一次循环里继续解码

  1. avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

释放资源

  1. av_free(buffer);
  2. av_free(pFrameRGBA);
  3.  
  4. // Free the YUV frame
  5. av_free(pFrame);
  6.  
  7. // Close the codecs
  8. avcodec_close(pCodecCtx);
  9.  
  10. // Close the video file
  11. avformat_close_input(&pFormatCtx);

完了,说是完了,这只是开始,我对FFmpeg的学习也是开始,以后我可能断断续续的分享我使用FFmpeg的心得。

博客首发地址
http://blog.csdn.net/z979451341

Android 音视频深入 六 使用FFmpeg播放视频(附源码下载)的更多相关文章

  1. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  2. Android 高仿 频道管理----网易、今日头条、腾讯视频 (可以拖动的GridView)附源码DEMO

    距离上次发布(android高仿系列)今日头条 --新闻阅读器 (二) 相关的内容已经半个月了,最近利用空闲时间,把今日头条客户端完善了下.完善的功能一个一个全部实现后,就放整个源码.开发的进度就是按 ...

  3. Android 音视频深入 十六 FFmpeg 推流手机摄像头,实现直播 (附源码下载)

    源码地址https://github.com/979451341/RtmpCamera/tree/master 配置RMTP服务器,虽然之前说了,这里就直接粘贴过来吧 1.配置RTMP服务器 这个我不 ...

  4. Android 音视频深入 十八 FFmpeg播放视频,有声音(附源码下载)

    项目地址https://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpegv%E6%92%AD%E6%94%BE%E8%A7% ...

  5. Android 音视频深入 二十 FFmpeg视频压缩(附源码下载)

    项目源码https://github.com/979451341/FFmpegCompress 这个视频压缩是通过类似在mac终端上输入FFmpeg命令来完成,意思是我们需要在Android上达到能够 ...

  6. Android 音视频深入 十一 FFmpeg和AudioTrack播放声音(附源码下载)

    项目地址,求starhttps://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpeg%E6%92%AD%E6%94%BE%E ...

  7. Android 音视频深入 十五 FFmpeg 推流mp4文件(附源码下载)

    源码地址https://github.com/979451341/Rtmp 1.配置RTMP服务器 这个我不多说贴两个博客分别是在mac和windows环境上的,大家跟着弄 MAC搭建RTMP服务器h ...

  8. Android 音视频深入 十 FFmpeg给视频加特效(附源码下载)

    项目地址,求starhttps://github.com/979451341/Audio-and-video-learning-materials/tree/master/FFmpeg(AVfilte ...

  9. Android 音视频深入 十七 FFmpeg 获取RTMP流保存为flv (附源码下载)

    项目地址https://github.com/979451341/RtmpSave 这个项目主要代码我是从雷神那弄过来的,不愧是雷神,我就配个环境搞个界面就可以用代码了. 这一次说的是将RTMP流媒体 ...

随机推荐

  1. ArrayList list = new ArrayList()在这个泛型为Integer的ArrayList中存放一个String类型的对象

    java面试要点---ArrayList list = new ArrayList(); 在这个泛型为Integer的ArrayList中存放一个String类型的对象. ArrayList list ...

  2. Python中什么是变量

    在Python中,变量的概念基本上和初中代数的方程变量是一致的. 例如,对于方程式 y=x*x ,x就是变量.当x=2时,计算结果是4,当x=5时,计算结果是25. 只是在计算机程序中,变量不仅可以是 ...

  3. Python Selenium Cookie 绕过验证码实现登录

    Python Selenium Cookie 绕过验证码实现登录 之前介绍过博客园的通过cookie 绕过验证码实现登录的方法.这里并不多余,会增加分析和另外一种方法实现登录. 1.思路介绍 1.1. ...

  4. C#模拟HTTP请求并发送二进制

    public static String Submit(String methodName) { string postData = "this is post data";//请 ...

  5. python logging日志输出个文件中

    # -*- coding:utf-8 -*- import logging # 引入logging模块 import os.path import time # 第一步,创建一个logger logg ...

  6. type convert

    背景# 在开发中,我们会碰到诸如String类型转换为Int等等问题,虽然处理起来简单,但是本着DRY(Don't Repeat Yourself )原则,还是有必要封装处理下: 具体代码:Maste ...

  7. 20165327 2017-2018-2 《Java程序设计》第一周学习总结

    第1章 Java入门 一.Java 的特点 简单 面向对象 平台无关 多线程:允许同时完成多个任务 动态:Java程序的基本组成单元就是类(有些类是自己编写的,有一些是从类库中引入的,而类又是运行时动 ...

  8. 利用Xml架构生成实体访问类

    由xml生成xsd及实体类   xmldataset工具 使用VS2005工具XSD.exe(SDK/v2.0/Bin/xsd.exe)自动生成实体类: xsd /c /namespace:myCom ...

  9. eclipse 快捷键Open Implementation 直接退出

    遇到eclipse 快捷键Open  Implementation 非正常退出.直接关闭的现象. 网查了一下   碰到一篇博客说  和google 输入法有关  卸载了google 输入法就好了 半信 ...

  10. android -------- ConstraintLayout介绍 (一)

    ConstraintLayout 翻译为 约束布局,也有人把它称作 增强型的相对布局,由 2016 年 Google I/O 推出. 扁平式的布局方式,无任何嵌套,减少布局的层级,优化渲染性能.从支持 ...