@Override public void removeAllDanmakus() { if (danmakuList == null || danmakuList.isEmpty()) return; synchronized (danmakuList) { danmakuList.clear(); } }
private static void updateSpecialDanmakusDate(float scaleX, float scaleY) { IDanmakus list = sSpecialDanmakus; IDanmakuIterator it = list.iterator(); while (it.hasNext()) { SpecialDanmaku speicalDanmaku = (SpecialDanmaku) it.next(); fillTranslationData( speicalDanmaku, speicalDanmaku.beginX, speicalDanmaku.beginY, speicalDanmaku.endX, speicalDanmaku.endY, speicalDanmaku.translationDuration, speicalDanmaku.translationStartDelay, scaleX, scaleY); LinePath[] linePaths = speicalDanmaku.linePaths; if (linePaths != null && linePaths.length > 0) { int length = linePaths.length; float[][] points = new float[length + 1][2]; for (int j = 0; j < length; j++) { points[j] = linePaths[j].getBeginPoint(); points[j + 1] = linePaths[j].getEndPoint(); } fillLinePathData(speicalDanmaku, points, scaleX, scaleY); } } }
@Override public void removeAllLiveDanmakus() { if (danmakuList == null || danmakuList.isEmpty()) return; synchronized (danmakuList) { IDanmakuIterator it = danmakuList.iterator(); while (it.hasNext()) { if (it.next().isLive) { it.remove(); } } } }
@Override public void addDanmaku(BaseDanmaku item) { if (danmakuList == null) return; synchronized (danmakuList) { if (item.isLive) { removeUnusedLiveDanmakusIn(5); } item.setTimer(mTimer); item.index = danmakuList.size(); danmakuList.addItem(item); } }
@Override public synchronized void removeAllLiveDanmakus() { if (danmakus == null || danmakus.isEmpty()) return; synchronized (danmakus) { IDanmakuIterator it = danmakus.iterator(); while (it.hasNext()) { BaseDanmaku danmaku = it.next(); if (danmaku.isLive) { it.remove(); onDanmakuRemoved(danmaku); } } } }
protected void removeUnusedLiveDanmakusIn(int msec) { if (danmakuList == null || danmakuList.isEmpty()) return; long startTime = System.currentTimeMillis(); IDanmakuIterator it = danmakuList.iterator(); while (it.hasNext()) { BaseDanmaku danmaku = it.next(); if (danmaku.isLive && danmaku.isTimeOut()) { it.remove(); } if (System.currentTimeMillis() - startTime > msec) { break; } } }
protected synchronized void removeUnusedLiveDanmakusIn(int msec) { if (danmakuList == null || danmakuList.isEmpty()) return; long startTime = System.currentTimeMillis(); IDanmakuIterator it = danmakuList.iterator(); while (it.hasNext()) { BaseDanmaku danmaku = it.next(); boolean isTimeout = danmaku.isTimeOut(); if (isTimeout && danmaku.isLive) { it.remove(); onDanmakuRemoved(danmaku); } if (!isTimeout || System.currentTimeMillis() - startTime > msec) { break; } } }
protected RenderingState drawDanmakus(AbsDisplayer<?> disp, DanmakuTimer timer) { if (danmakuList != null) { Canvas canvas = (Canvas) disp.getExtraData(); if (clearFlag > 0) { DrawHelper.clearCanvas(canvas); clearFlag--; } else { float[] refreshRect = mRenderer.getRefreshArea().mRefreshRect; mRectCache.push(refreshRect); float[] rect = mRectCache.getRect(); DrawHelper.clearCanvas( canvas, Math.max(0, rect[0]), Math.max(0, rect[1]), Math.min(disp.getWidth(), rect[2]), Math.min(disp.getHeight(), rect[3])); } long currMills = timer.currMillisecond; danmakus = danmakuList.sub(currMills - DanmakuFactory.MAX_DANMAKU_DURATION - 100, currMills); if (danmakus != null) { return mRenderer.draw(mDisp, danmakus, mStartRenderTime); } } return null; }
protected RenderingState drawDanmakus(AbsDisplayer<?> disp, DanmakuTimer timer) { if (clearRetainerFlag) { DanmakusRetainer.clear(); clearRetainerFlag = false; } if (danmakuList != null) { Canvas canvas = (Canvas) disp.getExtraData(); DrawHelper.clearCanvas(canvas); if (mIsHidden) { return mRenderingState; } long beginMills = timer.currMillisecond - DanmakuFactory.MAX_DANMAKU_DURATION - 100; long endMills = timer.currMillisecond + DanmakuFactory.MAX_DANMAKU_DURATION; if (mLastBeginMills > beginMills || timer.currMillisecond > mLastEndMills) { IDanmakus subDanmakus = danmakuList.sub(beginMills, endMills); if (subDanmakus != null) { danmakus = subDanmakus; } else { danmakus.clear(); } mLastBeginMills = beginMills; mLastEndMills = endMills; } else { beginMills = mLastBeginMills; endMills = mLastEndMills; } if (danmakus != null && !danmakus.isEmpty()) { RenderingState renderingState = mRenderingState = mRenderer.draw(mDisp, danmakus, mStartRenderTime); if (renderingState.nothingRendered) { if (renderingState.beginTime == RenderingState.UNKNOWN_TIME) { renderingState.beginTime = beginMills; } if (renderingState.endTime == RenderingState.UNKNOWN_TIME) { renderingState.endTime = endMills; } } return renderingState; } else { mRenderingState.nothingRendered = true; mRenderingState.beginTime = beginMills; mRenderingState.endTime = endMills; return mRenderingState; } } return null; }
/** * 创建弹幕数据请尽量使用此方法,参考BiliDanmakuParser或AcfunDanmakuParser * * @param type 弹幕类型 * @param viewportWidth danmakuview宽度,会影响滚动弹幕的存活时间(duration) * @param viewportHeight danmakuview高度 * @param viewportScale 缩放比例,会影响滚动弹幕的存活时间(duration) * @return */ public static BaseDanmaku createDanmaku( int type, float viewportWidth, float viewportHeight, float viewportScale) { boolean sizeChanged = false; if (CURRENT_DISP_WIDTH != (int) viewportWidth || CURRENT_DISP_HEIGHT != (int) viewportHeight) { sizeChanged = true; REAL_DANMAKU_DURATION = (long) (COMMON_DANMAKU_DURATION * (viewportScale * viewportWidth / BILI_PLAYER_WIDTH)); REAL_DANMAKU_DURATION = Math.min(MAX_DANMAKU_DURATION_HIGH_DENSITY, REAL_DANMAKU_DURATION); REAL_DANMAKU_DURATION = Math.max(MIN_DANMAKU_DURATION, REAL_DANMAKU_DURATION); } if (MAX_Duration_Scroll_Danmaku == null) { MAX_Duration_Scroll_Danmaku = new Duration(REAL_DANMAKU_DURATION); MAX_Duration_Scroll_Danmaku.setFactor(DanmakuGlobalConfig.DEFAULT.scrollSpeedFactor); } else if (sizeChanged) { MAX_Duration_Scroll_Danmaku.setValue(REAL_DANMAKU_DURATION); } if (MAX_Duration_Fix_Danmaku == null) { MAX_Duration_Fix_Danmaku = new Duration(COMMON_DANMAKU_DURATION); } if (sizeChanged && viewportWidth > 0) { updateMaxDanmakuDuration(); float scaleX = 1f; float scaleY = 1f; if (CURRENT_DISP_WIDTH > 0 && CURRENT_DISP_HEIGHT > 0) { scaleX = viewportWidth / (float) CURRENT_DISP_WIDTH; scaleY = viewportHeight / (float) CURRENT_DISP_HEIGHT; } CURRENT_DISP_WIDTH = (int) viewportWidth; CURRENT_DISP_HEIGHT = (int) viewportHeight; if (viewportHeight > 0) { updateSpecialDanmakusDate(scaleX, scaleY); } } BaseDanmaku instance = null; switch (type) { case 1: // 从右往左滚动 instance = new R2LDanmaku(MAX_Duration_Scroll_Danmaku); break; case 4: // 底端固定 instance = new FBDanmaku(MAX_Duration_Fix_Danmaku); break; case 5: // 顶端固定 instance = new FTDanmaku(MAX_Duration_Fix_Danmaku); break; case 6: // 从左往右滚动 instance = new L2RDanmaku(MAX_Duration_Scroll_Danmaku); break; case 7: // 特殊弹幕 instance = new SpecialDanmaku(); sSpecialDanmakus.addItem(instance); break; } return instance; }
public static void resetDurationsData() { sLastDisp = null; CURRENT_DISP_WIDTH = CURRENT_DISP_HEIGHT = 0; sSpecialDanmakus.clear(); MAX_Duration_Scroll_Danmaku = null; MAX_Duration_Fix_Danmaku = null; MAX_Duration_Special_Danmaku = null; MAX_DANMAKU_DURATION = MIN_DANMAKU_DURATION; }
@Override public synchronized void addDanmaku(BaseDanmaku item) { if (danmakuList == null) return; boolean added = false; if (item.isLive) { removeUnusedLiveDanmakusIn(10); } item.index = danmakuList.size(); if (mLastBeginMills <= item.time && item.time <= mLastEndMills) { synchronized (danmakus) { added = danmakus.addItem(item); } } else if (item.isLive) { mLastBeginMills = mLastEndMills = 0; } synchronized (danmakuList) { added = danmakuList.addItem(item); } if (added && mTaskListener != null) { mTaskListener.onDanmakuAdd(item); } }
@Override public void reset() { if (danmakus != null) danmakus.clear(); if (mRenderer != null) mRenderer.clear(); }
private long prepareCaches(boolean repositioned) { long curr = mCacheTimer.currMillisecond; long end = curr + mContext.mDanmakuFactory.MAX_DANMAKU_DURATION * mScreenSize; if (end < mTimer.currMillisecond) { return 0; } long startTime = SystemClock.uptimeMillis(); IDanmakus danmakus = null; int tryCount = 0; boolean hasException = false; do { try { danmakus = danmakuList.subnew(curr, end); } catch (Exception e) { hasException = true; SystemClock.sleep(10); } } while (++tryCount < 3 && danmakus == null && hasException); if (danmakus == null) { mCacheTimer.update(end); return 0; } BaseDanmaku first = danmakus.first(); BaseDanmaku last = danmakus.last(); if (first == null || last == null) { mCacheTimer.update(end); return 0; } long deltaTime = first.time - mTimer.currMillisecond; long sleepTime = 30 + 10 * deltaTime / mContext.mDanmakuFactory.MAX_DANMAKU_DURATION; sleepTime = Math.min(100, sleepTime); if (repositioned) { sleepTime = 0; } IDanmakuIterator itr = danmakus.iterator(); BaseDanmaku item = null; long consumingTime = 0; int orderInScreen = 0; int currScreenIndex = 0; int sizeInScreen = danmakus.size(); // String message = ""; while (!mPause && !mCancelFlag) { boolean hasNext = itr.hasNext(); if (!hasNext) { // message = "break at not hasNext"; break; } item = itr.next(); if (last.time < mTimer.currMillisecond) { // message = "break at last.time < mTimer.currMillisecond"; break; } if (item.hasDrawingCache()) { continue; } if (repositioned == false && (item.isTimeOut() || !item.isOutside())) { continue; } if (!item.hasPassedFilter()) { mContext.mDanmakuFilters.filter( item, orderInScreen, sizeInScreen, null, true, mContext); } // Log.e("prepareCache", currScreenIndex+","+orderInScreen+"," + item.time+"skip:"+skip); if (item.priority == 0 && item.isFiltered()) { continue; } if (item.getType() == BaseDanmaku.TYPE_SCROLL_RL) { // 同屏弹幕密度只对滚动弹幕有效 int screenIndex = (int) ((item.time - curr) / mContext.mDanmakuFactory.MAX_DANMAKU_DURATION); if (currScreenIndex == screenIndex) orderInScreen++; else { orderInScreen = 0; currScreenIndex = screenIndex; } } if (!repositioned) { try { synchronized (mDrawingNotify) { mDrawingNotify.wait(sleepTime); } } catch (InterruptedException e) { e.printStackTrace(); break; } } // build cache if (buildCache(item, false) == RESULT_FAILED) { // message = "break at build failed"; break; } if (!repositioned) { consumingTime = SystemClock.uptimeMillis() - startTime; if (consumingTime >= DanmakuFactory.COMMON_DANMAKU_DURATION * mScreenSize) { // message = "break at consumingTime out:" + consumingTime; break; } } } consumingTime = SystemClock.uptimeMillis() - startTime; if (item != null) { mCacheTimer.update(item.time); // Log.i("cache","stop at :"+item.time+","+count+",size:"+danmakus.size()+","+message); } else { mCacheTimer.update(end); } return consumingTime; }