diff --git a/app/build.gradle b/app/build.gradle index c25a65a1..df3cd9b6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,7 +5,7 @@ plugins { // 10,00,000 major-minor-build def AppMajorVersion = 1 def AppMinorVersion = 0 -def AppBuildNumber = 138 +def AppBuildNumber = 139 def AppVersionName = AppMajorVersion + "." + AppMinorVersion + "." + AppBuildNumber def AppVersionCode = AppMajorVersion * 100000 + AppMinorVersion * 1000 + AppBuildNumber diff --git a/app/src/main/java/com/xypower/mpapp/v2/Camera2VideoActivity.java b/app/src/main/java/com/xypower/mpapp/v2/Camera2VideoActivity.java index 1e6c52c6..e45ab8fa 100644 --- a/app/src/main/java/com/xypower/mpapp/v2/Camera2VideoActivity.java +++ b/app/src/main/java/com/xypower/mpapp/v2/Camera2VideoActivity.java @@ -52,6 +52,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.concurrent.Semaphore; public class Camera2VideoActivity extends AppCompatActivity { @@ -94,6 +95,9 @@ public class Camera2VideoActivity extends AppCompatActivity { private int mTimeMask = 0; private int mStatusBarHeight = -1; + private long mOsdTs = 0; + private Semaphore mOSDSemaphore = new Semaphore(0); + private Thread mOsdThread = null; private static class OSD_ITEM { @@ -134,12 +138,17 @@ public class Camera2VideoActivity extends AppCompatActivity { } // updateOSD(ts); - initOSD(ts); + Bitmap bitmap = mBitmap; + mBitmap = null; + mOSDFilter.updateBitmap(bitmap); + + mBitmap = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888); + mOsdTs = ts; + mOSDSemaphore.release(); mHandler.postDelayed(this, 1000 - ms); } }; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -261,6 +270,7 @@ public class Camera2VideoActivity extends AppCompatActivity { mTimeMask |= TIME_MASK_RB_ML; } } + if (!TextUtils.isEmpty(mOSDLeftBottom)) { mOSDLeftBottom = mOSDLeftBottom.replace("\r\n", "\n"); mOSDLeftBottom = mOSDLeftBottom.replace("\n\r", "\n"); @@ -278,20 +288,72 @@ public class Camera2VideoActivity extends AppCompatActivity { mHandler = new Handler(); + mOsdThread = new Thread(new Runnable() { + @Override + public void run() { + while (true) { + try { + mOSDSemaphore.acquire(); + } catch (Exception ex) { + + } + + if (mOsdTs == -1) { + break; + } + + updateOSD(mOsdTs); + } + } + }); + + mOsdThread.start(); + + if (!TextUtils.isEmpty(mOSDLeftTop) || !TextUtils.isEmpty(mOSDLeftTop) || !TextUtils.isEmpty(mOSDLeftTop) || !TextUtils.isEmpty(mOSDLeftTop)) { + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setStyle(Paint.Style.FILL); + mPaint.setColor(Color.WHITE); + int fontSize = DEFAULT_FONT_SIZE; + mPaint.setTextSize(fontSize); + + mPaintStroker = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaintStroker.setStyle(Paint.Style.STROKE); + mPaintStroker.setColor(Color.BLACK); + mPaintStroker.setTextSize(fontSize); + mPaintStroker.setStrokeWidth(1); + + mBitmap = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888); + + Canvas canvas = new Canvas(mBitmap); + canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + + mOSDFilter = new GlWatermarkFilter(mBitmap); + + long ts = System.currentTimeMillis(); + + initOSD(ts); + + mOsdTs = ts + 1000; + long ms = ts % 1000; + mOSDSemaphore.release(); + mHandler.postDelayed(mTimerRunnable, 1000 - ms); + } + mHandler.postDelayed(new Runnable() { @Override public void run() { mNextVideoAbsolutePath = getVideoFilePath(); + mGPUCameraRecorder.start(mNextVideoAbsolutePath); } - }, 200); + }, 32); mHandler.postDelayed(new Runnable() { @Override public void run() { mGPUCameraRecorder.stop(); } - }, 200 + mDuration * 1000); + }, 48 + mDuration * 1000); // getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } @@ -600,27 +662,6 @@ public class Camera2VideoActivity extends AppCompatActivity { runOnUiThread(() -> { - if (!TextUtils.isEmpty(mOSDLeftTop) || !TextUtils.isEmpty(mOSDLeftTop) || !TextUtils.isEmpty(mOSDLeftTop) || !TextUtils.isEmpty(mOSDLeftTop)) { - mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mPaint.setStyle(Paint.Style.FILL); - mPaint.setColor(Color.WHITE); - int fontSize = DEFAULT_FONT_SIZE; - mPaint.setTextSize(fontSize); - - mPaintStroker = new Paint(Paint.ANTI_ALIAS_FLAG); - mPaintStroker.setStyle(Paint.Style.STROKE); - mPaintStroker.setColor(Color.BLACK); - mPaintStroker.setTextSize(fontSize); - mPaintStroker.setStrokeWidth(1); - - mBitmap = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888); - - Canvas canvas = new Canvas(mBitmap); - canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); - - mOSDFilter = new GlWatermarkFilter(mBitmap); - } - FrameLayout frameLayout = findViewById(R.id.wrap_view); frameLayout.removeAllViews(); mPreviewView = null; @@ -644,6 +685,8 @@ public class Camera2VideoActivity extends AppCompatActivity { mNextVideoAbsolutePath = getVideoFilePath(this); } + + mGPUCameraRecorder = new GPUCameraRecorderBuilder(this, mPreviewView) //.recordNoFilter(true) .cameraRecordListener(new CameraRecordListener() { @@ -655,6 +698,8 @@ public class Camera2VideoActivity extends AppCompatActivity { @Override public void onRecordComplete() { mHandler.removeCallbacks(mTimerRunnable); + mOsdTs = -1; + mOSDSemaphore.release(); exportMp4ToGallery(getApplicationContext(), mNextVideoAbsolutePath); broadcastVideoFile(true, mNextVideoAbsolutePath); mHandler.postDelayed(new Runnable() { @@ -668,12 +713,7 @@ public class Camera2VideoActivity extends AppCompatActivity { @Override public void onRecordStart() { - if (mTimeMask != 0) { - long ts = System.currentTimeMillis(); - long ms = ts % 1000; - initOSD(ts - ms); - mHandler.postDelayed(mTimerRunnable, 1000 - ms); - } + } diff --git a/gpuv/src/main/java/com/xypower/gpuv/egl/filter/GlWatermarkFilter.java b/gpuv/src/main/java/com/xypower/gpuv/egl/filter/GlWatermarkFilter.java index 6a265971..07f0da9a 100644 --- a/gpuv/src/main/java/com/xypower/gpuv/egl/filter/GlWatermarkFilter.java +++ b/gpuv/src/main/java/com/xypower/gpuv/egl/filter/GlWatermarkFilter.java @@ -9,7 +9,9 @@ import android.util.Log; public class GlWatermarkFilter extends GlOverlayFilter { + private Object mLocker = new Object(); private Bitmap bitmap; + private boolean invalidated = true; private Position position = Position.LEFT_TOP; public GlWatermarkFilter(Bitmap bitmap) { @@ -22,12 +24,28 @@ public class GlWatermarkFilter extends GlOverlayFilter { this.position = position; } + public void updateBitmap(Bitmap bm) { + Bitmap oldBitmap = null; + synchronized (mLocker) { + invalidated = true; + oldBitmap = bitmap; + bitmap = bm; + } + + if (oldBitmap != null) { + // oldBitmap.recycle(); + } + } + @Override protected void drawCanvas(Canvas canvas) { - synchronized (bitmap) { + synchronized (mLocker) { Log.d("OSD", "drawCanvas"); - canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); - canvas.drawBitmap(bitmap, null, canvas.getClipBounds(), null); + if (invalidated) { + canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + canvas.drawBitmap(bitmap, null, canvas.getClipBounds(), null); + invalidated = false; + } } /*