Commit 2b592780 by xiongziliang

修复aac rtp解包内存越界的bug

parent f76a2037
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include "AACRtp.h" #include "AACRtp.h"
#define ADTS_HEADER_LEN 7
namespace mediakit{ namespace mediakit{
...@@ -91,8 +92,8 @@ AACRtpDecoder::AACRtpDecoder() { ...@@ -91,8 +92,8 @@ AACRtpDecoder::AACRtpDecoder() {
AACFrame::Ptr AACRtpDecoder::obtainFrame() { AACFrame::Ptr AACRtpDecoder::obtainFrame() {
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象 //从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto frame = ResourcePoolHelper<AACFrame>::obtainObj(); auto frame = ResourcePoolHelper<AACFrame>::obtainObj();
frame->aac_frame_length = 7; frame->aac_frame_length = ADTS_HEADER_LEN;
frame->iPrefixSize = 7; frame->iPrefixSize = ADTS_HEADER_LEN;
if(frame->syncword == 0 && !_aac_cfg.empty()) { if(frame->syncword == 0 && !_aac_cfg.empty()) {
makeAdtsHeader(_aac_cfg,*frame); makeAdtsHeader(_aac_cfg,*frame);
} }
...@@ -100,70 +101,45 @@ AACFrame::Ptr AACRtpDecoder::obtainFrame() { ...@@ -100,70 +101,45 @@ AACFrame::Ptr AACRtpDecoder::obtainFrame() {
} }
bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) { bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
// 获取rtp数据长度 //rtp数据开始部分
int length = rtppack->size() - rtppack->offset; uint8_t *ptr = (uint8_t *) rtppack->data() + rtppack->offset;
//rtp数据末尾
// 获取rtp数据 const uint8_t *end = (uint8_t *) rtppack->data() + rtppack->size();
const uint8_t *rtp_packet_buf = (uint8_t *)rtppack->data() + rtppack->offset;
//首2字节表示Au-Header的个数,单位bit,所以除以16得到Au-Header个数
do const uint16_t au_header_count = ((ptr[0] << 8) | ptr[1]) >> 4;
{ //忽略Au-Header区
// 查询头部的偏移,每次2字节 ptr += 2 + au_header_count * 2;
uint32_t au_header_offset = 0;
//首2字节表示Au-Header的长度,单位bit,所以除以16得到Au-Header字节数 static const uint32_t max_size = sizeof(AACFrame::buffer) - ADTS_HEADER_LEN;
const uint16_t au_header_length = (((rtp_packet_buf[au_header_offset] << 8) | rtp_packet_buf[au_header_offset + 1]) >> 4); while (ptr < end) {
au_header_offset += 2; auto size = std::min(max_size, (uint32_t) (end - ptr));
if (_adts->aac_frame_length + size > sizeof(AACFrame::buffer)) {
//assert(length > (2 + au_header_length * 2)); //数据太多了,先清空
if (length < (2 + au_header_length * 2)) flushData();
break;
// 存放每一个aac帧长度
std::vector<uint32_t > vec_aac_len;
for (int i = 0; i < au_header_length; ++i)
{
// 之后的2字节是AU_HEADER
const uint16_t au_header = ((rtp_packet_buf[au_header_offset] << 8) | rtp_packet_buf[au_header_offset + 1]);
// 其中高13位表示一帧AAC负载的字节长度,低3位无用
uint32_t nAac = (au_header >> 3);
vec_aac_len.push_back(nAac);
au_header_offset += 2;
}
// 真正aac负载开始处
const uint8_t *rtp_packet_payload = rtp_packet_buf + au_header_offset;
// 载荷查找
uint32_t next_aac_payload_offset = 0;
for (int j = 0; j < au_header_length; ++j)
{
// 当前aac包长度
const uint32_t cur_aac_payload_len = vec_aac_len.at(j);
if (_adts->aac_frame_length + cur_aac_payload_len > sizeof(AACFrame::buffer)) {
_adts->aac_frame_length = 7;
WarnL << "aac负载数据太长";
return false;
} }
//追加aac数据
// 提取每一包aac载荷数据 memcpy(_adts->buffer + _adts->aac_frame_length, ptr, size);
memcpy(_adts->buffer + _adts->aac_frame_length, rtp_packet_payload + next_aac_payload_offset, cur_aac_payload_len); _adts->aac_frame_length += size;
_adts->aac_frame_length += (cur_aac_payload_len);
if (rtppack->mark == true) {
_adts->timeStamp = rtppack->timeStamp; _adts->timeStamp = rtppack->timeStamp;
writeAdtsHeader(*_adts, _adts->buffer); ptr += size;
onGetAAC(_adts);
} }
next_aac_payload_offset += cur_aac_payload_len; if (rtppack->mark) {
//最后一个rtp分片
flushData();
} }
} while (0);
return false; return false;
} }
void AACRtpDecoder::onGetAAC(const AACFrame::Ptr &frame) {
//写入环形缓存 void AACRtpDecoder::flushData() {
RtpCodec::inputFrame(frame); if(_adts->aac_frame_length == ADTS_HEADER_LEN){
//没有有效数据
return;
}
writeAdtsHeader(*_adts, _adts->buffer);
RtpCodec::inputFrame(_adts);
_adts = obtainFrame(); _adts = obtainFrame();
} }
......
...@@ -56,8 +56,8 @@ public: ...@@ -56,8 +56,8 @@ public:
protected: protected:
AACRtpDecoder(); AACRtpDecoder();
private: private:
void onGetAAC(const AACFrame::Ptr &frame);
AACFrame::Ptr obtainFrame(); AACFrame::Ptr obtainFrame();
void flushData();
private: private:
AACFrame::Ptr _adts; AACFrame::Ptr _adts;
string _aac_cfg; string _aac_cfg;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论