ireader / media-server

RTSP/RTP/RTMP/FLV/HLS/MPEG-TS/MPEG-PS/MPEG-DASH/MP4/fMP4/MKV/WebM
MIT License
3.05k stars 1.07k forks source link

H264流文件如何保存MP4 #191

Open Irving2222222 opened 2 years ago

Irving2222222 commented 2 years ago

您好,mov_writer_h264中是把一个完整的264文件转成mp4,如果我是sensor直接出264码流,该如何保存成mp4文件呢?非常感谢!

ireader commented 2 years ago

参照h264_write即可。

Irving2222222 commented 2 years ago

非常感谢您的回复! 我的码流直接用h264_write写成mp4播放不了。

ireader commented 2 years ago

确认下码流格式,看看sensor是否可以选择annexb流格式。 annexb码流前面4字节是 00 00 00 01

Irving2222222 commented 2 years ago

不知道我的使用方法对不对。 1.首先定义一个全局变量,按照mov_writer_h264函数里对其填充 struct mov_h264_test_t ctx; ctx.track = -1; ctx.width = width; ctx.height = height; ctx.ptr ==》指向每一帧sensor出来的h264码流 FILE* fp = fopen(mp4, "wb+"); ctx.mov = mov_writer_create(mov_file_buffer(), fp, MOV_FLAG_FASTSTART);

2.然后在get到码流的地方把数据直接使用h264_write写入 ctx.ptr = (uint8_t *)stream.virAddr + pack->offset; h264_write(&ctx, ctx.ptr, pack->length);

确定sensor出来的码流是annexb流格式。

非常感谢!

ireader commented 2 years ago

static int h264_write(struct mov_h264_test_t ctx, const void data, int bytes)

data, bytes 填sensor出来的数据即可,不需要改ptr值。

ireader commented 2 years ago

annexb码流有sps/pps吗?

Irving2222222 commented 2 years ago

那ctx.ptr该怎么初始化呢?按照mov_writer_h264函数里是指向了h264源文件,所以我把它指向我的每一帧码流。 annexb码流有sps/pps吗?===》 在h264_write函数里打印的ctx->avc.nb_sps 和 ctx->avc.nb_pps都是1

ireader commented 2 years ago

调用h264_write函数,别的函数不用调用,不需要填ptr。

Irving2222222 commented 2 years ago

视频播放不了,有可能是什么问题呢? 对比了能播放的mp4文件,播放失败的文件好像没有moov,直接是ftyp-->free-->mdat了

ireader commented 2 years ago

mov_writer_destroy 调用了吗?

上传个小文件我看看?

Irving2222222 commented 2 years ago

