6

我正在尝试通过本地套接字从 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) {}
    }
}

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

提前谢谢,干杯。

4

3 回答 3

2

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

ftyp3gp4 3gp43gp6 宽 mdat

十六进制

0000001866747970336770340000030033677034336770360000000877696465000392D86D6461740000

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

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

于 2012-05-24T15:15:52.463 回答
1

您可以尝试使用 mp4box 来重组您的文件。moov 框给出了每个音频和视频样本的索引。如果那是在文件的末尾,则很难进行流式传输。

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

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

(我目前没有机会尝试)

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

于 2013-04-03T20:43:39.960 回答
0

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

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

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

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

一些链接如何从 SurfaceTexture 记录:

Bigflage:MediaCodec 的好例子。

Lablet 的 VideoRecorder 类。

也可能有用:spydroid-ipcamera 将来自 MediaRecorder 套接字的数据作为 RTP 流进行流式传输,但我找不到将其提供给 MediaCodec 的方法。(我已经在阅读正确的 NAL 单元大小时遇到​​了困难……)

于 2015-03-26T06:37:28.140 回答