x264直播(4) - http-mp4直播输出

代码中有接口支持mp4输出但是需要gpac或者lsmash库, 我选择使用lsmash, lsmash可以从github下载

  1. lsmash编译同前面的的方法类似, 有个修改比较麻烦: 结构体指定成员初始化
  2. 有个改动比较多的地方 box_default.c

#define INITIALIZE_PREDEFINED_CHILD_BY_DEFAULT_CONSTANT_PTR( child_name )
.child_name = (isom
##child_name##t *)&isom##child_name##_box_default

添加一个

#define INITIALIZE_BOX_MEMBER( box_name, child_name )
uint8_t box_name##
##child_name = (uint8_t)((isom_##box_name##box_default.child_name = (isom##child_name##t *)&isom##child_name##_box_default));

_#define DEFINE_SIMPLE_CONTAINER_BOX_DEFAULT_CONSTANT_2( box_name, _0 )
DEFINE_SIMPLE_CONTAINER_BOX_DEFAULT_CONSTANT_TEMPLATE( box_name,
EXPAND_VA_ARGS( INITIALIZE_PREDEFINED_CHILD_BY_DEFAULT_CONSTANT_PTR( _0 ) ) )

修改为

_#define DEFINE_SIMPLE_CONTAINER_BOX_DEFAULT_CONSTANT_2( box_name, _0 )
DEFINE_SIMPLE_CONTAINER_BOX_DEFAULT_CONSTANT_TEMPLATE( box_name, );
INITIALIZE_BOX_MEMBER(box_name, _0 )
以此类似

  1. 遇到一个奇怪的问题, 很多结构体无法找到符号 有const属性, 把const去掉后就正常了, 这个问题尝试了比较久的时间

  2. 在调试过程中用到VS的一些选项
    复杂宏调试时, 可以选项 C++\预处理\预处理到文件 开启, 可以生成宏展开后的全部文字
    链接时重复定义可以选项 链接\常规\强制文件输出 开启
    链接时手动分析lib信息可以在 链接\命令行 添加/VERBOSE 获取详细信息
    编译时VS调试信息可以修改来输出, 在IDE\devenv.exe.config, 添加如下
    <system.diagnostics> <switches> <add name="CPS" value="Verbose" /> </switches> </system.diagnostics>

  3. 编译成功后可以输出mp4格式文件了

  4. http-mp4 输出类似前面的flv, 集成mp4成一个 http_mp4_output

  5. mp4_output, 发现文件延迟非常大, 修改选项改善 file_param->max_chunk_duration = 0.1;

  6. 测试 http_mp4_output, 发现根本无法网络播放, 查找原因,
    原因: 发现mp4文件播放前必须读取一堆box, 主要是moov, 正常文件moov是mp4的尾部, 所以http肯定是无法播放的
    尝试 moov的定位在头部, 需要seek写入, 修改参数seek 让 file->bs->unseekable 有效, 发现还是不行
    尝试 查看代码发现一个 LSMASH_FILE_MODE_FRAGMENTED, 修改 mp4->b_fragments = TRUE;
    可以了, 就是把文件模式改成碎片模式

  7. 测试 http_mp4_output, 发现不能在中间连接, 连接上黑屏, 只能在启动后立即连接, 也就无法多人直播
    尝试 头部保存更多个数据, 无效
    尝试 使用 p_param->b_repeat_headers = 1; 无效
    尝试 mp4->b_force_flush_pool = 1; 无效
    尝试 mp4->file_param->force_moof_base = 1; 可以了
    原因: mp4的帧是作为sample处理, 这种方式是需要前面box的数据, 没有前面的数据, 解码就是失败, VLC打开就黑屏卡死, 其中主要的就是moof,
    在代码中有选项 file->allow_moof_base, 这个是根据版本来的, 代码默认是 ISOM_BRAND_TYPE_ISOM,
    allow_moof_base 需要 ISOM_BRAND_TYPE_ISO5以上才可支持
    自己修改代码添加选项 param->force_moof_base, 来控制allow_moof_base
    这个问题找了比较长时间, 还改了lsmash 的一些代码

  8. 测试 http_mp4_output, 发现延迟比较大, 原因在于 frame进入了sample_pool, 需要到关键帧才会写入出来
    如果强制关键帧, 可避免这个问题但是压缩率就极大降低了
    添加选项 mp4->b_force_flush_pool = 1; 让立即写出来

原来代码
if( p_mp4->b_fragments && p_mp4->i_numframe && p_sample->prop.ra_flags != ISOM_SAMPLE_RANDOM_ACCESS_FLAG_NONE )
修改为
if( (p_mp4->b_fragments && p_sample->prop.ra_flags != ISOM_SAMPLE_RANDOM_ACCESS_FLAG_NONE) ||
p_mp4->b_force_flush_pool
)

  1. 测试 http_mp4_output, 发现效果已经很好了, flv延迟1秒, mp4 稍微多点, 2s左右, 因为mp4另外做了复杂的封装处理
posted @ 2020-10-29 17:27  Yofoo  阅读(668)  评论(0编辑  收藏  举报