在使用FFmpeg编程,编码成h.264后,再封装成hls时,报警告
[mpegts] H.264 bitstream error, startcode missing, size 0
根据警告提示信息可知:264位流错误,开始码丢失,大小为0。
根据警告信息搜索源码,在 FFmpeg-n4.2.2/libavformat/mpegtsenc.c文件的函数ff_check_h264_startcode中,打印该警告信息。源码如下:
int ff_check_h264_startcode(AVFormatContext *s, const AVStream *st, const AVPacket *pkt)
{
if (pkt->size < 5 || AV_RB32(pkt->data) != 0x0000001 && AV_RB24(pkt->data) != 0x000001) {
if (!st->nb_frames) {
av_log(s, AV_LOG_ERROR, "H.264 bitstream malformed, "
"no startcode found, use the video bitstream filter 'h264_mp4toannexb' to fix it "
"('-bsf:v h264_mp4toannexb' option with ffmpeg)\n");
return AVERROR_INVALIDDATA;
}
av_log(s, AV_LOG_WARNING, "H.264 bitstream error, startcode missing, size %d", pkt->size);
if (pkt->size)
av_log(s, AV_LOG_WARNING, " data %08"PRIX32, AV_RB32(pkt->data));
av_log(s, AV_LOG_WARNING, "\n");
}
return 0;
}
对应打印信息和源码可知,size 0是指AVPacket.size,即AVPacket包中没有数据,当然要报警告了。
在分析这段源码中,有个宏定义AV_RB32,功能是将连续的4个uint8_t合成一个uint32_t的值。
下面分析它的源码实现
1> AV_RB32的宏定义
#ifndef AV_RB32
# define AV_RB32(p) AV_RB(32, p)
2> AV_RB的宏定义
# define AV_RB(s, p) av_bswap##s(AV_RN##s(p))
代码展开,即:av_bswap32(AV_RN32§)
3> AV_RN32的宏定义
# define AV_RN32(p) AV_RN(32, p)
# define AV_RN(s, p) (((const union unaligned_##s *) (p))->l)
union unaligned_32 { uint32_t l; } __attribute__((packed)) av_alias;
# define av_alias __attribute__((may_alias))
代码展开后,实际意思是uint32_t
4>、真正调用的是av_bswap32(uint32_t x) ,函数功能是将4字节x的字节序改变顺序后返回,如,将“0x12345678”改成“0x78563412”后返回。
static av_always_inline av_const uint32_t av_bswap32(uint32_t x)
{
return AV_BSWAP32C(x);
}
#define AV_BSWAP16C(x) (((x) << 8 & 0xff00) | ((x) >> 8 & 0x00ff)) // 将高八位和低八位互换
#define AV_BSWAP32C(x) (AV_BSWAP16C(x) << 16 | AV_BSWAP16C( (x)>>16) ) // 换字节序