RK3399安卓系统下通过RTSP流读取视频流并且可以提前每一帧画面的代码
时间: 2023-06-17 22:06:26 浏览: 173
rtsp视频流录制写入文件
以下是通过RTSP流读取视频流并且可以提前每一帧画面的Android代码:
```java
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaExtractor;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
import java.nio.ByteBuffer;
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback, Runnable {
private static final String TAG = "MainActivity";
private static final String VIDEO_PATH = "rtsp://192.168.1.1:554/stream";
private static final int MSG_START_PLAY = 0;
private static final int MSG_STOP_PLAY = 1;
private static final int MSG_PLAY_FRAME = 2;
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private MediaPlayer mMediaPlayer;
private MediaCodec mMediaCodec;
private MediaExtractor mMediaExtractor;
private ByteBuffer[] mInputBuffers;
private ByteBuffer[] mOutputBuffers;
private MediaFormat mMediaFormat;
private int mVideoTrackIndex;
private boolean mIsPlaying = false;
private boolean mIsCodecConfigured = false;
private long mStartTime;
private long mDuration;
private int mFrameIndex = 0;
private Handler mPlayHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_START_PLAY:
startPlay();
break;
case MSG_STOP_PLAY:
stopPlay();
break;
case MSG_PLAY_FRAME:
playFrame();
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSurfaceView = findViewById(R.id.surface_view);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
mPlayHandler.sendEmptyMessage(MSG_START_PLAY);
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
mPlayHandler.sendEmptyMessage(MSG_STOP_PLAY);
}
@Override
public void run() {
while (mIsPlaying) {
playFrame();
}
}
private void startPlay() {
try {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(getApplicationContext(), Uri.parse(VIDEO_PATH));
mMediaPlayer.setSurface(mSurfaceHolder.getSurface());
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mIsPlaying = true;
mStartTime = System.currentTimeMillis();
mDuration = mediaPlayer.getDuration();
mediaPlayer.start();
new Thread(MainActivity.this).start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
private void stopPlay() {
mIsPlaying = false;
mMediaPlayer.release();
mMediaCodec.stop();
mMediaCodec.release();
}
private void playFrame() {
if (mMediaExtractor == null) {
mMediaExtractor = new MediaExtractor();
try {
mMediaExtractor.setDataSource(VIDEO_PATH);
} catch (IOException e) {
e.printStackTrace();
}
mVideoTrackIndex = -1;
for (int i = 0; i < mMediaExtractor.getTrackCount(); i++) {
MediaFormat format = mMediaExtractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
mVideoTrackIndex = i;
mMediaFormat = format;
break;
}
}
mMediaExtractor.selectTrack(mVideoTrackIndex);
try {
mMediaCodec = MediaCodec.createDecoderByType(mMediaFormat.getString(MediaFormat.KEY_MIME));
mMediaCodec.configure(mMediaFormat, mSurfaceHolder.getSurface(), null, 0);
mMediaCodec.start();
mInputBuffers = mMediaCodec.getInputBuffers();
mOutputBuffers = mMediaCodec.getOutputBuffers();
} catch (IOException e) {
e.printStackTrace();
}
}
int inputBufferIndex = mMediaCodec.dequeueInputBuffer(10000);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = mInputBuffers[inputBufferIndex];
int sampleSize = mMediaExtractor.readSampleData(inputBuffer, 0);
if (sampleSize < 0) {
mMediaCodec.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
} else {
mMediaCodec.queueInputBuffer(inputBufferIndex, 0, sampleSize, mMediaExtractor.getSampleTime(), 0);
mMediaExtractor.advance();
}
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mMediaCodec.dequeueOutputBuffer(bufferInfo, 10000);
if (outputBufferIndex >= 0) {
if (!mIsCodecConfigured) {
mMediaCodec.releaseOutputBuffer(outputBufferIndex, false);
mIsCodecConfigured = true;
} else {
while (bufferInfo.presentationTimeUs / 1000 > System.currentTimeMillis() - mStartTime) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mMediaCodec.releaseOutputBuffer(outputBufferIndex, true);
if (mFrameIndex == 0) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(VIDEO_PATH);
String rotationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
int rotation = Integer.parseInt(rotationString);
if (rotation == 90 || rotation == 270) {
mMediaFormat.setInteger(MediaFormat.KEY_WIDTH, mMediaFormat.getInteger(MediaFormat.KEY_HEIGHT));
mMediaFormat.setInteger(MediaFormat.KEY_HEIGHT, mMediaFormat.getInteger(MediaFormat.KEY_WIDTH));
}
}
mFrameIndex++;
}
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
if (!mIsCodecConfigured) {
mMediaCodec.releaseOutputBuffer(outputBufferIndex, false);
mIsCodecConfigured = true;
} else {
MediaFormat format = mMediaCodec.getOutputFormat();
if (mFrameIndex == 0) {
String rotationString = format.getString(MediaFormat.KEY_ROTATION);
int rotation = Integer.parseInt(rotationString);
if (rotation == 90 || rotation == 270) {
format.setInteger(MediaFormat.KEY_WIDTH, format.getInteger(MediaFormat.KEY_HEIGHT));
format.setInteger(MediaFormat.KEY_HEIGHT, format.getInteger(MediaFormat.KEY_WIDTH));
}
}
mMediaCodec.releaseOutputBuffer(outputBufferIndex, false);
}
}
}
}
```
这个代码会通过RTSP流读取视频流并且可以提前每一帧画面。如果你要使用这个代码,需要将VIDEO_PATH替换为你的RTSP流地址。
阅读全文