我正在尝试使用MediaRecorder仅录制视频(H264 / 3gpp),并将LocalSocket描述符传递给MediaRecorder。我可以接收数据,但无法播放视频。相同的代码适用于音频(AMR)。
LocalSocket类
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();
答案 0 :(得分:1)
这个问题有点陈旧,但此刻我正在这个领域做一些工作,所以我想尝试添加一个可能有助于绊倒这种方式的人的答案。
这里的基本问题是3GPP(如MP4)不是实时的可流式格式,因此即使通过套接字捕获数据,通常在音频或视频捕获结束时写入的关键文件头,缺少(因为套接字不像本地文件那样可见) - 因此无法播放数据。
AMR没有此文件头限制,这就是为什么OP的录音可以正常使用上面的代码。
没有简单的方法对数据执行后处理以手动添加文件头。所以解决方案是:
希望这有帮助。
答案 1 :(得分:1)
您需要删除MPEG4格式的标头。 localscoket的输入流包含MPEG4标头,需要将其删除才能访问视频。
检查Spydroid,它做类似的事情
答案 2 :(得分:1)
您可以使用此示例删除MP4标头:
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;
}
我在lib libstreaming(VideoStream.java)中看到过这段代码。是否与Spydroid中使用的lib相同。