java aac rtp封装_分享一段H264视频和AAC音频的RTP封包代码

本文详细介绍了如何使用Java进行H264视频和AAC音频的RTP封包处理。通过分析h264_parse和aac_parse两个静态方法,展示了如何处理不同大小的NAL单元并进行FU-A分片,以及AAC数据的封装过程,为理解RTP封包提供参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. H264视频的RTP封包

static int h264_parse(Track *tr, uint8_t *data, size_t len)

{

h264_priv *priv = tr->private_data;

//    double nal_time; // see page 9 and 7.4.1.2

size_t nalsize = 0, index = 0;

uint8_t *p, *q;

if (priv->is_avc) {

while (1) {

unsigned int i;

if(index >= len) break;

//get the nal size

nalsize = 0;

for(i = 0; i < priv->nal_length_size; i++)

nalsize = (nalsize << 8) | data[index++];

if(nalsize <= 1 || nalsize > len) {

if(nalsize == 1) {

index++;

continue;

} else {

fnc_log(FNC_LOG_VERBOSE, "[h264] AVC: nal size %d", nalsize);

break;

}

}

if (DEFAULT_MTU >= nalsize) {

mparser_buffer_write(tr,

tr->properties.pts,

tr->properties.dts,

tr->properties.frame_duration,

1,

data + index, nalsize);

fnc_log(FNC_LOG_VERBOSE, "[h264] single NAL");

} else {

// single NAL, to be fragmented, FU-A;

frag_fu_a(data + index, nalsize, DEFAULT_MTU, tr);

}

index += nalsize;

}

} else {

//seek to the first startcode

for (p = data; p

if (p[0] == 0 && p[1] == 0 && p[2] == 1) {

break;

}

}

if (p >= data + len) return ERR_PARSE;

while (1) {

//seek to the next startcode [0 0 1]

for (q = p; q

if (q[0] == 0 && q[1] == 0 && q[2] == 1) {

break;

}

}

if (q >= data + len) break;

if (DEFAULT_MTU >= q - p) {

fnc_log(FNC_LOG_VERBOSE, "[h264] Sending NAL %d",p[0]&0x1f);

mparser_buffer_write(tr,

tr->properties.pts,

tr->properties.dts,

tr->properties.frame_duration,

1,

p, q - p);

fnc_log(FNC_LOG_VERBOSE, "[h264] single NAL");

} else {

//FU-A

fnc_log(FNC_LOG_VERBOSE, "[h264] frags");

frag_fu_a(p, q - p, DEFAULT_MTU, tr);

}

p = q;

}

// last NAL

fnc_log(FNC_LOG_VERBOSE, "[h264] last NAL %d",p[0]&0x1f);

if (DEFAULT_MTU >= len - (p - data)) {

fnc_log(FNC_LOG_VERBOSE, "[h264] no frags");

mparser_buffer_write(tr,

tr->properties.pts,

tr->properties.dts,

tr->properties.frame_duration,

1,

p, len - (p - data));

} else {

//FU-A

fnc_log(FNC_LOG_VERBOSE, "[h264] frags");

frag_fu_a(p, len - (p - data), DEFAULT_MTU, tr);

}

}

fnc_log(FNC_LOG_VERBOSE, "[h264] Frame completed");

return ERR_NOERROR;

}

static int h264_parse(Track *tr, uint8_t *data, size_t len)

