Reputation: 2418
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
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
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
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:
Hope this helps.
Upvotes: 1