From 109f690a06873f09f5deda0a9cd2d90751f34cfa Mon Sep 17 00:00:00 2001 From: Matthew Date: Mon, 20 May 2024 22:46:00 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=A7=86=E9=A2=91OSD?= =?UTF-8?q?=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 8 + .../com/xypower/mpapp/MicroPhotoService.java | 7 - .../mpapp/v2/Camera2VideoActivity.java | 446 ++++++++--------- ...yNew.java => Camera2VideoActivityOld.java} | 448 +++++++++--------- .../java/com/xypower/mpapp/v2/OsdUpdater.java | 11 + 5 files changed, 467 insertions(+), 453 deletions(-) rename app/src/main/java/com/xypower/mpapp/v2/{Camera2VideoActivityNew.java => Camera2VideoActivityOld.java} (69%) create mode 100644 app/src/main/java/com/xypower/mpapp/v2/OsdUpdater.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 390d8b1f..8ecf3ef2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,12 +90,20 @@ android:name=".video.VideoActivity" android:exported="false" android:screenOrientation="landscape" /> + + + 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 +97,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,49 +126,75 @@ 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) { - if (mBitmap != null) { - Bitmap bitmap = mBitmap; - mBitmap = null; - mOSDFilter.updateBitmap(bitmap); + Bitmap oldBm = null; + if (mBitmap != null) { + 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) { - } - - if (mOsdTs == -1) { - break; + Looper.prepare(); + + 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()); + + TimerRunner runner = new TimerRunner(bm); + mHandler.postDelayed(runner, targetTs.longValue() - ts); + } + } else if (msg.what == 0) { + Looper.myLooper().quitSafely(); + } } + }; - updateOSD(mOsdTs); - } + Looper.loop(); } }); - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -177,18 +203,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(); @@ -317,6 +331,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); @@ -330,22 +345,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); - Canvas canvas = new Canvas(mBitmap); + Bitmap bm = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888); + + 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() { @@ -359,25 +379,26 @@ 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); - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - mGPUCameraRecorder.stop(); - } - }, 16 + mDuration * 1000); - // getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } @@ -393,7 +414,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)); @@ -401,184 +422,183 @@ public class Camera2VideoActivity extends AppCompatActivity { mStatusBarHeight = getStatusBarHeight(this); } int statusHeight = mStatusBarHeight; - synchronized (mBitmapLocker) { - 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); + int bmWidth = bm.getWidth(); + int bmHeight = bm.getHeight(); + int margin = mOSDMargin; + int x = 0; + int y = 0; - if (!TextUtils.isEmpty(mOSDLeftTop)) { - String[] items = mOSDLeftTop.split("\n"); - Point origin = new Point(margin, margin + statusHeight); + Canvas canvas = new Canvas(bm); + Rect textBounds = new Rect(); - for (String item : items) { + canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); - 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; - } + if (!TextUtils.isEmpty(mOSDLeftTop)) { + String[] items = mOSDLeftTop.split("\n"); + Point origin = new Point(margin, margin + statusHeight); - OSD_ITEM osdItem = new OSD_ITEM(); - osdItem.text = item; - osdItem.mask = mask; - osdItem.origin = new Point(origin); + for (String item : items) { - if (mask == 0) { - canvas.drawText(item, origin.x, origin.y, mPaint); - canvas.drawText(item, origin.x, origin.y, mPaintStroker); + 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; + } - mPaintStroker.getTextBounds(item, 0, item.length(), textBounds); - } else { - String newText = updateOSDTime(item, ts); + OSD_ITEM osdItem = new OSD_ITEM(); + osdItem.text = item; + osdItem.mask = mask; + osdItem.origin = new Point(origin); - canvas.drawText(newText, origin.x, origin.y, mPaint); - canvas.drawText(newText, origin.x, origin.y, mPaintStroker); + if (mask == 0) { + canvas.drawText(item, origin.x, origin.y, mPaint); + canvas.drawText(item, origin.x, origin.y, mPaintStroker); - mPaintStroker.getTextBounds(newText, 0, item.length(), textBounds); - } + mPaintStroker.getTextBounds(item, 0, item.length(), textBounds); + } else { + String newText = updateOSDTime(item, ts); - osdItem.previousRect = new Rect(origin.x, origin.y, origin.x + textBounds.width(), origin.y + textBounds.height()); + canvas.drawText(newText, origin.x, origin.y, mPaint); + canvas.drawText(newText, origin.x, origin.y, mPaintStroker); - mOSDItems.add(osdItem); - origin.y += (textBounds.height() * 3) >> 1; + mPaintStroker.getTextBounds(newText, 0, item.length(), textBounds); } - } - if (!TextUtils.isEmpty(mOSDLeftBottom)) { + osdItem.previousRect = new Rect(origin.x, origin.y, origin.x + textBounds.width(), origin.y + textBounds.height()); - String[] items = mOSDLeftBottom.split("\n"); - Point origin = new Point(margin, bmHeight - margin); + mOSDItems.add(osdItem); + origin.y += (textBounds.height() * 3) >> 1; + } + } - for(int idx = items.length-1; idx >= 0; idx--) { + if (!TextUtils.isEmpty(mOSDLeftBottom)) { - 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; - } + String[] items = mOSDLeftBottom.split("\n"); + Point origin = new Point(margin, bmHeight - margin); - 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(); + for(int idx = items.length-1; idx >= 0; idx--) { - canvas.drawText(item, origin.x, y, mPaint); - canvas.drawText(item, origin.x, y, mPaintStroker); - } else { - String newText = updateOSDTime(item, ts); + 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; + } - mPaintStroker.getTextBounds(newText, 0, newText.length(), textBounds); - y = origin.y - textBounds.height(); + 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(newText, origin.x, y, mPaint); - canvas.drawText(newText, origin.x, y, mPaintStroker); - } + 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(); - osdItem.previousRect = new Rect(origin.x, y, origin.x + textBounds.width(), y + textBounds.height()); - mOSDItems.add(osdItem); - origin.y -= (textBounds.height() * 3) >> 1; + 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)) { + if (!TextUtils.isEmpty(mOSDRightTop)) { - String[] items = mOSDRightTop.split("\n"); - Point origin = new Point(bmWidth - margin, margin + statusHeight); + String[] items = mOSDRightTop.split("\n"); + Point origin = new Point(bmWidth - margin, margin + statusHeight); - for (String item : items) { + 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; - } + 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; + 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); + 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 { + 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); + 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; + 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)) { + if (!TextUtils.isEmpty(mOSDRightBottom)) { - String[] items = mOSDRightBottom.split("\n"); - Point origin = new Point(bmWidth - margin, bmHeight - margin); + String[] items = mOSDRightBottom.split("\n"); + Point origin = new Point(bmWidth - margin, bmHeight - margin); - for(int idx = items.length-1; idx >= 0; idx--) { + 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); + 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; + } - canvas.drawText(newText, origin.x - textBounds.width(), origin.y - textBounds.height(), mPaint); - canvas.drawText(newText, origin.x - textBounds.width(), origin.y - textBounds.height(), mPaintStroker); - } + 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); + 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; - } + origin.y -= (textBounds.height() * 3) >> 1; } } + } - private void updateOSD(long ts) { + private void updateOSD(Bitmap bm, long ts) { Log.d("OSD", "prepareOSD " + Long.toString(ts / 1000)); if (mStatusBarHeight == -1) { @@ -586,8 +606,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(); @@ -638,9 +656,6 @@ public class Camera2VideoActivity extends AppCompatActivity { } } - synchronized (mBitmapLocker) { - mBitmap = bm; - } } private String updateOSDTime(String osd, long ts) { @@ -688,11 +703,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); }); } @@ -713,21 +725,23 @@ public class Camera2VideoActivity extends AppCompatActivity { @Override public void onRecordComplete() { - mHandler.removeCallbacks(mTimerRunnable); - mOsdTs = -1; - mOSDSemaphore.release(); - exportMp4ToGallery(getApplicationContext(), mNextVideoAbsolutePath); - broadcastVideoFile(true, mNextVideoAbsolutePath); + // mHandler.removeCallbacks(mTimerRunnable); + Message msg = Message.obtain(); + msg.what = 0; + mOsdHandler.sendMessage(msg); + } + + @Override + public void onRecordStart() { + Log.d("OSD", "Record Start "); mHandler.postDelayed(new Runnable() { @Override public void run() { - Camera2VideoActivity.this.finish(); + mGPUCameraRecorder.stop(); + Log.d("OSD", "Record Stop " + Long.toString(mDuration)); } - }, 500); - } + }, 256 + mDuration * 1000); - @Override - public void onRecordStart() { } @Override @@ -742,6 +756,14 @@ public class Camera2VideoActivity extends AppCompatActivity { @Override public void onVideoFileReady() { + // exportMp4ToGallery(getApplicationContext(), mNextVideoAbsolutePath); + broadcastVideoFile(true, mNextVideoAbsolutePath); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + Camera2VideoActivity.this.finish(); + } + }, 100); } }) .videoSize(mVideoWidth, mVideoHeight) diff --git a/app/src/main/java/com/xypower/mpapp/v2/Camera2VideoActivityNew.java b/app/src/main/java/com/xypower/mpapp/v2/Camera2VideoActivityOld.java similarity index 69% rename from app/src/main/java/com/xypower/mpapp/v2/Camera2VideoActivityNew.java rename to app/src/main/java/com/xypower/mpapp/v2/Camera2VideoActivityOld.java index d5339f01..87f6851f 100644 --- a/app/src/main/java/com/xypower/mpapp/v2/Camera2VideoActivityNew.java +++ b/app/src/main/java/com/xypower/mpapp/v2/Camera2VideoActivityOld.java @@ -17,8 +17,6 @@ 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; @@ -51,10 +49,9 @@ 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 Camera2VideoActivityNew extends AppCompatActivity { +public class Camera2VideoActivityOld 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"; @@ -84,12 +81,11 @@ public class Camera2VideoActivityNew extends AppCompatActivity { private int mOSDMargin = 0; private Paint mPaint; private Paint mPaintStroker; - - private List mBitmaps = new ArrayList<>(); - + private Bitmap mBitmap; private GlWatermarkFilter mOSDFilter = null; private Object mBitmapLocker = new Object(); + private SimpleDateFormat mDateFormater; // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a"); @@ -98,6 +94,9 @@ public class Camera2VideoActivityNew 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 { @@ -127,75 +126,49 @@ public class Camera2VideoActivityNew 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 class TimerRunner implements Runnable { - private Bitmap mBitmap; - - TimerRunner(Bitmap bm) { - mBitmap = bm; - } - + private Runnable mTimerRunnable = new Runnable() { @Override public void run() { - Bitmap oldBm = null; - if (mBitmap != null) { - oldBm = mOSDFilter.updateBitmap(mBitmap); - } - if (oldBm != null) { - synchronized (mBitmapLocker) { - mBitmaps.add(oldBm); + 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; Log.d("OSD", "Cur TS=" + Long.toString(ts / 1000) + " Timer=" + Long.toString(1000 - ms)); - Message msg = Message.obtain(); - msg.what = 1; - msg.obj = new Long(ts - ms + 1000); - mOsdHandler.sendMessage(msg); + mOSDSemaphore.release(); + + mHandler.postDelayed(this, 1000 - ms); } - } + }; - private Handler mOsdHandler; private Thread mOsdThread = new Thread(new Runnable() { @Override public void run() { - Looper.prepare(); - - 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()); - - TimerRunner runner = new TimerRunner(bm); - mHandler.postDelayed(runner, targetTs.longValue() - ts); - } - } else if (msg.what == 0) { - Looper.myLooper().quitSafely(); - } + while (true) { + try { + mOSDSemaphore.acquire(); + } catch (Exception ex) { + } + + if (mOsdTs == -1) { + break; } - }; - Looper.loop(); + updateOSD(mOsdTs); + } } }); + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -204,6 +177,18 @@ public class Camera2VideoActivityNew 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(); @@ -212,7 +197,7 @@ public class Camera2VideoActivityNew extends AppCompatActivity { onCreateActivity(); getWindow().getDecorView().setOnApplyWindowInsetsListener((v, insets) -> { - mStatusBarHeight = px2dip(Camera2VideoActivityNew.this, insets.getStableInsetTop()); + mStatusBarHeight = px2dip(Camera2VideoActivityOld.this, insets.getStableInsetTop()); return insets; }); @@ -332,7 +317,6 @@ public class Camera2VideoActivityNew 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); @@ -346,27 +330,22 @@ public class Camera2VideoActivityNew extends AppCompatActivity { mPaintStroker.setTextSize(fontSize); mPaintStroker.setStrokeWidth(1); - bm2 = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888); + mBitmap = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888); - Bitmap bm = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888); - - Canvas canvas = new Canvas(bm); + Canvas canvas = new Canvas(mBitmap); canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); ts = System.currentTimeMillis(); zeroTs = ts - (ts % 1000); - initOSD(bm, zeroTs); - mOSDFilter = new GlWatermarkFilter(bm); + initOSD(zeroTs); - if (mGPUCameraRecorder != null) { - mGPUCameraRecorder.setFilter(mOSDFilter); - } + mOSDFilter = new GlWatermarkFilter(mBitmap); - updateOSD(bm2, zeroTs + 1000); + mBitmap = Bitmap.createBitmap(mVideoWidth, mVideoHeight, Bitmap.Config.ARGB_8888); + updateOSD(zeroTs + 1000); } final long prevZeroTs = zeroTs; - final Bitmap finalBm = bm2; mHandler.postDelayed(new Runnable() { @Override public void run() { @@ -380,33 +359,18 @@ public class Camera2VideoActivityNew extends AppCompatActivity { if (zeroTs2 > prevZeroTs) { // Next second - 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)); + 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)); } } }, 0); - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - mGPUCameraRecorder.stop(); - } - }, 16 + mDuration * 1000); - // getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } @@ -422,7 +386,7 @@ public class Camera2VideoActivityNew extends AppCompatActivity { releaseCamera(); } - private void initOSD(Bitmap bm, long ts) { + private void initOSD(long ts) { Log.d("OSD", "INIT OSD " + Long.toString(ts / 1000)); @@ -430,183 +394,184 @@ public class Camera2VideoActivityNew extends AppCompatActivity { mStatusBarHeight = getStatusBarHeight(this); } int statusHeight = mStatusBarHeight; + synchronized (mBitmapLocker) { + int bmWidth = mBitmap.getWidth(); + int bmHeight = mBitmap.getHeight(); + int margin = mOSDMargin; + int x = 0; + int y = 0; + // mOSDFilter. - 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 canvas = new Canvas(mBitmap); + Rect textBounds = new Rect(); - canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); + canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); - if (!TextUtils.isEmpty(mOSDLeftTop)) { - String[] items = mOSDLeftTop.split("\n"); - Point origin = new Point(margin, margin + statusHeight); + if (!TextUtils.isEmpty(mOSDLeftTop)) { + String[] items = mOSDLeftTop.split("\n"); + Point origin = new Point(margin, margin + statusHeight); - for (String item : items) { + 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; - } + 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); + 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); + 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); + 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); + canvas.drawText(newText, origin.x, origin.y, mPaint); + canvas.drawText(newText, origin.x, origin.y, mPaintStroker); - mPaintStroker.getTextBounds(newText, 0, item.length(), textBounds); - } + mPaintStroker.getTextBounds(newText, 0, item.length(), textBounds); + } - osdItem.previousRect = new Rect(origin.x, origin.y, origin.x + textBounds.width(), origin.y + textBounds.height()); + 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; + mOSDItems.add(osdItem); + origin.y += (textBounds.height() * 3) >> 1; + } } - } - if (!TextUtils.isEmpty(mOSDLeftBottom)) { + if (!TextUtils.isEmpty(mOSDLeftBottom)) { - String[] items = mOSDLeftBottom.split("\n"); - Point origin = new Point(margin, bmHeight - margin); + String[] items = mOSDLeftBottom.split("\n"); + Point origin = new Point(margin, bmHeight - margin); - for(int idx = items.length-1; idx >= 0; idx--) { + 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; - } + 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(); + 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); + 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(); + 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); - } + 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; + 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)) { + if (!TextUtils.isEmpty(mOSDRightTop)) { - String[] items = mOSDRightTop.split("\n"); - Point origin = new Point(bmWidth - margin, margin + statusHeight); + String[] items = mOSDRightTop.split("\n"); + Point origin = new Point(bmWidth - margin, margin + statusHeight); - for (String item : items) { + 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; - } + 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; + 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); + 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 { + 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); + 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); + 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; + origin.y += (textBounds.height() * 3) >> 1; + } } - } - if (!TextUtils.isEmpty(mOSDRightBottom)) { + if (!TextUtils.isEmpty(mOSDRightBottom)) { - String[] items = mOSDRightBottom.split("\n"); - Point origin = new Point(bmWidth - margin, bmHeight - margin); + String[] items = mOSDRightBottom.split("\n"); + Point origin = new Point(bmWidth - margin, bmHeight - margin); - for(int idx = items.length-1; idx >= 0; idx--) { + 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; - } + 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); - } + 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); - osdItem.previousRect = new Rect(origin.x - textBounds.width(), origin.y - textBounds.height(), origin.x, origin.y); - mOSDItems.add(osdItem); + 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); - origin.y -= (textBounds.height() * 3) >> 1; + 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) { + private void updateOSD(long ts) { Log.d("OSD", "prepareOSD " + Long.toString(ts / 1000)); if (mStatusBarHeight == -1) { @@ -614,6 +579,8 @@ public class Camera2VideoActivityNew 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(); @@ -664,6 +631,9 @@ public class Camera2VideoActivityNew extends AppCompatActivity { } } + synchronized (mBitmapLocker) { + mBitmap = bm; + } } private String updateOSDTime(String osd, long ts) { @@ -711,8 +681,11 @@ public class Camera2VideoActivityNew extends AppCompatActivity { if (mGPUCameraRecorder == null) return; mGPUCameraRecorder.changeManualFocusPoint(event.getX(), event.getY(), width, height); }); - frameLayout.addView(mPreviewView); + + if (mGPUCameraRecorder != null) { + mGPUCameraRecorder.setFilter(mOSDFilter); + } }); } @@ -733,23 +706,23 @@ public class Camera2VideoActivityNew extends AppCompatActivity { @Override public void onRecordComplete() { - // mHandler.removeCallbacks(mTimerRunnable); - Message msg = Message.obtain(); - msg.what = 0; - mOsdHandler.sendMessage(msg); + mHandler.removeCallbacks(mTimerRunnable); + mOsdTs = -1; + mOSDSemaphore.release(); + // exportMp4ToGallery(getApplicationContext(), mNextVideoAbsolutePath); + } - exportMp4ToGallery(getApplicationContext(), mNextVideoAbsolutePath); - broadcastVideoFile(true, mNextVideoAbsolutePath); + @Override + public void onRecordStart() { + Log.d("OSD", "Record Start "); mHandler.postDelayed(new Runnable() { @Override public void run() { - Camera2VideoActivityNew.this.finish(); + mGPUCameraRecorder.stop(); + Log.d("OSD", "Record Stop"); } - }, 500); - } + }, 64 + mDuration * 1000); - @Override - public void onRecordStart() { } @Override @@ -764,6 +737,13 @@ public class Camera2VideoActivityNew extends AppCompatActivity { @Override public void onVideoFileReady() { + broadcastVideoFile(true, mNextVideoAbsolutePath); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + Camera2VideoActivityOld.this.finish(); + } + }, 100); } }) .videoSize(mVideoWidth, mVideoHeight) diff --git a/app/src/main/java/com/xypower/mpapp/v2/OsdUpdater.java b/app/src/main/java/com/xypower/mpapp/v2/OsdUpdater.java new file mode 100644 index 00000000..ecaada07 --- /dev/null +++ b/app/src/main/java/com/xypower/mpapp/v2/OsdUpdater.java @@ -0,0 +1,11 @@ +package com.xypower.mpapp.v2; + +public class OsdUpdater { + + private static final int DEFAULT_FONT_SIZE = 20; + + public OsdUpdater() { + + } + +}