Explorar o código

修复混淆后无法使用media插件的问题;
优化 视频剪切功能中的时间调整控件

zengjiebin %!s(int64=7) %!d(string=hai) anos
pai
achega
6cd913e47b

+ 3 - 0
app/build.gradle

@@ -424,6 +424,9 @@ dependencies {
     }
     implementation project(':media/share_library')
     implementation 'com.didi.virtualapk:core:0.9.8'
+    //fast json
+    implementation 'com.alibaba:fastjson:1.2.52'
+    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.34'
 }
 
 static def releaseTime() {

+ 5 - 1
app/proguard-rules.pro

@@ -470,4 +470,8 @@
 
  -dontwarn com.didi.virtualapk.**
  -dontwarn android.**
- -keep class android.** { *; }
+ -keep class android.** { *; }
+ #下面的库在host和media plugin中都有使用,混淆后在media中找不到类,暂时不混淆
+-keep class com.alibaba.fastjson.** { *; }
+-keep class com.chad.library.** { *; }
+-keep class com.bumptech.glide.** { *; }

+ 3 - 1
app/src/main/java/com/sheep/gamegroup/module/plugin/util/PluginUtil.java

@@ -50,7 +50,9 @@ public class PluginUtil {
                 String pluginPath = ClassFileHelper.DIR + "/media_release.apk";
 //                LogUtil.println(PluginUtil.class.getSimpleName(), "CPU_ABI =", cpuAbi, "pluginPath =", pluginPath);
                 File file = new File(pluginPath);
-                File pluginFile = TestUtil.isTest() && file.exists() ? file : getFile(plugin);
+                boolean isUserTestFile = TestUtil.isTest() && file.exists();
+                LogUtil.println("startPlugin", isUserTestFile);
+                File pluginFile = isUserTestFile ? file : getFile(plugin);
                 if(!pluginFile.exists()){
                     emitter.onError(new Throwable("更新数据中,请稍候"));
                     return;

+ 8 - 2
app/src/main/java/com/sheep/gamegroup/util/TestUtil.java

@@ -820,10 +820,16 @@ public class TestUtil {
             return;
         }
         OkHttpUtils.get().url(url).build().execute(new FileCallBack(DIR, name) {
+            private long time;
             @Override
             public void inProgress(float progress, long total, int id) {
-                if (action1 == null)
-                    G.showToast(String.format(Locale.CHINA, "%d%%", Math.round(progress * 100)));
+                if (action1 == null) {
+                    long newTime = System.currentTimeMillis();
+                    if(time == 0 || newTime - time > 1000) {
+                        time = newTime;
+                        G.showToast(String.format(Locale.CHINA, "%d%%", Math.round(progress * 100)));
+                    }
+                }
             }
 
             @Override

+ 0 - 1
app/src/main/java/com/sheep/gamegroup/view/fragment/FgtFootprint.java

@@ -74,7 +74,6 @@ public class FgtFootprint extends BaseListFragment4<UserFootprint> {
 
     @Override
     public void initView() {
-        per_page = 1;
         CustomMonthView.class.getSimpleName();
         CustomWeekView.class.getSimpleName();
         TitleBarUtils

+ 6 - 3
media/app/build.gradle

@@ -58,8 +58,8 @@ dependencies {
     testImplementation 'junit:junit:4.12'
     androidTestImplementation 'com.android.support.test:runner:1.0.2'
     androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
-    //显示图片视频帧,在插件中不兼容x86模拟器,所以不考虑
-//    implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever:1.0.14'
+    //显示图片视频帧,在插件中不兼容x86模拟器,所以x86不考虑
+    implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever:1.0.14'
     implementation project(':share_library')
     implementation("com.android.support:recyclerview-v7:$supportLibVersion")
     implementation 'com.android.support.constraint:constraint-layout:1.1.3'
@@ -74,7 +74,10 @@ dependencies {
 //        exclude group: 'com.github.bumptech.glide', module: 'disklrucache'
 //        exclude group: 'com.github.bumptech.glide', module: 'annotations'
     }
-    annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
+    annotationProcessor 'com.github.bumptech.glide:compiler:4.1.1'
+    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.34'
+    //fast json
+    implementation 'com.alibaba:fastjson:1.2.52'
 }
 
 

+ 132 - 110
media/app/src/main/java/com/kfzs/cfyl/media/customview/VideoFramesView.java

@@ -64,81 +64,108 @@ public class VideoFramesView extends RelativeLayout {
         recyclerView = findViewById(R.id.recyclerView);
         line_start = findViewById(R.id.line_start);
         line_end = findViewById(R.id.line_end);
-        line_start.setOnTouchListener(new OnTouchListener() {
-            private float lastEventX;
-
+        recyclerView.setOnTouchListener(new OnTouchListener() {
+            private View view;
+            private OnTouchListener onTouchListener;
             @SuppressLint("ClickableViewAccessibility")
             @Override
-            public boolean onTouch(View view, MotionEvent event) {
-                float maxX = line_end.getX();
-                float minX = maxX - (firstEndX - firstStartX);//结束位置 - 可以设置的长度
+            public boolean onTouch(View v, MotionEvent event) {
                 switch (event.getAction()) {
                     case MotionEvent.ACTION_DOWN:
-                        lastEventX = event.getX();
-                        break;
-                    case MotionEvent.ACTION_MOVE:
-                        float mx = Math.max(firstStartX, view.getX() + event.getX() - lastEventX);
-                        if (mx > maxX)
-                            mx = maxX;
-                        if (mx < minX) {
-                            maxX += mx - minX;
-                            line_end.setX(maxX);
-                            view.setX(mx);
+                        float x = event.getX();
+                        if(Math.abs(x - line_start.getX()) > Math.abs(x - line_end.getX())){
+                            view = line_end;
+                            onTouchListener = endOnTouchListener;
                         } else {
-                            view.setX(mx);
-                        }
-                        if (onTimeChangeListener != null) {
-                            onTimeChangeListener.call((maxX - mx) * video.getDuration() / (rvW - lineW));
+                            view = line_start;
+                            onTouchListener = startOnTouchListener;
                         }
                         break;
-                    case MotionEvent.ACTION_UP:
-                        break;
-                    case MotionEvent.ACTION_CANCEL:
-                        break;
                 }
-                view.invalidate();
-                return true;
-            }
-        });
-        line_end.setOnTouchListener(new OnTouchListener() {
-            private float lastEventX;
-
-            @SuppressLint("ClickableViewAccessibility")
-            @Override
-            public boolean onTouch(View view, MotionEvent event) {
-                float minX = line_start.getX();
-                float maxX = firstEndX - firstStartX + minX;
-                float endX = firstStartX + rvW - lineW;
-                switch (event.getAction()) {
-                    case MotionEvent.ACTION_DOWN:
-                        lastEventX = event.getX();
-                        break;
-                    case MotionEvent.ACTION_MOVE:
-                        float mx = Math.min(view.getX() + event.getX() - lastEventX, endX);
-                        if (mx < minX)
-                            mx = minX;
-                        if (mx > maxX) {
-                            minX += mx - maxX;
-                            line_start.setX(minX);
-                            view.setX(mx);
-                        } else {
-                            view.setX(mx);
-                        }
-                        if (onTimeChangeListener != null) {
-                            onTimeChangeListener.call((mx - minX) * video.getDuration() / (rvW - lineW));
-                        }
-                        break;
-                    case MotionEvent.ACTION_UP:
-                        break;
-                    case MotionEvent.ACTION_CANCEL:
-                        break;
+                if(view != null){
+                    MotionEvent motionEvent = MotionEvent.obtain(event.getDownTime(), event.getEventTime(), event.getAction(), event.getX() - view.getX(), event.getY(),event.getMetaState());
+                    return onTouchListener.onTouch(view, motionEvent);
                 }
-                view.invalidate();
-                return true;
+                return false;
             }
         });
+        line_start.setOnTouchListener(startOnTouchListener);
+        line_end.setOnTouchListener(endOnTouchListener);
     }
 
+    private OnTouchListener endOnTouchListener = new OnTouchListener() {
+        private float lastEventX;
+
+        @SuppressLint("ClickableViewAccessibility")
+        @Override
+        public boolean onTouch(View view, MotionEvent event) {
+            float minX = line_start.getX();
+            float maxX = firstEndX - firstStartX + minX;
+            float endX = firstStartX + rvW - lineW;
+            switch (event.getAction()) {
+                case MotionEvent.ACTION_DOWN:
+                    lastEventX = event.getX();
+                    break;
+                case MotionEvent.ACTION_MOVE:
+                    float mx = Math.min(view.getX() + event.getX() - lastEventX, endX);
+                    if (mx < minX)
+                        mx = minX;
+                    if (mx > maxX) {
+                        minX += mx - maxX;
+                        line_start.setX(minX);
+                        view.setX(mx);
+                    } else {
+                        view.setX(mx);
+                    }
+                    if (onTimeChangeListener != null) {
+                        onTimeChangeListener.call((mx - minX) * video.getDuration() / (rvW - lineW));
+                    }
+                    break;
+                case MotionEvent.ACTION_UP:
+                    break;
+                case MotionEvent.ACTION_CANCEL:
+                    break;
+            }
+            view.invalidate();
+            return true;
+        }
+    };
+    private OnTouchListener startOnTouchListener = new OnTouchListener() {
+        private float lastEventX;
+
+        @SuppressLint("ClickableViewAccessibility")
+        @Override
+        public boolean onTouch(View view, MotionEvent event) {
+            float maxX = line_end.getX();
+            float minX = maxX - (firstEndX - firstStartX);//结束位置 - 可以设置的长度
+            switch (event.getAction()) {
+                case MotionEvent.ACTION_DOWN:
+                    lastEventX = event.getX();
+                    break;
+                case MotionEvent.ACTION_MOVE:
+                    float mx = Math.max(firstStartX, view.getX() + event.getX() - lastEventX);
+                    if (mx > maxX)
+                        mx = maxX;
+                    if (mx < minX) {
+                        maxX += mx - minX;
+                        line_end.setX(maxX);
+                        view.setX(mx);
+                    } else {
+                        view.setX(mx);
+                    }
+                    if (onTimeChangeListener != null) {
+                        onTimeChangeListener.call((maxX - mx) * video.getDuration() / (rvW - lineW));
+                    }
+                    break;
+                case MotionEvent.ACTION_UP:
+                    break;
+                case MotionEvent.ACTION_CANCEL:
+                    break;
+            }
+            view.invalidate();
+            return true;
+        }
+    };
     //开头线的进度
     public float getStartPercent() {
         if (line_start != null && recyclerView != null) {
@@ -284,7 +311,7 @@ public class VideoFramesView extends RelativeLayout {
     /**
      * 显示视频帧图片列表
      */
-    public VideoFramesView showVideoList(final Activity activity) {
+    public VideoFramesView showVideoList1(final Activity activity) {
         List<VideoFrame> videoFrameList = new ArrayList<>();
         final int size = 10;
         long duration = video.getDuration();
@@ -306,7 +333,48 @@ public class VideoFramesView extends RelativeLayout {
             protected void convert(BaseViewHolder helper, VideoFrame item) {
                 ImageView imageView = helper.getView(R.id.item_iv);
                 Glide.with(activity.getApplicationContext()).load(item.getVideoPath())
-                        .apply(RequestOptions.frameOf(item.getAtTime()).set(VideoBitmapDecoder.FRAME_OPTION, MediaMetadataRetriever.OPTION_CLOSEST).transform(new VideoFrameTransform(item)))
+                        .apply(RequestOptions.frameOf(item.getAtTime()).set(VideoBitmapDecoder.FRAME_OPTION, MediaMetadataRetriever.OPTION_CLOSEST).transform(new VideoFrameTransform(item, false)))
+                        .into(imageView);
+            }
+        };
+        recyclerView.setAdapter(baseQuickAdapter);
+
+        return this;
+    }
+    /**
+     * 显示视频帧图片列表
+     */
+    public VideoFramesView showVideoList(final Activity activity) {
+        if(TextUtils.equals(android.os.Build.CPU_ABI, "x86")) {//x86不兼容,不能在模拟器中连续调用FFmpegMediaMetadataRetriever
+            return showVideoList1(activity);
+        } else {
+            return showVideoList2(activity);
+        }
+    }
+    /**
+     * 显示视频帧图片列表
+     */
+    public VideoFramesView showVideoList2(final Activity activity) {
+        List<VideoFrame> videoFrameList = new ArrayList<>();
+        final int size = 10;
+        long duration = video.getDuration();
+        final long per = duration * 1000L / (size -1);
+        String path = video.getFilePath();
+
+        for (int i = 0; i < size; i++) {
+            long atTime = i + 1 == size ? (duration / 1000L * 1000_000L - per / 5) : i * per;
+//            LogUtil.println(VideoFramesView.class.getSimpleName(), "showVideoList2", duration, i, per, atTime);
+            videoFrameList.add(new VideoFrame().setVideoPath(path).setAtTime(atTime)
+                    .setWidth(video.getWidth()).setHeight(video.getHeight())
+            );
+        }
+        recyclerView.setLayoutManager(new GridLayoutManager(activity.getApplicationContext(), size));
+        BaseQuickAdapter<VideoFrame, BaseViewHolder> baseQuickAdapter = new BaseQuickAdapter<VideoFrame, BaseViewHolder>(R.layout.item_iv_mh, videoFrameList) {
+            @Override
+            protected void convert(BaseViewHolder helper, VideoFrame item) {
+                ImageView imageView = helper.getView(R.id.item_iv);
+                Glide.with(activity.getApplicationContext()).load(R.drawable.qiandao)
+                        .apply(new RequestOptions().transform(new VideoFrameTransform(item)))
                         .into(imageView);
             }
         };
@@ -314,52 +382,6 @@ public class VideoFramesView extends RelativeLayout {
 
         return this;
     }
-//    /**
-//     * 显示视频帧图片列表
-//     */
-//    public VideoFramesView showVideoList(final Activity activity) {
-//        if(TextUtils.equals(android.os.Build.CPU_ABI, "x86")) {//x86不兼容,不能在模拟器中连续调用FFmpegMediaMetadataRetriever
-//            return showVideoList1(activity);
-//        } else {
-//            return showVideoList2(activity);
-//        }
-//    }
-//    /**
-//     * 显示视频帧图片列表
-//     */
-//    public VideoFramesView showVideoList2(final Activity activity) {
-//        List<VideoFrame> videoFrameList = new ArrayList<>();
-//        final int size = 10;
-//        long duration = video.getDuration();
-//        final long per = duration * 1000L / size;
-//        int max = 20;
-//        int width = max, height = max;
-//        if (video.getWidth() > video.getHeight()) {
-//            width = max * video.getWidth() / video.getHeight();
-//        } else {
-//            height = max * video.getHeight() / video.getWidth();
-//        }
-//        String path = video.getFilePath();
-//        for (int i = 0; i < size; i++) {
-//            videoFrameList.add(new VideoFrame().setVideoPath(path).setAtTime(i * per)
-//                    .setWidth(width).setHeight(height)
-//                    .setWidth(video.getWidth()).setHeight(video.getHeight())
-//            );
-//        }
-//        recyclerView.setLayoutManager(new GridLayoutManager(activity.getApplicationContext(), size));
-//        BaseQuickAdapter<VideoFrame, BaseViewHolder> baseQuickAdapter = new BaseQuickAdapter<VideoFrame, BaseViewHolder>(R.layout.item_iv_mh, videoFrameList) {
-//            @Override
-//            protected void convert(BaseViewHolder helper, VideoFrame item) {
-//                ImageView imageView = helper.getView(R.id.item_iv);
-//                Glide.with(activity.getApplicationContext()).load(R.drawable.qiandao)
-//                        .apply(new RequestOptions().transform(new VideoFrameTransform(item)))
-//                        .into(imageView);
-//            }
-//        };
-//        recyclerView.setAdapter(baseQuickAdapter);
-//
-//        return this;
-//    }
 
     private Action1<Float> onTimeChangeListener;
 

+ 22 - 9
media/app/src/main/java/com/kfzs/cfyl/media/glide/VideoFrameTransform.java

@@ -6,6 +6,8 @@ import android.support.annotation.NonNull;
 import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
 import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
 import com.kfzs.cfyl.media.bean.VideoFrame;
+import com.kfzs.cfyl.media.util.VideoUtil;
+import com.kfzs.cfyl.share_library.util.LogUtil;
 
 import java.security.MessageDigest;
 import java.util.Locale;
@@ -17,23 +19,34 @@ import java.util.Locale;
 public class VideoFrameTransform extends BitmapTransformation {
 
     private VideoFrame videoFrame;
-//    private boolean isTransform = true;
+    private boolean isTransform = true;
 
     public VideoFrameTransform(VideoFrame videoFrame) {
         super();
         this.videoFrame = videoFrame;
     }
-//    public VideoFrameTransform(VideoFrame videoFrame, boolean isTransform) {
-//        super();
-//        this.videoFrame = videoFrame;
-//        this.isTransform = isTransform;
-//    }
+    public VideoFrameTransform(VideoFrame videoFrame, boolean isTransform) {
+        super();
+        this.videoFrame = videoFrame;
+        this.isTransform = isTransform;
+    }
 
     @Override
     protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
-//        if(isTransform) {
-//            return VideoUtil.getVideoFrameBitmap(videoFrame);
-//        }
+        if(isTransform) {
+            if(videoFrame.getWidth() > 100 || videoFrame.getHeight() > 100){
+                int width = 100;
+                int height = 100;
+                if(videoFrame.getWidth() > videoFrame.getHeight()){
+                    width = videoFrame.getWidth() * 100 / videoFrame.getHeight();
+                } else {
+                    height = videoFrame.getHeight() * 100 / videoFrame.getWidth();
+                }
+                return VideoUtil.getScaledFrameAtTime(videoFrame.setWidth(width).setHeight(height));
+            } else {
+                return VideoUtil.getFrameAtTime(videoFrame);
+            }
+        }
         return toTransform;
     }
 

+ 39 - 18
media/app/src/main/java/com/kfzs/cfyl/media/util/VideoUtil.java

@@ -8,6 +8,7 @@ import android.media.MediaMuxer;
 import android.util.Log;
 
 import com.kfzs.cfyl.media.bean.VideoFrame;
+import com.kfzs.cfyl.media.customview.VideoFramesView;
 import com.kfzs.cfyl.share_library.util.LogUtil;
 import com.sheep.gamegroup.model.entity.Video;
 
@@ -15,7 +16,7 @@ import java.nio.ByteBuffer;
 import java.util.Locale;
 
 import rx.functions.Action1;
-//import wseemann.media.FFmpegMediaMetadataRetriever;
+import wseemann.media.FFmpegMediaMetadataRetriever;
 
 /**
  * Created by realicing on 2018/12/6.
@@ -23,23 +24,43 @@ import rx.functions.Action1;
  */
 public class VideoUtil {
 
-//    public static Bitmap getVideoFrameBitmap(VideoFrame videoFrame) {
-//        long time = System.currentTimeMillis();
-//        long durationTime = time;
-//        FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
-//        try {
-//            mmr.setDataSource(videoFrame.getVideoPath());
-//            durationTime = System.currentTimeMillis();
-//            return mmr.getScaledFrameAtTime(videoFrame.getAtTime(), FFmpegMediaMetadataRetriever.OPTION_CLOSEST, videoFrame.getWidth(), videoFrame.getHeight());
-//        } catch (Exception e) {
-//            e.printStackTrace();
-//            Log.i("videoUtil", (System.currentTimeMillis() - time) + "\t"+ (durationTime - time) + "\t" + e.getMessage());
-//        } finally {
-//            mmr.release();
-//            Log.i("videoUtil", (System.currentTimeMillis() - time) + "\t" + (durationTime - time) + "\t 成功");
-//        }
-//        return null;
-//    }
+    public static Bitmap getScaledFrameAtTime(VideoFrame videoFrame) {
+        long time = System.currentTimeMillis();
+        long durationTime = time;
+        FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
+        try {
+            mmr.setDataSource(videoFrame.getVideoPath());
+            durationTime = System.currentTimeMillis();
+//            LogUtil.println(VideoFramesView.class.getSimpleName(), "getScaledFrameAtTime", videoFrame.getWidth(), videoFrame.getHeight(), videoFrame.getAtTime());
+            return mmr.getScaledFrameAtTime(videoFrame.getAtTime(), FFmpegMediaMetadataRetriever.OPTION_CLOSEST, videoFrame.getWidth(), videoFrame.getHeight());
+        } catch (Exception e) {
+            e.printStackTrace();
+            Log.i("videoUtil", (System.currentTimeMillis() - time) + "\t"+ (durationTime - time) + "\t" + e.getMessage());
+        } finally {
+            mmr.release();
+            Log.i("videoUtil", (System.currentTimeMillis() - time) + "\t" + (durationTime - time) + "\t 成功");
+        }
+        return null;
+    }
+    public static Bitmap getFrameAtTime(VideoFrame videoFrame) {
+        long time = System.currentTimeMillis();
+        long durationTime = time;
+        FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
+        try {
+            mmr.setDataSource(videoFrame.getVideoPath());
+//            long duration = Long.parseLong(mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_DURATION));
+//            LogUtil.println(VideoFramesView.class.getSimpleName(), "getFrameAtTime", duration, videoFrame.getAtTime());
+            durationTime = System.currentTimeMillis();
+            return mmr.getFrameAtTime(videoFrame.getAtTime(), FFmpegMediaMetadataRetriever.OPTION_CLOSEST);
+        } catch (Exception e) {
+            e.printStackTrace();
+            Log.i("videoUtil", (System.currentTimeMillis() - time) + "\t"+ (durationTime - time) + "\t" + e.getMessage());
+        } finally {
+            mmr.release();
+            Log.i("videoUtil", (System.currentTimeMillis() - time) + "\t" + (durationTime - time) + "\t 成功");
+        }
+        return null;
+    }
 //    public synchronized static Bitmap getVideoFrameBitmap2(VideoFrame videoFrame) {
 //        long time = System.currentTimeMillis();
 //        long durationTime = time;

+ 1 - 2
media/share_library/build.gradle

@@ -24,6 +24,5 @@ android {
 
 dependencies {
     //fast json
-    api 'com.alibaba:fastjson:1.2.52'
-    api 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.34'
+    compileOnly 'com.alibaba:fastjson:1.2.52'
 }