You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
TermApp/app/src/main/java/com/xypower/mpapp/v2/Camera2VideoActivity.java

951 lines
35 KiB
Java

package com.xypower.mpapp.v2;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
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.Rect;
import android.net.Uri;
import android.opengl.GLException;
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;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowMetrics;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.xypower.gpuv.camerarecorder.CameraRecordListener;
import com.xypower.gpuv.camerarecorder.GPUCameraRecorder;
import com.xypower.gpuv.camerarecorder.GPUCameraRecorderBuilder;
import com.xypower.gpuv.egl.filter.GlWatermarkFilter;
import com.xypower.mpapp.v2.AutoFitGLView;
import com.xypower.mpapp.MicroPhotoService;
import com.xypower.mpapp.R;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.opengles.GL10;
import java.io.File;
import java.io.FileNotFoundException;
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 {
public static final String ACTION_FINISH = "com.xypower.mvapp.ACT_FINISH";
public static final String ACTION_MP_VIDEO_FINISHED = "com.xypower.mpapp.ACT_V_FINISHED";
public final static int REQUEST_CODE_RECORDING = 2;
private static final int DEFAULT_FONT_SIZE = 32;
private static final float DEFAULT_STROKE_WIDTH = 0.8f;
private AutoFitGLView mPreviewView;
protected GPUCameraRecorder mGPUCameraRecorder;
// protected LensFacing lensFacing = LensFacing.BACK;
protected int mCameraWidth = 1280;
protected int mCameraHeight = 720;
protected int mVideoWidth = 1280;
protected int mVideoHeight = 720;
protected int mPreviewWidth = 1280;
protected int mPreviewHeight = 720;
private int mCameraId;
private long mVideoId = 0;
private long mDuration = 0;
private int mOrientation = -1;
private String mNextVideoAbsolutePath;
private String mOSDLeftTop = null;
private String mOSDRightTop = null;
private String mOSDRightBottom = null;
private String mOSDLeftBottom = null;
private int mOSDMargin = 0;
private Paint mPaint;
private Paint mPaintStroker;
private GlWatermarkFilter mOSDFilter = null;
private SimpleDateFormat mDateFormater;
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
private final String TIME_MICRO_TS = "$$TS$$";
private final String TIME_MICRO_DT = "$$DATETIME$$";
private int mTimeMask = 0;
private int mStatusBarHeight = -1;
private boolean mActivityResult = false;
private static class OSD_ITEM
{
String text;
int mask;
Point origin;
Rect previousRect;
}
private List<OSD_ITEM> 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;
private final static int TIME_MASK_LT = TIME_MASK_LT_TS | TIME_MASK_LT_DT | TIME_MASK_LT_ML;
private final static int TIME_MASK_RT_TS = 8;
private final static int TIME_MASK_RT_DT = 16;
private final static int TIME_MASK_RT_ML = 32;
private final static int TIME_MASK_RT = TIME_MASK_RT_TS | TIME_MASK_RT_DT | TIME_MASK_RT_ML;
private final static int TIME_MASK_RB_TS = 64;
private final static int TIME_MASK_RB_DT = 128;
private final static int TIME_MASK_RB_ML = 256;
private final static int TIME_MASK_RB = TIME_MASK_RB_TS | TIME_MASK_RB_DT | TIME_MASK_RB_ML;
private final static int TIME_MASK_LB_TS = 512;
private final static int TIME_MASK_LB_DT = 1024;
private final static int TIME_MASK_LB_ML = 2048;
private final static int TIME_MASK_LB = TIME_MASK_LB_TS | TIME_MASK_LB_DT | TIME_MASK_LB_ML;
private Handler mHandler = null;
private Thread mOsdThread = new Thread(new Runnable() {
@Override
public void run() {
try {
long ts = System.currentTimeMillis();
1 year ago
Bitmap bm = Bitmap.createBitmap(mPreviewWidth, mPreviewHeight, Bitmap.Config.ARGB_8888);
Bitmap oldBm = null;
Canvas canvas = new Canvas(bm);
long zeroTs = ts - (ts % 1000);
long nextTs = zeroTs + 1000;
while (true) {
try {
if (nextTs > ts) {
Log.i("OSD", "Sleep " + Long.toString(nextTs - ts));
Thread.sleep(nextTs - ts);
}
} catch (InterruptedException ex){
break;
} catch(Exception ex){
}
canvas.setBitmap(bm);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
updateOSD(bm, nextTs);
oldBm = mOSDFilter.updateBitmap(bm);
bm = oldBm;
ts = System.currentTimeMillis();
zeroTs = ts - (ts % 1000);
if (zeroTs + 1000 > nextTs) {
nextTs = zeroTs + 1000;
}
}
} catch (Exception ex) {
}
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
Window win = getWindow();
int flags = /*WindowManager.LayoutParams.FLAG_FULLSCREEN
| */WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
int mask = /*WindowManager.LayoutParams.FLAG_FULLSCREEN |
| */WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
win.setFlags(flags, mask);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(true);
}
setContentView(R.layout.activity_camera2_video);
getSupportActionBar().hide();
// mStatusBarHeight = getStatusBarHeight(this);
onCreateActivity();
getWindow().getDecorView().setOnApplyWindowInsetsListener((v, insets) -> {
mStatusBarHeight = px2dip(Camera2VideoActivity.this, insets.getStableInsetTop());
return insets;
});
}
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();
1 year ago
Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.statusBars() | WindowInsets.Type.displayCutout());
return px2dip(this, insets.top);
}
Rect frame = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
if (statusBarHeight == 0) {
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
}
return px2dip(context, statusBarHeight);
}
protected void onCreateActivity() {
Intent intent = getIntent();
mCameraId = intent.getIntExtra("cameraId", 0);
mVideoId = intent.getLongExtra("videoId", 0);
mDuration = intent.getIntExtra("duration", 0);
mVideoWidth = intent.getIntExtra("width", 0);
mVideoHeight = intent.getIntExtra("height", 0);
mOrientation = intent.getIntExtra("orientation", -1);
mOSDLeftTop = intent.getStringExtra("leftTopOsd");
mOSDLeftBottom = intent.getStringExtra("leftBottomOsd");
mOSDRightBottom = intent.getStringExtra("rightBottomOsd");
mOSDRightTop = intent.getStringExtra("rightTopOsd");
1 year ago
mOSDMargin = intent.getIntExtra("margin", 12);
mActivityResult = intent.getBooleanExtra("ActivityResult", false);
mCameraWidth = mVideoWidth;
mCameraHeight = mVideoHeight;
AspectRatioFrameLayout frameLayout = (AspectRatioFrameLayout)findViewById(R.id.wrap_view);
frameLayout.setOnSizeChangedListener(new AspectRatioFrameLayout.OnSizeChangeListener() {
@Override
public void onSizeChanged(int width, int height) {
Log.i("OSD", "width=" + Integer.toString(width));
}
});
frameLayout.setAspectRatio((float)mVideoWidth / (float)mVideoHeight);
mTimeMask = 0;
if (!TextUtils.isEmpty(mOSDLeftTop)) {
if (mOSDLeftTop.indexOf(TIME_MICRO_TS) != 0) {
mTimeMask |= TIME_MASK_LT_TS;
}
if (mOSDLeftTop.indexOf(TIME_MICRO_DT) != 0) {
mTimeMask |= TIME_MASK_LT_DT;
}
if (mOSDLeftTop.indexOf("\n") != 0) {
mTimeMask |= TIME_MASK_LT_ML;
}
}
if (!TextUtils.isEmpty(mOSDRightTop)) {
if (mOSDRightTop.indexOf(TIME_MICRO_TS) != 0) {
mTimeMask |= TIME_MASK_RT_TS;
}
if (mOSDRightTop.indexOf(TIME_MICRO_DT) != 0) {
mTimeMask |= TIME_MASK_RT_DT;
}
if (mOSDRightTop.indexOf("\n") != 0) {
mTimeMask |= TIME_MASK_RT_ML;
}
}
if (!TextUtils.isEmpty(mOSDRightBottom)) {
if (mOSDRightBottom.indexOf(TIME_MICRO_TS) != 0) {
mTimeMask |= TIME_MASK_RB_TS;
}
if (mOSDRightBottom.indexOf(TIME_MICRO_DT) != 0) {
mTimeMask |= TIME_MASK_RB_DT;
}
if (mOSDRightBottom.indexOf("\n") != 0) {
mTimeMask |= TIME_MASK_RB_ML;
}
}
if (!TextUtils.isEmpty(mOSDLeftBottom)) {
if (mOSDLeftBottom.indexOf(TIME_MICRO_TS) != 0) {
mTimeMask |= TIME_MASK_LB_TS;
}
if (mOSDLeftBottom.indexOf(TIME_MICRO_DT) != 0) {
mTimeMask |= TIME_MASK_LB_DT;
}
if (mOSDLeftBottom.indexOf("\n") != 0) {
mTimeMask |= TIME_MASK_LB_ML;
}
}
mHandler = new Handler();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
setUpCamera();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mNextVideoAbsolutePath = getVideoFilePath();
if (mGPUCameraRecorder != null) {
mGPUCameraRecorder.start(mNextVideoAbsolutePath);
} else {
int aa = 0;
}
}
}, 0);
}
}, 100);
// getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
@Override
protected void onResume() {
super.onResume();
Log.i("OSD", "onResume");
}
@Override
protected void onStop() {
super.onStop();
Log.i("OSD", "onStop");
}
@Override
protected void onDestroy() {
Log.i("OSD", "onDestroy");
releaseCamera();
super.onDestroy();
}
private void initOSD(Bitmap bm, long ts) {
Log.i("OSD", "INIT OSD " + Long.toString(ts / 1000));
if (mStatusBarHeight == -1) {
mStatusBarHeight = getStatusBarHeight(this);
}
int statusHeight = mStatusBarHeight;
1 year ago
int bmWidth = bm.getWidth();
int bmHeight = bm.getHeight();
int margin = mOSDMargin;
int x = 0;
int y = 0;
Canvas canvas = new Canvas(bm);
Rect textBounds = new Rect();
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
if (!TextUtils.isEmpty(mOSDLeftTop)) {
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);
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() * 3) >> 1;
}
}
if (!TextUtils.isEmpty(mOSDLeftBottom)) {
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() * 3) >> 1;
}
}
if (!TextUtils.isEmpty(mOSDRightTop)) {
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() * 3) >> 1;
}
}
if (!TextUtils.isEmpty(mOSDRightBottom)) {
String[] items = mOSDRightBottom.split("\n");
Point origin = new Point(bmWidth - margin, bmHeight - margin);
1 year ago
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() * 3) >> 1;
}
}
}
private void updateOSD(Bitmap bm, long ts) {
Log.i("OSD", "prepareOSD " + Long.toString(ts / 1000));
if (mStatusBarHeight == -1) {
mStatusBarHeight = getStatusBarHeight(this);
}
int statusHeight = mStatusBarHeight;
Canvas canvas = new Canvas(bm);
// boolean aa = canvas.isHardwareAccelerated();
Rect textBounds = new Rect();
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) {
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);
}
}
}
private String updateOSDTime(String osd, long ts) {
String newOSD = osd;
if (newOSD.indexOf(TIME_MICRO_TS) != -1) {
newOSD = newOSD.replace(TIME_MICRO_TS, Long.toString(ts / 1000));
}
if (newOSD.indexOf(TIME_MICRO_DT) != -1) {
if (mDateFormater == null) {
mDateFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
Date dt = new Date(ts);
newOSD = newOSD.replace(TIME_MICRO_DT, mDateFormater.format(dt));
}
return newOSD;
}
private void releaseCamera() {
if (mPreviewView != null) {
mPreviewView.onPause();
}
if (mGPUCameraRecorder != null) {
mGPUCameraRecorder.stop();
mGPUCameraRecorder.release();
mGPUCameraRecorder = null;
Log.i("OSD", "mGPUCameraRecorder destroyed");
}
if (mPreviewView != null) {
((FrameLayout) findViewById(R.id.wrap_view)).removeView(mPreviewView);
mPreviewView = null;
}
}
private void setUpCameraView() {
runOnUiThread(() -> {
final AspectRatioFrameLayout frameLayout = (AspectRatioFrameLayout)findViewById(R.id.wrap_view);
frameLayout.removeAllViews();
mPreviewView = null;
mPreviewView = new AutoFitGLView(getApplicationContext());
mPreviewView.setTouchListener((event, width, height) -> {
if (mGPUCameraRecorder == null) return;
mGPUCameraRecorder.changeManualFocusPoint(event.getX(), event.getY(), width, height);
});
mPreviewView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
}
@Override
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
if (width > 0 && height > 0) {
}
}
@Override
public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
}
});
frameLayout.addView(mPreviewView);
frameLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
int width = right - left;
int height = bottom - top;
if (width <= 0 || height <= 0) {
return;
}
frameLayout.removeOnLayoutChangeListener(this);
if (!TextUtils.isEmpty(mOSDLeftTop) || !TextUtils.isEmpty(mOSDLeftTop) || !TextUtils.isEmpty(mOSDLeftTop) || !TextUtils.isEmpty(mOSDLeftTop)) {
mPreviewWidth = frameLayout.getMeasuredWidth();
mPreviewHeight = frameLayout.getMeasuredHeight();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.WHITE);
int fontSize = DEFAULT_FONT_SIZE * mPreviewHeight / 1024;
float strokeWidth = DEFAULT_STROKE_WIDTH * mPreviewHeight / 1024;
mPaint.setTextSize(fontSize);
mPaintStroker = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaintStroker.setStyle(Paint.Style.STROKE);
mPaintStroker.setColor(Color.BLACK);
mPaintStroker.setTextSize(fontSize);
mPaintStroker.setStrokeWidth(strokeWidth);
Bitmap bm = Bitmap.createBitmap(mPreviewWidth, mPreviewHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
long ts = System.currentTimeMillis();
long zeroTs = ts - (ts % 1000);
initOSD(bm, zeroTs);
mOSDFilter = new GlWatermarkFilter(bm);
if (mGPUCameraRecorder != null) {
mGPUCameraRecorder.setFilter(mOSDFilter);
}
mOsdThread.start();
}
}
});
});
}
private void setUpCamera() {
setUpCameraView();
if (mNextVideoAbsolutePath == null || mNextVideoAbsolutePath.isEmpty()) {
mNextVideoAbsolutePath = getVideoFilePath(this);
}
mGPUCameraRecorder = new GPUCameraRecorderBuilder(this, mPreviewView)
//.recordNoFilter(true)
.cameraRecordListener(new CameraRecordListener() {
@Override
public void onGetFlashSupport(boolean flashSupport) {
}
@Override
public void onRecordComplete() {
// mHandler.removeCallbacks(mTimerRunnable);
}
@Override
public void onRecordStart() {
Log.i("OSD", "Record Start ");
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Log.i("OSD", "Record Stop " + Long.toString(mDuration));
mGPUCameraRecorder.stop();
int aa = 0;
}
1 year ago
}, 1200L + mDuration * 1000);
}
@Override
public void onError(Exception exception) {
Log.e("GPUCameraRecorder", exception.toString());
mOsdThread.interrupt();
broadcastVideoFile(false, mNextVideoAbsolutePath);
}
@Override
public void onCameraThreadFinish() {
}
@Override
public void onVideoFileReady() {
// exportMp4ToGallery(getApplicationContext(), mNextVideoAbsolutePath);
mOsdThread.interrupt();
broadcastVideoFile(true, mNextVideoAbsolutePath);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Camera2VideoActivity.this.finish();
}
}, 1000);
}
@Override
public void onDurationArrived() {
}
})
.videoSize(mVideoWidth, mVideoHeight)
.cameraSize(mCameraWidth, mCameraHeight)
.cameraId(Integer.toString(mCameraId))
.mute(true)
.duration(mDuration * 1000)
.build();
Log.i("OSD", "mGPUCameraRecorder created");
if (mOSDFilter != null) {
mGPUCameraRecorder.setFilter(mOSDFilter);
}
}
// private void changeFilter(Filters filters) {
// GPUCameraRecorder.setFilter(Filters.getFilterInstance(filters, getApplicationContext()));
// }
private interface BitmapReadyCallbacks {
void onBitmapReady(Bitmap bitmap);
}
private void captureBitmap(final BitmapReadyCallbacks bitmapReadyCallbacks) {
mPreviewView.queueEvent(() -> {
EGL10 egl = (EGL10) EGLContext.getEGL();
GL10 gl = (GL10) egl.eglGetCurrentContext().getGL();
Bitmap snapshotBitmap = createBitmapFromGLSurface(mPreviewView.getMeasuredWidth(), mPreviewView.getMeasuredHeight(), gl);
runOnUiThread(() -> {
bitmapReadyCallbacks.onBitmapReady(snapshotBitmap);
});
});
}
private void broadcastVideoFile(boolean result, String path) {
if (mDuration <= 0) {
return;
}
Context context = getApplicationContext();
String receiverName = MicroPhotoService.AlarmReceiver.class.getName();
String packageName = context.getPackageName();
Intent intent = new Intent(ACTION_MP_VIDEO_FINISHED);
// intent.setPackage(packageName);
intent.putExtra("result", result);
intent.putExtra("path", path);
intent.putExtra("videoId", mVideoId);
// intent.setComponent(new ComponentName(packageName, receiverName));
if (mActivityResult) {
setResult(RESULT_OK, intent);
} else {
// Log.i(TAG, "Notify recording videoId=" + Long.toString(mVideoId) + " " + path);
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(getApplicationContext());
localBroadcastManager.sendBroadcast(intent);
context.sendBroadcast(intent);
}
}
private String getVideoFilePath(Context context) {
// final File dir = context.getExternalFilesDir(null);
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
if (!path.endsWith(File.separator)) {
path += File.separator;
}
path += context.getPackageName() + File.separator;
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
path += System.currentTimeMillis() + ".mp4";
return path;
}
private Bitmap createBitmapFromGLSurface(int w, int h, GL10 gl) {
int bitmapBuffer[] = new int[w * h];
int bitmapSource[] = new int[w * h];
IntBuffer intBuffer = IntBuffer.wrap(bitmapBuffer);
intBuffer.position(0);
try {
gl.glReadPixels(0, 0, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, intBuffer);
int offset1, offset2, texturePixel, blue, red, pixel;
for (int i = 0; i < h; i++) {
offset1 = i * w;
offset2 = (h - i - 1) * w;
for (int j = 0; j < w; j++) {
texturePixel = bitmapBuffer[offset1 + j];
blue = (texturePixel >> 16) & 0xff;
red = (texturePixel << 16) & 0x00ff0000;
pixel = (texturePixel & 0xff00ff00) | red | blue;
bitmapSource[offset2 + j] = pixel;
}
}
} catch (GLException e) {
Log.e("CreateBitmap", "createBitmapFromGLSurface: " + e.getMessage(), e);
return null;
}
return Bitmap.createBitmap(bitmapSource, w, h, Bitmap.Config.ARGB_8888);
}
public void saveAsPngImage(Bitmap bitmap, String filePath) {
try {
File file = new File(filePath);
FileOutputStream outStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void exportMp4ToGallery(Context context, String filePath) {
final ContentValues values = new ContentValues(2);
values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
values.put(MediaStore.Video.Media.DATA, filePath);
context.getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
values);
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.parse("file://" + filePath)));
}
public static String getVideoFilePath() {
return getAndroidMoviesFolder().getAbsolutePath() + "/" + new SimpleDateFormat("yyyyMM_dd-HHmmss").format(new Date()) + "GPUCameraRecorder.mp4";
}
public static File getAndroidMoviesFolder() {
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
}
private static void exportPngToGallery(Context context, String filePath) {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(filePath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
context.sendBroadcast(mediaScanIntent);
}
public static String getImageFilePath() {
return getAndroidImageFolder().getAbsolutePath() + "/" + new SimpleDateFormat("yyyyMM_dd-HHmmss").format(new Date()) + "GPUCameraRecorder.png";
}
public static File getAndroidImageFolder() {
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
}
}