|
|
|
@ -17,6 +17,8 @@ import android.os.Build;
|
|
|
|
|
import android.os.Bundle;
|
|
|
|
|
import android.os.Environment;
|
|
|
|
|
import android.os.Handler;
|
|
|
|
|
import android.os.Looper;
|
|
|
|
|
import android.os.Message;
|
|
|
|
|
import android.provider.MediaStore;
|
|
|
|
|
import android.text.TextUtils;
|
|
|
|
|
import android.util.Log;
|
|
|
|
@ -49,6 +51,7 @@ import java.text.SimpleDateFormat;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Timer;
|
|
|
|
|
import java.util.concurrent.Semaphore;
|
|
|
|
|
|
|
|
|
|
public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
@ -81,11 +84,12 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
private int mOSDMargin = 0;
|
|
|
|
|
private Paint mPaint;
|
|
|
|
|
private Paint mPaintStroker;
|
|
|
|
|
private Bitmap mBitmap;
|
|
|
|
|
|
|
|
|
|
private List<Bitmap> mBitmaps = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
private GlWatermarkFilter mOSDFilter = null;
|
|
|
|
|
private Object mBitmapLocker = new Object();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private SimpleDateFormat mDateFormater;
|
|
|
|
|
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
|
|
|
|
|
|
|
|
|
@ -94,9 +98,6 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
|
|
|
|
|
private int mTimeMask = 0;
|
|
|
|
|
private int mStatusBarHeight = -1;
|
|
|
|
|
private long mOsdTs = 0;
|
|
|
|
|
private Semaphore mOSDSemaphore = new Semaphore(0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static class OSD_ITEM
|
|
|
|
|
{
|
|
|
|
@ -126,48 +127,74 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
private final static int TIME_MASK_LB = TIME_MASK_LB_TS | TIME_MASK_LB_DT | TIME_MASK_LB_ML;
|
|
|
|
|
|
|
|
|
|
private Handler mHandler = null;
|
|
|
|
|
private Runnable mTimerRunnable = new Runnable() {
|
|
|
|
|
|
|
|
|
|
private class TimerRunner implements Runnable {
|
|
|
|
|
private Bitmap mBitmap;
|
|
|
|
|
|
|
|
|
|
TimerRunner(Bitmap bm) {
|
|
|
|
|
mBitmap = bm;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
|
|
|
|
|
synchronized (mBitmapLocker) {
|
|
|
|
|
Bitmap oldBm = null;
|
|
|
|
|
if (mBitmap != null) {
|
|
|
|
|
Bitmap bitmap = mBitmap;
|
|
|
|
|
mBitmap = null;
|
|
|
|
|
mOSDFilter.updateBitmap(bitmap);
|
|
|
|
|
oldBm = mOSDFilter.updateBitmap(mBitmap);
|
|
|
|
|
}
|
|
|
|
|
if (oldBm != null) {
|
|
|
|
|
synchronized (mBitmapLocker) {
|
|
|
|
|
mBitmaps.add(oldBm);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long ts = System.currentTimeMillis();
|
|
|
|
|
mOsdTs = ts + 1000; // next second
|
|
|
|
|
long ms = ts % 1000;
|
|
|
|
|
|
|
|
|
|
Log.d("OSD", "Cur TS=" + Long.toString(ts / 1000) + " Timer=" + Long.toString(1000 - ms));
|
|
|
|
|
|
|
|
|
|
mOSDSemaphore.release();
|
|
|
|
|
|
|
|
|
|
mHandler.postDelayed(this, 1000 - ms);
|
|
|
|
|
Message msg = Message.obtain();
|
|
|
|
|
msg.what = 1;
|
|
|
|
|
msg.obj = new Long(ts - ms + 1000);
|
|
|
|
|
mOsdHandler.sendMessage(msg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private Handler mOsdHandler;
|
|
|
|
|
private Thread mOsdThread = new Thread(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
while (true) {
|
|
|
|
|
try {
|
|
|
|
|
mOSDSemaphore.acquire();
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
}
|
|
|
|
|
Looper.prepare();
|
|
|
|
|
|
|
|
|
|
if (mOsdTs == -1) {
|
|
|
|
|
break;
|
|
|
|
|
mOsdHandler = new Handler(Looper.myLooper()) {
|
|
|
|
|
public void handleMessage(Message msg) {
|
|
|
|
|
if (msg.what == 1) {
|
|
|
|
|
Long targetTs = (Long)msg.obj;
|
|
|
|
|
long ts = System.currentTimeMillis();
|
|
|
|
|
if (ts > targetTs.longValue()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
Bitmap bm = null;
|
|
|
|
|
synchronized (mBitmapLocker) {
|
|
|
|
|
if (!mBitmaps.isEmpty()) {
|
|
|
|
|
bm = mBitmaps.remove(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (bm != null) {
|
|
|
|
|
updateOSD(bm, targetTs.longValue());
|
|
|
|
|
|
|
|
|
|
updateOSD(mOsdTs);
|
|
|
|
|
TimerRunner runner = new TimerRunner(bm);
|
|
|
|
|
mHandler.postDelayed(runner, targetTs.longValue() - ts);
|
|
|
|
|
}
|
|
|
|
|
} else if (msg.what == 0) {
|
|
|
|
|
Looper.myLooper().quitSafely();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Looper.loop();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
@ -177,18 +204,6 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
Window win = getWindow();
|
|
|
|
|
win.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
|
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
|
|
|
/*
|
|
|
|
|
win.setDecorFitsSystemWindows(false);
|
|
|
|
|
WindowInsetsController controller = win.getInsetsController();
|
|
|
|
|
if (controller != null) {
|
|
|
|
|
controller.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars());
|
|
|
|
|
controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setContentView(R.layout.activity_camera2_video);
|
|
|
|
|
|
|
|
|
|
getSupportActionBar().hide();
|
|
|
|
@ -222,6 +237,13 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
|
|
|
|
|
int statusBarHeight = frame.top;
|
|
|
|
|
|
|
|
|
|
if (statusBarHeight == 0) {
|
|
|
|
|
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
|
|
|
|
|
if (resourceId > 0) {
|
|
|
|
|
statusBarHeight = px2dip(context, getResources().getDimensionPixelSize(resourceId));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return statusBarHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -239,7 +261,7 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
mOSDLeftBottom = intent.getStringExtra("leftBottomOsd");
|
|
|
|
|
mOSDRightBottom = intent.getStringExtra("rightBottomOsd");
|
|
|
|
|
mOSDRightTop = intent.getStringExtra("rightTopOsd");
|
|
|
|
|
mOSDMargin = intent.getIntExtra("margin", 0);
|
|
|
|
|
mOSDMargin = px2dip(this, intent.getIntExtra("margin", 12));
|
|
|
|
|
|
|
|
|
|
mCameraWidth = mVideoWidth;
|
|
|
|
|
mCameraHeight = mVideoHeight;
|
|
|
|
@ -310,6 +332,7 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
long ts = 0;
|
|
|
|
|
long zeroTs = 0;
|
|
|
|
|
|
|
|
|
|
Bitmap bm2 = null;
|
|
|
|
|
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);
|
|
|
|
@ -323,22 +346,27 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
mPaintStroker.setTextSize(fontSize);
|
|
|
|
|
mPaintStroker.setStrokeWidth(1);
|
|
|
|
|
|
|
|
|
|
mBitmap = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888);
|
|
|
|
|
bm2 = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888);
|
|
|
|
|
|
|
|
|
|
Bitmap bm = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888);
|
|
|
|
|
|
|
|
|
|
Canvas canvas = new Canvas(mBitmap);
|
|
|
|
|
Canvas canvas = new Canvas(bm);
|
|
|
|
|
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
|
|
|
|
|
|
|
|
|
|
ts = System.currentTimeMillis();
|
|
|
|
|
zeroTs = ts - (ts % 1000);
|
|
|
|
|
initOSD(zeroTs);
|
|
|
|
|
initOSD(bm, zeroTs);
|
|
|
|
|
mOSDFilter = new GlWatermarkFilter(bm);
|
|
|
|
|
|
|
|
|
|
mOSDFilter = new GlWatermarkFilter(mBitmap);
|
|
|
|
|
if (mGPUCameraRecorder != null) {
|
|
|
|
|
mGPUCameraRecorder.setFilter(mOSDFilter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mBitmap = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888);
|
|
|
|
|
updateOSD(zeroTs + 1000);
|
|
|
|
|
updateOSD(bm2, zeroTs + 1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final long prevZeroTs = zeroTs;
|
|
|
|
|
final Bitmap finalBm = bm2;
|
|
|
|
|
mHandler.postDelayed(new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
@ -352,14 +380,22 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
|
|
|
|
|
if (zeroTs2 > prevZeroTs) {
|
|
|
|
|
// Next second
|
|
|
|
|
mOSDFilter.updateBitmap(mBitmap);
|
|
|
|
|
mBitmap = null;
|
|
|
|
|
mOsdTs = zeroTs2 + 1000;
|
|
|
|
|
mOSDSemaphore.release();
|
|
|
|
|
Bitmap oldBm = mOSDFilter.updateBitmap(finalBm);
|
|
|
|
|
if (oldBm != null) {
|
|
|
|
|
synchronized (mBitmapLocker) {
|
|
|
|
|
mBitmaps.add(oldBm);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Message msg = Message.obtain();
|
|
|
|
|
msg.what = 1;
|
|
|
|
|
msg.obj = new Long(zeroTs2 + 1000);
|
|
|
|
|
// mOsdTs = zeroTs2 + 1000;
|
|
|
|
|
mOsdHandler.sendMessage(msg);
|
|
|
|
|
} else {
|
|
|
|
|
TimerRunner runner = new TimerRunner(finalBm);
|
|
|
|
|
mHandler.postDelayed(runner, 1000 - (ts2 - zeroTs2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Log.d("OSD", "Cur TS=" + Long.toString(ts2 / 1000) + " Timer=" + Long.toString(1000 - (ts2 - zeroTs2)));
|
|
|
|
|
mHandler.postDelayed(mTimerRunnable, 1000 - (ts2 - zeroTs2));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}, 0);
|
|
|
|
@ -386,7 +422,7 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
releaseCamera();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void initOSD(long ts) {
|
|
|
|
|
private void initOSD(Bitmap bm, long ts) {
|
|
|
|
|
|
|
|
|
|
Log.d("OSD", "INIT OSD " + Long.toString(ts / 1000));
|
|
|
|
|
|
|
|
|
@ -394,15 +430,14 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
mStatusBarHeight = getStatusBarHeight(this);
|
|
|
|
|
}
|
|
|
|
|
int statusHeight = mStatusBarHeight;
|
|
|
|
|
synchronized (mBitmapLocker) {
|
|
|
|
|
int bmWidth = mBitmap.getWidth();
|
|
|
|
|
int bmHeight = mBitmap.getHeight();
|
|
|
|
|
|
|
|
|
|
int bmWidth = bm.getWidth();
|
|
|
|
|
int bmHeight = bm.getHeight();
|
|
|
|
|
int margin = mOSDMargin;
|
|
|
|
|
int x = 0;
|
|
|
|
|
int y = 0;
|
|
|
|
|
// mOSDFilter.
|
|
|
|
|
|
|
|
|
|
Canvas canvas = new Canvas(mBitmap);
|
|
|
|
|
Canvas canvas = new Canvas(bm);
|
|
|
|
|
Rect textBounds = new Rect();
|
|
|
|
|
|
|
|
|
|
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
|
|
|
|
@ -568,10 +603,10 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
origin.y -= (textBounds.height() * 5) >> 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateOSD(long ts) {
|
|
|
|
|
private void updateOSD(Bitmap bm, long ts) {
|
|
|
|
|
|
|
|
|
|
Log.d("OSD", "prepareOSD " + Long.toString(ts / 1000));
|
|
|
|
|
if (mStatusBarHeight == -1) {
|
|
|
|
@ -579,8 +614,6 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
}
|
|
|
|
|
int statusHeight = mStatusBarHeight;
|
|
|
|
|
|
|
|
|
|
Bitmap bm = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888);
|
|
|
|
|
|
|
|
|
|
Canvas canvas = new Canvas(bm);
|
|
|
|
|
boolean aa = canvas.isHardwareAccelerated();
|
|
|
|
|
Rect textBounds = new Rect();
|
|
|
|
@ -631,9 +664,6 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
synchronized (mBitmapLocker) {
|
|
|
|
|
mBitmap = bm;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String updateOSDTime(String osd, long ts) {
|
|
|
|
@ -681,11 +711,8 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
if (mGPUCameraRecorder == null) return;
|
|
|
|
|
mGPUCameraRecorder.changeManualFocusPoint(event.getX(), event.getY(), width, height);
|
|
|
|
|
});
|
|
|
|
|
frameLayout.addView(mPreviewView);
|
|
|
|
|
|
|
|
|
|
if (mGPUCameraRecorder != null) {
|
|
|
|
|
mGPUCameraRecorder.setFilter(mOSDFilter);
|
|
|
|
|
}
|
|
|
|
|
frameLayout.addView(mPreviewView);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -706,9 +733,11 @@ public class Camera2VideoActivity extends AppCompatActivity {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onRecordComplete() {
|
|
|
|
|
mHandler.removeCallbacks(mTimerRunnable);
|
|
|
|
|
mOsdTs = -1;
|
|
|
|
|
mOSDSemaphore.release();
|
|
|
|
|
// mHandler.removeCallbacks(mTimerRunnable);
|
|
|
|
|
Message msg = Message.obtain();
|
|
|
|
|
msg.what = 0;
|
|
|
|
|
mOsdHandler.sendMessage(msg);
|
|
|
|
|
|
|
|
|
|
exportMp4ToGallery(getApplicationContext(), mNextVideoAbsolutePath);
|
|
|
|
|
broadcastVideoFile(true, mNextVideoAbsolutePath);
|
|
|
|
|
mHandler.postDelayed(new Runnable() {
|
|
|
|
|