一定要调用mov_writer_destroy 吗?假如我录视频过程中断电了这样没有调用mov_writer_destroy ,是不是视频就不能播放了? 调用mov_writer_destroy 报错了:source/mov-writer.c: 185: mov_writer_destroy: Assertion `mov_buffer_tell(&mov->io) == offset2 + co64' failed. 还在查找原因中。

非常感谢您!

ireader commented 2 years ago

mov_writer_destroy 必须要调用。 如果靠断电情况,可以用fmp4,接口与mov write很相近。

Irving2222222 commented 2 years ago

那是我搞错了,我看到h264的例子只有mov的那个。 我想把H264码流转成fmp4,该使用哪个接口?

非常感谢!

Irving2222222 commented 2 years ago

我看了项目中的例子:fmp4-writer-test.cpp和fmp4-writer-test2.cpp,是分别把flv和mp4文件转成fmp4,但是我的是h264裸流,该怎么转呢?

非常感谢您!

ireader commented 2 years ago

跟mov_writer_h264一样的用法,接口稍微改下。

Irving2222222 commented 2 years ago

是这个接口吗? fmp4_writer_write

Irving2222222 commented 2 years ago

https://user-images.githubusercontent.com/31495913/150452380-990122c7-e64c-4394-80fc-d49b73edb8b9.mp4

您好!我把h264码流直接调用函数fmp4_writer_add_video和fmp4_writer_write写入,得到的视频播放不了,可以帮忙看看吗?非常感谢您!

Irving2222222 commented 2 years ago

VID_00000001_015449 0.zip

ireader commented 2 years ago
static int h264_write(struct mov_h264_test_t* ctx, const void* data, int bytes)
{
    int vcl = 0;
    int update = 0;
    int n = h264_annexbtomp4(&ctx->avc, data, bytes, s_buffer, sizeof(s_buffer), &vcl, &update);

    if (ctx->track < 0)
    {
        if (ctx->avc.nb_sps < 1 || ctx->avc.nb_pps < 1)
        {
            //ctx->ptr = end;
            return -2; // waiting for sps/pps
        }

        int extra_data_size = mpeg4_avc_decoder_configuration_record_save(&ctx->avc, s_extra_data, sizeof(s_extra_data));
        if (extra_data_size <= 0)
        {
            // invalid AVCC
            assert(0);
            return -1;
        }

        // TODO: waiting for key frame ???
        ctx->track = mov_writer_add_video(ctx->mov, MOV_OBJECT_H264, ctx->width, ctx->height, s_extra_data, extra_data_size);
        if (ctx->track < 0)
            return -1;
    }

    mov_writer_write(ctx->mov, ctx->track, s_buffer, n, ctx->pts, ctx->pts, 1 == vcl ? MOV_AV_FLAG_KEYFREAME : 0);
    ctx->pts += 40;
    ctx->dts += 40;
    return 0;
}

你写入的数据不对,mov_writer_add_video extra_data是mpeg4_avc_decoder_configuration_record_save生成的。

Irving2222222 commented 2 years ago

mov_writer_add_video和mov_writer_write是要替换成mp4_writer_add_video和fmp4_writer_write吗?因为我想要生成fmp4

Irving2222222 commented 2 years ago

您好,我想把h264码流保存成fmp4。我做了如下修改: 1.把mov_h264_test_t结构体中的mov_writer_t mov成员改成fmp4_writer_t mov: struct mov_h264_test_t { //mov_writer_t mov; fmp4_writer_t mov; struct mpeg4_avc_t avc;

int track;
int width;
int height;
uint32_t pts, dts;
const uint8_t* ptr;

int vcl;

};

2.创建全局变量struct mov_h264_test_t ctx并初始化: memset(&ctx, 0, sizeof(ctx)); ctx.track = -1; ctx.width = 2704; ctx.height = 1520;

fmp4_fp = fopen(mp4path, "wb+");
ctx.mov = fmp4_writer_create(mov_file_buffer(), fmp4_fp, 0);     

3.获取码流调用h264_write h264_write(&ctx, pack, pack->length); 其中h264_write替换了函数fmp4_writer_add_video和fmp4_writer_write如下: int h264_write(struct mov_h264_test_t ctx, const void data, int bytes) { int vcl = 0; int update = 0; int n = h264_annexbtomp4(&ctx->avc, data, bytes, s_buffer, sizeof(s_buffer), &vcl, &update);

if (ctx->track < 0)
{
    if (ctx->avc.nb_sps < 1 || ctx->avc.nb_pps < 1)
    {
        //ctx->ptr = end;
        return -2; // waiting for sps/pps
    }

    int extra_data_size = mpeg4_avc_decoder_configuration_record_save(&ctx->avc, s_extra_data, sizeof(s_extra_data));

    if (extra_data_size <= 0)
    {
        // invalid AVCC
        assert(0);
        return -1;
    }

    // TODO: waiting for key frame ???
    ctx->track = fmp4_writer_add_video(ctx->mov, MOV_OBJECT_H264, ctx->width, ctx->height, s_extra_data, extra_data_size);

    if (ctx->track < 0)
        return -1;
}

fmp4_writer_write(ctx->mov, ctx->track, s_buffer, n, ctx->pts, ctx->pts, 1 == vcl ? MOV_AV_FLAG_KEYFREAME : 0);

ctx->pts += 40;
ctx->dts += 40;
return 0;

}

请问这样做是否正确?

非常感谢您!

Irving2222222 commented 2 years ago

按照上面的方法录出来的mp4文件打不开,文件很小,感觉少写了很多东西 VID_00000001_005906 0.zip

ireader commented 2 years ago

这个文件只有fmp4文件头,没有写数据。 在各处加些日志看看?

Irving2222222 commented 2 years ago

调试发现录视频小于8s的话就只有个文件头,大于8s可以正常播放。码流是一直都有的,而且每一帧都在fmp4_writer_write函数中copy到sample了==>memcpy(sample->data, data, bytes); 请问有可能是哪里的问题呢?

ireader commented 2 years ago

fmp4默认按照gop写入文件,确认下你的视频流关键帧间隔是否为8s。

如果需要强制写入,可以调用fmp4_writer_save_segment接口。

Irving2222222 commented 2 years ago

非常感谢!这个问题已经解决。还有个小问题是,录出来的视频用vlc播放查看文件信息,没有帧率。

Irving2222222 commented 2 years ago

image 查看视频属性,没有码率

ireader commented 2 years ago

fmp4是流式存储,读不到这些信息正常。

Irving2222222 commented 2 years ago

明白了,非常感谢!

yeungcat commented 2 years ago

明白了,非常感谢!

你好 可以把demo开源吗

Irving2222222 commented 2 years ago

明白了,非常感谢!

你好 可以把demo开源吗

需要的话可以留个邮箱

yeungcat commented 2 years ago

明白了,非常感谢!

你好 可以把demo开源吗

需要的话可以留个邮箱

345446315@qq.com QQ邮箱 谢谢

Irving2222222 commented 2 years ago

明白了,非常感谢!

你好 可以把demo开源吗

需要的话可以留个邮箱

345446315@qq.com QQ邮箱 谢谢

已发,请注意查收

1565430482 commented 1 year ago

明白了,非常感谢!

你好 可以把demo开源吗

需要的话可以留个邮箱

H264裸流转FMP4的demo,能发我一份吗?如果可以万分感谢!1565430482@qq.com

lqfjbvc commented 1 year ago

demo可以发我一份吗?可以的话万分感谢!785435771@qq.com

docterling commented 1 year ago

为什么不是给陈老大,然后传到demo里面,造福全人类