简体   繁体   English

FFmpeg相机编码H264 MP4混合原子AVCC太小

[英]FFmpeg camera encode h264 mp4 muxing atom avcC is too small

I tried to encode Android camera preview frame to h264, and mux to mp4 container. 我试图将Android相机预览帧编码为h264,将mux编码为mp4容器。

I can created mp4 file successfully. 我可以成功创建mp4文件。 But the mp4 format seems corrupted. 但是mp4格式似乎已损坏。

Use the ffprobe , I got the following error. 使用ffprobe ,出现以下错误。

$ ffprobe o.mp4
[h264 @ 0x209fe50] non-existing PPS 0 referenced
[h264 @ 0x209fe50] decode_slice_header error
[h264 @ 0x209fe50] no frame!
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x209ea60] decoding for stream 0 failed
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x209ea60] Could not find codec parameters for stream 0 (Video: h264 (avc1 / 0x31637661), none, 568x320, 505 kb/s): unspecified pixel format

Then I use mp4info tool to see if the information is correct. 然后,我使用mp4info工具查看信息是否正确。 I found this. 我找到了这个。

$ mp4info o.mp4 
mp4info version 2.0.0
o.mp4:
ReadProperties: atom 'avcC' is too small; overrun at property: configurationVersion (src/mp4atom.cpp,386)
mp4info: can't open o.mp4

By hexdump the content of file, I got this 通过hexdump文件的内容,我得到了

$ xxd o.mp4 |grep -A 5 -B 5 avcC
0039170: 6331 0000 0000 0000 0001 0000 0000 0000  c1..............
0039180: 0000 0000 0000 0000 0000 0238 0140 0048  ...........8.@.H
0039190: 0000 0048 0000 0000 0000 0001 0000 0000  ...H............
00391a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00391b0: 0000 0000 0000 0000 0000 0000 0018 ffff  ................
00391c0: 0000 0008 6176 6343 0000 0020 7374 7473  ....avcC... stts
00391d0: 0000 0000 0000 0002 0000 004f 0000 0ea6  ...........O....
00391e0: 0000 0001 0000 0000 0000 0058 7374 7373  ...........Xstss
00391f0: 0000 0000 0000 0012 0000 0001 0000 0005  ................
0039200: 0000 000a 0000 000f 0000 0014 0000 0019  ................
0039210: 0000 001e 0000 0023 0000 0028 0000 0029  .......#...(...)

If I didn't add global header to AVCodecContext , 如果我没有将全局标头添加到AVCodecContext

if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) {
    // oc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}

ffprobe can detect the format without error, also ffplay can play it. ffprobe可以检测格式没有错误,也ffplay可以玩。 But the avcC atom still not correct. 但是avcC原子仍然不正确。 Other player cannot play it. 其他玩家无法播放。

Why the muxer didn't write the correct avcC atom? 为什么avcC未编写正确的avcC原子?

How can I solve it? 我该如何解决?

You must set the extradata field in the codec context. 您必须在编解码器上下文中设置extradata字段。 The format is referenced here: Possible Locations for Sequence/Picture Parameter Set(s) for H.264 Stream 此处引用该格式: H.264流的序列/图片参数集的可能位置

Solved. 解决了。 This problem only happened in the new version ffmpeg. 仅在新版本ffmpeg中发生此问题。

When call ffmpeg api avformat_write_header/av_write_tailer , it uses the data in AVStream->codecpar since AVStream->codec was marked deprecated. 调用ffmpeg api avformat_write_header/av_write_tailer ,由于AVStream->codec已被标记为已弃用,因此它将使用AVStream->codecpar的数据。

And the extra data is filled after avcodec_open2 , so I need to copy extra data back to AVStream->codecpar . 并且在avcodec_open2之后填充了额外的数据,因此我需要将额外的数据复制回AVStream->codecpar

stream->codecpar->extradata = av_malloc(oc_ctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
stream->codecpar->extradata_size = oc_ctx->extradata_size;
memcpy(stream->codecpar->extradata, oc_ctx->extradata, oc_ctx->extradata_size);

Similar code snippet also can be found in ffmpeg project ffmpeg.c 在ffmpeg项目ffmpeg.c中也可以找到类似的代码片段

if (!ost->st->codecpar->extradata && avctx->extradata) {
    ost->st->codecpar->extradata = av_malloc(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
    if (!ost->st->codecpar->extradata) {
        av_log(NULL, AV_LOG_ERROR, "Could not allocate extradata buffer to copy parser data.\n");
        exit_program(1);
    }    
    ost->st->codecpar->extradata_size = avctx->extradata_size;
    memcpy(ost->st->codecpar->extradata, avctx->extradata, avctx->extradata_size);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM