forked from q215613905/TVBoxOS
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request q215613905#47 from okjackcaptain/main
支持挂载字幕 by okjack
- Loading branch information
Showing
28 changed files
with
5,067 additions
and
11 deletions.
There are no files selected for viewing
29 changes: 29 additions & 0 deletions
29
app/src/main/java/com/github/tvbox/osc/player/MyVideoView.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.github.tvbox.osc.player; | ||
|
||
import android.content.Context; | ||
import android.util.AttributeSet; | ||
|
||
import androidx.annotation.NonNull; | ||
import androidx.annotation.Nullable; | ||
|
||
import xyz.doikki.videoplayer.player.AbstractPlayer; | ||
import xyz.doikki.videoplayer.player.VideoView; | ||
|
||
public class MyVideoView extends VideoView { | ||
public MyVideoView(@NonNull Context context) { | ||
super(context, null); | ||
} | ||
|
||
public MyVideoView(@NonNull Context context, @Nullable AttributeSet attrs) { | ||
super(context, attrs, 0); | ||
} | ||
|
||
public MyVideoView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { | ||
super(context, attrs, defStyleAttr); | ||
} | ||
|
||
public AbstractPlayer getMediaPlayer() { | ||
return mMediaPlayer; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
227 changes: 227 additions & 0 deletions
227
app/src/main/java/com/github/tvbox/osc/subtitle/DefaultSubtitleEngine.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
/* | ||
* Copyright (C) of Avery | ||
* | ||
* _ooOoo_ | ||
* o8888888o | ||
* 88" . "88 | ||
* (| -_- |) | ||
* O\ = /O | ||
* ____/`- -'\____ | ||
* .' \\| |// `. | ||
* / \\||| : |||// \ | ||
* / _||||| -:- |||||- \ | ||
* | | \\\ - /// | | | ||
* | \_| ''\- -/'' | | | ||
* \ .-\__ `-` ___/-. / | ||
* ___`. .' /- -.- -\ `. . __ | ||
* ."" '< `.___\_<|>_/___.' >'"". | ||
* | | : `- \`.;`\ _ /`;.`/ - ` : | | | ||
* \ \ `-. \_ __\ /__ _/ .-` / / | ||
* ======`-.____`-.___\_____/___.-`____.-'====== | ||
* `=- -=' | ||
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
* Buddha bless, there will never be bug!!! | ||
*/ | ||
|
||
package com.github.tvbox.osc.subtitle; | ||
|
||
import android.os.Handler; | ||
import android.os.HandlerThread; | ||
import android.os.Message; | ||
import androidx.annotation.Nullable; | ||
import android.text.TextUtils; | ||
import android.util.Log; | ||
|
||
import com.github.tvbox.osc.subtitle.cache.SubtitleCache; | ||
import com.github.tvbox.osc.subtitle.model.Subtitle; | ||
import com.github.tvbox.osc.subtitle.model.TimedTextObject; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.TreeMap; | ||
|
||
import xyz.doikki.videoplayer.player.AbstractPlayer; | ||
|
||
/** | ||
* @author AveryZhong. | ||
*/ | ||
|
||
public class DefaultSubtitleEngine implements SubtitleEngine { | ||
private static final String TAG = DefaultSubtitleEngine.class.getSimpleName(); | ||
private static final int MSG_REFRESH = 0x888; | ||
private static final int REFRESH_INTERVAL = 100; | ||
|
||
@Nullable | ||
private HandlerThread mHandlerThread; | ||
@Nullable | ||
private Handler mWorkHandler; | ||
@Nullable | ||
private List<Subtitle> mSubtitles; | ||
private UIRenderTask mUIRenderTask; | ||
private AbstractPlayer mMediaPlayer; | ||
private SubtitleCache mCache; | ||
private OnSubtitlePreparedListener mOnSubtitlePreparedListener; | ||
private OnSubtitleChangeListener mOnSubtitleChangeListener; | ||
|
||
public DefaultSubtitleEngine() { | ||
mCache = new SubtitleCache(); | ||
|
||
} | ||
|
||
@Override | ||
public void bindToMediaPlayer(AbstractPlayer mediaPlayer) { | ||
mMediaPlayer = mediaPlayer; | ||
} | ||
|
||
@Override | ||
public void setSubtitlePath(final String path) { | ||
initWorkThread(); | ||
reset(); | ||
if (TextUtils.isEmpty(path)) { | ||
Log.w(TAG, "loadSubtitleFromRemote: path is null."); | ||
return; | ||
} | ||
mSubtitles = mCache.get(path); | ||
if (mSubtitles != null && !mSubtitles.isEmpty()) { | ||
Log.d(TAG, "from cache."); | ||
notifyPrepared(); | ||
return; | ||
} | ||
SubtitleLoader.loadSubtitle(path, new SubtitleLoader.Callback() { | ||
@Override | ||
public void onSuccess(final TimedTextObject timedTextObject) { | ||
if (timedTextObject == null) { | ||
Log.d(TAG, "onSuccess: timedTextObject is null."); | ||
return; | ||
} | ||
final TreeMap<Integer, Subtitle> captions = timedTextObject.captions; | ||
if (captions == null) { | ||
Log.d(TAG, "onSuccess: captions is null."); | ||
return; | ||
} | ||
mSubtitles = new ArrayList<>(captions.values()); | ||
notifyPrepared(); | ||
mCache.put(path, new ArrayList<>(captions.values())); | ||
} | ||
|
||
@Override | ||
public void onError(final Exception exception) { | ||
Log.e(TAG, "onError: " + exception.getMessage()); | ||
} | ||
}); | ||
} | ||
|
||
@Override | ||
public void reset() { | ||
stop(); | ||
mSubtitles = null; | ||
mUIRenderTask = null; | ||
} | ||
|
||
@Override | ||
public void start() { | ||
Log.d(TAG, "start: "); | ||
if (mMediaPlayer == null) { | ||
Log.w(TAG, "MediaPlayer is not bind, You must bind MediaPlayer to " | ||
+ SubtitleEngine.class.getSimpleName() | ||
+ " before start() method be called," | ||
+ " you can do this by call " + | ||
"bindToMediaPlayer(MediaPlayer mediaPlayer) method."); | ||
return; | ||
} | ||
stop(); | ||
if (mWorkHandler != null) { | ||
mWorkHandler.sendEmptyMessageDelayed(MSG_REFRESH, REFRESH_INTERVAL); | ||
} | ||
|
||
} | ||
|
||
@Override | ||
public void pause() { | ||
stop(); | ||
} | ||
|
||
@Override | ||
public void resume() { | ||
start(); | ||
} | ||
|
||
@Override | ||
public void stop() { | ||
if (mWorkHandler != null) { | ||
mWorkHandler.removeMessages(MSG_REFRESH); | ||
} | ||
} | ||
|
||
@Override | ||
public void destroy() { | ||
Log.d(TAG, "destroy: "); | ||
stopWorkThread(); | ||
reset(); | ||
|
||
} | ||
|
||
private void initWorkThread() { | ||
stopWorkThread(); | ||
mHandlerThread = new HandlerThread("SubtitleFindThread"); | ||
mHandlerThread.start(); | ||
mWorkHandler = new Handler(mHandlerThread.getLooper(), new Handler.Callback() { | ||
@Override | ||
public boolean handleMessage(final Message msg) { | ||
try { | ||
long delay = REFRESH_INTERVAL; | ||
if (mMediaPlayer != null && mMediaPlayer.isPlaying()) { | ||
long position = mMediaPlayer.getCurrentPosition(); | ||
Subtitle subtitle = SubtitleFinder.find(position, mSubtitles); | ||
notifyRefreshUI(subtitle); | ||
if (subtitle != null) { | ||
delay = subtitle.end.mseconds - position; | ||
} | ||
|
||
} | ||
if (mWorkHandler != null) { | ||
mWorkHandler.sendEmptyMessageDelayed(MSG_REFRESH, delay); | ||
} | ||
} catch (Exception e) { | ||
// ignored | ||
} | ||
return true; | ||
} | ||
}); | ||
} | ||
|
||
private void stopWorkThread() { | ||
if (mHandlerThread != null) { | ||
mHandlerThread.quit(); | ||
mHandlerThread = null; | ||
} | ||
if (mWorkHandler != null) { | ||
mWorkHandler.removeCallbacksAndMessages(null); | ||
mWorkHandler = null; | ||
} | ||
} | ||
|
||
private void notifyRefreshUI(final Subtitle subtitle) { | ||
if (mUIRenderTask == null) { | ||
mUIRenderTask = new UIRenderTask(mOnSubtitleChangeListener); | ||
} | ||
mUIRenderTask.execute(subtitle); | ||
} | ||
|
||
private void notifyPrepared() { | ||
if (mOnSubtitlePreparedListener != null) { | ||
mOnSubtitlePreparedListener.onSubtitlePrepared(mSubtitles); | ||
} | ||
} | ||
|
||
@Override | ||
public void setOnSubtitlePreparedListener(final OnSubtitlePreparedListener listener) { | ||
mOnSubtitlePreparedListener = listener; | ||
} | ||
|
||
@Override | ||
public void setOnSubtitleChangeListener(final OnSubtitleChangeListener listener) { | ||
mOnSubtitleChangeListener = listener; | ||
} | ||
|
||
} |
Oops, something went wrong.