从MediaRecorder通过LocalSocket流式传输视频

时间:2012-05-23 13:18:56

标签: android sockets video

我正在尝试通过本地Socket从Android的MediaRecorder发送h264 / AAC视频。目标是通过RTMP或RTSP将视频发送到WOWZA服务器,但它给我带来了很多麻烦,而现在我只是试图将数据写入LocalServerSocket中的文件。

这是一些代码。对不起,它不是很干净,但我花了好几个小时测试很多东西,现在我的项目很乱。

在Camera活动中,输出文件设置:

LocalSocket outSocket = new LocalSocket();

try {
    outSocket.connect(new LocalSocketAddress(LOCAL_SOCKET));
} catch (Exception e) {
    Log.i(LOG_TAG, "Error connecting socket: "+e);
}
mMediaRecorder.setOutputFile(outSocket.getFileDescriptor());

LocalServerSocket实现:

try {
    mLocalServerSocket = new LocalServerSocket(mName);
} catch (Exception e) {
    Log.e(LOG_TAG, "Error creating server socket: "+e);
    return;
}

while (true) {

    File out = null;
    FileOutputStream fop = null;
    try {
        mLocalClientSocket = mLocalServerSocket.accept();

        InputStream in = mLocalClientSocket.getInputStream();

        out = new File(mContext.getExternalFilesDir(null), "testfile.mp4");
        fop = new FileOutputStream(out);

        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) >= 0) {

            Log.i(LOG_TAG, "Writing "+len+" bytes");
            fop.write(buffer, 0, len);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    finally{
        try {
            fop.close();
            mLocalClientSocket.close();
        } catch (Exception e2) {}
    }
}

问题是任何媒体播放器都无法读取由此产生的文件。你认为这是因为编码问题吗?如果我理解的话,这段代码应该生成一个二进制文件?!

先谢谢,欢呼。

3 个答案:

答案 0 :(得分:2)

好的,我已经找到了文件无法播放的原因。在MP4和3GPP文件中,有一个包含字节的标头:

  

ftyp3gp4 3gp43gp6宽mdat

在HEX中

  

0000001866747970336770340000030033677034336770360000000877696465000392D86D6461740000

'mdat'标记之前的4个字节表示位于文件末尾的另一个'moov'标记的位置。通常在录制结束时设置位置,但由于MediaRecorder无法搜索套接字,因此在我们的情况下,它无法将这些字节设置为正确的值。

我现在的问题是找到一种方法使这样的文件可以流式传输,因为它涉及在录制结束之前播放它。

答案 1 :(得分:1)

您可以尝试使用mp4box重新构建文件。 moov框为每个音频和视频样本提供索引。如果它位于文件的末尾,则会使其难以流式传输。

这可能会有所帮助: http://boliston.wordpress.com/tag/moov-box/

或者这个: mp4box -inter 0.5 some_file.mp4

(我目前没有机会尝试)

如果您需要使用此应用程序,我不知道将mp4box移植到Android的任何活动。

答案 2 :(得分:0)

我今天尝试做同样的事情,但是mp4并不是很容易流式传输(如前所述,有些部分是在最后写的)。我不能说这是不可能的,但似乎至少相当困难。

因此,针对较新的Android API(4.3)的解决方法可能是:

  • 将相机预览设置为SurfaceTexture:camera.setPreviewTexture
  • 使用OpenGL和MediaCodex + Muxer
  • 记录此纹理

此解决方案的缺点是相机的预览尺寸可能小于视频尺寸。这意味着根据您的设备,您无法以最高分辨率录制。提示:有些相机表示他们不支持更高的预览尺寸,但他们会这样做,您可以尝试配置相机以将预览尺寸设置为视频尺寸。如果这样做,请捕获camera.setParameters的RuntimeException,如果失败则仅使用支持的预览大小。

一些链接如何从SurfaceTexture记录:

Bigflage: great examples for MediaCodec stuff.

The VideoRecorder class from Lablet.

也可能有用:spydroid-ipcamera将来自MediaRecorder套接字的数据作为RTP流进行流式传输,但我发现无法将其提供给MediaCodec。 (我已经卡住了读正确的NAL单位尺寸......)