wei*_*gyn 4 java android h.264 android-mediaplayer android-videoview
我正在编写一个应用程序,它应该通过一个组件从Axis M7014 视频编码器播放 h.264 流VideoView。我的初衷是mjpg通过rtsp传输协议播放内容,但我愿意接受任何其他解决方案(与此视频编码器兼容)。谈到Axis支持,我发现通过Android本机组件可播放的格式/协议的唯一可能安排应该h.264结束rtsp。
这是Activity负责播放视频的代码。我还放了一个EditText来插入流 URI 和一个Button来开始视频:
package it.acme.tux.controllerview;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.VideoView;
public class CameraActivity extends Activity {
private boolean playing = false;
private VideoView videoView;
private EditText textUri;
private Button buttonPlay;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
getActionBar().setDisplayHomeAsUpEnabled(true);
textUri = (EditText) findViewById(R.id.video_uri);
videoView=(VideoView) findViewById(R.id.videoView);
buttonPlay = (Button)findViewById(R.id.action_play);
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
videoView.start();
playing = true;
}
});
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
playing = false;
}
});
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
return false;
}
});
}
public void playVideo(View view)
{
if(!playing) {
String uri = (String) textUri.getText();
videoView.setVideoURI(Uri.parse(uri));
}
else {
videoView.stopPlayback();
playing = false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="it.acme.tux.controllerview.CameraActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/video_uri"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/default_uri"
android:textSize="12sp" />
<Button
android:id="@+id/action_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="playVideo"
android:text="@string/action_play_title"
android:textSize="12sp" />
</LinearLayout>
<VideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
布局中使用的字符串:
<resources>
<string name="action_play_title">Play</string>
<string name="default_uri">http://192.168.10.101:8080/stream</string>
</resources>
Run Code Online (Sandbox Code Playgroud)
据我所知,OnPreparedListener它从来没有像OnCompletionListener或那样被触发OnErrorListener。我阅读了我在那里找到的所有内容,而且我也阅读了MediaPlayer课程文档,但运气不佳(我采取的唯一好建议是在OnPreparedListener触发事件后开始视频播放)。
顺便说一句,当不可用时,我以这种方式通过VLC模拟视频编码器流:
vlc.exe video.mp4 --repeat :sout=#transcode{vcodec=h264,vb=800,scale=Auto,acodec=none}:http{mux=ffmpeg{mux=flv},dst=:8080/stream} :sout-all :sout-keep
Run Code Online (Sandbox Code Playgroud)
我很确定这个流可以工作,因为我可以h.264从我用来测试我的应用程序的同一个Android手机上查看来自 VLC的流(当然使用外部查看器)。
我错在哪里?为什么OnPreparedListener事件永远不会被触发?
我也尝试过使用SurfaceView组件VideoView和MediaPlayer SurfaceHolder实例的不同方法,但我也没有运气。这是代码:
package it.acme.tux.test;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.EditText;
import java.io.IOException;
public class MainActivity extends AppCompatActivity implements
SurfaceHolder.Callback,
MediaPlayer.OnPreparedListener,
MediaPlayer.OnInfoListener,
MediaPlayer.OnErrorListener,
MediaPlayer.OnCompletionListener
{
private MediaPlayer mediaPlayer;
private SurfaceView videoView;
private SurfaceHolder surfaceHolder;
boolean play = false;
private EditText textUri;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
videoView = (SurfaceView)findViewById(R.id.videoView);
textUri = (EditText)findViewById(R.id.textUri);
surfaceHolder = videoView.getHolder();
surfaceHolder.addCallback(this);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnInfoListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnCompletionListener(this);
}
@Override
protected void onPause() {
super.onPause();
mediaPlayer.release();
}
@Override
protected void onDestroy() {
super.onDestroy();
mediaPlayer.release();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mediaPlayer.setDisplay(holder);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
void playAction(View view){
try {
String source = textUri.getText().toString();
Log.d("MainActivity" , "Playing: " + source);
mediaPlayer.setDataSource(source);
mediaPlayer.prepareAsync();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
Log.d("MainActivity" , "Completed");
play = false;
}
@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
Log.d("MainActivity" , String.format("Info %d/%d", i, i1));
return false;
}
@Override
public boolean onInfo(MediaPlayer mediaPlayer, int i, int i1) {
Log.d("MainActivity" , String.format("Info %d/%d", i, i1));
return false;
}
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
Log.d("MainActivity" , "Prepared");
mediaPlayer.start();
play = true;
}
}
Run Code Online (Sandbox Code Playgroud)
我从中获得的唯一数据是从视频prepareAsync到start视频的更详细的进展(最终没有导致错误,但也没有显示任何视频)。在这种情况下,OnPreparedListener事件似乎被触发:
12-18 15:44:51.320 14445-14445/it.acme.tux.test V/MediaPlayer: setVideoSurfaceTexture
12-18 15:44:51.320 14445-14445/it.acme.tux.test V/MediaPlayer: prepareAsync
12-18 15:44:51.323 14445-14522/it.acme.tux.test V/MediaPlayer: message received msg=200, ext1=701, ext2=0
12-18 15:44:51.323 14445-14522/it.acme.tux.test W/MediaPlayer: info/warning (701, 0)
12-18 15:44:51.323 14445-14522/it.acme.tux.test V/MediaPlayer: callback application
12-18 15:44:51.323 14445-14522/it.acme.tux.test V/MediaPlayer: back from callback
12-18 15:44:51.330 14445-14445/it.acme.tux.test D/MainActivity: Info: 701 / 0
12-18 15:44:51.333 14445-14445/it.acme.tux.test V/MediaPlayer-JNI: getCurrentPosition: 0 (msec)
12-18 15:44:51.636 14445-14457/it.acme.tux.test V/MediaPlayer: message received msg=200, ext1=10972, ext2=0
12-18 15:44:51.636 14445-14457/it.acme.tux.test W/MediaPlayer: info/warning (10972, 0)
12-18 15:44:51.636 14445-14457/it.acme.tux.test V/MediaPlayer: callback application
12-18 15:44:51.636 14445-14457/it.acme.tux.test V/MediaPlayer: back from callback
12-18 15:44:51.637 14445-14445/it.acme.tux.test D/MainActivity: Info: 10972 / 0
12-18 15:44:51.638 14445-14522/it.acme.tux.test V/MediaPlayer: message received msg=5, ext1=0, ext2=0
12-18 15:44:51.638 14445-14522/it.acme.tux.test V/MediaPlayer: New video size 0 x 0
12-18 15:44:51.638 14445-14522/it.acme.tux.test V/MediaPlayer: callback application
12-18 15:44:51.639 14445-14522/it.acme.tux.test V/MediaPlayer: back from callback
12-18 15:44:58.645 14445-14458/it.acme.tux.test V/MediaPlayer: message received msg=200, ext1=702, ext2=0
12-18 15:44:58.645 14445-14458/it.acme.tux.test W/MediaPlayer: info/warning (702, 0)
12-18 15:44:58.645 14445-14458/it.acme.tux.test V/MediaPlayer: callback application
12-18 15:44:58.646 14445-14445/it.acme.tux.test D/MainActivity: Info: 702 / 0
12-18 15:44:58.647 14445-14458/it.acme.tux.test V/MediaPlayer: back from callback
12-18 15:44:58.647 14445-14445/it.acme.tux.test V/MediaPlayer-JNI: getCurrentPosition: 0 (msec)
12-18 15:44:59.645 14445-14458/it.acme.tux.test V/MediaPlayer: message received msg=1, ext1=0, ext2=0
12-18 15:44:59.645 14445-14458/it.acme.tux.test V/MediaPlayer: prepared
12-18 15:44:59.645 14445-14458/it.acme.tux.test V/MediaPlayer: callback application
12-18 15:44:59.646 14445-14445/it.acme.tux.test D/MediaPlayer: setSubtitleAnchor in MediaPlayer
12-18 15:44:59.647 14445-14458/it.acme.tux.test V/MediaPlayer: back from callback
12-18 15:44:59.652 14445-14445/it.acme.tux.test V/MediaPlayer: invoke 68
12-18 15:44:59.659 14445-14445/it.acme.tux.test D/MainActivity: Prepared
12-18 15:44:59.659 14445-14445/it.acme.tux.test V/MediaPlayer-JNI: start
12-18 15:44:59.659 14445-14445/it.acme.tux.test V/MediaPlayer: start
Run Code Online (Sandbox Code Playgroud)
我也尝试使用这个 uri:
rtsp://184.72.239.149/vod/mp4:BigBuckBunny_175k.mov
Run Code Online (Sandbox Code Playgroud)
那当然是一个h.264流rtsp。
总结一下我的请求,我需要帮助来解决这个问题。为什么视频没有播放?
是否有第三方组件可以播放 h.264 流(兼容Android Dev Studio 3.0.1)?如何播放MJPEG流?
最好的问候,迈克
我已经将 rtsp 与 wowza 一起使用。我会让你知道的几种方式
尝试一次,如果您遇到问题,请告诉我。如果您在 vlc 中的流式传输工作正常,则应用程序方面存在问题。如果这些方法不起作用,请尝试使用其他手机。它还可以帮助您。
1. 尝试使用视频视图
vvVideoPlay = (VideoView) findViewById(R.id.vvVideoPlay);
MediaController mediaController = new MediaController(this);
String videoUrl = "rtsp://184.72.239.149:8554/vid.mp4";
mediaController.setAnchorView(vvVideoPlay);
Uri uri = Uri.parse(videoUrl);
vvVideoPlay.setVideoURI(uri);
vvVideoPlay.setMediaController(mediaController);
vvVideoPlay.requestFocus();
vvVideoPlay.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
pdialog.dismiss();
mp.setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
mp.start();
}
});
}
});
Run Code Online (Sandbox Code Playgroud)
2. 直接用手机播放器试试
startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("rtsp://184.72.239.149:8554/vid.mp4")));
Run Code Online (Sandbox Code Playgroud)
3. 第三种方法尝试在您的应用程序中使用带有自定义播放器的库。
第1步。将它添加到你的gradle
compile "fm.jiecao:jiecaovideoplayer:4.7.0"
Run Code Online (Sandbox Code Playgroud)
第2步。将其添加为 xml 布局中的视频播放。
<fm.jiecao.jcvideoplayer_lib.JCVideoPlayerStandard
android:id="@+id/videoPlayer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Run Code Online (Sandbox Code Playgroud)
第 3 步。从这里检查如何在您的班级中使用此库,
public class PlayVideoActivity extends BaseActivity {
@BindView(R.id.videoPlayer)
JCVideoPlayerStandard mVideoPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
restoreFromIntent(getIntent());
}
@Override
public int getLayout() {
return R.layout.activity_play_video;
}
// get video path from intent and play the video here
private void restoreFromIntent(Intent intent) {
mVideoPlayer.setUp("rtsp://184.72.239.149:8554/vid.mp4"
, JCVideoPlayerStandard.SCREEN_LAYOUT_LIST, "");
}
@Override
public void onBackPressed() {
if (JCVideoPlayer.backPress()) {
return;
}
super.onBackPressed();
}
@Override
protected void onPause() {
super.onPause();
JCVideoPlayer.releaseAllVideos();
}
}
Run Code Online (Sandbox Code Playgroud)
希望这能帮助您解决问题。谢谢
| 归档时间: |
|
| 查看次数: |
4523 次 |
| 最近记录: |