|
|
|
@ -10,7 +10,6 @@ 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;
|
|
|
|
@ -23,12 +22,10 @@ import android.text.TextUtils;
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
import android.view.Window;
|
|
|
|
|
import android.view.WindowInsets;
|
|
|
|
|
import android.view.WindowInsetsController;
|
|
|
|
|
import android.view.WindowManager;
|
|
|
|
|
import android.view.WindowMetrics;
|
|
|
|
|
import android.widget.FrameLayout;
|
|
|
|
|
|
|
|
|
|
import androidx.annotation.RequiresApi;
|
|
|
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
|
|
|
|
|
|
|
@ -85,7 +82,9 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
private Paint mPaint;
|
|
|
|
|
private Paint mPaintStroker;
|
|
|
|
|
private Bitmap mBitmap;
|
|
|
|
|
GlWatermarkFilter mOSDFilter = null;
|
|
|
|
|
private GlWatermarkFilter mOSDFilter = null;
|
|
|
|
|
private Object mBitmapLocker = new Object();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private SimpleDateFormat mDateFormater;
|
|
|
|
|
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
|
|
|
|
@ -97,7 +96,7 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
private int mStatusBarHeight = -1;
|
|
|
|
|
private long mOsdTs = 0;
|
|
|
|
|
private Semaphore mOSDSemaphore = new Semaphore(0);
|
|
|
|
|
private Thread mOsdThread = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static class OSD_ITEM
|
|
|
|
|
{
|
|
|
|
@ -130,32 +129,53 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
private Runnable mTimerRunnable = new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
|
|
|
|
|
synchronized (mBitmapLocker) {
|
|
|
|
|
if (mBitmap != null) {
|
|
|
|
|
Bitmap bitmap = mBitmap;
|
|
|
|
|
mBitmap = null;
|
|
|
|
|
mOSDFilter.updateBitmap(bitmap);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long ts = System.currentTimeMillis();
|
|
|
|
|
mOsdTs = ts + 1000; // next second
|
|
|
|
|
long ms = ts % 1000;
|
|
|
|
|
if (ms > 900) {
|
|
|
|
|
ts += 1000 - ms;
|
|
|
|
|
ms = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// updateOSD(ts);
|
|
|
|
|
Bitmap bitmap = mBitmap;
|
|
|
|
|
mBitmap = null;
|
|
|
|
|
mOSDFilter.updateBitmap(bitmap);
|
|
|
|
|
Log.d("OSD", "Cur TS=" + Long.toString(ts / 1000) + " Timer=" + Long.toString(1000 - ms));
|
|
|
|
|
|
|
|
|
|
mBitmap = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888);
|
|
|
|
|
mOsdTs = ts;
|
|
|
|
|
mOSDSemaphore.release();
|
|
|
|
|
|
|
|
|
|
mHandler.postDelayed(this, 1000 - ms);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private Thread mOsdThread = new Thread(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
while (true) {
|
|
|
|
|
try {
|
|
|
|
|
mOSDSemaphore.acquire();
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mOsdTs == -1) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateOSD(mOsdTs);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
|
|
|
|
|
|
|
|
|
Window win = getWindow();
|
|
|
|
|
// win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
|
|
|
|
win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
|
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
|
|
|
/*
|
|
|
|
@ -206,9 +226,6 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void onCreateActivity() {
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
// SysApi.setCam3V3Enable(true);
|
|
|
|
|
|
|
|
|
|
Intent intent = getIntent();
|
|
|
|
|
|
|
|
|
@ -288,27 +305,11 @@ 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();
|
|
|
|
|
|
|
|
|
|
long ts = 0;
|
|
|
|
|
long zeroTs = 0;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
@ -327,33 +328,46 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
Canvas canvas = new Canvas(mBitmap);
|
|
|
|
|
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
|
|
|
|
|
|
|
|
|
|
mOSDFilter = new GlWatermarkFilter(mBitmap);
|
|
|
|
|
|
|
|
|
|
long ts = System.currentTimeMillis();
|
|
|
|
|
ts = System.currentTimeMillis();
|
|
|
|
|
zeroTs = ts - (ts % 1000);
|
|
|
|
|
initOSD(zeroTs);
|
|
|
|
|
|
|
|
|
|
initOSD(ts);
|
|
|
|
|
mOSDFilter = new GlWatermarkFilter(mBitmap);
|
|
|
|
|
|
|
|
|
|
mOsdTs = ts + 1000;
|
|
|
|
|
long ms = ts % 1000;
|
|
|
|
|
mOSDSemaphore.release();
|
|
|
|
|
mHandler.postDelayed(mTimerRunnable, 1000 - ms);
|
|
|
|
|
mBitmap = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888);
|
|
|
|
|
updateOSD(zeroTs + 1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final long prevZeroTs = zeroTs;
|
|
|
|
|
mHandler.postDelayed(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
mNextVideoAbsolutePath = getVideoFilePath();
|
|
|
|
|
|
|
|
|
|
mGPUCameraRecorder.start(mNextVideoAbsolutePath);
|
|
|
|
|
|
|
|
|
|
long ts2 = System.currentTimeMillis();
|
|
|
|
|
long zeroTs2 = ts2 - (ts2 % 1000);
|
|
|
|
|
|
|
|
|
|
if (zeroTs2 > prevZeroTs) {
|
|
|
|
|
// Next second
|
|
|
|
|
mOSDFilter.updateBitmap(mBitmap);
|
|
|
|
|
mBitmap = null;
|
|
|
|
|
mOsdTs = zeroTs2 + 1000;
|
|
|
|
|
mOSDSemaphore.release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Log.d("OSD", "Cur TS=" + Long.toString(ts2 / 1000) + " Timer=" + Long.toString(1000 - (ts2 - zeroTs2)));
|
|
|
|
|
mHandler.postDelayed(mTimerRunnable, 1000 - (ts2 - zeroTs2));
|
|
|
|
|
}
|
|
|
|
|
}, 32);
|
|
|
|
|
}, 0);
|
|
|
|
|
|
|
|
|
|
mHandler.postDelayed(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
mGPUCameraRecorder.stop();
|
|
|
|
|
}
|
|
|
|
|
}, 48 + mDuration * 1000);
|
|
|
|
|
}, 16 + mDuration * 1000);
|
|
|
|
|
|
|
|
|
|
// getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
|
|
|
|
}
|
|
|
|
@ -372,11 +386,13 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
|
|
|
|
|
private void initOSD(long ts) {
|
|
|
|
|
|
|
|
|
|
Log.d("OSD", "INIT OSD " + Long.toString(ts / 1000));
|
|
|
|
|
|
|
|
|
|
if (mStatusBarHeight == -1) {
|
|
|
|
|
mStatusBarHeight = getStatusBarHeight(this);
|
|
|
|
|
}
|
|
|
|
|
int statusHeight = mStatusBarHeight;
|
|
|
|
|
synchronized (mBitmap) {
|
|
|
|
|
synchronized (mBitmapLocker) {
|
|
|
|
|
int bmWidth = mBitmap.getWidth();
|
|
|
|
|
int bmHeight = mBitmap.getHeight();
|
|
|
|
|
int margin = mOSDMargin;
|
|
|
|
@ -416,7 +432,6 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
} 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);
|
|
|
|
|
|
|
|
|
@ -556,72 +571,67 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
|
|
|
|
|
private void updateOSD(long ts) {
|
|
|
|
|
|
|
|
|
|
Log.d("OSD", "prepareOSD " + Long.toString(ts / 1000));
|
|
|
|
|
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();
|
|
|
|
|
Bitmap bm = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888);
|
|
|
|
|
|
|
|
|
|
// mBitmap.eraseColor(Color.argb(0, 0, 0, 0));
|
|
|
|
|
// bitmap.eraseColor(Color.argb(0, 0, 0, 0));
|
|
|
|
|
Canvas canvas = new Canvas(bm);
|
|
|
|
|
boolean aa = canvas.isHardwareAccelerated();
|
|
|
|
|
Rect textBounds = new Rect();
|
|
|
|
|
|
|
|
|
|
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
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) {
|
|
|
|
|
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) {
|
|
|
|
|
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) {
|
|
|
|
|
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) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
synchronized (mBitmapLocker) {
|
|
|
|
|
mBitmap = bm;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String updateOSDTime(String osd, long ts) {
|
|
|
|
@ -640,7 +650,6 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
return newOSD;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void releaseCamera() {
|
|
|
|
|
if (mPreviewView != null) {
|
|
|
|
|
mPreviewView.onPause();
|
|
|
|
@ -685,8 +694,6 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
mNextVideoAbsolutePath = getVideoFilePath(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mGPUCameraRecorder = new GPUCameraRecorderBuilder(this, mPreviewView)
|
|
|
|
|
//.recordNoFilter(true)
|
|
|
|
|
.cameraRecordListener(new CameraRecordListener() {
|
|
|
|
@ -712,9 +719,6 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onRecordStart() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -729,7 +733,6 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onVideoFileReady() {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.videoSize(mVideoWidth, mVideoHeight)
|
|
|
|
@ -740,7 +743,6 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
if (mOSDFilter != null) {
|
|
|
|
|
mGPUCameraRecorder.setFilter(mOSDFilter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// private void changeFilter(Filters filters) {
|
|
|
|
@ -846,7 +848,6 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static void exportMp4ToGallery(Context context, String filePath) {
|
|
|
|
|
final ContentValues values = new ContentValues(2);
|
|
|
|
|
values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
|
|
|
|
|