Java 无法在Android VideoView中播放h264流
我正在编写一个应用程序,它应该通过Java 无法在Android VideoView中播放h264流,java,android,android-mediaplayer,h.264,android-videoview,Java,Android,Android Mediaplayer,H.264,Android Videoview,我正在编写一个应用程序,它应该通过VideoView组件从Axis M7014视频编码器播放h.264流。 我的初衷是通过rtsp传输协议播放mjpg内容,但我愿意接受任何其他解决方案(与此视频编码器兼容)。 在与Axis支持人员交谈时,我发现通过Android本地组件播放格式/协议的唯一可能安排应该是h.264overrtsp 这是负责播放视频的活动的代码。 我还放置了一个EditText来插入流URI,以及一个按钮来启动视频: package it.acme.tux.controllervi
VideoView
组件从Axis M7014视频编码器播放h.264流。
我的初衷是通过rtsp
传输协议播放mjpg
内容,但我愿意接受任何其他解决方案(与此视频编码器兼容)。
在与Axis支持人员交谈时,我发现通过Android本地组件播放格式/协议的唯一可能安排应该是h.264
overrtsp
这是负责播放视频的活动的代码。
我还放置了一个EditText
来插入流URI,以及一个按钮来启动视频:
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>
我很确定这条流是有效的,因为我可以从我用来测试我的应用程序的同一部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流
致以最良好的祝愿,
迈克使用exoplayer。它支持更多的视频格式。
我已经将rtsp与wowza一起使用。有几种方法可以让您知道
试试它一次,让我知道如果你有问题。如果你的流在vlc工作良好,然后与应用程序端的问题。如果这些方法不起作用,请尝试使用不同的手机。它也对你有帮助
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();
}
});
}
});
startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("rtsp://184.72.239.149:8554/vid.mp4")));
2。尝试直接使用手机播放器
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();
}
});
}
});
startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("rtsp://184.72.239.149:8554/vid.mp4")));
3。第三种方法是尝试在应用程序中使用自定义播放器使用此库。
第1步。将其添加到渐变中
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" />
希望这能帮助您解决问题。感谢ExoPlayer支持H.264 AVC编解码器流。这是解决办法。
首先,您必须在Build.Gradle(模块应用程序)文件中指定ExoPlayer的依赖项,请记住,我使用的是ExoPlayer的2.8.0版本
implementation 'com.google.android.exoplayer:exoplayer-core:2.8.0'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.8.0'
在XML文件中,创建要在其中播放视频的ExoPlayer的PlayerView容器
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
tools:context=".MainActivity">
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/playerView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</com.google.android.exoplayer2.ui.PlayerView>
</androidx.constraintlayout.widget.ConstraintLayout>
有什么信息/警告吗?@Myszsoda没有。但也许我没能测试它。您有什么建议吗?我想您确实调用了playVideo(该视图毫无意义),因此mediaPlayer应该在Logcat中返回一些内容。最近,我还尝试使用SurfaceView
(而不是VideoView
)组件和mediaPlayer
实例,但运气不佳(再次).@MyszsodaplayVIdeo
是通过action\u play
按钮的onClick
事件启动的。我不知道是否可以在没有View
参数的情况下声明事件处理程序。无论如何,在未来我可能需要这个参数来区分哪个小部件触发了事件(假设我会添加更多按钮等)库在任何地方都有效,问题是它是否支持您的Android设备三星Galaxy Player。。。在http
上使用h.264
效果非常好,但它不支持mjpg
和rtsp
协议。似乎android不支持扩展Ep它不支持我希望exoPlayer有一个这种格式/协议的扩展。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
tools:context=".MainActivity">
<com.google.android.exoplayer2.ui.PlayerView
android:id="@+id/playerView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</com.google.android.exoplayer2.ui.PlayerView>
</androidx.constraintlayout.widget.ConstraintLayout>
public class MainActivity extends AppCompatActivity {
PlayerView playerView;
SimpleExoPlayer simpleExoPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playerView=findViewById(R.id.playerView);
}
@Override
protected void onStart() {
playerView = findViewById(R.id.playerView);
simpleExoPlayer= ExoPlayerFactory.newSimpleInstance(this,new DefaultTrackSelector());
DefaultDataSourceFactory defaultDataSourceFactory=new DefaultDataSourceFactory(this, Util.getUserAgent(this,"YourApplicationName"));
simpleExoPlayer.setPlayWhenReady(true);
ExtractorMediaSource extractorMediaSource=new ExtractorMediaSource.Factory(defaultDataSourceFactory).createMediaSource(RawResourceDataSource.buildRawResourceUri(R.raw.video));
simpleExoPlayer.prepare(extractorMediaSource);
playerView.setPlayer(simpleExoPlayer);
super.onStart();
}
@Override
protected void onStop() {
playerView.setPlayer(null);
simpleExoPlayer.release();
simpleExoPlayer=null;
super.onStop();
}
}