ffmpeg和代码生成的碎片化的mp4文件不同

时间:2017-02-24 04:31:16

标签: c++ ffmpeg libavformat media-source fmp4

目前,使用libavformat从代码生成碎片化MP4文件时遇到问题。我的文件可以使用VLC播放,但无法在(Chrome)浏览器中流式传输(通过WebSocket)和播放(通过MediaSource)。 (我使用this通过WebSocket测试流式分段MP4文件到浏览器。

注意:下面的文件由Baseline profile 4级编码。因此,您应该将MIME类型(在index.html中)更改为const mimeCodec =' video / mp4;编解码器=" avc1.42C028"&#39 ;;能够发挥它们。

我检查过,发现我生成的Mp4文件与使用.AsParallel()工具生成的文件略有不同。

这就是我所做的:

我有一个.h264 file

  1. 第一种方法,我使用ffmpeg生成fragmented MP4 file

    ffmpeg

    生成的文件可以由Quicktime播放器和VLC播放器播放

  2. 第二种方法,我以编程方式生成fragmented Mp4 file by using libavformat

    首先我初始化上下文,代码中的ffmpeg -i temp.h264 -vcodec copy -f mp4 -movflags empty_moov+default_base_moof+frag_keyframe ffmpeg.mp4 是输入流的codec

    AVCodecContext*

    其次,我实现了onWritePacket回调

     av_register_all();
     avcodec_register_all();
     int ret;
     AVOutputFormat* fmt = av_guess_format("mp4", 0, 0);
     if(!fmt) {
       return;
     }
    
     AVFormatContext* ctx = avformat_alloc_context();
     // Create AVIO context to capture generated Mp4 contain
     uint8_t *avio_ctx_buffer = NULL;
     size_t avio_ctx_buffer_size = 50000;
     IOOutput buffer = {};
     const size_t bd_buf_size = 50000;
     avio_ctx_buffer = (uint8_t*)av_malloc(avio_ctx_buffer_size);
     buffer.buff = (uint8_t*)av_malloc(bd_buf_size);
    
     buffer.size = bd_buf_size;
     AVIOContext* ioCtx = avio_alloc_context(avio_ctx_buffer, (int)avio_ctx_buffer_size, 1, &buffer, NULL, MP4Formatter::onWritePacket, NULL);
    
     ctx->oformat = fmt;
     if (ctx->oformat->flags & AVFMT_GLOBALHEADER)
       ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
     ctx->pb = ioCtx;
     av_opt_set(ctx, "movflags", "frag_keyframe+empty_moov+default_base_moof", 0);
    
     AVStream* st = avformat_new_stream(ctx, codec->codec);
     if (!st) {
       return;
     }
    
     st->id = (ctx->nb_streams - 1);
     avcodec_parameters_from_context(st->codecpar, codec);
     st->time_base = codec->time_base;
     ioCtx->seekable = false;
    

    第三,在h264文件的每个数据包上,我使用 int MP4Formatter::onWritePacket(void *opaque, uint8_t* buf, int buf_size) { file.write((char*)buf, buf_size); }

    编写它
    av_interleaved_write_frame
  3. 你们可以看一下我的档案,看看有什么不对吗?

1 个答案:

答案 0 :(得分:1)

也许你可以试试这个:

AVDictionary* opts = NULL;
av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);

然后:

avformat_write_header(formatContext, &opts);

作为这个问题 How to generate fragmented mp4 files programmatically