一:使用IjkMediaPlayer+SurfaceView的播放方式,和截图方式

需要到官网拉取自己编译的so库

拉取安卓代码 git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-android

编译步骤百度搜索一下吧,都一样,可能会有些环境配置的问题,ndk推荐使用r14的版本;太低编译不过去,太高java版本不支持;

自己封装一个播放器的话,直接继承Surface ,实现需要继承的方法,

1:初始化

在构造函数中初始化,设置播放画面到Surface

    public BlibiliVideoPlayer(Context context) {super(context);init();}
    private void init() {IjkMediaPlayer.loadLibrariesOnce(null);IjkMediaPlayer.native_profileBegin("libijkplayer.so");ijkMediaPlayer=new IjkMediaPlayer();//开启日志
//        ijkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_DEBUG);getHolder().addCallback(new SurfaceHolder.Callback() {@Overridepublic void surfaceCreated(SurfaceHolder holder) {ijkMediaPlayer.setDisplay(holder);}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {ijkMediaPlayer.setDisplay(holder);
//                ijkMediaPlayer.prepareAsync();
//                loadVideo();}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {if(ijkMediaPlayer!=null){ijkMediaPlayer.setDisplay(null);}}});ijkMediaPlayer.setOnSeekCompleteListener(new IMediaPlayer.OnSeekCompleteListener() {@Overridepublic void onSeekComplete(IMediaPlayer iMediaPlayer) {inSeek = false;}});ijkMediaPlayer.setOnCompletionListener(new IMediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(IMediaPlayer iMediaPlayer) {inSeek = false;//关闭定时器stopProgressUpdateTimer();try{if(null != listener) {listener.completed();}}catch (Exception e){}}});ijkMediaPlayer.setOnInfoListener(new IMediaPlayer.OnInfoListener() {@Overridepublic boolean onInfo(IMediaPlayer iMediaPlayer, int i, int i1) {if(null != listener) {listener.info(VideoPlayerConstants.ALI,i,0);}return false;}});ijkMediaPlayer.setOnPreparedListener(new IMediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(IMediaPlayer iMediaPlayer) {prepared = true;if(null != listener){listener.prepared();}}});//ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_clear", 1);ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"http-detect-range-support", 1);//        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_timeout", -1);
//        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 0);
//        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);
//        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);
//        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);
//        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);
//        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
//        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT,"safe",0);
//        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "protocol_whitelist", "hls,async,cache,crypto,file,http,https,ijkhttphook,ijkinject,ijklivehook,ijklongurl,ijksegment,ijktcphook,pipe,rtp,tcp,tls,udp,ijkurlhook,data,concat,subfile,udp,ffconcat");
//
//        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
//        ijkMediaPlayer.
//        ijkMediaPlayer.setOnVideoDecoderErrorListener(new IMediaPlayer.OnVideoDecoderErrorListener() {
//            @Override
//            public void onVideoDecoderError(IMediaPlayer iMediaPlayer) {
//                Log.d("log","解码错误");
//            }
//        });}
private void loadVideo() {ijkMediaPlayer.prepareAsync();ijkMediaPlayer.setDisplay(getHolder());ijkMediaPlayer.start();
//        startProgressUpdateTimer();
}

添加请求头,防盗链,refer的方式:

Map<String, String> headers = new HashMap<>();
headers.put("Referer","内容");//
if (headers != null) {try{ijkMediaPlayer.setDataSource(url,headers);}catch (Exception e){}}else{try{ijkMediaPlayer.setDataSource(url);}catch (Exception e){}
}//有header和没header的播放方式

到这里就可以正常播放啦。

2截图实现:需要改到ijkplayer-android/ijkmedia/ijkplayer下的ff_ffplay.c        ijkplayer.c        ff_ffplay-def.h文件,Android.mk以及ijkplayer-android/ijkmedia/ijkplayer/android/的ijkplayer_jni.c

jni添加:ijkplayer_jni.c

#include <android/bitmap.h>//需要引入这个包static jboolean
IjkMediaPlayer_getCurrentFrame(JNIEnv *env, jobject thiz, jobject bitmap)
{jboolean retval = JNI_TRUE;IjkMediaPlayer *mp = jni_get_media_player(env, thiz);JNI_CHECK_GOTO(mp, env, NULL, "mpjni: getCurrentFrame: null mp", LABEL_RETURN);uint8_t *frame_buffer = NULL;if (0 > AndroidBitmap_lockPixels(env, bitmap, (void **)&frame_buffer)) {(*env)->ThrowNew(env, "java/io/IOException", "Unable to lock pixels.");return JNI_FALSE;}ijkmp_get_current_frame(mp, frame_buffer);if (0 > AndroidBitmap_unlockPixels(env, bitmap)) {(*env)->ThrowNew(env, "java/io/IOException", "Unable to unlock pixels.");return JNI_FALSE;}/Users/hoge/ijkplayer-android/ijkmedia/ijkplayer/android/ijkplayer_jni.cLABEL_RETURN:ijkmp_dec_ref_p(&mp);return retval;
}JNINativeMethod中添加{ "getCurrentFrame", "(Landroid/graphics/Bitmap;)Z", (void *) IjkMediaPlayer_getCurrentFrame },//添加这条
{ "_setOption",             "(ILjava/lang/String;Ljava/lang/String;)V", (void *) IjkMediaPlayer_setOption },//这条已经有了

Android.mk:

include $(CLEAR_VARS)
# -mfloat-abi=soft is a workaround for FP register corruption on Exynos 4210
# http://www.spinics.net/lists/arm-kernel/msg368417.html
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_CFLAGS += -mfloat-abi=soft
endif
LOCAL_CFLAGS += -std=c99
LOCAL_LDLIBS += -llog -landroid -ljnigraphics//添加这个-ljnigraphics

ijkplayer.c:

static void ijkmp_get_current_frame_l(IjkMediaPlayer *mp, uint8_t *frame_buf)
{ffp_get_current_frame_l(mp->ffplayer, frame_buf);
}void ijkmp_get_current_frame(IjkMediaPlayer *mp, uint8_t *frame_buf)
{assert(mp);pthread_mutex_lock(&mp->mutex);ijkmp_get_current_frame_l(mp, frame_buf);pthread_mutex_unlock(&mp->mutex);
}

ff_ffplay.c

void ffp_get_current_frame_l(FFPlayer *ffp, uint8_t *frame_buf)
{ALOGD("=============>start snapshot\n");VideoState *is = ffp->is;Frame *vp;int i = 0, linesize = 0, pixels = 0;uint8_t *src;vp = &is->pictq.queue[is->pictq.rindex];int height = vp->bmp->h;int width = vp->bmp->w;ALOGD("=============>%d X %d === %d\n", width, height, vp->bmp->pitches[0]);// copy data to bitmap in java codelinesize = vp->bmp->pitches[0];src = vp->bmp->pixels[0];pixels = width * 4;for (i = 0; i < height; i++) {memcpy(frame_buf + i * pixels, src + i * linesize, pixels);}ALOGD("=============>end snapshot\n");
}

ff_ffplay-def.h:


typedef struct FFPlayer {//在这个方法里添加这些变量,就放在最开头吧AVFormatContext *m_ofmt_ctx;AVOutputFormat *m_ofmt;pthread_mutex_t record_mutex;char *screen_file_name;int is_record;int record_error;int is_first;int is_screenshot;//是否截图,是一次性的,一次只能截一张图int64_t start_pts;int64_t start_dts;}

修改完毕开始编译,在jkplayer-android/android/contrib目录下执行

./compile-ffmpeg.sh clean
 ./compile-ffmpeg.sh armv7a                //armv7a可以改成想要的,活着all编译全部

然后cd .. 到上一个目录 jkplayer-android/android下执行

./compile-ijk.sh armv7a//生成so文件

生成的so在对应的文件目录下,比如这边编译的armv7a就在ijkplayer-android/android/ijkplayer/ijkplayer-armv7a/src/main/libs/armeabi-v7a目录下

tips:

如果有编译过一次了,再次修改上面的这些c文件就可以不用再执行上面的

./compile-ffmpeg.sh clean,可以大大加快编译速度

二:java 添加截图方法,

把生成的so文件放到项目中,修改IMediaPlayer.java:

添加

boolean getCurrentFrame(Bitmap bitmap);方法

因为有好多个文件继承这个IMediaPlayer.java,添加这个后需要到继承他的子类中实现这个getCurrentFrame,比如IjkMediaPlayer.java中添加nativa方法

@Override
public native boolean getCurrentFrame(Bitmap bitmap);

有好几个文件哦,记得都添加上;

截图实现:

if(ijkMediaPlayer!=null){int width = getVideoWidth();//想要的宽度int height = getVideoHeight();//想要的高度Bitmap srcBitmap = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_4444);//建议4444比较小,8888报错过一次SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss");String picName = dateFormat.format(new java.util.Date());//按照日期生成图片文件//Util.getScreenShotPath() 是路径,一般放data/包名/目录下.//这个路径不存在会报错,没读写权限也会报错,怎么申请权限自己百度String mPath2 = Util.getScreenShotPath() + picName + ".png";boolean flag = ijkMediaPlayer.getCurrentFrame(srcBitmap);if (flag) {File imageFile = new File(mPath2);try {if(imageFile!=null){//保存图片OutputStream fout = new FileOutputStream(imageFile);srcBitmap.compress(Bitmap.CompressFormat.PNG, 100, fout);fout.flush();fout.close();}} catch (Exception e) {e.printStackTrace();callback.onFaild();}}}

三:问题记录

1,播放https的m3u8流失败,请求内部的ts文件失败,没有解决这个问题,问题点在于这个流是https的协议,但是这个m3u8流里面的ts文件是http的,切换协议失败,可以改成http播放,或者后台把这个m3u8流里面的ts文件都改成https,反正就是要跟这个m3u8流一样的开头,我这边是cdn上有把http的都转换成https,所以就没处理了    

2播放https的流切换到http后会播放失败

官方git上的提问https://github.com/bilibili/ijkplayer/issues/4905

给出的解决方案是设置清理dns,但是目测没啥用,切换一次后又不行了

ijkMediaPlayer.setOption( IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_clear", 1);

别人的汇总:

ijkplayer中遇到的问题汇总 - 掘金

好啦到这里就完结了,有哪里有遗漏或者问题的话留个评论,谢谢

android ijkplayer添加防盗链refer,截图,支持rtsp,修改底层增加截图功能,以及ijk播放的部分问题相关推荐

  1. 织梦后台添加友链,前台不显示|修改友情链接的显示行数

    在我们建设网站的过程中有一个程序是我们经常用到的,那就是织梦CMS信息管理系统,这是一个很强大的开源程序,企业站.门户站都可以用他做,但是当我们的织梦程序网站在跟别人换友情链接的时候,我们奇怪的发现当 ...

  2. Snipaste截图工具如何修改默认的截图快捷键

    Snipaste截图工具可以在电脑上的"360软件管家"下载,可以通过下载安装包的方式执行安装. 安装包下载后进行解压操作,可以将文件夹下面的Snipaste应用程序在桌面创建快捷 ...

  3. springboot使用阿里云oss教程,oss使用+安全访问(防盗链、防盗刷、流量控制)

    文章目录 一.基本使用 ① 引入依赖 ② application.yml 添加访问oss需要的参数 ③ 编写oss工具类 ④ 编写controller ⑤ 访问文件? 安全使用 ①防止资源盗用--防盗 ...

  4. 基于NodeJS的HTTP server Plus 2:防盗链(referer)

    什么是 "盗链"? "盗链" 说白了就是利用别人网站的资源链接放在自己的站点,在未经允许的情况下去获取别人网站里面的图片或者视频等资源,导致资源所有者的网站的流 ...

  5. lighttpd 之防盗链

    为防止静态服务器上的静态资源被其网站盗用,现添加防盗链如下: ####referer ### 1 方法一,当图片来自非frank.com和frank.cn域名时,跳转到http://freehat.b ...

  6. 新建网站提升曝光率设置集合(边使用边更新)(包括:SEO优化,Robots设置,CDN加速,防盗链)

    目前处于边学习边记录的状态,将自己建站中遇到的问题记录下来,以供大家参考,最终效果可以访问我的主页进行查看:alvincr.com Table of Contents 1.1 SEO优化目的(搜索引擎 ...

  7. Ubuntu 编译 哔哩哔哩 IJKPlayer so库,并支持RTSP

    1. 环境与配置 1.1 系统版本 系统我这里使用的Ubuntu 18.04.4 LTS 1.2 更新软件源列表 sudo apt update 1.3 安装git sudo apt install ...

  8. Nginx盗链和防盗链

    目录 一.配置盗链 ①准备工作 ②配服务端192.168.58.58 ③配置盗链端192.168.58.58 Ⅰ配置地址映射 Ⅱ修改盗链端html ④在whindows里实验 Ⅰ修改windows h ...

  9. 防盗链Nginx设置图片防盗链

    切记,替换的图片地址要使用没有防盗链的网站图片,否则由于替换的图片其实也处于防盗链情况下,会造成仍旧无法显示设置的图片. 一.全站图片防盗链 在/usr/local/nginx/conf/nginx. ...

最新文章

  1. 『第12天』从ipc$ 连接失败讲起
  2. niginx高性能原因
  3. 李浩:无限节点的CDN架构演进
  4. 嵌入式linux+io+优化,嵌入式Linux系统内存优化使用方法研究
  5. 【题解】牛客小白月赛16(部分题,待补充……)
  6. [opencv] Unsupported depth of input image
  7. qt同时两个动画执行_Qt 动画应用
  8. unity 加载关卡_Unity手游实战:从0开始SLG——本地化篇(四)提取本地化元素
  9. 单商户商城系统功能拆解13—分类管理
  10. 大数据前端个人提升与团队规划
  11. 卡巴斯基变相提供一年免费服务
  12. 爬取人民日报_抓取人民日报
  13. CR渲染器全景图如何渲染颜色通道_Corona渲染器如何处理材质溢色?【渲云渲染】...
  14. gomarket服务器位置,V712双核版机型常见问题集解答.pdf
  15. 计算机专业网名英语翻译,英语网名大全带翻译【三篇】
  16. Vue Eslint语法检测工具
  17. conversion failed: could not load input document
  18. 安卓系统怎么模拟java_电脑上安装安卓系统模拟器的方法(直接用JAVA虚拟成手机)...
  19. Windows系统安装虚拟机以及Linux系统
  20. Python图像处理之透视变换

热门文章

  1. 评论一下现有几个开源IM框架(Msn/QQ/Fetion/Gtalk...)
  2. LES09 :编译器与Makefile
  3. python优雅代码大全_10个Python技巧帮你写出更优雅的代码
  4. Unity体积光实现
  5. Java开发入门与实战!java用数组输出杨辉三角
  6. 什么是计算机网络及主要功能有哪些?
  7. 威盾IIS防火墙升级到V3.7
  8. RK3288 Android 7.1 屏蔽“您的设备内部出现了问题。请联系您的设备制造商了解详情。”弹窗
  9. [战术] 1.20-1.21时代魔兽各族战术总结(写的肤浅,仅供参考)
  10. Ubuntu手机开发者创新大赛-西安站-6月3日 周三07:00-10:30 西安邮电大学长安校区东区fz118