{

h264_priv *priv = tr->private_data;

//    double nal_time; // see page 9 and 7.4.1.2

size_t nalsize = 0, index = 0;

uint8_t *p, *q;

if (priv->is_avc) {

while (1) {

unsigned int i;

if(index >= len) break;

//get the nal size

nalsize = 0;

for(i = 0; i nal_length_size; i++)

nalsize = (nalsize <

if(nalsize <= 1 || nalsize > len) {

if(nalsize == 1) {

index++;

continue;

} else {

fnc_log(FNC_LOG_VERBOSE, "[h264] AVC: nal size %d", nalsize);

break;

}

}

if (DEFAULT_MTU >= nalsize) {

mparser_buffer_write(tr,

tr->properties.pts,

tr->properties.dts,

tr->properties.frame_duration,

1,

data + index, nalsize);

fnc_log(FNC_LOG_VERBOSE, "[h264] single NAL");

} else {

// single NAL, to be fragmented, FU-A;

frag_fu_a(data + index, nalsize, DEFAULT_MTU, tr);

}

index += nalsize;

}

} else {

//seek to the first startcode

for (p = data; p

if (p[0] == 0 && p[1] == 0 && p[2] == 1) {

break;

}

}

if (p >= data + len) return ERR_PARSE;

while (1) {

//seek to the next startcode [0 0 1]

for (q = p; q

if (q[0] == 0 && q[1] == 0 && q[2] == 1) {

break;

}

}

if (q >= data + len) break;

if (DEFAULT_MTU >= q - p) {

fnc_log(FNC_LOG_VERBOSE, "[h264] Sending NAL %d",p[0]&0x1f);

mparser_buffer_write(tr,

tr->properties.pts,

tr->properties.dts,

tr->properties.frame_duration,

1,

p, q - p);

fnc_log(FNC_LOG_VERBOSE, "[h264] single NAL");

} else {

//FU-A

fnc_log(FNC_LOG_VERBOSE, "[h264] frags");

frag_fu_a(p, q - p, DEFAULT_MTU, tr);

}

p = q;

}

// last NAL

fnc_log(FNC_LOG_VERBOSE, "[h264] last NAL %d",p[0]&0x1f);

if (DEFAULT_MTU >= len - (p - data)) {

fnc_log(FNC_LOG_VERBOSE, "[h264] no frags");

mparser_buffer_write(tr,

tr->properties.pts,

tr->properties.dts,

tr->properties.frame_duration,

1,

p, len - (p - data));

} else {

//FU-A

fnc_log(FNC_LOG_VERBOSE, "[h264] frags");

frag_fu_a(p, len - (p - data), DEFAULT_MTU, tr);

}

}

fnc_log(FNC_LOG_VERBOSE, "[h264] Frame completed");

return ERR_NOERROR;

}

2. AAC的RTP封包

static int aac_parse(Track *tr, uint8_t *data, size_t len)

{

//XXX handle the last packet on EOF

int off = 0;

uint32_t payload = DEFAULT_MTU - AU_HEADER_SIZE;

uint8_t *packet = g_malloc0(DEFAULT_MTU);

if(!packet) return ERR_ALLOC;

// trim away extradata

//    data += AAC_EXTRA;

//    len -= AAC_EXTRA;

packet[0] = 0x00;

packet[1] = 0x10;

packet[2] = (len & 0x1fe0) >> 5;

packet[3] = (len & 0x1f) << 3;

if (len > payload) {

while (len > payload) {

memcpy(packet + AU_HEADER_SIZE, data + off, payload);

mparser_buffer_write(tr,

tr->properties.pts,

tr->properties.dts,

tr->properties.frame_duration,

0,

packet, DEFAULT_MTU);

len -= payload;

off += payload;

}

}

memcpy(packet + AU_HEADER_SIZE, data + off, len);

mparser_buffer_write(tr,

tr->properties.pts,

tr->properties.dts,

tr->properties.frame_duration,

1,

packet, len + AU_HEADER_SIZE);

g_free(packet);

return ERR_NOERROR;

}

static int aac_parse(Track *tr, uint8_t *data, size_t len)

{

//XXX handle the last packet on EOF

int off = 0;

uint32_t payload = DEFAULT_MTU - AU_HEADER_SIZE;

uint8_t *packet = g_malloc0(DEFAULT_MTU);

if(!packet) return ERR_ALLOC;

// trim away extradata

//    data += AAC_EXTRA;

//    len -= AAC_EXTRA;

packet[0] = 0x00;

packet[1] = 0x10;

packet[2] = (len & 0x1fe0) >> 5;

packet[3] = (len & 0x1f) <

if (len > payload) {

while (len > payload) {

memcpy(packet + AU_HEADER_SIZE, data + off, payload);

mparser_buffer_write(tr,

tr->properties.pts,

tr->properties.dts,

tr->properties.frame_duration,

0,

packet, DEFAULT_MTU);

len -= payload;

off += payload;

}

}

memcpy(packet + AU_HEADER_SIZE, data + off, len);

mparser_buffer_write(tr,

tr->properties.pts,

tr->properties.dts,

tr->properties.frame_duration,

1,

packet, len + AU_HEADER_SIZE);

g_free(packet);

return ERR_NOERROR;

}

上面的变量 AU_HEADER_SIZE=4

/* au header

+---------------------------------------+

|     AU-size                           |

+---------------------------------------+

|     AU-Index / AU-Index-delta         |

+---------------------------------------+

|     CTS-flag                          |

+---------------------------------------+

|     CTS-delta                         |

+---------------------------------------+

|     DTS-flag                          |

+---------------------------------------+

|     DTS-delta                         |

+---------------------------------------+

|     RAP-flag                          |

+---------------------------------------+

|     Stream-state                      |

+---------------------------------------+

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值