android ijkplayer添加防盗链refer,截图,支持rtsp,修改底层增加截图功能,以及ijk播放的部分问题
一:使用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播放的部分问题相关推荐
- 织梦后台添加友链,前台不显示|修改友情链接的显示行数
在我们建设网站的过程中有一个程序是我们经常用到的,那就是织梦CMS信息管理系统,这是一个很强大的开源程序,企业站.门户站都可以用他做,但是当我们的织梦程序网站在跟别人换友情链接的时候,我们奇怪的发现当 ...
- Snipaste截图工具如何修改默认的截图快捷键
Snipaste截图工具可以在电脑上的"360软件管家"下载,可以通过下载安装包的方式执行安装. 安装包下载后进行解压操作,可以将文件夹下面的Snipaste应用程序在桌面创建快捷 ...
- springboot使用阿里云oss教程,oss使用+安全访问(防盗链、防盗刷、流量控制)
文章目录 一.基本使用 ① 引入依赖 ② application.yml 添加访问oss需要的参数 ③ 编写oss工具类 ④ 编写controller ⑤ 访问文件? 安全使用 ①防止资源盗用--防盗 ...
- 基于NodeJS的HTTP server Plus 2:防盗链(referer)
什么是 "盗链"? "盗链" 说白了就是利用别人网站的资源链接放在自己的站点,在未经允许的情况下去获取别人网站里面的图片或者视频等资源,导致资源所有者的网站的流 ...
- lighttpd 之防盗链
为防止静态服务器上的静态资源被其网站盗用,现添加防盗链如下: ####referer ### 1 方法一,当图片来自非frank.com和frank.cn域名时,跳转到http://freehat.b ...
- 新建网站提升曝光率设置集合(边使用边更新)(包括:SEO优化,Robots设置,CDN加速,防盗链)
目前处于边学习边记录的状态,将自己建站中遇到的问题记录下来,以供大家参考,最终效果可以访问我的主页进行查看:alvincr.com Table of Contents 1.1 SEO优化目的(搜索引擎 ...
- Ubuntu 编译 哔哩哔哩 IJKPlayer so库,并支持RTSP
1. 环境与配置 1.1 系统版本 系统我这里使用的Ubuntu 18.04.4 LTS 1.2 更新软件源列表 sudo apt update 1.3 安装git sudo apt install ...
- Nginx盗链和防盗链
目录 一.配置盗链 ①准备工作 ②配服务端192.168.58.58 ③配置盗链端192.168.58.58 Ⅰ配置地址映射 Ⅱ修改盗链端html ④在whindows里实验 Ⅰ修改windows h ...
- 防盗链Nginx设置图片防盗链
切记,替换的图片地址要使用没有防盗链的网站图片,否则由于替换的图片其实也处于防盗链情况下,会造成仍旧无法显示设置的图片. 一.全站图片防盗链 在/usr/local/nginx/conf/nginx. ...
最新文章
- 『第12天』从ipc$ 连接失败讲起
- niginx高性能原因
- 李浩:无限节点的CDN架构演进
- 嵌入式linux+io+优化,嵌入式Linux系统内存优化使用方法研究
- 【题解】牛客小白月赛16(部分题,待补充……)
- [opencv] Unsupported depth of input image
- qt同时两个动画执行_Qt 动画应用
- unity 加载关卡_Unity手游实战:从0开始SLG——本地化篇(四)提取本地化元素
- 单商户商城系统功能拆解13—分类管理
- 大数据前端个人提升与团队规划
- 卡巴斯基变相提供一年免费服务
- 爬取人民日报_抓取人民日报
- CR渲染器全景图如何渲染颜色通道_Corona渲染器如何处理材质溢色?【渲云渲染】...
- gomarket服务器位置,V712双核版机型常见问题集解答.pdf
- 计算机专业网名英语翻译,英语网名大全带翻译【三篇】
- Vue Eslint语法检测工具
- conversion failed: could not load input document
- 安卓系统怎么模拟java_电脑上安装安卓系统模拟器的方法(直接用JAVA虚拟成手机)...
- Windows系统安装虚拟机以及Linux系统
- Python图像处理之透视变换
热门文章
- 评论一下现有几个开源IM框架(Msn/QQ/Fetion/Gtalk...)
- LES09 :编译器与Makefile
- python优雅代码大全_10个Python技巧帮你写出更优雅的代码
- Unity体积光实现
- Java开发入门与实战!java用数组输出杨辉三角
- 什么是计算机网络及主要功能有哪些?
- 威盾IIS防火墙升级到V3.7
- RK3288 Android 7.1 屏蔽“您的设备内部出现了问题。请联系您的设备制造商了解详情。”弹窗
- [战术] 1.20-1.21时代魔兽各族战术总结(写的肤浅,仅供参考)
- Ubuntu手机开发者创新大赛-西安站-6月3日 周三07:00-10:30 西安邮电大学长安校区东区fz118