前提条件:
在pc上播放网络视频的时候,有一个视频预览,当鼠标移动到某个点的时候,会显示当前视频帧的图片,在Android设备上,安装第三方网络应用,通过自己写的apk来进行视频预览,因为受限于网络抽帧等限制,暂时只能抽取某几个时间点的帧进行预览:
步骤:
1、首先写一个广播来接受按键显示视频预览,悬浮在视频apk的上面,界面必须是透明的,不然会影响视频的播放,广播来接受按键或者当视频启动的时候接受从am发送过来的广播; if(action.equals("TV_LongPressDownKey")){
Log.d(TAG, "videopreivew onkey");
Intent in = new Intent(context, VideoPreviewService.class);
in.putExtra("cmd", "onkey");
ComponentName cn = context.startService(in);
Log.d(TAG, "cn-----" + cn.getPackageName());
Log.d(TAG, "videopreivew start service");
}
if(action.equals("com.changhong.online.videopreview.start")){
Log.d(TAG, "videopreivew start");
Intent in = new Intent(context, VideoPreviewService.class);
in.putExtra("cmd", "start");
ComponentName cn = context.startService(in);
Log.d(TAG, "cn-----" + cn.getPackageName());
Log.d(TAG, "videopreivew start service online");
}
通过广播启动service,第一次启动service的时候,会执行service的oncreate方法,再执行onstart方法,后面的启动service都是只执行onstart方法,可以通过在onstart方法里面接受Intent来获取传递的值,如果中间service停止运行,会再次启动,public void onStart(Intent intent, int startId) ,这个intent可能为空,需要加上判断;
2.通过jni调用来获取底层的mediaplayer的接口,获取当前时间,总时长,已经到了某个点seekto();totalTime = jniGetDuration();
currentTime = jniGetCurrentPosition();
url = jniGetUrl();
int resolution = jniGetResolution();
static {
System.loadLibrary("playercontrol");
}
public native int jniSeekTo(int msec);
public native int jniGetDuration();
public native int jniGetCurrentPosition();
3.通过ffmpeg来抽帧:
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
Map<String, String> headers = new HashMap<String, String>();
headers.put("X-tv-Retriever-Player", "USE_FFMPEG");
retriever.setDataSource(url, headers);
new MyTask().execute(url);
class MyTask extends AsyncTask<String, Void, ArrayList<Bitmap>> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected ArrayList<Bitmap> doInBackground(String... params) {
Log.d(TAG, "AsyncTask ------");
FileOutputStream fos = null;
try {
bm1 = retriever.getFrameAtTime(totalTime / 6 * 1000L);
fos = new FileOutputStream(previewImageOne);
bm1.compress(CompressFormat.JPEG, 80, fos);
fos.close();
bm2 = retriever.getFrameAtTime(2 * totalTime / 6 * 1000L);
fos = new FileOutputStream(previewImageTwo);
bm2.compress(CompressFormat.JPEG, 80, fos);
fos.close();
bm3 = retriever.getFrameAtTime(3 * totalTime / 6 * 1000L);
fos = new FileOutputStream(previewImageThree);
bm3.compress(CompressFormat.JPEG, 80, fos);
fos.close();
bm4 = retriever.getFrameAtTime(4 * totalTime / 6 * 1000L);
fos = new FileOutputStream(previewImageFour);
bm4.compress(CompressFormat.JPEG, 80, fos);
fos.close();
bm5 = retriever.getFrameAtTime(5 * totalTime / 6 * 1000L);
fos = new FileOutputStream(previewImageFive);
bm5.compress(CompressFormat.JPEG, 80, fos);
fos.close();
Log.d(TAG, "AsyncTask ---doInBackground end ---");
mHandler.sendEmptyMessage(SHOW_IMAGE);
} catch (Exception e) {
e.printStackTrace();
}
return bmList;
}
@Override
protected void onPostExecute(ArrayList<Bitmap> result) {
super.onPostExecute(result);
}
}
4.在WindowManager上显示图片
WindowManager mWM = (WindowManager) mcontext.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams mLP = new WindowManager.LayoutParams();
mLP.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
mLP.width = WindowManager.LayoutParams.MATCH_PARENT;
mLP.height = WindowManager.LayoutParams.MATCH_PARENT;
mLP.format = PixelFormat.RGBA_8888;
mLP.dimAmount = 0;
mLP.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
mWM.addView(mVpView, mLP);