我正在编写一个应用程序,它应该通过VideoView
组件从Axis M7014视频编码器播放h.264流。我最初的意图是在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;
}
}
}
这是布局文件:
<?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>
布局中使用的字符串:
<resources>
<string name="action_play_title">Play</string>
<string name="default_uri">http://192.168.10.101:8080/stream</string>
</resources>
据我所知,OnPreparedListener
它从未被触发过OnCompletionListener
或OnErrorListener
。我读了我在那里找到的所有东西,我也读了MediaPlayer
类文档没有运气(我采取的唯一好建议是一旦OnPreparedListener
事件被解雇就开始视频播放)。
BTW当不可用时,我通过这种方式通过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
我很确定这个流是有效的,因为我能够从我用来测试我的应用程序的同一个Android手机中查看来自VLC的h.264
流(当然还有外部查看器)。
哪里我错了?为什么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;
}
}
我从中获得的唯一数据是从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
我也尝试使用这个uri:
rtsp://184.72.239.149/vod/mp4:BigBuckBunny_175k.mov
这当然是h.264
流过rtsp
。
总结我的要求,我需要一个帮助来解决这个问题。为什么没有播放视频?
有第三方组件可以播放h.264流(Android Dev Studio 3.0.1兼容)吗?我该如何播放MJPEG流?
最好的问候,迈克
我已经使用rtsp和wowza.Few方式我会告诉你
尝试一次,如果你有问题让我知道。如果你在vlc中的流媒体工作正常,那么app方面的问题。如果这些方法不起作用,请尝试使用不同的手机。它也可以帮到你。
1.尝试使用videoview
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();
}
});
}
});
2.尝试直接使用手机播放器
startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("rtsp://184.72.239.149:8554/vid.mp4")));
3.第三种方法尝试在您的应用中使用自定义播放器使用此库。
步骤1。将它添加到您的gradle中
compile "fm.jiecao:jiecaovideoplayer:4.7.0"
第2步。将其添加为xml布局中的视频播放。
<fm.jiecao.jcvideoplayer_lib.JCVideoPlayerStandard
android:id="@+id/videoPlayer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
步骤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();
}
}
希望这能帮助你解决问题。谢谢
使用exoplayer。它支持更多格式的视频。 https://github.com/google/ExoPlayer