Procházet zdrojové kódy

涂鸦功能简单完成

zengjiebin před 7 roky
rodič
revize
f0fbc29234

+ 0 - 1
app/build.gradle

@@ -428,7 +428,6 @@ dependencies {
     implementation 'com.alibaba:fastjson:1.2.52'
     implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.34'
 //    implementation 'com.github.yangjie10930:EpMedia:v0.9.5'
-    implementation project(':joevideolib')
 }
 
 static def releaseTime() {

+ 4 - 4
app/src/main/java/com/sheep/gamegroup/view/activity/MiddleSchemeAct.java

@@ -74,7 +74,7 @@ public class MiddleSchemeAct extends Activity {
             default://尝试获取game_id
                 tryGoSplashAct(uri);
                 break;
-            //sheep://small.kfzs.com/sheep?type=jhl&data={"Jump":"1"}
+            //sheep://small.kfzs.com/xmy?type=jhl&data={"Jump":"1"}
             case "jump_home_list"://跳转homeList
             case "jhl":
                 try {
@@ -86,7 +86,7 @@ public class MiddleSchemeAct extends Activity {
                         G.showToast(e.getMessage());
                 }
                 break;
-            //sheep://small.kfzs.com/sheep?type=jum&data={"jump":1}
+            //sheep://small.kfzs.com/xmy?type=jum&data={"jump":1}
             case "jump_user_module"://跳转个人中心列表功能模块
             case "jum":
                 try {
@@ -98,7 +98,7 @@ public class MiddleSchemeAct extends Activity {
                         G.showToast(e.getMessage());
                 }
                 break;
-            //sheep://small.kfzs.com/sheep?type=jss&data={"Type":1}
+            //sheep://small.kfzs.com/xmy?type=jss&data={"Type":1}
             case "jump_slide_show"://跳转banner(主页banner或者游戏banner)
             case "jss":
                 try {
@@ -110,7 +110,7 @@ public class MiddleSchemeAct extends Activity {
                         G.showToast(e.getMessage());
                 }
                 break;
-            //sheep://small.kfzs.com/sheep?type=run_app&packageName=com.realicing.android.upgrade.sheep&className=com.realicing.android.upgrade.sheep.MainActivity
+            //sheep://small.kfzs.com/xmy?type=run_app&packageName=com.realicing.android.upgrade.sheep&className=com.realicing.android.upgrade.sheep.MainActivity
             case "run_app":
             case "run":
                 String packageName = uri.getQueryParameter("packageName");

+ 2 - 0
joevideolib/proguard-rules.pro

@@ -24,3 +24,5 @@
 #保留注解,如果不添加改行会导致我们的@Keep注解失效
 -keepattributes *Annotation*
 -keep @android.support.annotation.Keep class **
+-keep class Jni.** { *; }
+-keep class VideoHandle.** { *; }

+ 4 - 2
media/app/src/main/AndroidManifest.xml

@@ -104,9 +104,11 @@
         </activity>
         <activity android:name=".activity.ActCutVideo"
             android:theme="@style/media_AppTheme"
-            android:screenOrientation="portrait"/>
+            android:configChanges="orientation|keyboardHidden|navigation|screenSize"
+            android:screenOrientation="sensor"/>
         <activity android:name=".activity.ActEditVideo"
             android:theme="@style/media_AppTheme"
-            android:screenOrientation="portrait"/>
+            android:configChanges="orientation|keyboardHidden|navigation|screenSize"
+            android:screenOrientation="sensor"/>
     </application>
 </manifest>

+ 1 - 1
media/app/src/main/java/com/kfzs/cfyl/media/BaseListFgtActivity.java

@@ -65,7 +65,7 @@ public abstract class BaseListFgtActivity extends BaseActivity {
                 onHideFragment(fragment, index);
             }
             if(fragment instanceof BaseListFgtFgt){
-                ((BaseListFgtFgt) fragment).initFragments(getSupportFragmentManager(), getFgtTagByPosition(index), index);
+                ((BaseListFgtFgt) fragment).initFragments(this, getFgtTagByPosition(index), index);
             }
             index++;
         }

+ 31 - 22
media/app/src/main/java/com/kfzs/cfyl/media/BaseListFgtFgt.java

@@ -29,11 +29,12 @@ public abstract class BaseListFgtFgt extends BaseFragment {
     private String curTag;
     private int backFgtPosition;
     //初始化并加载fgt列表
-    public void initFragments(FragmentManager fragmentManager, String backTag, int backFgtPosition) {
+    public void initFragments(BaseListFgtActivity baseListFgtActivity, String backTag, int backFgtPosition) {
         this.curTag = backTag;
         this.backFgtPosition = backFgtPosition;
         List<FgtCreater> fgtCreaterList = getFgtCreaterList();
         fgtCount = fgtCreaterList.size();
+        FragmentManager fragmentManager = baseListFgtActivity.getSupportFragmentManager();
         if (fragmentManager != null) {
             FragmentTransaction transaction = fragmentManager.beginTransaction();
             int index = 0;
@@ -42,12 +43,12 @@ public abstract class BaseListFgtFgt extends BaseFragment {
                 Fragment fragment = fragmentManager.findFragmentByTag(tag);
                 if (fragment == null) {
                     fragment = item.newInstance();
-                    onInitFragment(fragment, index);
+                    onInitFragment(baseListFgtActivity, fragment, index);
                 }
                 transaction.add(R.id.media_frame_container, fragment, tag);
-                onBeforeHideFragment(fragment, index);
+                onBeforeHideFragment(baseListFgtActivity, fragment, index);
                 transaction.hide(fragment);
-                onHideFragment(fragment, index);
+                onHideFragment(baseListFgtActivity, fragment, index);
                 index++;
             }
             transaction.commitAllowingStateLoss();
@@ -104,18 +105,22 @@ public abstract class BaseListFgtFgt extends BaseFragment {
     public boolean back() {
         if(curTag != null){
             if (getSupportFragmentManager() != null) {
+                BaseListFgtActivity baseListFgtActivity = null;
+                if(getActivity() instanceof BaseListFgtActivity){
+                    baseListFgtActivity = (BaseListFgtActivity) getActivity();
+                }
                 FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                 Fragment cFragment = getSupportFragmentManager().findFragmentByTag(curTag);
                 Fragment lFragment = getFgtByPosition(lastPosition);
                 if (lFragment != null) {
-                    onBeforeHideFragment(lFragment, lastPosition);
+                    onBeforeHideFragment(baseListFgtActivity, lFragment, lastPosition);
                     transaction.hide(lFragment);
-                    onHideFragment(lFragment, lastPosition);
+                    onHideFragment(baseListFgtActivity, lFragment, lastPosition);
                 }
                 if (cFragment != null) {
-                    onBeforeShowFragment(cFragment, backFgtPosition);
+                    onBeforeShowFragment(baseListFgtActivity, cFragment, backFgtPosition);
                     transaction.show(cFragment);
-                    onShowFragment(cFragment, backFgtPosition);
+                    onShowFragment(baseListFgtActivity, cFragment, backFgtPosition);
                 }
                 transaction.commitAllowingStateLoss();
                 if (lFragment != null)
@@ -132,18 +137,22 @@ public abstract class BaseListFgtFgt extends BaseFragment {
     public void switchFgt(int position) {
         if (lastPosition != position) {
             if (getSupportFragmentManager() != null) {
+                BaseListFgtActivity baseListFgtActivity = null;
+                if(getActivity() instanceof BaseListFgtActivity){
+                    baseListFgtActivity = (BaseListFgtActivity) getActivity();
+                }
                 FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                 Fragment cFragment = getFgtByPosition(position);
                 Fragment lFragment = getFgtByPosition(lastPosition);
                 if (lFragment != null) {
-                    onBeforeHideFragment(lFragment, lastPosition);
+                    onBeforeHideFragment(baseListFgtActivity, lFragment, lastPosition);
                     transaction.hide(lFragment);
-                    onHideFragment(lFragment, lastPosition);
+                    onHideFragment(baseListFgtActivity, lFragment, lastPosition);
                 }
                 if (cFragment != null) {
-                    onBeforeShowFragment(cFragment, position);
+                    onBeforeShowFragment(baseListFgtActivity, cFragment, position);
                     transaction.show(cFragment);
-                    onShowFragment(cFragment, position);
+                    onShowFragment(baseListFgtActivity, cFragment, position);
                 }
                 transaction.commitAllowingStateLoss();
                 if (lFragment != null)
@@ -172,27 +181,27 @@ public abstract class BaseListFgtFgt extends BaseFragment {
     }
 
     //初始化fragment时
-    protected void onInitFragment(Fragment fragment, int position) {
-
+    protected void onInitFragment(BaseListFgtActivity baseListFgtActivity, Fragment fragment, int position) {
+        baseListFgtActivity.onInitFragment(fragment, position);
     }
 
     //显示fgt前
-    protected void onBeforeShowFragment(Fragment fragment, int position) {
-
+    protected void onBeforeShowFragment(BaseListFgtActivity baseListFgtActivity, Fragment fragment, int position) {
+        baseListFgtActivity.onBeforeShowFragment(fragment, position);
     }
 
     //显示fgt后
-    protected void onShowFragment(Fragment fragment, int position) {
-
+    protected void onShowFragment(BaseListFgtActivity baseListFgtActivity, Fragment fragment, int position) {
+        baseListFgtActivity.onShowFragment(fragment, position);
     }
 
     //隐藏fgt前
-    protected void onBeforeHideFragment(Fragment fragment, int position) {
-
+    protected void onBeforeHideFragment(BaseListFgtActivity baseListFgtActivity, Fragment fragment, int position) {
+        baseListFgtActivity.onBeforeHideFragment(fragment, position);
     }
 
     //隐藏fgt后
-    protected void onHideFragment(Fragment fragment, int position) {
-
+    protected void onHideFragment(BaseListFgtActivity baseListFgtActivity, Fragment fragment, int position) {
+        baseListFgtActivity.onHideFragment(fragment, position);
     }
 }

+ 4 - 0
media/app/src/main/java/com/kfzs/cfyl/media/activity/ActCutVideo.java

@@ -15,6 +15,7 @@ import com.kfzs.cfyl.media.api.FgtCreater;
 import com.kfzs.cfyl.media.api.IdChooser;
 import com.kfzs.cfyl.media.bean.EditVideoType;
 import com.kfzs.cfyl.media.fragment.FgtDiscoveryTopic;
+import com.kfzs.cfyl.media.fragment.FgtDoodle;
 import com.kfzs.cfyl.media.fragment.FgtEditVideoTypeList;
 import com.kfzs.cfyl.media.fragment.FgtVideoFrameList;
 import com.kfzs.cfyl.media.util.G;
@@ -101,6 +102,9 @@ public class ActCutVideo extends BaseListFgtActivity implements IdChooser {
         if (fragment instanceof FgtVideoFrameList) {
             if(data != null)
                 ((FgtVideoFrameList) fragment).tryCheckDuration();
+        } else if(fragment instanceof FgtDoodle){
+            if(data != null)
+                ((FgtDoodle) fragment).loadData(data);
         }
     }
 

+ 38 - 9
media/app/src/main/java/com/kfzs/cfyl/media/activity/ActEditVideo.java

@@ -1,5 +1,6 @@
 package com.kfzs.cfyl.media.activity;
 
+import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -9,6 +10,7 @@ import android.support.v4.app.Fragment;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.SeekBar;
 
@@ -20,6 +22,7 @@ import com.kfzs.cfyl.media.api.Levelble;
 import com.kfzs.cfyl.media.bean.BeautifyFilter;
 import com.kfzs.cfyl.media.bean.Size;
 import com.kfzs.cfyl.media.fragment.FgtChooseEditList;
+import com.kfzs.cfyl.media.fragment.FgtDoodle;
 import com.kfzs.cfyl.media.util.BitmapUtil;
 import com.kfzs.cfyl.media.util.G;
 import com.kfzs.cfyl.media.util.ViewUtil;
@@ -31,6 +34,7 @@ import org.wysaid.nativePort.CGEFFmpegNativeLibrary;
 import org.wysaid.nativePort.CGENativeLibrary;
 import org.wysaid.view.VideoPlayerGLSurfaceView;
 
+import java.io.File;
 import java.util.Locale;
 
 import cn.finalteam.rxgalleryfinal.utils.MediaUtils;
@@ -75,6 +79,7 @@ public class ActEditVideo extends BaseContainerActivity implements Filterble, Le
         if (this instanceof BaseContainerActivity) {
             super.initView();
         }
+        loadDoodleFile();
         mPlayerView = findViewById(R.id.videoGLSurfaceView);
         data = (Video) getIntent().getSerializableExtra(Video.class.getSimpleName());
         mPlayerView.setZOrderOnTop(false);
@@ -147,15 +152,7 @@ public class ActEditVideo extends BaseContainerActivity implements Filterble, Le
     private String tryGenerateVideoWithFilter() {
         String srcFilPath = data.getFilePath();
         String outputFilename = String.format(Locale.CHINA, "%s_%d_%f.mp4", srcFilPath.substring(0, srcFilPath.lastIndexOf(".")), mCurrentConfig.hashCode(), mIntensity);
-        Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.media_sheep_logo_3);
-        //left 30px top 60px width 750
-        Bitmap logo = data.getOrientation() / 90 % 2 == 0 ?
-            BitmapUtil.createBigLogo(bmp, new Size().setWidth(data.getWidth()).setHeight(data.getHeight()).setX(data.getWidth() * 30 / 750).setY(data.getWidth() * 60 / 750)) :
-            BitmapUtil.createBigLogo(bmp, new Size().setWidth(data.getHeight()).setHeight(data.getWidth()).setX(data.getHeight() * 30 / 750).setY(data.getHeight() * 60 / 750));
-        Bitmap rotateBmp = data.getOrientation() != 0 ? MediaUtils.rotateBimap(360 - data.getOrientation(), logo) : logo;
-        if(logo != rotateBmp)
-            logo.recycle();
-        bmp.recycle();
+        Bitmap rotateBmp = getRotateBmp(getApplicationContext(), data);
 
         CGEFFmpegNativeLibrary.generateVideoWithFilter(outputFilename, srcFilPath, mCurrentConfig, mIntensity, rotateBmp, CGENativeLibrary.TextureBlendMode.CGE_BLEND_ADDREV, 1.0f, false);
         rotateBmp.recycle();
@@ -163,6 +160,27 @@ public class ActEditVideo extends BaseContainerActivity implements Filterble, Le
         return outputFilename;
     }
 
+    public static Bitmap getRotateBmp(Context context, Video data) {
+        File doodleFile = FgtDoodle.getDoodleFile(context);
+        Bitmap doodleBitmap;
+        Bitmap logo = null;
+        if(doodleFile.exists()){
+            doodleBitmap = BitmapFactory.decodeFile(doodleFile.getAbsolutePath());
+        } else {
+            logo = BitmapFactory.decodeResource(context.getResources(), R.drawable.media_sheep_logo_3);
+            //left 30px top 60px width 750
+            doodleBitmap = data.getOrientation() / 90 % 2 == 0 ?
+                    BitmapUtil.createBigLogo(logo, new Size().setWidth(data.getWidth()).setHeight(data.getHeight()).setX(data.getWidth() * 30 / 750).setY(data.getWidth() * 60 / 750)) :
+                    BitmapUtil.createBigLogo(logo, new Size().setWidth(data.getHeight()).setHeight(data.getWidth()).setX(data.getHeight() * 30 / 750).setY(data.getHeight() * 60 / 750));
+        }
+        Bitmap rotateBmp = data.getOrientation() != 0 ? MediaUtils.rotateBimap(360 - data.getOrientation(), doodleBitmap) : doodleBitmap;
+        if(doodleBitmap != rotateBmp)
+            doodleBitmap.recycle();
+        if(logo != null)
+            logo.recycle();
+        return rotateBmp;
+    }
+
     private IFilter filter;
     //设置滤镜
     @Override
@@ -355,4 +373,15 @@ public class ActEditVideo extends BaseContainerActivity implements Filterble, Le
         return new FgtChooseEditList();
     }
 
+
+    //加载之前保存的图片
+    private void loadDoodleFile() {
+        ImageView act_edit_video_doodle_iv = findViewById(R.id.act_edit_video_doodle_iv);
+        File doodleFile = FgtDoodle.getDoodleFile(getApplicationContext());
+        if(doodleFile.exists()){
+            Bitmap doodleBitmap = BitmapFactory.decodeFile(doodleFile.getAbsolutePath());
+            act_edit_video_doodle_iv.setImageBitmap(doodleBitmap);
+        }
+    }
+
 }

+ 26 - 1
media/app/src/main/java/com/kfzs/cfyl/media/activity/MainActivity.java

@@ -2,8 +2,10 @@ package com.kfzs.cfyl.media.activity;
 
 import android.app.Activity;
 import android.content.DialogInterface;
+import android.graphics.Bitmap;
 import android.support.v7.app.AlertDialog;
 import android.view.View;
+import android.widget.ImageView;
 
 import com.kfzs.cfyl.media.BaseActivity;
 import com.kfzs.cfyl.media.R;
@@ -75,10 +77,30 @@ public class MainActivity extends BaseActivity {
             }
         }).start();
     }
+    private void testDoodleAndLogo() {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                List<MediaBean> mediaBeanList = MediaUtils.getMediaWithVideoList(getApplicationContext(), page++, 1);
+                MediaBean mediaBean = ListUtil.getItem(mediaBeanList, 0);
+                if(mediaBean != null) {
+                    final Video video = Video.from(mediaBean);
+                    final Bitmap bmp = ActEditVideo.getRotateBmp(getApplicationContext(), video);
+                    runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            ImageView media_act_main_iv = findViewById(R.id.media_act_main_iv);
+                            media_act_main_iv.setImageBitmap(bmp);
+                        }
+                    });
+                }
+            }
+        }).start();
+    }
 
     public void onClickHelloWorld(View view) {
         Activity activity = this;
-        final String[] items = {"剪切视频", "编辑视频"};
+        final String[] items = {"剪切视频", "编辑视频", "涂鸦与logo"};
         AlertDialog dialog = new AlertDialog.Builder(activity).setTitle("请选择测试项目")
                 .setItems(items, new DialogInterface.OnClickListener() {
 
@@ -91,6 +113,9 @@ public class MainActivity extends BaseActivity {
                             case "编辑视频":
                                 goEdit();
                                 break;
+                            case "涂鸦与logo":
+                                testDoodleAndLogo();
+                                break;
                         }
                     }
                 }).create();

+ 17 - 15
media/app/src/main/java/com/kfzs/cfyl/media/customview/VideoFramesView.java

@@ -389,23 +389,25 @@ public class VideoFramesView extends RelativeLayout {
 
     public void setOnTimeChangeListener(Action1<Float> action1) {
         onTimeChangeListener = action1;
-        postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                firstStartX = line_start.getX();
-                firstEndX = line_end.getX();
-                lineW = line_start.getWidth();
-                rvW = recyclerView.getWidth();
-                long duration = video.getDuration();
-                if (maxVideoDuration > 0) {
-                    if (duration > maxVideoDuration) {
-                        firstEndX = firstStartX + ((maxVideoDuration * 1.0f / duration) * (rvW - lineW));
-                        line_end.setX(firstEndX);
+        if(lineW == 0) {
+            postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    firstStartX = line_start.getX();
+                    firstEndX = line_end.getX();
+                    lineW = line_start.getWidth();
+                    rvW = recyclerView.getWidth();
+                    long duration = video.getDuration();
+                    if (maxVideoDuration > 0) {
+                        if (duration > maxVideoDuration) {
+                            firstEndX = firstStartX + ((maxVideoDuration * 1.0f / duration) * (rvW - lineW));
+                            line_end.setX(firstEndX);
+                        }
                     }
+                    onTimeChangeListener.call((float) getLineDuration());
                 }
-                onTimeChangeListener.call((float) duration);
-            }
-        }, 100);
+            }, 100);
+        }
     }
 
     //开始的时间,单位秒

+ 61 - 17
media/app/src/main/java/com/kfzs/cfyl/media/fragment/FgtDoodle.java

@@ -1,6 +1,8 @@
 package com.kfzs.cfyl.media.fragment;
 
 import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Color;
@@ -12,12 +14,17 @@ import android.widget.ImageView;
 
 import com.kfzs.cfyl.media.BaseFragment;
 import com.kfzs.cfyl.media.BaseListFgtActivity;
-import com.kfzs.cfyl.media.BaseListFgtFgt;
 import com.kfzs.cfyl.media.R;
+import com.kfzs.cfyl.media.activity.ActCutVideo;
 import com.kfzs.cfyl.media.adapter.ViewPagerFragmentAdapter;
+import com.kfzs.cfyl.media.bean.Size;
+import com.kfzs.cfyl.media.util.BitmapUtil;
 import com.kfzs.cfyl.media.util.G;
 import com.kfzs.cfyl.media.util.ListUtil;
+import com.kfzs.cfyl.share_library.util.LogUtil;
+import com.sheep.gamegroup.model.entity.Video;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -68,9 +75,6 @@ public class FgtDoodle extends BaseFragment {
         media_viewPager.setAdapter(mViewPagerFragmentAdapter);
         media_viewPager.setOffscreenPageLimit(mViewPagerFragmentAdapter.getCount());
 
-        ViewGroup media_fgt_doodle_container = findViewById(R.id.media_fgt_doodle_container);
-        initDoodleView(media_fgt_doodle_container);
-
         ImageView media_video_back_iv = findViewById(R.id.media_video_back_iv);
         media_video_back_iv.setOnClickListener(new View.OnClickListener() {
             @Override
@@ -79,8 +83,16 @@ public class FgtDoodle extends BaseFragment {
             }
         });
 
-        View media_video_redo_iv = findViewById(R.id.media_video_redo_iv);
-        media_video_redo_iv.setOnClickListener(new View.OnClickListener() {
+        View media_video_undo_tv = findViewById(R.id.media_video_undo_tv);
+        media_video_undo_tv.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                onClickUndo(view);
+            }
+        });
+
+        View media_video_redo_tv = findViewById(R.id.media_video_redo_tv);
+        media_video_redo_tv.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
                 onClickRedo(view);
@@ -104,8 +116,15 @@ public class FgtDoodle extends BaseFragment {
         });
     }
 
-    //点击撤销
+    //点击返回
     public void onClickBackImg(View view) {
+        Activity activity = getActivity();
+        if (activity instanceof BaseListFgtActivity) {
+            ((BaseListFgtActivity) activity).switchFgt(FgtEditVideoTypeList.POSITION, this);
+        }
+    }
+    //点击撤销
+    public void onClickUndo(View view) {
         if(mDoodleView != null){
             IDoodleItem lastItem = ListUtil.getLast(mDoodleView.getAllItem());
             if(lastItem != null){
@@ -133,12 +152,12 @@ public class FgtDoodle extends BaseFragment {
         }
     }
 
-    //点击下一步
+    //点击保存
     public void onClickNext(View view) {
-        Activity activity = getActivity();
-        if (activity instanceof BaseListFgtActivity) {
-            ((BaseListFgtActivity) activity).switchFgt(FgtEditVideoTypeList.POSITION, this);
+        if(mDoodleView != null){
+            mDoodleView.save();
         }
+        onClickBackImg(view);
     }
 
 
@@ -150,22 +169,38 @@ public class FgtDoodle extends BaseFragment {
         }
     }
 
-    private void initDoodleView(ViewGroup media_fgt_doodle_container) {
+    public static File getDoodleFile(Context context){
+        File dir = context.getDir("png", Context.MODE_PRIVATE);
+        return new File(dir, "doodle.png");
+    }
+    private void initDoodleView(final ViewGroup media_fgt_doodle_container) {
         // 涂鸦参数
         mDoodleParams = new DoodleParams();
         mDoodleParams.mIsFullScreen = true;
         mDoodleParams.mIsDrawableOutside = true;
         // 初始画笔大小
         mDoodleParams.mPaintUnitSize = DoodleView.DEFAULT_SIZE;
-        final Bitmap bitmap = Bitmap.createBitmap(G.WIDTH, G.HEIGHT, Bitmap.Config.ARGB_4444);
-        mDoodle = mDoodleView = new DoodleView(media_fgt_doodle_container.getContext(), bitmap, new IDoodleListener() {
+        final Context context = media_fgt_doodle_container.getContext();
+        final File doodleFile = getDoodleFile(context);
+        final Bitmap loadBitmap = BitmapUtil.getDefaultBitmap(getResources(), data);
+        doodleFile.deleteOnExit();//删除之前的图片
+        mDoodle = mDoodleView = new DoodleView(context, loadBitmap, new IDoodleListener() {
             /*
             called when save the doodled iamge.
             保存涂鸦图像时调用
              */
             @Override
-            public void onSaved(IDoodle doodle, Bitmap bitmap, Runnable callback) {
-                //do something
+            public void onSaved(IDoodle doodle, Bitmap bgBitmap, Runnable callback) {
+                Bitmap logo = BitmapFactory.decodeResource(context.getResources(), R.drawable.media_sheep_logo_3);
+                int w = bgBitmap.getWidth();
+                int h = bgBitmap.getHeight();
+                Size size = new Size().setWidth(w).setHeight(h).setX(w * 30 / 750).setY(w * 60 / 750);
+                Bitmap logoFull = BitmapUtil.createBigLogo(logo, size);
+                Bitmap result = BitmapUtil.mergeBitmap(bgBitmap, logoFull);
+                BitmapUtil.saveImage(result, doodleFile);
+                BitmapUtil.recycle(logo);
+                BitmapUtil.recycle(logoFull);
+                BitmapUtil.recycle(result);
             }
 
             /*
@@ -218,7 +253,7 @@ public class FgtDoodle extends BaseFragment {
                     IDoodleSelectableItem item = new DoodleText(mDoodle, "hello", 20 * mDoodle.getUnitSize(), new DoodleColor(Color.RED), x, y);
                     mDoodle.addItem(item);
                 } else if (mDoodle.getPen() == DoodlePen.BITMAP) {
-                    IDoodleSelectableItem item = new DoodleBitmap(mDoodle, bitmap, 80 * mDoodle.getUnitSize(), x, y);
+                    IDoodleSelectableItem item = new DoodleBitmap(mDoodle, loadBitmap, 80 * mDoodle.getUnitSize(), x, y);
                     mDoodle.addItem(item);
                 }
             }
@@ -243,4 +278,13 @@ public class FgtDoodle extends BaseFragment {
     private DoodleParams mDoodleParams;
     private Map<IDoodlePen, Float> mPenSizeMap = new HashMap<>(); //保存每个画笔对应的最新大小
     private DoodleOnTouchGestureListener mTouchGestureListener;
+
+    private Video data;
+    public void loadData(Video data) {
+        if(this.data == null) {
+            this.data = data;
+            ViewGroup media_fgt_doodle_container = findViewById(R.id.media_fgt_doodle_container);
+            initDoodleView(media_fgt_doodle_container);
+        }
+    }
 }

+ 1 - 1
media/app/src/main/java/com/kfzs/cfyl/media/fragment/FgtVideoFrameList.java

@@ -113,7 +113,7 @@ public class FgtVideoFrameList extends BaseFragment {
         if(activity instanceof BaseActivity) {
             final BaseActivity baseActivity = (BaseActivity) activity;
             baseActivity.showProgress().getTextView().setText("剪切视频中");
-            VideoUtil.tryCutVideo(data.getFilePath(), videoFramesView.getStartPoint() * 1000, videoFramesView.getLineDuration() * 1000, new Action1<Object>() {
+            VideoUtil.tryCutVideoByMedia(data.getFilePath(), videoFramesView.getStartPoint() * 1000, videoFramesView.getLineDuration() * 1000, new Action1<Object>() {
                 @Override
                 public void call(final Object result) {
                     baseActivity.runOnUiThread(new Runnable() {

+ 200 - 0
media/app/src/main/java/com/kfzs/cfyl/media/util/BitmapUtil.java

@@ -1,11 +1,22 @@
 package com.kfzs.cfyl.media.util;
 
+import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Paint;
+import android.graphics.Rect;
 
 import com.kfzs.cfyl.media.bean.Size;
+import com.kfzs.cfyl.media.fragment.FgtDoodle;
+import com.kfzs.cfyl.share_library.util.LogUtil;
+import com.sheep.gamegroup.model.entity.Video;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
 
 
 /**
@@ -13,6 +24,125 @@ import com.kfzs.cfyl.media.bean.Size;
  * realicing@sina.com
  */
 public class BitmapUtil {
+    /**
+     * 把两个位图覆盖合成为一个位图,以底层位图的长宽为基准
+     * @param backBitmap 在底部的位图
+     * @param frontBitmap 盖在上面的位图
+     * @return
+     */
+    public static Bitmap mergeBitmap(Bitmap backBitmap, Bitmap frontBitmap) {
+
+        if (backBitmap == null || backBitmap.isRecycled()
+                || frontBitmap == null || frontBitmap.isRecycled()) {
+            LogUtil.println("backBitmap=" + backBitmap + ";frontBitmap=" + frontBitmap);
+            return null;
+        }
+        Bitmap bitmap = backBitmap.copy(Bitmap.Config.ARGB_8888, true);
+        Canvas canvas = new Canvas(bitmap);
+        Rect baseRect  = new Rect(0, 0, backBitmap.getWidth(), backBitmap.getHeight());
+        Rect frontRect = new Rect(0, 0, frontBitmap.getWidth(), frontBitmap.getHeight());
+        canvas.drawBitmap(frontBitmap, frontRect, baseRect, null);
+        return bitmap;
+    }
+
+    /**
+     * 把两个位图覆盖合成为一个位图,左右拼接
+     * @param leftBitmap
+     * @param rightBitmap
+     * @param isBaseMax 是否以宽度大的位图为准,true则小图等比拉伸,false则大图等比压缩
+     * @return
+     */
+    public static Bitmap mergeBitmap_LR(Bitmap leftBitmap, Bitmap rightBitmap, boolean isBaseMax) {
+
+        if (leftBitmap == null || leftBitmap.isRecycled()
+                || rightBitmap == null || rightBitmap.isRecycled()) {
+            LogUtil.println("leftBitmap=" + leftBitmap + ";rightBitmap=" + rightBitmap);
+            return null;
+        }
+        int height = 0; // 拼接后的高度,按照参数取大或取小
+        if (isBaseMax) {
+            height = leftBitmap.getHeight() > rightBitmap.getHeight() ? leftBitmap.getHeight() : rightBitmap.getHeight();
+        } else {
+            height = leftBitmap.getHeight() < rightBitmap.getHeight() ? leftBitmap.getHeight() : rightBitmap.getHeight();
+        }
+
+        // 缩放之后的bitmap
+        Bitmap tempBitmapL = leftBitmap;
+        Bitmap tempBitmapR = rightBitmap;
+
+        if (leftBitmap.getHeight() != height) {
+            tempBitmapL = Bitmap.createScaledBitmap(leftBitmap, (int)(leftBitmap.getWidth()*1f/leftBitmap.getHeight()*height), height, false);
+        } else if (rightBitmap.getHeight() != height) {
+            tempBitmapR = Bitmap.createScaledBitmap(rightBitmap, (int)(rightBitmap.getWidth()*1f/rightBitmap.getHeight()*height), height, false);
+        }
+
+        // 拼接后的宽度
+        int width = tempBitmapL.getWidth() + tempBitmapR.getWidth();
+
+        // 定义输出的bitmap
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+
+        // 缩放后两个bitmap需要绘制的参数
+        Rect leftRect = new Rect(0, 0, tempBitmapL.getWidth(), tempBitmapL.getHeight());
+        Rect rightRect  = new Rect(0, 0, tempBitmapR.getWidth(), tempBitmapR.getHeight());
+
+        // 右边图需要绘制的位置,往右边偏移左边图的宽度,高度是相同的
+        Rect rightRectT  = new Rect(tempBitmapL.getWidth(), 0, width, height);
+
+        canvas.drawBitmap(tempBitmapL, leftRect, leftRect, null);
+        canvas.drawBitmap(tempBitmapR, rightRect, rightRectT, null);
+        return bitmap;
+    }
+
+
+    /**
+     * 把两个位图覆盖合成为一个位图,上下拼接
+     * @param topBitmap
+     * @param bottomBitmap
+     * @param isBaseMax 是否以高度大的位图为准,true则小图等比拉伸,false则大图等比压缩
+     * @return
+     */
+    public static Bitmap mergeBitmap_TB(Bitmap topBitmap, Bitmap bottomBitmap, boolean isBaseMax) {
+
+        if (topBitmap == null || topBitmap.isRecycled()
+                || bottomBitmap == null || bottomBitmap.isRecycled()) {
+            LogUtil.println("topBitmap=" + topBitmap + ";bottomBitmap=" + bottomBitmap);
+            return null;
+        }
+        int width = 0;
+        if (isBaseMax) {
+            width = topBitmap.getWidth() > bottomBitmap.getWidth() ? topBitmap.getWidth() : bottomBitmap.getWidth();
+        } else {
+            width = topBitmap.getWidth() < bottomBitmap.getWidth() ? topBitmap.getWidth() : bottomBitmap.getWidth();
+        }
+        Bitmap tempBitmapT = topBitmap;
+        Bitmap tempBitmapB = bottomBitmap;
+
+        if (topBitmap.getWidth() != width) {
+            tempBitmapT = Bitmap.createScaledBitmap(topBitmap, width, (int)(topBitmap.getHeight()*1f/topBitmap.getWidth()*width), false);
+        } else if (bottomBitmap.getWidth() != width) {
+            tempBitmapB = Bitmap.createScaledBitmap(bottomBitmap, width, (int)(bottomBitmap.getHeight()*1f/bottomBitmap.getWidth()*width), false);
+        }
+
+        int height = tempBitmapT.getHeight() + tempBitmapB.getHeight();
+
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+
+        Rect topRect = new Rect(0, 0, tempBitmapT.getWidth(), tempBitmapT.getHeight());
+        Rect bottomRect  = new Rect(0, 0, tempBitmapB.getWidth(), tempBitmapB.getHeight());
+
+        Rect bottomRectT  = new Rect(0, tempBitmapT.getHeight(), width, height);
+
+        canvas.drawBitmap(tempBitmapT, topRect, topRect, null);
+        canvas.drawBitmap(tempBitmapB, bottomRect, bottomRectT, null);
+        return bitmap;
+    }
+    public static Bitmap createBigLogo(Bitmap bmp, Size size, Bitmap bgBitmap) {
+        Bitmap bitmap = createBigLogo(bmp, size);
+        return mergeBitmap(bgBitmap, bitmap);
+    }
     public static Bitmap createBigLogo(Bitmap bmp, Size size) {
         Bitmap result = Bitmap.createBitmap(size.getWidth(), size.getHeight(), Bitmap.Config.ARGB_4444);
         Canvas canvas = new Canvas(result);
@@ -32,4 +162,74 @@ public class BitmapUtil {
         canvas.drawBitmap(bmp, matrix, paint);
         return result;
     }
+
+    public static File saveImage(Bitmap bmp, String dir, String fileName) {
+        File appDir = new File(dir);
+        if (!appDir.exists()) {
+            appDir.mkdir();
+        }
+        File file = new File(appDir, fileName);
+        try {
+            FileOutputStream fos = new FileOutputStream(file);
+            bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
+            fos.flush();
+            fos.close();
+            return file;
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+    public static void saveImage(Bitmap bitmap, File file) {
+        File appDir = file.getParentFile();
+        if (!appDir.exists()) {
+            appDir.mkdir();
+        }
+        try {
+            FileOutputStream fos = new FileOutputStream(file);
+            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
+            fos.flush();
+            fos.close();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static Bitmap getDefaultBitmap(Resources resources, Video data) {
+        int a = G.WIDTH;
+        int b = G.HEIGHT;
+        if(data != null){
+            a = data.getWidth();
+            b = data.getHeight();
+        }
+        boolean needExchange = false;
+        if(resources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
+            LogUtil.println(FgtDoodle.class.getSimpleName(), "info", "landscape");
+            needExchange = b > a;
+        } else if (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+            LogUtil.println(FgtDoodle.class.getSimpleName(), "info", "portrait");
+            needExchange = a > b;
+        }
+        if(needExchange) {
+            int tmp = b;
+            b = a;
+            a = tmp;
+        }
+        return Bitmap.createBitmap(a, b, Bitmap.Config.ARGB_4444);
+    }
+
+    //释放bitmap
+    public static void recycle(Bitmap bitmap) {
+        if(bitmap != null && !bitmap.isRecycled()){
+            try {
+                bitmap.recycle();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
 }

+ 36 - 0
media/app/src/main/java/com/kfzs/cfyl/media/util/VideoUtil.java

@@ -15,6 +15,9 @@ import com.sheep.gamegroup.model.entity.Video;
 import java.nio.ByteBuffer;
 import java.util.Locale;
 
+import VideoHandle.EpEditor;
+import VideoHandle.EpVideo;
+import VideoHandle.OnEditorListener;
 import cn.finalteam.rxgalleryfinal.utils.MediaUtils;
 import rx.functions.Action1;
 //import wseemann.media.FFmpegMediaMetadataRetriever;
@@ -179,6 +182,39 @@ public class VideoUtil {
     }
 
     private static final String TAG = VideoUtil.class.getSimpleName();
+    public static void tryCutVideoByMedia(final String filePath, long clipPoint, final long clipDuration, final Action1<Object> action1) {
+        final Video video = new Video();
+        if (clipPoint < 0) {
+            Log.e(TAG, "clipPoint is error! but reset clipPoint " + clipPoint + "0 ");
+            clipPoint = 0;
+        }
+        LogUtil.println(TAG, filePath, clipPoint, clipDuration);
+        String outFilePath = getCutVideoFilePath(filePath, clipPoint, clipDuration);
+        video.setFilePath(outFilePath);
+        //开始剪切
+        EpVideo epVideo = new EpVideo(filePath);
+//输出选项,参数为输出文件路径(目前仅支持mp4格式输出)
+        EpEditor.OutputOption outputOption = new EpEditor.OutputOption(outFilePath);
+        outputOption.frameRate = 10;//输出视频帧率,默认30
+        outputOption.bitRate = 1;//输出视频码率,默认10
+        epVideo.clip(clipPoint / 1000_000f, clipDuration / 1000_000f);//此处单位为秒
+        EpEditor.exec(epVideo, outputOption, new OnEditorListener() {
+            @Override
+            public void onSuccess() {
+                action1.call(video);
+            }
+
+            @Override
+            public void onFailure() {
+                action1.call(new Throwable("剪切失败"));
+            }
+
+            @Override
+            public void onProgress(float progress) {
+
+            }
+        });
+    }
     /**
      * 剪切视频
      *

+ 7 - 5
media/app/src/main/res/layout/main_activity.xml

@@ -1,17 +1,19 @@
 <?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     xmlns:tools="http://schemas.android.com/tools"
-    android:orientation="vertical"
     tools:context=".activity.MainActivity">
 
+    <ImageView
+        android:id="@+id/media_act_main_iv"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
     <TextView
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginTop="100dp"
-        android:layout_gravity="center"
+        android:layout_centerInParent="true"
         android:gravity="center"
         android:onClick="onClickHelloWorld"
         android:text="HelloWorld" />
-</LinearLayout>
+</RelativeLayout>

+ 4 - 1
media/app/src/main/res/layout/media_act_edit_video.xml

@@ -54,7 +54,10 @@
 
         </LinearLayout>
     </HorizontalScrollView>
-
+    <ImageView
+        android:id="@+id/act_edit_video_doodle_iv"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
     <FrameLayout
         android:id="@+id/media_frame_container"
         android:layout_width="match_parent"

+ 24 - 8
media/app/src/main/res/layout/media_fgt_doodle.xml

@@ -18,16 +18,32 @@
         android:src="@drawable/media_narrow_back_white"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent" />
-    <ImageView
-        android:id="@+id/media_video_redo_iv"
-        android:layout_width="?attr/actionBarSize"
+    <TextView
+        android:id="@+id/media_video_undo_tv"
+        android:layout_width="wrap_content"
         android:layout_height="?attr/actionBarSize"
         android:layout_marginTop="20dp"
-        android:scaleType="centerInside"
-        android:rotation="180"
-        android:src="@drawable/media_narrow_back_white"
+        android:text="撤销"
+        android:textColor="@color/media_white"
+        android:textSize="15sp"
+        android:gravity="center"
+        android:paddingStart="10dp"
+        android:paddingEnd="10dp"
         app:layout_constraintStart_toEndOf="@id/media_video_back_iv"
-        app:layout_constraintTop_toTopOf="parent" />
+        app:layout_constraintTop_toTopOf="parent"/>
+    <TextView
+        android:id="@+id/media_video_redo_tv"
+        android:layout_width="wrap_content"
+        android:layout_height="?attr/actionBarSize"
+        android:layout_marginTop="20dp"
+        android:text="重做"
+        android:textColor="@color/media_white"
+        android:textSize="15sp"
+        android:gravity="center"
+        android:paddingStart="10dp"
+        android:paddingEnd="10dp"
+        app:layout_constraintStart_toEndOf="@id/media_video_undo_tv"
+        app:layout_constraintTop_toTopOf="parent"/>
     <TextView
         android:id="@+id/media_video_reset_tv"
         android:layout_width="wrap_content"
@@ -39,7 +55,7 @@
         android:gravity="center"
         android:paddingStart="10dp"
         android:paddingEnd="10dp"
-        app:layout_constraintStart_toEndOf="@id/media_video_redo_iv"
+        app:layout_constraintStart_toEndOf="@id/media_video_redo_tv"
         app:layout_constraintTop_toTopOf="parent"/>
 
     <ImageView

+ 3 - 1
media/settings.gradle

@@ -1 +1,3 @@
-include ':app', ':share_library'//, ':view', ':ucrop', ':WaterWaveProgress'//, ':media/app'//, ':RxGalleryFinal', ':Aria', ':datashare', ':AriaAnnotations'
+include ':app', ':share_library', ':joevideolib'//, ':view', ':ucrop', ':WaterWaveProgress'//, ':media/app'//, ':RxGalleryFinal', ':Aria', ':datashare', ':AriaAnnotations'
+
+project(':joevideolib').projectDir = new File('../joevideolib')

+ 1 - 0
media/share_library/build.gradle

@@ -25,4 +25,5 @@ android {
 dependencies {
     //fast json
     compileOnly 'com.alibaba:fastjson:1.2.52'
+    api project(':joevideolib')
 }