From d13afaa7feff73b36869f7f8071be6f3549a0e35 Mon Sep 17 00:00:00 2001 From: Matthew Date: Sun, 12 May 2024 16:54:47 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=9F=AD=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mpapp/v2/Camera2VideoActivity.java | 290 +++++++++++++++--- .../gpuv/egl/filter/GlOverlayFilter.java | 4 +- .../gpuv/egl/filter/GlWatermarkFilter.java | 5 + 3 files changed, 251 insertions(+), 48 deletions(-) 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 62f192de..bdbd0c83 100644 --- a/app/src/main/java/com/xypower/mpapp/v2/Camera2VideoActivity.java +++ b/app/src/main/java/com/xypower/mpapp/v2/Camera2VideoActivity.java @@ -8,7 +8,9 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Insets; import android.graphics.Paint; +import android.graphics.Point; import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.net.Uri; import android.opengl.GLException; @@ -47,7 +49,9 @@ import java.io.FileOutputStream; import java.io.IOException; import java.nio.IntBuffer; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; +import java.util.List; public class Camera2VideoActivity extends AppCompatActivity { @@ -79,7 +83,9 @@ public class Camera2VideoActivity extends AppCompatActivity { private int mOSDMargin = 0; private Paint mPaint; private Paint mPaintStroker; + private Paint mEmptyPaint; private Bitmap mBitmap; + private Bitmap mBitmapTime; GlWatermarkFilter mOSDFilter = null; private SimpleDateFormat mDateFormater; @@ -91,6 +97,16 @@ public class Camera2VideoActivity extends AppCompatActivity { private int mTimeMask = 0; private int mStatusBarHeight = -1; + private static class OSD_ITEM + { + String text; + int mask; + Point origin; + Rect previousRect; + } + + private List mOSDItems = new ArrayList<>(); + private final static int TIME_MASK_LT_TS = 1; private final static int TIME_MASK_LT_DT = 2; private final static int TIME_MASK_LT_ML = 4; @@ -119,8 +135,8 @@ public class Camera2VideoActivity extends AppCompatActivity { ms = 0; } - updateOSD(ts); - + // updateOSD(ts); + initOSD(ts); mHandler.postDelayed(this, 1000 - ms); } }; @@ -160,19 +176,14 @@ public class Camera2VideoActivity extends AppCompatActivity { }); } - public static int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); } - public int getStatusBarHeight(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - - - WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); WindowMetrics windowMetrics = wm.getCurrentWindowMetrics(); WindowInsets windowInsets = windowMetrics.getWindowInsets(); @@ -187,7 +198,6 @@ public class Camera2VideoActivity extends AppCompatActivity { return statusBarHeight; } - protected void onCreateActivity() { // @@ -300,7 +310,7 @@ public class Camera2VideoActivity extends AppCompatActivity { releaseCamera(); } - private void updateOSD(long ts) { + private void initOSD(long ts) { if (mStatusBarHeight == -1) { mStatusBarHeight = getStatusBarHeight(this); @@ -310,64 +320,248 @@ public class Camera2VideoActivity extends AppCompatActivity { int bmWidth = mBitmap.getWidth(); int bmHeight = mBitmap.getHeight(); int margin = mOSDMargin; + int x = 0; + int y = 0; // mOSDFilter. Canvas canvas = new Canvas(mBitmap); + Rect textBounds = new Rect(); + canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); if (!TextUtils.isEmpty(mOSDLeftTop)) { - String osd = ((mTimeMask | TIME_MASK_LT) == 0) ? mOSDLeftTop : updateOSDTime(mOSDLeftTop, ts); - // mPaint.setTextAlign(Paint.Align.LEFT); - int x = margin; - int y = margin + statusHeight; - canvas.drawText(osd, x, y, mPaint); - canvas.drawText(osd, x, y, mPaintStroker); + String[] items = mOSDLeftTop.split("\n"); + Point origin = new Point(margin, margin + statusHeight); + + for (String item : items) { + + int mask = 0; + if (item.indexOf(TIME_MICRO_TS) != 0) { + mask |= TIME_MASK_LT_TS; + } + if (item.indexOf(TIME_MICRO_DT) != 0) { + mask |= TIME_MASK_LT_DT; + } + + OSD_ITEM osdItem = new OSD_ITEM(); + osdItem.text = item; + osdItem.mask = mask; + osdItem.origin = new Point(origin); + + if (mask == 0) { + canvas.drawText(item, origin.x, origin.y, mPaint); + canvas.drawText(item, origin.x, origin.y, mPaintStroker); + + mPaintStroker.getTextBounds(item, 0, item.length(), textBounds); + } else { + String newText = updateOSDTime(item, ts); + + Log.d("OSD", "INIT OSD x=" + origin.x + " y=" + origin.y); + canvas.drawText(newText, origin.x, origin.y, mPaint); + canvas.drawText(newText, origin.x, origin.y, mPaintStroker); + + mPaintStroker.getTextBounds(newText, 0, item.length(), textBounds); + } + + osdItem.previousRect = new Rect(origin.x, origin.y, origin.x + textBounds.width(), origin.y + textBounds.height()); + + mOSDItems.add(osdItem); + origin.y += (textBounds.height() * 5) >> 2; + } } if (!TextUtils.isEmpty(mOSDLeftBottom)) { - String osd = ((mTimeMask | TIME_MASK_LB) == 0) ? mOSDLeftBottom : updateOSDTime(mOSDLeftBottom, ts); - // mPaint.setTextAlign(Paint.Align.LEFT); - Rect textBounds = new Rect(); - mPaint.getTextBounds(osd, 0, osd.length(), textBounds); - float y = bmHeight - margin - textBounds.height(); - canvas.drawText(osd, margin, y, mPaint); - canvas.drawText(osd, margin, y, mPaintStroker); + + String[] items = mOSDLeftBottom.split("\n"); + Point origin = new Point(margin, bmHeight - margin); + + for(int idx = items.length-1; idx >= 0; idx--) { + + int mask = 0; + String item = items[idx]; + if (item.indexOf(TIME_MICRO_TS) != 0) { + mask |= TIME_MASK_LB_TS; + } + if (item.indexOf(TIME_MICRO_DT) != 0) { + mask |= TIME_MASK_LB_DT; + } + + OSD_ITEM osdItem = new OSD_ITEM(); + osdItem.text = item; + osdItem.mask = mask; + osdItem.origin = new Point(origin); + if (mask == 0) { + mPaintStroker.getTextBounds(item, 0, item.length(), textBounds); + y = origin.y - textBounds.height(); + + canvas.drawText(item, origin.x, y, mPaint); + canvas.drawText(item, origin.x, y, mPaintStroker); + } else { + String newText = updateOSDTime(item, ts); + + mPaintStroker.getTextBounds(newText, 0, newText.length(), textBounds); + y = origin.y - textBounds.height(); + + canvas.drawText(newText, origin.x, y, mPaint); + canvas.drawText(newText, origin.x, y, mPaintStroker); + } + + osdItem.previousRect = new Rect(origin.x, y, origin.x + textBounds.width(), y + textBounds.height()); + mOSDItems.add(osdItem); + origin.y -= (textBounds.height() * 5) >> 2; + } } if (!TextUtils.isEmpty(mOSDRightTop)) { - String osd = ((mTimeMask | TIME_MASK_RT) == 0) ? mOSDRightTop : updateOSDTime(mOSDRightTop, ts); - // mPaint.setTextAlign(Paint.Align.RIGHT); - Rect textBounds = new Rect(); - mPaint.getTextBounds(osd, 0, osd.length(), textBounds); - float x = bmWidth - margin - textBounds.width(); - int y = margin + statusHeight; - canvas.drawText(osd, x, y, mPaint); - canvas.drawText(osd, x, y, mPaintStroker); + + String[] items = mOSDRightTop.split("\n"); + Point origin = new Point(bmWidth - margin, margin + statusHeight); + + for (String item : items) { + + int mask = 0; + if (item.indexOf(TIME_MICRO_TS) != 0) { + mask |= TIME_MASK_RT_TS; + } + if (item.indexOf(TIME_MICRO_DT) != 0) { + mask |= TIME_MASK_RT_DT; + } + + OSD_ITEM osdItem = new OSD_ITEM(); + osdItem.text = item; + osdItem.origin = new Point(origin); + osdItem.mask = mask; + + if (mask == 0) { + mPaintStroker.getTextBounds(item, 0, item.length(), textBounds); + + canvas.drawText(item, origin.x - textBounds.width(), origin.y, mPaint); + canvas.drawText(item, origin.x - textBounds.width(), origin.y, mPaintStroker); + } else { + + String newText = updateOSDTime(item, ts); + mPaintStroker.getTextBounds(newText, 0, item.length(), textBounds); + + canvas.drawText(newText, origin.x - textBounds.width(), origin.y, mPaint); + canvas.drawText(newText, origin.x - textBounds.width(), origin.y, mPaintStroker); + } + osdItem.previousRect = new Rect(origin.x - textBounds.width(), origin.y, origin.x, origin.y + textBounds.height()); + mOSDItems.add(osdItem); + + origin.y += (textBounds.height() * 5) >> 2; + } } if (!TextUtils.isEmpty(mOSDRightBottom)) { - String osd = ((mTimeMask | TIME_MASK_RB) == 0) ? mOSDRightBottom : updateOSDTime(mOSDRightBottom, ts); - // mPaint.setTextAlign(Paint.Align.RIGHT); - Rect textBounds = new Rect(); - mPaint.getTextBounds(osd, 0, osd.length(), textBounds); - float x = bmWidth - margin - textBounds.width(); - float y = bmHeight - margin - textBounds.height(); - canvas.drawText(osd, x, y, mPaint); - canvas.drawText(osd, x, y, mPaintStroker); + + String[] items = mOSDRightBottom.split("\n"); + Point origin = new Point(bmWidth - margin, bmHeight - margin); + + for(int idx = items.length-1; idx >= 0; idx--) { + + int mask = 0; + String item = items[idx]; + if (item.indexOf(TIME_MICRO_TS) != 0) { + mask |= TIME_MASK_RB_TS; + } + if (item.indexOf(TIME_MICRO_DT) != 0) { + mask |= TIME_MASK_RB_DT; + } + + OSD_ITEM osdItem = new OSD_ITEM(); + osdItem.text = item; + osdItem.origin = new Point(origin); + osdItem.mask = mask; + if (mask == 0) { + mPaintStroker.getTextBounds(item, 0, item.length(), textBounds); + + canvas.drawText(item, origin.x - textBounds.width(), origin.y - textBounds.height(), mPaint); + canvas.drawText(item, origin.x - textBounds.width(), origin.y - textBounds.height(), mPaintStroker); + } else { + String newText = updateOSDTime(item, ts); + mPaintStroker.getTextBounds(newText, 0, item.length(), textBounds); + + canvas.drawText(newText, origin.x - textBounds.width(), origin.y - textBounds.height(), mPaint); + canvas.drawText(newText, origin.x - textBounds.width(), origin.y - textBounds.height(), mPaintStroker); + } + + osdItem.previousRect = new Rect(origin.x - textBounds.width(), origin.y - textBounds.height(), origin.x, origin.y); + mOSDItems.add(osdItem); + + origin.y -= (textBounds.height() * 5) >> 2; + } } } + } + private void updateOSD(long ts) { - /* - SurfaceHolder surfaceHolder = sampleGLView.getHolder(); - Canvas surfaceCanvas = surfaceHolder.lockCanvas(); - if (surfaceCanvas != null) { - surfaceCanvas.drawBitmap(mBitmap, 0, 0, null); - surfaceHolder.unlockCanvasAndPost(surfaceCanvas); + if (mStatusBarHeight == -1) { + mStatusBarHeight = getStatusBarHeight(this); } + int statusHeight = mStatusBarHeight; + synchronized (mBitmap) { + int bmWidth = mBitmap.getWidth(); + int bmHeight = mBitmap.getHeight(); + int margin = mOSDMargin; - */ + Canvas canvas = new Canvas(mBitmap); + boolean aa = canvas.isHardwareAccelerated(); + Rect textBounds = new Rect(); + + // mBitmap.eraseColor(Color.argb(0, 0, 0, 0)); + // bitmap.eraseColor(Color.argb(0, 0, 0, 0)); + canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + + for (OSD_ITEM osdItem : mOSDItems) { + String text = updateOSDTime(osdItem.text, ts); + + int x = osdItem.previousRect.left; + int y = osdItem.previousRect.top; + + if ((osdItem.mask & TIME_MASK_LT) != 0) { + // canvas.drawRect(osdItem.previousRect, mEmptyPaint); + mPaintStroker.getTextBounds(text, 0, text.length(), textBounds); + + Log.d("OSD", "UPD OSD x=" + x + " y=" + y); + canvas.drawText(text, x, y, mPaint); + canvas.drawText(text, x, y, mPaintStroker); + osdItem.previousRect.set(x, y, x + textBounds.width(), y + textBounds.height()); + + } else if ((osdItem.mask & TIME_MASK_LB) != 0) { + // canvas.drawRect(osdItem.previousRect, mEmptyPaint); + mPaintStroker.getTextBounds(text, 0, text.length(), textBounds); + + y = osdItem.origin.y - textBounds.height(); + canvas.drawText(text, x, y, mPaint); + canvas.drawText(text, x, y, mPaintStroker); + osdItem.previousRect.set(x, y, x + textBounds.width(), y + textBounds.height()); + + } else if ((osdItem.mask & TIME_MASK_RT) != 0) { + // canvas.drawRect(osdItem.previousRect, mEmptyPaint); + mPaintStroker.getTextBounds(text, 0, text.length(), textBounds); + + x = osdItem.origin.x - textBounds.width(); + canvas.drawText(text, x, osdItem.origin.y, mPaint); + canvas.drawText(text, x, osdItem.origin.y, mPaintStroker); + osdItem.previousRect.set(x, osdItem.origin.y, x + textBounds.width(), osdItem.origin.y + textBounds.height()); + + } else if ((osdItem.mask & TIME_MASK_RB) != 0) { + // canvas.drawRect(osdItem.previousRect, mEmptyPaint); + mPaintStroker.getTextBounds(text, 0, text.length(), textBounds); + + x = osdItem.origin.x - textBounds.width(); + y = osdItem.origin.y - textBounds.height(); + canvas.drawText(text, x, y, mPaint); + canvas.drawText(text, x, y, mPaintStroker); + osdItem.previousRect.set(x, y, x + textBounds.width(), y + textBounds.height()); + } else { + canvas.drawText(text, x, y, mPaint); + canvas.drawText(text, x, y, mPaintStroker); + } + } + } } private String updateOSDTime(String osd, long ts) { @@ -404,7 +598,6 @@ public class Camera2VideoActivity extends AppCompatActivity { } } - private void setUpCameraView() { runOnUiThread(() -> { @@ -422,6 +615,9 @@ public class Camera2VideoActivity extends AppCompatActivity { mPaintStroker.setTextSize(fontSize); mPaintStroker.setStrokeWidth(1); + mEmptyPaint = new Paint(); + mEmptyPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + mBitmap = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(mBitmap); @@ -480,7 +676,7 @@ public class Camera2VideoActivity extends AppCompatActivity { if (mTimeMask != 0) { long ts = System.currentTimeMillis(); long ms = ts % 1000; - updateOSD(ts - ms); + initOSD(ts - ms); mHandler.postDelayed(mTimerRunnable, 1000 - ms); } diff --git a/gpuv/src/main/java/com/xypower/gpuv/egl/filter/GlOverlayFilter.java b/gpuv/src/main/java/com/xypower/gpuv/egl/filter/GlOverlayFilter.java index f3ca899f..617432f8 100644 --- a/gpuv/src/main/java/com/xypower/gpuv/egl/filter/GlOverlayFilter.java +++ b/gpuv/src/main/java/com/xypower/gpuv/egl/filter/GlOverlayFilter.java @@ -3,6 +3,7 @@ package com.xypower.gpuv.egl.filter; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.PorterDuff; import android.opengl.GLES20; import android.opengl.GLUtils; import android.util.Size; @@ -46,6 +47,7 @@ public abstract class GlOverlayFilter extends GlFilter { private void createBitmap() { releaseBitmap(bitmap); bitmap = Bitmap.createBitmap(inputResolution.getWidth(), inputResolution.getHeight(), Bitmap.Config.ARGB_8888); + bitmap.eraseColor(Color.argb(0, 0, 0, 0)); } @Override @@ -71,7 +73,7 @@ public abstract class GlOverlayFilter extends GlFilter { createBitmap(); } - bitmap.eraseColor(Color.argb(0, 0, 0, 0)); + // bitmap.eraseColor(Color.argb(0, 0, 0, 0)); Canvas bitmapCanvas = new Canvas(bitmap); bitmapCanvas.scale(1, -1, bitmapCanvas.getWidth() / 2, bitmapCanvas.getHeight() / 2); drawCanvas(bitmapCanvas); 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 26aeeb18..6a265971 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 @@ -2,7 +2,10 @@ package com.xypower.gpuv.egl.filter; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.PorterDuff; import android.graphics.Rect; +import android.util.Log; public class GlWatermarkFilter extends GlOverlayFilter { @@ -22,6 +25,8 @@ public class GlWatermarkFilter extends GlOverlayFilter { @Override protected void drawCanvas(Canvas canvas) { synchronized (bitmap) { + Log.d("OSD", "drawCanvas"); + canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); canvas.drawBitmap(bitmap, null, canvas.getClipBounds(), null); }