13

我正在尝试通过本地 unix 套接字从 android 相机流式传输视频并将文件从流写入 sdcard。一切正常,除了文件不能用任何播放器播放。这是因为 Android 没有填补文件中的一些空白,因为套接字是不可搜索的。据我了解,我需要在视频流结束后进行一些修改。我在这里这里这里阅读了几篇文章,但没有一篇对我有帮助。我正在使用十六进制编辑器来学习如何手动进行操作,因此之后在 Android 代码中执行相同操作将是微不足道的。

这是从流中保存的示例文件:https ://dl.dropbox.com/u/17510473/sample_not_playable.3gp

任何人都可以修复以使其可玩并告诉他是如何做到的吗?

编辑:我删除 3gp 文件的标题并编写新的如下:

00 00 00 18 66 74 79 70 33 67 70 34 00 00 03 00 33 67 70 34 33 67 70 36 00 00 00 00

然后我使用以下命令找到 mdat 和 moov 原子的起始位置:

grep -aobE "ftyp|mdat|moov" sample_not_playable.3gp

它给了我以下输出:

4:ftyp
28:mdat
1414676:moov

然后制作1414676 - 28 = 1,414,648 = 0x1595F8

然后我将 0x1595F8 写为 25-28 个字节,就在 mdat 原子之前。所以我的标题现在看起来像这样:

00 00 00 18 66 74 79 70 33 67 70 34 00 00 03 00 33 67 70 34 33 67 70 36 00 15 95 F8

当我尝试用 mplayer 播放它时,我得到一些损坏的视频和音频输出。以下是 mplayer 输出的部分内容:

[amrwb @ 0x7f72ad652380]Frame too small (33 bytes). Truncated file?
[amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame
[amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame
[amrwb @ 0x7f72ad652380]Frame too small (33 bytes). Truncated file?
[amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame
[amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame
[amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame
A:  11.0 V:   1.4 A-V:  9.650 ct:  0.023   0/  0 10%  1%  1.6% 0 0                                                        
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f72adeafc40]stream 1, offset 0x15e62b: partial file
[h263 @ 0x7f72ad652380]Bad picture start code
[h263 @ 0x7f72ad652380]header damaged
Error while decoding frame!
[h263 @ 0x7f72ad652380]Bad picture start code
[h263 @ 0x7f72ad652380]header damaged
Error while decoding frame!
[h263 @ 0x7f72ad652380]Bad picture start code
[h263 @ 0x7f72ad652380]header damaged
Error while decoding frame!
A:  11.1 V:   1.5 A-V:  9.558 ct:  0.027   0/  0  9%  1%  1.4% 0 0                                                        
[h263 @ 0x7f72ad652380]Bad picture start code
[h263 @ 0x7f72ad652380]header damaged
Error while decoding frame!

我做错了什么?

4

2 回答 2

14

您需要了解的是 mp4 不是实时流媒体格式。因此,无论如何您都无法破解以使其实时流式传输。标题 [moov atom] 写在最后。Android 创建一个帧大小和其他参数的内存表,然后在记录结束时将其写入文件开头,因此它需要文件句柄的可查找性。[插座不是]

如果您正在将加密的内容写入磁盘并且您希望这样做以便没有人可以播放该文件,您不必加密整个文件。您只需要加密标题,整个文件就无法播放。

如果您因为不相信我之前的段落而迫切需要完整的文件编码,那么请使用 ffmpeg 之类的东西来进行编码。修改它给你加密输出本身并再次将其保存到硬盘 - 再次删除套接字部分。

您无法在 android 中实时流式传输 mp4 文件。我见过很多人徒劳地尝试它,如果您了解视频/格式,就没有办法做到这一点。mp4 不是为直播而设计的。除非您事先知道帧大小 [您不知道] 和编码的确切长度 [您很可能不知道;t],否则您无法预先创建标头。

附言。mp4 和 3gp 是堂兄弟,所以同样适用。

许多人将实时流媒体与 http pd 和伪流媒体混淆。实时流媒体意味着我没有整个文件,它正在创建并且还在动态流中。http pd 和伪流使用完全可用的文件进行。

编辑:

如果您的目标是在存储到 sdcard 之前加密记录的文件,则需要编码器支持。这意味着在其中安装您自己的编码器。拿ffmpeg,交叉编译到android。为您的应用程序编写一个小的 JNI 接口。先把它弄好,不用加密。完成后,在 ffmpeg fwrite 流的位置,添加您的加密模块。解码时同样的事情。Y3ng 创作。这是最干净的方法。

编辑 2:请参阅 spydroid 为您获取一些功能。那里有类似的。

编辑 3:为了提高答案的质量,我正在解释其他答案也给出的不完美的解决方法:

人们仍然可以通过解析生成的 mp4 并通过套接字单独发送基本流来流式传输 AV。您将面临的唯一问题是您将无法获得完美的 AV 同步,因为您不知道确切的 AV 样本时间戳。只有 android 知道这一点,并将其写入最后的 mp4 标头中。所以对你没有好处。您必须对视频帧的完美采样率做出假设,并且您的音频必须是 amr 才能假设 20ms 数据包。在其他音频案例中,您将开始看到长时间运行的漂移[尤其是在您开始出现高运动场景的情况下]。这是因为生成的每个音频包都没有对应固定的时长[amr等语音编解码器除外]

于 2012-08-28T20:31:23.560 回答
4

首先,你要做什么不是很清楚。

您是否只想以编程方式将视频保存到可播放文件中?如果是这样,您只需要使用文件描述符而不是 unix 套接字。MediaRecord 的这个 API 设计用于处理文件(不是 unix 套接字),正是出于随机访问的原因。因此,我的第一个建议是使用文件描述符,您将在录制结束时获得正确的文件。

您可以在此处获取示例:如何在 Android 上捕获视频录制?

在这种情况下,如果您尝试编写从设备流式传输视频的应用程序,则需要实时解析流,将其按帧划分并分别发送帧。最复杂的部分是解析流(一些视频编解码器,例如 H263 可以解析,而其他则不能,特别是如果数据与音频交错)。

我相信这两个项目之一实现了这样的功能: http ://sipdroid.org/ http://code.google.com/p/imsdroid/

于 2012-08-23T18:55:07.350 回答