alexeyvasilyev / rtsp-client-android

Lightweight RTSP client library for Android
Apache License 2.0
223 stars 57 forks source link

how to record stream? #3

Open ahmedchoteri opened 3 years ago

ahmedchoteri commented 3 years ago

First of all, thank you so much for this library. I checked several other libs but this one has the best performance I got.

I required to place record button while a user is streaming video. can you please help me how I can achieve this.

alexeyvasilyev commented 3 years ago

You can use Android MediaMuxer class to copy all H264 and AAC stream into MP4 file without any reencoding. Do something like that.

@Override
public void onRtspConnected(@NonNull RtspClient.SdpInfo sdpInfo) {
  _muxer = new MediaMuxer("/mnt/sdcard/my.mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
  // Create videoTrackFormat and audioTrackFormat before
  _muxer.addTrack(videoTrackFormat);
  _muxer.addTrack(audioTrackFormat);
  _muxer.start();
}

@Override
public void onRtspVideoNalUnitReceived(@NonNull byte[] data, int offset, int length, long timestamp) {
  ...
  MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
  bufferInfo.presentationTimeUs = timestamp * 1000L;
  bufferInfo.size = length;
  ByteBuffer encodedData = ByteBuffer.wrap(data, offset, length);
  _muxer.writeSampleData(0, encodedData, bufferInfo);
}

@Override
public void onRtspAudioSampleReceived(@NonNull byte[] data, int offset, int length, long timestamp) {
  MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
  bufferInfo.presentationTimeUs = timestamp * 1000L;
  bufferInfo.size = length;
  ByteBuffer encodedData = ByteBuffer.wrap(data, offset, length);
  _muxer.writeSampleData(1, encodedData, bufferInfo);
}

@Override
public void onRtspDisconnected() {
  _muxer.stop();
  _muxer.release();
  _muxer = null;
}

See https://bigflake.com/mediacodec/ how to use MediaMuxer.

pranishres commented 3 years ago

You can use Android MediaMuxer class to copy all H264 and AAC stream into MP4 file without any reencoding. Do something like that.

@Override
public void onRtspConnected(@NonNull RtspClient.SdpInfo sdpInfo) {
  _muxer = new MediaMuxer("/mnt/sdcard/my.mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
  // Create videoTrackFormat and audioTrackFormat before
  _muxer.addTrack(videoTrackFormat);
  _muxer.addTrack(audioTrackFormat);
  _muxer.start();
}

@Override
public void onRtspVideoNalUnitReceived(@NonNull byte[] data, int offset, int length, long timestamp) {
  ...
  MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
  bufferInfo.presentationTimeUs = timestamp * 1000L;
  bufferInfo.size = length;
  ByteBuffer encodedData = ByteBuffer.wrap(data, offset, length);
  _muxer.writeSampleData(0, encodedData, bufferInfo);
}

@Override
public void onRtspAudioSampleReceived(@NonNull byte[] data, int offset, int length, long timestamp) {
  MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
  bufferInfo.presentationTimeUs = timestamp * 1000L;
  bufferInfo.size = length;
  ByteBuffer encodedData = ByteBuffer.wrap(data, offset, length);
  _muxer.writeSampleData(1, encodedData, bufferInfo);
}

@Override
public void onRtspDisconnected() {
  _muxer.stop();
  _muxer.release();
  _muxer = null;
}

See https://bigflake.com/mediacodec/ how to use MediaMuxer.

Can I get more updates in this?

z742323813 commented 1 year ago

你好为啥我用这个代码区录制 之后根本无法播放呢

sarimmehdi commented 1 year ago

Has anyone managed to implement this? I don't understand what to put for videoTrackFormat and audioTrackFormat in the sample code provided by @alexeyvasilyev

pranishres commented 1 year ago

Has anyone managed to implement this? I don't understand what to put for videoTrackFormat and audioTrackFormat in the sample code provided by @alexeyvasilyev

You can use vlc's free github library. That saved my life.

sarimmehdi commented 1 year ago

@pranishres do you have a sample app I could use for viewing rtsp stream and also recording it at the same time?

alirehan commented 1 year ago

@sarimmehdi were you able to make it work? Please share if you have any learnings from the process?

cleancoderob commented 11 months ago

I needed to modify the sample code with these changes to get it working. I only setup video (H.264), no audio in my tests.

  1. The MediaMuxer needs to know about key frames in the flags. When setting up the bufferInfo:

        bufferInfo.presentationTimeUs = timestamp; // value is already in microseconds
        bufferInfo.flags = (bytes[4] & 0x1f) == 5 ? MediaCodec.BUFFER_FLAG_KEY_FRAME : 0;
  2. The videoFormat is setup as follows:

          String mimeType = "video/avc";
          int width = 1920;
          int height = 1080;
          byte[] sps = sdpInfo.videoTrack.sps;
          byte[] pps = sdpInfo.videoTrack.pps;
    
          MediaFormat videoTrackFormat = MediaFormat.createVideoFormat(mimeType, width, height);
          videoTrackFormat.setByteBuffer("csd-0", ByteBuffer.wrap(sps));
          videoTrackFormat.setByteBuffer("csd-1", ByteBuffer.wrap(pps));

More info: https://stackoverflow.com/questions/53637969/mediamuxer-writing-h264-stream-to-mpg-file