From 7c51f7894df0d7c0013254e6cb37e4abd668f418 Mon Sep 17 00:00:00 2001 From: liuguijing <1440265357@qq.com> Date: Thu, 10 Apr 2025 16:34:57 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=86=E9=A2=91=E6=8B=89=E6=B5=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/xypower/mpremote/StreamActivity.java | 220 ++++-------------- app/src/main/res/layout/activity_stream.xml | 34 +-- 2 files changed, 64 insertions(+), 190 deletions(-) diff --git a/app/src/main/java/com/xypower/mpremote/StreamActivity.java b/app/src/main/java/com/xypower/mpremote/StreamActivity.java index 4b62087..18c99d0 100644 --- a/app/src/main/java/com/xypower/mpremote/StreamActivity.java +++ b/app/src/main/java/com/xypower/mpremote/StreamActivity.java @@ -14,34 +14,27 @@ import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.source.ProgressiveMediaSource; import androidx.media3.ui.PlayerView; +import android.app.AlertDialog; import android.content.Intent; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.Menu; import android.view.MenuItem; -import android.view.Surface; -import android.view.SurfaceHolder; -import android.view.SurfaceView; import android.view.View; import android.widget.Toast; import com.xypower.mpremote.databinding.ActivityStreamBinding; import com.xypower.mpremote.utils.AdbUtils; +import com.xypower.mpremote.utils.AlertDialogUtils; -import org.videolan.libvlc.LibVLC; -import org.videolan.libvlc.Media; import org.videolan.libvlc.MediaPlayer; -import java.util.ArrayList; - import dadb.AdbShellResponse; import dadb.Dadb; public class StreamActivity extends AppCompatActivity implements View.OnClickListener { - // private PlayerView playerView; private static final String TAG = "STRM"; private static final int MAX_RETRIES = 5; @@ -65,9 +58,8 @@ public class StreamActivity extends AppCompatActivity implements View.OnClickLis private long bufferingStartTime = 0; private static final long BUFFERING_TIMEOUT_MS = 10000; // 10秒缓冲超时 private String RTMP_URL; - private SurfaceView playerView; - private MediaPlayer mediaPlayer; - private LibVLC libVLC; + private PlayerView playerView; + private AlertDialog alertDialog; @Override protected void onCreate(Bundle savedInstanceState) { @@ -82,37 +74,19 @@ public class StreamActivity extends AppCompatActivity implements View.OnClickLis private void initEvent() { RTMP_URL = "rtmp://" + mDeviceIp + "/live/0"; - - String cmd = "am start -n com.xypower.mplive/com.xypower.mplive.MainActivity" - + " --ei cameraId " + Integer.toString(cameraId) - + " --ei rotation " + Integer.toString(rotation) - + " --ei netCamera " + Integer.toString(netCamera) - + " --ei vendor " + Integer.toString(vendor) - + " --ei autoStart 1" - + " --es url \"" + RTMP_URL + "\""; + String cmd = "am start -n com.xypower.mplive/com.xypower.mplive.MainActivity" + " --ei cameraId " + Integer.toString(cameraId) + " --ei rotation " + Integer.toString(rotation) + " --ei netCamera " + Integer.toString(netCamera) + " --ei vendor " + Integer.toString(vendor) + " --ei autoStart 1" + " --es url \"" + RTMP_URL + "\""; Runnable runnable = new Runnable() { @Override public void run() { initializePlayer(); } }; + alertDialog = AlertDialogUtils.show(this, "视频加载中"); startStreaming(cmd, runnable); - - - } private void initHandler() { // mHandler = new Handler(); - - // 配置 VLC 参数 - ArrayList options = new ArrayList<>(); - options.add("--aout=opensles"); // 优化音频延迟‌:ml-citation{ref="6" data="citationList"} - options.add("--audio-time-stretch"); - - libVLC = new LibVLC(this, options); - mediaPlayer = new MediaPlayer(libVLC); - } private void initIntent() { @@ -131,29 +105,9 @@ public class StreamActivity extends AppCompatActivity implements View.OnClickLis binding.toolbar.back.setOnClickListener(this); binding.toolbar.refresh.setOnClickListener(this); playerView = binding.playerView; - SurfaceHolder holder = playerView.getHolder(); - holder.addCallback(new SurfaceHolder.Callback() { - @Override - public void surfaceCreated(SurfaceHolder holder) { - Surface surface = holder.getSurface(); - mediaPlayer.getVLCVout().setVideoSurface(surface,holder); - mediaPlayer.getVLCVout().attachViews(); // 绑定视图‌:ml-citation{ref="8" data="citationList"} - } - - @Override - public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { - - } - - @Override - public void surfaceDestroyed(@NonNull SurfaceHolder holder) { - - } - }); } private void startStreaming(final String cmd, final Runnable runnable) { - Log.d(TAG, cmd); Thread th = new Thread(new Runnable() { @Override public void run() { @@ -197,12 +151,10 @@ public class StreamActivity extends AppCompatActivity implements View.OnClickLis } } }); - th.start(); } private void stopStreaming() { - // String cmd = "am start -n com.xypower.mplive/com.xypower.mplive.MainActivity --ei autoClose 1"; String cmd = "am force-stop com.xypower.mplive"; Thread th = new Thread(new Runnable() { @Override @@ -240,107 +192,42 @@ public class StreamActivity extends AppCompatActivity implements View.OnClickLis th.start(); } - private void initializePlayer2() { -// // 创建重试策略 -// DefaultLoadControl loadControl = new DefaultLoadControl.Builder() -// .setBufferDurationsMs( -// 5000, // minBufferMs -// 10000, // maxBufferMs -// 500, // bufferForPlaybackMs -// 500 // bufferForPlaybackAfterRebufferMs -// ).build(); -// player = new ExoPlayer.Builder(this).build(); -// playerView.setPlayer(player); -// player.addListener(new Player.Listener() { -// @Override -// public void onPlayerError(PlaybackException error) { -// Log.e(TAG, "播放错误: " + error.getMessage()); -// handlePlaybackError(); -// } -// -// @Override -// public void onPlaybackStateChanged(int state) { -// if (state == Player.STATE_READY) { -// // 重置重试计数器当成功连接时 -// retryCount = 0; -// } -// } -// }); -// startPlayback(); - } - -// private void handlePlaybackError2() { -// if (retryCount < MAX_RETRIES) { -// retryCount++; -// Log.d(TAG, "准备重试 (" + retryCount + "/" + MAX_RETRIES + ")..."); -// mHandler.postDelayed(() -> { -// if (player != null) { -// startPlayback(); -// } -// }, 3000); -// } else { -// Log.e(TAG, "达到最大重试次数,停止尝试"); -// // 这里可以添加UI提示或执行其他错误处理 -// } -// } - - private void startPlayback2() { - if (player == null) return; - Log.d(TAG, "开始播放,重试次数: " + retryCount); - MediaItem mediaItem = MediaItem.fromUri("rtmp://" + mDeviceIp + "/live/0"); - ProgressiveMediaSource videoSource = new ProgressiveMediaSource.Factory(new RtmpDataSource.Factory()) - .createMediaSource(mediaItem); - player.setMediaSource(videoSource); - player.prepare(); - player.setPlayWhenReady(true); - } - - private void initializePlayer() { -// if (player == null) { -// player = new ExoPlayer.Builder(this) -// .setLoadControl(new DefaultLoadControl.Builder() -// .setBufferDurationsMs( -// 5000, // minBufferMs -// 10000, // maxBufferMs -// 500, // bufferForPlaybackMs -// 500 // bufferForPlaybackAfterRebufferMs -// ).setPrioritizeTimeOverSizeThresholds(true) -// .build()) -// .build(); -// -//// playerView.setPlayer(player); -// -// player.addListener(new Player.Listener() { -// @Override -// public void onPlayerError(PlaybackException error) { -// Log.e(TAG, "播放错误: " + error.getMessage()); -// handlePlaybackError(); -// } -// -// @Override -// public void onPlaybackStateChanged(int state) { -// if (state == Player.STATE_BUFFERING) { -// if (!isBuffering) { -// isBuffering = true; -// bufferingStartTime = System.currentTimeMillis(); -// // 启动缓冲超时检查 -// retryHandler.postDelayed(bufferingTimeoutRunnable, BUFFERING_TIMEOUT_MS); -// } -// } else if (state == Player.STATE_READY) { -// isBuffering = false; -// retryHandler.removeCallbacks(bufferingTimeoutRunnable); -// retryCount = 0; -// currentRetryDelay = INITIAL_RETRY_DELAY_MS; -// Log.d(TAG, "播放器准备就绪"); -// } -// } -// }); -// } -// startPlayback(); - Media media = new Media(libVLC, Uri.parse(RTMP_URL)); - mediaPlayer.setMedia(media); - mediaPlayer.play(); + if (player == null) { + player = new ExoPlayer.Builder(this).setLoadControl(new DefaultLoadControl.Builder().setBufferDurationsMs(5000, // minBufferMs + 10000, // maxBufferMs + 500, // bufferForPlaybackMs + 500 // bufferForPlaybackAfterRebufferMs + ).setPrioritizeTimeOverSizeThresholds(true).build()).build(); + playerView.setPlayer(player); + player.addListener(new Player.Listener() { + @Override + public void onPlayerError(PlaybackException error) { + Log.e(TAG, "播放错误: " + error.getMessage()); + handlePlaybackError(); + } + + @Override + public void onPlaybackStateChanged(int state) { + if (state == Player.STATE_BUFFERING) { + if (!isBuffering) { + isBuffering = true; + bufferingStartTime = System.currentTimeMillis(); + // 启动缓冲超时检查 + retryHandler.postDelayed(bufferingTimeoutRunnable, BUFFERING_TIMEOUT_MS); + } + } else if (state == Player.STATE_READY) { + AlertDialogUtils.dismiss(alertDialog); + isBuffering = false; + retryHandler.removeCallbacks(bufferingTimeoutRunnable); + retryCount = 0; + currentRetryDelay = INITIAL_RETRY_DELAY_MS; + Log.d(TAG, "播放器准备就绪"); + } + } + }); + } + startPlayback(); } @@ -356,13 +243,9 @@ public class StreamActivity extends AppCompatActivity implements View.OnClickLis private void startPlayback() { if (player == null) return; - Log.d(TAG, "开始播放,重试次数: " + retryCount); -// MediaItem mediaItem = MediaItem.fromUri(Uri.parse(RTMP_URL)); - MediaItem mediaItem = MediaItem.fromUri(RTMP_URL); - ProgressiveMediaSource videoSource = new ProgressiveMediaSource.Factory(new RtmpDataSource.Factory()) - .createMediaSource(mediaItem); + ProgressiveMediaSource videoSource = new ProgressiveMediaSource.Factory(new RtmpDataSource.Factory()).createMediaSource(mediaItem); player.setMediaSource(videoSource); // player.setMediaItem(mediaItem); player.prepare(); @@ -371,15 +254,13 @@ public class StreamActivity extends AppCompatActivity implements View.OnClickLis private void handlePlaybackError() { releasePlayerInternal(); - if (retryCount < MAX_RETRIES) { retryCount++; Log.d(TAG, "准备重试 (" + retryCount + "), 延迟: " + currentRetryDelay + "ms"); - retryHandler.postDelayed(() -> { initializePlayer(); // 增加下次重试的延迟时间(使用退避算法) - currentRetryDelay = Math.min((long)(currentRetryDelay * RETRY_BACKOFF_MULTIPLIER), MAX_RETRY_DELAY_MS); + currentRetryDelay = Math.min((long) (currentRetryDelay * RETRY_BACKOFF_MULTIPLIER), MAX_RETRY_DELAY_MS); }, currentRetryDelay); } } @@ -394,12 +275,11 @@ public class StreamActivity extends AppCompatActivity implements View.OnClickLis } - - - @Override protected void onDestroy() { super.onDestroy(); + AlertDialogUtils.dismiss(alertDialog); + releasePlayerInternal(); stopStreaming(); } @@ -408,7 +288,7 @@ public class StreamActivity extends AppCompatActivity implements View.OnClickLis protected void onPause() { super.onPause(); if (Util.SDK_INT < 24) { - releasePlayer(); + releasePlayerInternal(); } } @@ -417,16 +297,10 @@ public class StreamActivity extends AppCompatActivity implements View.OnClickLis protected void onStop() { super.onStop(); if (Util.SDK_INT >= 24) { - releasePlayer(); + releasePlayerInternal(); } } - private void releasePlayer() { - if (player != null) { - player.release(); - player = null; - } - } @Override public boolean onCreateOptionsMenu(Menu menu) { diff --git a/app/src/main/res/layout/activity_stream.xml b/app/src/main/res/layout/activity_stream.xml index 43b0de9..79c7f7f 100644 --- a/app/src/main/res/layout/activity_stream.xml +++ b/app/src/main/res/layout/activity_stream.xml @@ -11,24 +11,24 @@ android:id="@+id/toolbar" layout="@layout/toolbar" /> - + + + + + + - - - - - - - - - - - +