shantanu
shantanu

Reputation: 2418

Can not play video received from LocalSocket in android

I am trying to record only video(H264/3gpp) using MediaRecorder, and passed a LocalSocket descriptor to MediaRecorder. I can receive data but can't play the video. Same code is working for audio(AMR).

LocalSocket class

public class MediaStreamer extends MediaRecorder{

    private static int id = 0;

    private LocalServerSocket lss = null;
    private LocalSocket receiver, sender = null;

    public void prepare() throws IllegalStateException,IOException {

        receiver = new LocalSocket();
        try {
            lss = new LocalServerSocket("librtp-"+id);
            receiver.connect(new LocalSocketAddress("librtp-"+id));
            receiver.setReceiveBufferSize(4096);
            receiver.setSendBufferSize(4096);
            sender = lss.accept();
            sender.setReceiveBufferSize(4096);
            sender.setSendBufferSize(4096); 
            id++;
        } catch (IOException e1) {
            throw new IOException("Can't create local socket !");
        }

        setOutputFile(sender.getFileDescriptor());

        try {
            super.prepare();
        } catch (IllegalStateException e) {
            closeSockets();
            throw e;
        } catch (IOException e) {
            closeSockets();
            throw e;
        }

    }

    public InputStream getInputStream() {

        InputStream out = null;

        try {
            out = receiver.getInputStream();
        } catch (IOException e) {
        }

        return out;

    }


    public void stop() {
        closeSockets();
        super.stop();
    }

    private void closeSockets() {
        if (lss!=null) {
            try {
                lss.close();
                sender.close();
                receiver.close();
            }
            catch (IOException e) {

            }
            lss = null; sender = null; receiver = null;
        }
    }
}

MediaRecorder

video = new MediaStreamer();
video.reset();

video.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
video.setPreviewDisplay(holder.getSurface());
video.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
video.setVideoFrameRate(VideoConstants.frameRate);
video.setVideoEncodingBitRate(VideoConstants.bitRate*1000);
video.setVideoSize(VideoConstants.resolationX, VideoConstants.resolationY);
video.setVideoEncoder(MediaRecorder.VideoEncoder.H264);

try {
   video.prepare();
   videoWriter = new Writer(Environment.getExternalStorageDirectory()+"/video.mp4",video.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
video.start();
videoWriter.startWriting();

Upvotes: 1

Views: 1194

Answers (3)

user3725936
user3725936

Reputation: 11

You could use this example to remove the MP4 header:

InputStream reader = video.getInputStream();
byte buffer[] = new byte[4];
while (!Thread.interrupted()) {
   while (reader.read() != 'm');
      reader.read(buffer,0,3);
      if (buffer[0] == 'd' && buffer[1] == 'a' && buffer[2] == 't') break;
}

I have seen this code in lib libstreaming (VideoStream.java). Is the same lib used in Spydroid.

Upvotes: 1

Nishanth Kumar
Nishanth Kumar

Reputation: 121

You need to remove header of the MPEG4 format. The inputstream from the localscoket contains the MPEG4 header, which needs to be removed to access the video.

Check Spydroid, which does similar thing

Upvotes: 1

Steven
Steven

Reputation: 1620

This question is a bit old but I'm doing some work in this area at the moment, so figured I would try and add an answer that might help someone who stumbles this way.

The fundamental problem here is that 3GPP (like MP4) is not a live, streamable format, so even though data is captured via the socket, the crucial file headers which are normally written at the conclusion of an audio or video capture, are missing (because sockets are not seekeable like local files) - hence the unplayable data.

AMR does not have this file header limitation which is why the OP's audio recordings work fine with the code above.

There is no easy way to perform post-processing on the data to manually add the file headers. So the solution is either:

  1. don't use 3GPP or MP4 as the recording format
  2. write a packetiser similar to what is used in the Spydroid project

Hope this helps.

Upvotes: 1

Related Questions