rtmp推流异常分析

发布于:2023-09-10 ⋅ 阅读:(112) ⋅ 点赞:(0)

问题描述

向srs媒体服务上推送rtmp流,推送失败

分析过程

srs日志分析

从日志中看到发生错误时层次调用关系

[2023-09-05 11:10:29.933][Error][13594][9w5og10q][11] serve error code=3001 : service cycle : rtmp: stream service : rtmp: receive thread : handle publish message : rtmp: consume message : rtmp: consume video : meta update video : demux SPS/PPS : avc decode sequence header

去代码中搜索"avc decode sequence header"相关信息,发现是解析sps/pps信息异常

// src/kernel/srs_kernel_codec.cpp
srs_error_t SrsFormat::avc_demux_sps_pps(SrsBuffer* stream)
{
    // AVCDecoderConfigurationRecord
    // 5.2.4.1.1 Syntax, ISO_IEC_14496-15-AVC-format-2012.pdf, page 16
    int avc_extra_size = stream->size() - stream->pos();
    if (avc_extra_size > 0) {
        char *copy_stream_from = stream->data() + stream->pos();
        vcodec->avc_extra_data = std::vector<char>(copy_stream_from, copy_stream_from + avc_extra_size);
    }

    if (!stream->require(6)) {
        return srs_error_new(ERROR_HLS_DECODE_ERROR, "avc decode sequence header");
    }

    ......
}

stream对应的buffer中不够6个字节???

抓包分析

推流端给服务端发送完publish之后,服务端回复的onStatus,以及客户端给服务端发送的setDataFrame、onMetaData都没有被解析成rtmp,只能根据rtmp协议标准分析onMetaData(及ECMA Array)之后的数据,srs日志中也表示获取到了meta data                        

[2023-09-05 11:10:29.927][Trace][13594][9w5og10q] got metadata, width=1280, height=720, vcodec=7, acodec=10

再结合srs的日志,猜测是sps/pps解析引起的

onMetaData的"End Of Object Marker"对应着0x00 0x00 0x09序列,其后对应着其他的rtmp包

rtmp的header中各字段含义表示为

RTMP字段
字段分类 字段含义 位宽 描述
Header format 2bits

0表示header长度为11字节

1表示header长度为7字节

2表示header长度为3字节

3表示header长度为0字节

(不含本字节)

ChunkStreamID 6bits
TimeStamp 3Bytes
BodySize 3Bytes
TypeId 1Byte

0x08对应语音数据

0x09对应视频数据

StreamId 4Bytes

Body

(需要根据header中TypeId区分,这里只描述audio/video)

Control 1Byte 视频数据        Type: 4bits, 1表示Key Frame; 2表示inter-frame     
Format: 4bits, 7表示H264
语音数据

Format: 4bits, 10表示HE-AAc

SampleRate: 2bits, 3表示44kHz

SampleSize: 1bit, 1表示16bits

Channels: 1bit, 1表示Stereo

Data BodySize - 1

抓包和rtmp协议规范对着看吧,第一个视频帧长度为5并且有效数据是00 00 00 00,代码中要求长度是6,所以对上号了

结论

推流端首帧视频数据长度为5,真实数据为00 00 00 00, 代码中要求是6,所以srs代码中校验不通过,报错。

猜测是客户端首帧编码异常,或者发送的太早了,数据还没编码好就开始发送了......

参考

setDataFrame、onMetaData协议格式参考手撕Rtmp协议细节(8)——publish推流_视界音你而不同的博客-CSDN博客

本文含有隐藏内容,请 开通VIP 后查看