[Video Record]关于文件4G限制的处理方式

问题描述


 目前代码中的录像默认会有4G的限制,之所以有这样的限制,是因为目前很多存储设备都是fat格式的,fat的size是32位表示的,天然就有4G的限制,而且实际上在限制4G的情况下只能录出来3.8G。是因为
a)要留一部分buffer写moovbox
b)有的还要留部分buffer作为写数据的cache

具体请查看代码

/frameworks/av/media/libstagefright/MPEG4Writer.cpp

1684bool MPEG4Writer::exceedsFileSizeLimit() {
.........
1701 // Be conservative in the estimate: do not exceed 95% of
1702 // the target file limit. For small target file size limit, though,
1703 // this will not help.
1704 return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);// 4G * 95% = 3.8G
1705}

解决方案


  1. 通过adb shell  blkid dev/block/mmcblk1p1判断sdcard的限制,此时如果输出的结果:dev/block/mmcblk1p1: UUID="70CD-07EB" TYPE="vfat",则表示sdcard是fat型的,fat用32位表示文件的大小,天然就有2^32 = 4G的限制
    这种情况下,软件无法处理,接受现状
  2. 在sdcard没有限制的情况下,可以通过软件在/frameworks/base/media/java/android/media/MediaRecorder.java的setVideoEncodingBitRate()中加入语句 setParameter("param-use-64bit-offset=1");来突破4G的限制,逻辑如下:从后往前查找 /frameworks/av/media/libstagefright/MPEG4Writer.cpp的param->findInt32(kKey64BitFileOffset, &use64BitOffset)如果设置了的话,就表示文件是64位表示的,也就没有4G的限制了,而use64BitOffset的值取决于kKey64BitFileOffset kKey64BitFileOffset的值又是在/frameworks/av/media/libmediaplayerservice/StagefrightRecorder.cpp中通过语句(*meta)->setInt32(kKey64BitFileOffset, mUse64BitFileOffset)设置的,也就意味着此时需要查看mUse64BitFileOffset的值,这个值又是借助status_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit)通过key == "param-use-64bit-offset"决定的,所以添加语句 setParameter("param-use-64bit-offset=1");就 意味着文件的大小可以超过4G
  3. 在https://android.googlesource.com/platform/frameworks/av/+/android-8.1.0_r14/media/libmediaplayerservice/StagefrightRecorder.cpp中也有看到如下处理方式(但此方法未经过实测验证,不能保证没有风险,仅供参考):Enable recording files larger than 4GB by forcing 64-bit file-offsets
    in the writer, if application indicates max-file-size greater than 4GB. 

    CRs-Fixed: 807377
    Change-Id: Id1af5bdf3543af156e6d3d80be2e00c7df3b4134

     

    --- a/media/libmediaplayerservice/StagefrightRecorder.cpp
    +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
    @@ -87,6 +87,7 @@ static const char *kRecorderVideoLevel = "android.media.mediarecorder.video-enco
    static const char *kRecorderCaptureFpsEnable = "android.media.mediarecorder.capture-fpsenable";
    static const char *kRecorderCaptureFps = "android.media.mediarecorder.capture-fps";
    static const char *kRecorderRotation = "android.media.mediarecorder.rotation";
    +static const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 4GB

    // To collect the encoder usage for the battery app
    static void addBatteryData(uint32_t params) {
    @@ -581,6 +582,10 @@ status_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
    }

    mMaxFileSizeBytes = bytes;
    +
    + // If requested size is >4GB, force 64-bit offsets
    + mUse64BitFileOffset |= (bytes >= kMax32BitFileSize);
    +

作者: RESSRC

个人资源站

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据