Android 音视频深入 六 使用FFmpeg播放视频(附源码下载)

本篇项目地址,求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文件,例子代码如下:

android {
compileSdkVersion 26
defaultConfig {
applicationId "jonesx.videoplayer"
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
abiFilters ‘armeabi‘
}
externalNativeBuild {
cmake {
arguments ‘-DANDROID_TOOLCHAIN=clang‘,‘-DANDROID_STL=gnustl_static‘
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
}

3.代码说明

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

public class VideoPlayer {

static {
    System.loadLibrary("VideoPlayer");
}

public static native int play(Object surface);

}

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

@Override
public void surfaceCreated(SurfaceHolder holder) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            VideoPlayer.play(surfaceHolder.getSurface());
        }
    }).start();
}

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

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

AVFormatContext *pFormatCtx = avformat_alloc_context();

if (avformat_open_input(&pFormatCtx, file_name, NULL, NULL) != 0) {

    LOGD("Couldn‘t open file:%s\n", file_name);
    return -1; // Couldn‘t open file
}

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

if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
    LOGD("Couldn‘t find stream information.");
    return -1;
}

int videoStream = -1, i;
for (i = 0; i < pFormatCtx->nb_streams; i++) {
    if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO
        && videoStream < 0) {
        videoStream = i;
    }
}
if (videoStream == -1) {
    LOGD("Didn‘t find a video stream.");
    return -1; // Didn‘t find a video stream
}

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

AVCodecContext *pCodecCtx = pFormatCtx->streams[videoStream]->codec;

// Find the decoder for the video stream
AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
    LOGD("Codec not found.");
    return -1; // Codec not found
}

if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
    LOGD("Could not open codec.");
    return -1; // Could not open codec
}

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

// 获取native window
ANativeWindow *nativeWindow = ANativeWindow_fromSurface(env, surface);

// 获取视频宽高
int videoWidth = pCodecCtx->width;
int videoHeight = pCodecCtx->height;

// 设置native window的buffer大小,可自动拉伸
ANativeWindow_setBuffersGeometry(nativeWindow, videoWidth, videoHeight,
                                 WINDOW_FORMAT_RGBA_8888);
ANativeWindow_Buffer windowBuffer;

if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
    LOGD("Could not open codec.");
    return -1; // Could not open codec
}

转格式

struct SwsContext *sws_ctx = sws_getContext(pCodecCtx->width,
pCodecCtx->height,
pCodecCtx->pix_fmt,
pCodecCtx->width,
pCodecCtx->height,
AV_PIX_FMT_RGBA,
SWS_BILINEAR,
NULL,
NULL,
NULL);

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

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

释放资源

av_free(buffer);
av_free(pFrameRGBA);

// Free the YUV frame
av_free(pFrame);

// Close the codecs
avcodec_close(pCodecCtx);

// Close the video file
avformat_close_input(&pFormatCtx);

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

原文地址:http://blog.51cto.com/13591594/2069318

时间: 2024-10-02 20:54:16

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

android Listview分批加载+自动加载(附源码下载)

直接上代码,代码有注释: public class TestForListviewActivity extends Activity implements OnScrollListener { private ListView mListview = null; private View mFooterView; private PaginationAdapter mAdapter; private Handler handler=new Handler(); private boolean i

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

距离上次发布(android高仿系列)今日头条 --新闻阅读器 (二) 相关的内容已经半个月了,最近利用空闲时间,把今日头条客户端完善了下.完善的功能一个一个全部实现后,就放整个源码.开发的进度就是按照一个一个功能的思路走的,所以开发一个小的功能,如果有用,就写一个专门的博客以便有人用到独立的功能可以方便使用. 这次实现的功能是很多新闻阅读器(网易,今日头条,360新闻等)以及腾讯视频等里面都会出现的频道管理功能. 下面先上这次实现功能的效果图:(注:这个效果图没有拖拽的时候移动动画,DEMO里

你也可以用java的swing可以做出这么炫的mp3播放器_源码下载

I had published the blog : 你用java的swing可以做出这么炫的mp3播放器吗? and to display some screenshots about this MP3 Player. The target for this blog is that to publish the source code, and you can download the source code and give me some advices if possible. The

Android UI开发: 横向ListView(HorizontalListView)及一个简单相册的完整实现 (附源码下载)

Android UI开发: 横向ListView(HorizontalListView)及一个简单相册的完整实现 (附源码下载) POSTED ON 2014年6月27日 BY 天边的星星 本文内容: 1.横向ListView的所有实现思路; 2.其中一个最通用的思路HorizontalListView,并基于横向ListView开发一个简单的相册: 3.实现的横向ListView在点击.浏览时item背景会变色,并解决了listview里setSelected造成item的选择状态混乱的问题.

Android中Loader及LoaderManager的使用(附源码下载)

managedQuery方法的缺陷 Loader是用来更好地加载数据的,在我们谈论Loader之前,我们先研究一下Activity的managedQuery方法,该方法也是用于在Activity中加载数据的.在Android 3.0之前的版本中,我们如果想在Activity中通过ContentResolver对ContentProvider进行查询,我们可以方便的调用Activity的managedQuery方法,该方法的源码如下: @Deprecated public final Cursor

Android 5.0内核和源代码学习(2)——源码下载和系统启动过程分析

一.Android源码下载 上一次简单介绍了Android系统的层次结构,这次开始动真格了--下载源码和分析源码! 那么,Android的源码从哪下?当然是谷歌官网,下载方法官网也讲得很详细,但是奈何中国的墙比较厚,所以上面的办法是没用的,当然,有些是有用的,地址:http://source.android.com/source/downloading.html 谷歌官网没办法下,幸好还有一些国内网站,废话不多说,直接开始步骤: 工具和环境:VM虚拟机+Ubantu14系统 第一步:Ubantu

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

源码地址https://github.com/979451341/RtmpCamera/tree/master 配置RMTP服务器,虽然之前说了,这里就直接粘贴过来吧 1.配置RTMP服务器 这个我不多说贴两个博客分别是在mac和windows环境上的,大家跟着弄MAC搭建RTMP服务器https://www.jianshu.com/p/6fcec3b9d644这个是在windows上的,RTMP服务器搭建(crtmpserver和nginx) https://www.jianshu.com/p

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

项目地址https://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpegv%E6%92%AD%E6%94%BE%E8%A7%86%E9%A2%91%E6%9C%89%E5%A3%B0%E9%9F%B3%EF%BC%8C%E6%9A%82%E5%81%9C%EF%BC%8C%E9%87%8A%E6%94%BE%E3%80%81%E5%BF%AB%E8%BF%9B%E3%80%81%E9%80%80%E5%90%8E 这个项

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

项目地址,求starhttps://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpeg%E6%92%AD%E6%94%BE%E9%9F%B3%E4%B9%90%EF%BC%88%E4%BF%9D%E7%A8%8B%E5%BA%8F%E4%B8%8D%E6%AD%BB%EF%BC%89 这个是FFmpeg解码出音频,给AudioTrack播放,这回才算是java与c语言之间合作 这回我们将会从c++里调用java函数,下面就