|
|
|
@ -9,9 +9,16 @@ import android.content.DialogInterface;
|
|
|
|
|
import android.content.Intent;
|
|
|
|
|
import android.content.pm.PackageManager;
|
|
|
|
|
import android.content.res.Configuration;
|
|
|
|
|
import android.graphics.Bitmap;
|
|
|
|
|
import android.graphics.Canvas;
|
|
|
|
|
import android.graphics.Color;
|
|
|
|
|
import android.graphics.Matrix;
|
|
|
|
|
import android.graphics.Paint;
|
|
|
|
|
import android.graphics.PorterDuff;
|
|
|
|
|
import android.graphics.Rect;
|
|
|
|
|
import android.graphics.RectF;
|
|
|
|
|
import android.graphics.SurfaceTexture;
|
|
|
|
|
import android.graphics.drawable.BitmapDrawable;
|
|
|
|
|
import android.hardware.camera2.CameraAccessException;
|
|
|
|
|
import android.hardware.camera2.CameraCaptureSession;
|
|
|
|
|
import android.hardware.camera2.CameraCharacteristics;
|
|
|
|
@ -36,11 +43,13 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
|
|
|
import android.os.Environment;
|
|
|
|
|
import android.os.Handler;
|
|
|
|
|
import android.os.HandlerThread;
|
|
|
|
|
import android.text.TextUtils;
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
import android.util.Size;
|
|
|
|
|
import android.util.SparseIntArray;
|
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
|
import android.view.Surface;
|
|
|
|
|
import android.view.SurfaceHolder;
|
|
|
|
|
import android.view.TextureView;
|
|
|
|
|
import android.view.View;
|
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
@ -52,10 +61,13 @@ import com.xypower.mpapp.R;
|
|
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Collections;
|
|
|
|
|
import java.util.Comparator;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Locale;
|
|
|
|
|
import java.util.concurrent.Semaphore;
|
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
|
|
|
@ -97,10 +109,6 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Med
|
|
|
|
|
INVERSE_ORIENTATIONS.append(Surface.ROTATION_270, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int mCameraId;
|
|
|
|
|
private long mVideoId = 0;
|
|
|
|
|
private int mDuration = 0;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An {@link AutoFitTextureView} for camera preview.
|
|
|
|
|
*/
|
|
|
|
@ -133,6 +141,7 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Med
|
|
|
|
|
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
|
|
|
|
|
int width, int height) {
|
|
|
|
|
openCamera(width, height);
|
|
|
|
|
mMainHandler.postDelayed(mWatermarkRunnable, 16);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -143,6 +152,7 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Med
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
|
|
|
|
|
mMainHandler.removeCallbacks(mWatermarkRunnable);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -162,7 +172,22 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Med
|
|
|
|
|
*/
|
|
|
|
|
private Size mVideoSize;
|
|
|
|
|
|
|
|
|
|
private int mCameraId;
|
|
|
|
|
private long mVideoId = 0;
|
|
|
|
|
private int mDuration = 0;
|
|
|
|
|
|
|
|
|
|
private int mOrientation = -1;
|
|
|
|
|
private String mLeftTopOsd = null;
|
|
|
|
|
private String mRightTopOsd = null;
|
|
|
|
|
private String mRightBottomOsd = null;
|
|
|
|
|
private String mLeftBottomOsd = null;
|
|
|
|
|
|
|
|
|
|
private Bitmap mWatermarkBitmap = null;
|
|
|
|
|
private Paint mWatermarkPaint = null;
|
|
|
|
|
|
|
|
|
|
private Runnable mWatermarkRunnable = null;
|
|
|
|
|
|
|
|
|
|
private SurfaceHolder mSurfaceHolder = null;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* MediaRecorder
|
|
|
|
@ -357,9 +382,37 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Med
|
|
|
|
|
int width = argument.getInt("width", 0);
|
|
|
|
|
int height = argument.getInt("height", 0);
|
|
|
|
|
mOrientation = argument.getInt("orientation", -1);
|
|
|
|
|
mLeftTopOsd = argument.getString("leftTopOsd", null);
|
|
|
|
|
mLeftBottomOsd = argument.getString("leftBottomOsd", null);
|
|
|
|
|
mRightBottomOsd = argument.getString("rightBottomOsd", null);
|
|
|
|
|
mLeftBottomOsd = argument.getString("leftBottomOsd", null);
|
|
|
|
|
|
|
|
|
|
if (width > 0 && height > 0) {
|
|
|
|
|
mVideoSize = new Size(width, height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!TextUtils.isEmpty(mLeftTopOsd) || !TextUtils.isEmpty(mLeftTopOsd) || !TextUtils.isEmpty(mLeftTopOsd) || !TextUtils.isEmpty(mLeftTopOsd)) {
|
|
|
|
|
mWatermarkRunnable = new Runnable() {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
updateWatermark();
|
|
|
|
|
|
|
|
|
|
long ms = System.currentTimeMillis() % 1000;
|
|
|
|
|
if (ms == 0) {
|
|
|
|
|
ms = 1000;
|
|
|
|
|
}
|
|
|
|
|
mMainHandler.postDelayed(this, ms);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
mWatermarkPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
|
|
|
|
mWatermarkPaint.setColor(Color.WHITE);
|
|
|
|
|
mWatermarkPaint.setTextSize(32);
|
|
|
|
|
|
|
|
|
|
mWatermarkBitmap = Bitmap.createBitmap(mVideoSize.getWidth(), mVideoSize.getHeight(), Bitmap.Config.ARGB_8888);
|
|
|
|
|
|
|
|
|
|
// mMainHandler.post(mWatermarkRunnable);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Log.i(TAG, "Recv recording request CameraId=" + mCameraId + " videoId=" + Long.toString(mVideoId));
|
|
|
|
@ -556,6 +609,7 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Med
|
|
|
|
|
try {
|
|
|
|
|
closePreviewSession();
|
|
|
|
|
SurfaceTexture texture = mTextureView.getSurfaceTexture();
|
|
|
|
|
|
|
|
|
|
assert texture != null;
|
|
|
|
|
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
|
|
|
|
|
mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
|
|
|
|
@ -800,6 +854,56 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Med
|
|
|
|
|
startPreview();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateWatermark() {
|
|
|
|
|
Canvas canvas = new Canvas(mWatermarkBitmap);
|
|
|
|
|
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
|
|
|
|
|
|
|
|
|
|
Date date = new Date();
|
|
|
|
|
String ts = Long.toString(date.getTime() / 1000);
|
|
|
|
|
|
|
|
|
|
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
|
|
|
|
|
String dateStr = simpleDateFormat.format(date);
|
|
|
|
|
|
|
|
|
|
String osd = null;
|
|
|
|
|
if (!TextUtils.isEmpty(mLeftTopOsd)) {
|
|
|
|
|
osd = mLeftTopOsd.replace("%%DATETIME%%", dateStr).replace("%%TS%%", ts);
|
|
|
|
|
canvas.drawText(osd, 20, 20, mWatermarkPaint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!TextUtils.isEmpty(mRightTopOsd)) {
|
|
|
|
|
osd = mRightTopOsd.replace("%%DATETIME%%", dateStr).replace("%%TS%%", ts);
|
|
|
|
|
Rect rect = new Rect();
|
|
|
|
|
mWatermarkPaint.getTextBounds(osd, 0, osd.length(), rect);
|
|
|
|
|
|
|
|
|
|
canvas.drawText(osd, mVideoSize.getWidth() - rect.width() - 20, 20, mWatermarkPaint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!TextUtils.isEmpty(mRightBottomOsd)) {
|
|
|
|
|
osd = mRightBottomOsd.replace("$$DATETIME%%", dateStr).replace("%%TS%%", ts);
|
|
|
|
|
Rect rect = new Rect();
|
|
|
|
|
mWatermarkPaint.getTextBounds(osd, 0, osd.length(), rect);
|
|
|
|
|
|
|
|
|
|
canvas.drawText(osd, mVideoSize.getWidth() - rect.width() - 20, mVideoSize.getHeight() - rect.height() - 20, mWatermarkPaint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!TextUtils.isEmpty(mLeftBottomOsd)) {
|
|
|
|
|
osd = mLeftBottomOsd.replace("$$DATETIME%%", dateStr).replace("%%TS%%", ts);
|
|
|
|
|
Rect rect = new Rect();
|
|
|
|
|
mWatermarkPaint.getTextBounds(osd, 0, osd.length(), rect);
|
|
|
|
|
|
|
|
|
|
canvas.drawText(osd, 20, mVideoSize.getHeight() - rect.height() - 20, mWatermarkPaint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// mTextureView.setForeground(new BitmapDrawable(mWatermarkBitmap));
|
|
|
|
|
|
|
|
|
|
boolean isAvailable = mTextureView.isAvailable();
|
|
|
|
|
Canvas textureCanvas = mTextureView.lockCanvas();
|
|
|
|
|
if (textureCanvas != null) {
|
|
|
|
|
textureCanvas.drawBitmap(mWatermarkBitmap, 0, 0, null);
|
|
|
|
|
}
|
|
|
|
|
mTextureView.unlockCanvasAndPost(textureCanvas);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Compares two {@code Size}s based on their areas.
|
|
|
|
|
*/
|
|
|
|
|