C++ ffmpeg生成的片段mp4文件与代码生成的片段mp4文件不同
目前,当使用libavformat从代码生成碎片化的MP4文件时,我遇到了一个问题。我的文件可以使用VLC播放,但不能在(Chrome)浏览器中流式传输(通过WebSocket)和播放(通过MediaSource)。(我曾经通过WebSocket测试将碎片化的MP4文件流式传输到浏览器) 注:以下文件由基线配置文件4级编码。因此,您应该将MIME类型(在index.html中)更改为const mimeCodec='video/mp4;编解码器=“avc1.42C028”;能够玩他们 我检查发现,我生成的Mp4文件与使用C++ ffmpeg生成的片段mp4文件与代码生成的片段mp4文件不同,c++,ffmpeg,libavformat,media-source,fmp4,C++,Ffmpeg,Libavformat,Media Source,Fmp4,目前,当使用libavformat从代码生成碎片化的MP4文件时,我遇到了一个问题。我的文件可以使用VLC播放,但不能在(Chrome)浏览器中流式传输(通过WebSocket)和播放(通过MediaSource)。(我曾经通过WebSocket测试将碎片化的MP4文件流式传输到浏览器) 注:以下文件由基线配置文件4级编码。因此,您应该将MIME类型(在index.html中)更改为const mimeCodec='video/mp4;编解码器=“avc1.42C028”;能够玩他们 我检查发现
ffmpeg
工具生成的文件有点不同
以下是我所做的:
我有一个
codec
是输入流的AVCodecContext*
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;
其次,我实现了onWritePacket回调
int MP4Formatter::onWritePacket(void *opaque, uint8_t* buf, int buf_size) {
file.write((char*)buf, buf_size);
}
第三,在h264文件中的每个数据包上,我使用av\u交错\u write\u frame
if (firstFrame) {
AVDictionary *opts = NULL;
av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov+default_base_moof", 0);
if(!parseSPSPPS(data, length)) {
return;
}
cout << "spslen " << spslen << " ppslen " << ppslen << endl;
auto c = st->codecpar;
// Extradata contains PPS & SPS for AVCC format
int extradata_len = 8 + spslen + 1 + 2 + ppslen;
c->extradata = (uint8_t*)av_mallocz(extradata_len);
c->extradata_size = extradata_len;
c->extradata[0] = 0x01;
c->extradata[1] = sps[1];
c->extradata[2] = sps[2];
c->extradata[3] = sps[3];
c->extradata[4] = 0xFC | 3;
c->extradata[5] = 0xE0 | 1;
int tmp = spslen;
c->extradata[6] = (tmp >> 8) & 0x00ff;
c->extradata[7] = tmp & 0x00ff;
int i = 0;
for (i=0; i<tmp; i++) {
c->extradata[8 + i] = sps[i];
}
c->extradata[8 + tmp] = 0x01;
int tmp2 = ppslen;
c->extradata[8 + tmp + 1] = (tmp2 >> 8) & 0x00ff;
c->extradata[8 + tmp + 2] = tmp2 & 0x00ff;
for (i=0; i<tmp2; i++) {
c->extradata[8 + tmp + 3 + i] = pps[i];
}
int ret = avformat_write_header(ctx, &opts);
if(ret < 0) {
return;
}
firstFrame = false;
}
AVPacket pkt;
av_init_packet(&pkt);
pkt.buf = av_buffer_alloc(length);
memcpy(pkt.buf->data, data, length);
pkt.buf->size = length;
pkt.data = pkt.buf->data;
pkt.size = pkt.buf->size;
pkt.pts = ts;
pkt.dts = ts;
if (keyFrame) {
pkt.flags |= AV_PKT_FLAG_KEY;
}
else {
pkt.flags = 0;
}
pkt.stream_index = st->id;
av_interleaved_write_frame(ctx, &pkt);
av_buffer_unref(&pkt.buf);
av_packet_unref(&pkt);
if(第一帧){
AVDictionary*opts=NULL;
av_dict_set(&opts,“movflags”,“frag_关键帧+空_moov+默认_base_moof”,0);
如果(!parseSPSPPS(数据,长度)){
返回;
}
cout extrada[1]=sps[1];
c->extradata[2]=sps[2];
c->extradata[3]=sps[3];
c->extradata[4]=0xFC | 3;
c->extradata[5]=0xE0 | 1;
int tmp=spslen;
c->extradata[6]=(tmp>>8)&0x00ff;
c->extradata[7]=tmp&0x00ff;
int i=0;
对于(i=0;iextradata[8+i]=sps[i];
}
c->extradata[8+tmp]=0x01;
int tmp2=ppslen;
c->extradata[8+tmp+1]=(tmp2>>8)&0x00ff;
c->extradata[8+tmp+2]=tmp2&0x00ff;
对于(i=0;iextradata[8+tmp+3+i]=pps[i];
}
int-ret=avformat\u write\u头(ctx和opts);
如果(ret<0){
返回;
}
firstFrame=false;
}
AVPacket-pkt;
av_初始_数据包(&pkt);
pkt.buf=av_buffer_alloc(长度);
memcpy(pkt.buf->data,data,length);
包装尺寸->尺寸=长度;
pkt.data=pkt.buf->data;
pkt.size=pkt.buf->size;
pkt.pts=ts;
pkt.dts=ts;
如果(关键帧){
pkt.flags |=AV_upkt_FLAG_KEY;
}
否则{
pkt.flags=0;
}
pkt.stream_index=st->id;
av交织写入帧(ctx和pkt);
av_buffer_unref(&pkt.buf);
av_数据包_unref(&pkt);
你们能看一下我的文件看看有什么问题吗?也许你们可以试试这个:
AVDictionary* opts = NULL;
av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
然后:
avformat_write_header(formatContext, &opts);
正如这句话
h264文件:,ffmpeg生成的mp4文件:,libavformat生成的mp4文件:您解决了这个问题吗?有什么更新吗?您尝试过自己的解决方案吗?@pastaleg对我来说效果很好。
avformat_write_header(formatContext, &opts);