diff --git a/danmaku/src/main/java/master/flame/danmaku/controller/CacheManagingDrawTask.java b/danmaku/src/main/java/master/flame/danmaku/controller/CacheManagingDrawTask.java index 23cea23c5..4bdb870f3 100644 --- a/danmaku/src/main/java/master/flame/danmaku/controller/CacheManagingDrawTask.java +++ b/danmaku/src/main/java/master/flame/danmaku/controller/CacheManagingDrawTask.java @@ -132,7 +132,6 @@ public class CacheManagingDrawTask extends DrawTask { @Override public void start() { super.start(); - NativeBitmapFactory.loadLibs(); if (mCacheManager == null) { mCacheManager = new CacheManager(mMaxCacheSize, MAX_CACHE_SCREEN_SIZE); mCacheManager.begin(); diff --git a/danmaku/src/main/java/master/flame/danmaku/ui/widget/DanmakuView.java b/danmaku/src/main/java/master/flame/danmaku/ui/widget/DanmakuView.java index ca090bccb..3c2505dbc 100644 --- a/danmaku/src/main/java/master/flame/danmaku/ui/widget/DanmakuView.java +++ b/danmaku/src/main/java/master/flame/danmaku/ui/widget/DanmakuView.java @@ -20,7 +20,6 @@ import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; -import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; @@ -47,38 +46,36 @@ public class DanmakuView extends View implements IDanmakuView, IDanmakuViewContr private static final int MAX_RECORD_SIZE = 50; private static final int ONE_SECOND = 1000; - protected volatile DrawHandler handler; - protected int mDrawingThreadType = THREAD_TYPE_NORMAL_PRIORITY; - protected boolean mRequestRender = false; - protected boolean mClearFlag; + private Callback mCallback; - private HandlerThread mHandlerThread; - private boolean isSurfaceCreated; - private boolean mEnableDanmakuDrwaingCache = true; + private Object mDrawMonitor; private OnDanmakuClickListener mOnDanmakuClickListener; - private float mXOff; - private float mYOff; - private OnClickListener mOnClickListener; private DanmakuTouchHelper mTouchHelper; + private HandlerThread mHandlerThread; + private LinkedList mDrawTimes; + private volatile DrawHandler handler; + private boolean mEnableDrawingCache; + private boolean isSurfaceCreated; + private boolean mDanmakuVisible; + private boolean mRequestRender; + private boolean mDrawFinished; + private boolean mClearFlag; private boolean mShowFps; - private boolean mDanmakuVisible = true; - private Object mDrawMonitor = new Object(); - private boolean mDrawFinished = false; + private int mDrawingThreadType; + private int mResumeTryCount; private long mUiThreadId; - private LinkedList mDrawTimes; - private int mResumeTryCount = 0; - private Runnable mResumeRunnable = new Runnable() { + private float mXOff; + private float mYOff; + + private final Runnable mResumeRunnable = new Runnable() { @Override public void run() { DrawHandler drawHandler = handler; - if (drawHandler == null) { - return; - } - mResumeTryCount++; - if (mResumeTryCount > 4 || DanmakuView.super.isShown()) { + if (drawHandler == null) return; + if (++mResumeTryCount > 4 || DanmakuView.super.isShown()) { drawHandler.resume(); } else { - drawHandler.postDelayed(this, 100 * mResumeTryCount); + drawHandler.postDelayed(this, 100L * mResumeTryCount); } } }; @@ -99,53 +96,45 @@ public class DanmakuView extends View implements IDanmakuView, IDanmakuViewContr } private void init() { + mDanmakuVisible = true; + mEnableDrawingCache = true; + mDrawMonitor = new Object(); mUiThreadId = Thread.currentThread().getId(); setBackgroundColor(Color.TRANSPARENT); setDrawingCacheBackgroundColor(Color.TRANSPARENT); DrawHelper.useDrawColorToClearCanvas(true, false); mTouchHelper = DanmakuTouchHelper.instance(this); + mDrawingThreadType = THREAD_TYPE_NORMAL_PRIORITY; } public void addDanmaku(BaseDanmaku item) { - if (handler != null) { - handler.addDanmaku(item); - } + if (handler != null) handler.addDanmaku(item); } @Override public void invalidateDanmaku(BaseDanmaku item, boolean remeasure) { - if (handler != null) { - handler.invalidateDanmaku(item, remeasure); - } + if (handler != null) handler.invalidateDanmaku(item, remeasure); } @Override public void removeAllDanmakus(boolean isClearDanmakusOnScreen) { - if (handler != null) { - handler.removeAllDanmakus(isClearDanmakusOnScreen); - } + if (handler != null) handler.removeAllDanmakus(isClearDanmakusOnScreen); } @Override public void removeAllLiveDanmakus() { - if (handler != null) { - handler.removeAllLiveDanmakus(); - } + if (handler != null) handler.removeAllLiveDanmakus(); } @Override public IDanmakus getCurrentVisibleDanmakus() { - if (handler != null) { - return handler.getCurrentVisibleDanmakus(); - } + if (handler != null) return handler.getCurrentVisibleDanmakus(); return null; } public void setCallback(Callback callback) { + if (handler != null) handler.setCallback(callback); mCallback = callback; - if (handler != null) { - handler.setCallback(callback); - } } @Override @@ -160,15 +149,11 @@ public class DanmakuView extends View implements IDanmakuView, IDanmakuViewContr } private synchronized void stopDraw() { - if (this.handler == null) { - return; - } + if (handler == null) return; DrawHandler handler = this.handler; this.handler = null; unlockCanvasAndPost(); - if (handler != null) { - handler.quit(); - } + if (handler != null) handler.quit(); HandlerThread handlerThread = this.mHandlerThread; mHandlerThread = null; if (handlerThread != null) { @@ -186,7 +171,6 @@ public class DanmakuView extends View implements IDanmakuView, IDanmakuViewContr mHandlerThread.quit(); mHandlerThread = null; } - int priority; switch (type) { case THREAD_TYPE_MAIN_THREAD: @@ -228,9 +212,7 @@ public class DanmakuView extends View implements IDanmakuView, IDanmakuViewContr @Override public DanmakuContext getConfig() { - if (handler == null) { - return null; - } + if (handler == null) return null; return handler.getConfig(); } @@ -243,23 +225,17 @@ public class DanmakuView extends View implements IDanmakuView, IDanmakuViewContr long lastTime = SystemClock.uptimeMillis(); mDrawTimes.addLast(lastTime); Long first = mDrawTimes.peekFirst(); - if (first == null) { - return 0.0f; - } + if (first == null) return 0.0f; float dtime = lastTime - first; int frames = mDrawTimes.size(); - if (frames > MAX_RECORD_SIZE) { - mDrawTimes.removeFirst(); - } + if (frames > MAX_RECORD_SIZE) mDrawTimes.removeFirst(); return dtime > 0 ? mDrawTimes.size() * ONE_SECOND / dtime : 0.0f; } @Override public long drawDanmakus() { - if (!isSurfaceCreated) - return 0; - if (!isShown()) - return -1; + if (!isSurfaceCreated) return 0; + if (!isShown()) return -1; long stime = SystemClock.uptimeMillis(); lockCanvas(); return SystemClock.uptimeMillis() - stime; @@ -268,24 +244,18 @@ public class DanmakuView extends View implements IDanmakuView, IDanmakuViewContr @SuppressLint("NewApi") private void postInvalidateCompat() { mRequestRender = true; - if (Build.VERSION.SDK_INT >= 16) { - this.postInvalidateOnAnimation(); - } else { - this.postInvalidate(); - } + this.postInvalidateOnAnimation(); } protected void lockCanvas() { - if (mDanmakuVisible == false) { - return; - } + if (!mDanmakuVisible) return; postInvalidateCompat(); synchronized (mDrawMonitor) { while ((!mDrawFinished) && (handler != null)) { try { mDrawMonitor.wait(200); } catch (InterruptedException e) { - if (mDanmakuVisible == false || handler == null || handler.isStop()) { + if (!mDanmakuVisible || handler == null || handler.isStop()) { break; } else { Thread.currentThread().interrupt(); @@ -321,11 +291,8 @@ public class DanmakuView extends View implements IDanmakuView, IDanmakuViewContr if (handler != null) { RenderingState rs = handler.draw(canvas); if (mShowFps) { - if (mDrawTimes == null) - mDrawTimes = new LinkedList(); - String fps = String.format(Locale.getDefault(), - "fps %.2f,time:%d s,cache:%d,miss:%d", fps(), getCurrentTime() / 1000, - rs.cacheHitCount, rs.cacheMissCount); + if (mDrawTimes == null) mDrawTimes = new LinkedList<>(); + String fps = String.format(Locale.getDefault(), "fps %.2f,time:%d s,cache:%d,miss:%d", fps(), getCurrentTime() / 1000, rs.cacheHitCount, rs.cacheMissCount); DrawHelper.drawFPS(canvas, fps); } } @@ -337,21 +304,15 @@ public class DanmakuView extends View implements IDanmakuView, IDanmakuViewContr @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); - if (handler != null) { - handler.notifyDispSizeChanged(right - left, bottom - top); - } + if (handler != null) handler.notifyDispSizeChanged(right - left, bottom - top); isSurfaceCreated = true; } public void toggle() { - if (isSurfaceCreated) { - if (handler == null) - start(); - else if (handler.isStop()) { - resume(); - } else - pause(); - } + if (!isSurfaceCreated) return; + if (handler == null) start(); + else if (handler.isStop()) resume(); + else pause(); } @Override @@ -374,9 +335,7 @@ public class DanmakuView extends View implements IDanmakuView, IDanmakuViewContr @Override public boolean isPaused() { - if (handler != null) { - return handler.isStop(); - } + if (handler != null) return handler.isStop(); return false; } @@ -407,26 +366,21 @@ public class DanmakuView extends View implements IDanmakuView, IDanmakuViewContr @Override public boolean onTouchEvent(MotionEvent event) { boolean isEventConsumed = mTouchHelper.onTouchEvent(event); - if (!isEventConsumed) { - return super.onTouchEvent(event); - } + if (!isEventConsumed) return super.onTouchEvent(event); return isEventConsumed; } public void seekTo(Long ms) { - if (handler != null) { - handler.seekTo(ms); - } + if (handler != null) handler.seekTo(ms); } - public void enableDanmakuDrawingCache(boolean enable) { - mEnableDanmakuDrwaingCache = enable; + mEnableDrawingCache = enable; } @Override public boolean isDanmakuDrawingCacheEnabled() { - return mEnableDanmakuDrwaingCache; + return mEnableDrawingCache; } @Override @@ -458,35 +412,27 @@ public class DanmakuView extends View implements IDanmakuView, IDanmakuViewContr public void showAndResumeDrawTask(Long position) { mDanmakuVisible = true; mClearFlag = false; - if (handler == null) { - return; - } + if (handler == null) return; handler.showDanmakus(position); } @Override public void hide() { mDanmakuVisible = false; - if (handler == null) { - return; - } + if (handler == null) return; handler.hideDanmakus(false); } @Override public long hideAndPauseDrawTask() { mDanmakuVisible = false; - if (handler == null) { - return 0; - } + if (handler == null) return 0; return handler.hideDanmakus(true); } @Override public void clear() { - if (!isViewReady()) { - return; - } + if (!isViewReady()) return; if (!mDanmakuVisible || Thread.currentThread().getId() == mUiThreadId) { mClearFlag = true; postInvalidateCompat(); @@ -507,28 +453,13 @@ public class DanmakuView extends View implements IDanmakuView, IDanmakuViewContr @Override public long getCurrentTime() { - if (handler != null) { - return handler.getCurrentTime(); - } + if (handler != null) return handler.getCurrentTime(); return 0; } - @Override - @SuppressLint("NewApi") - public boolean isHardwareAccelerated() { - // >= 3.0 - if (Build.VERSION.SDK_INT >= 11) { - return super.isHardwareAccelerated(); - } else { - return false; - } - } - @Override public void clearDanmakusOnScreen() { - if (handler != null) { - handler.clearDanmakusOnScreen(); - } + if (handler != null) handler.clearDanmakusOnScreen(); } @Override diff --git a/danmaku/src/main/java/tv/cjump/jni/NativeBitmapFactory.java b/danmaku/src/main/java/tv/cjump/jni/NativeBitmapFactory.java index 2306d1c3e..dd5f14027 100644 --- a/danmaku/src/main/java/tv/cjump/jni/NativeBitmapFactory.java +++ b/danmaku/src/main/java/tv/cjump/jni/NativeBitmapFactory.java @@ -14,30 +14,23 @@ public class NativeBitmapFactory { static Field nativeIntField = null; - static boolean nativeLibLoaded = false; + static { + System.loadLibrary("ndkbitmap"); + } public static void loadLibs() { - System.loadLibrary("ndkbitmap"); - nativeLibLoaded = true; boolean libInit = init(); if (!libInit) { release(); - nativeLibLoaded = false; } else { initField(); - boolean confirm = testLib(); - if (!confirm) { - release(); - nativeLibLoaded = false; - } + if (!testLib()) release(); } } public static synchronized void releaseLibs() { - boolean loaded = nativeLibLoaded; nativeIntField = null; - nativeLibLoaded = false; - if (loaded) release(); + release(); } static void initField() { @@ -103,7 +96,7 @@ public class NativeBitmapFactory { } public static synchronized Bitmap createBitmap(int width, int height, Bitmap.Config config, boolean hasAlpha) { - if (!nativeLibLoaded || nativeIntField == null) return Bitmap.createBitmap(width, height, config); + if (nativeIntField == null) return Bitmap.createBitmap(width, height, config); return createNativeBitmap(width, height, config, hasAlpha); } diff --git a/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ui/SubtitleParser.java b/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ui/SubtitleParser.java new file mode 100644 index 000000000..a02acd1b9 --- /dev/null +++ b/ijkplayer/src/main/java/tv/danmaku/ijk/media/player/ui/SubtitleParser.java @@ -0,0 +1,32 @@ +package tv.danmaku.ijk.media.player.ui; + +import android.text.Html; +import android.text.TextUtils; + +import androidx.media3.common.text.Cue; + +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +public class SubtitleParser { + + private static final Pattern BRACES_PATTERN = Pattern.compile("\\{([^}]*)\\}"); + private static final String DIALOGUE_LINE_PREFIX = "Dialogue:"; + + public static List parse(String text) { + if (TextUtils.isEmpty(text) || text.length() >= 4096) return null; + if (text.startsWith(DIALOGUE_LINE_PREFIX)) text = parseDialogueLine(text); + text = text.replaceAll("\r\n", "
").replaceAll("\r", "
").replaceAll("\n", "
").replaceAll("\\{\\\\.*?\\}", ""); + if (text.endsWith("
")) text = text.substring(0, text.lastIndexOf("
")); + return Arrays.asList(new Cue.Builder().setText(Html.fromHtml(text)).build()); + } + + private static String parseDialogueLine(String text) { + String[] lineValues = text.substring(DIALOGUE_LINE_PREFIX.length()).split(","); + String rawText = lineValues[lineValues.length - 1]; + rawText = BRACES_PATTERN.matcher(rawText).replaceAll(""); + rawText = rawText.replace("\\N", "\n").replace("\\n", "\n").replace("\\h", "\u00A0"); + return rawText; + } +}