/**
* 生产者调用,获取一个可用unit buffer并将帧内容拷贝其中填充帧头
*
* @ctx: avdm上下文
* @unit: unit信息,包括帧所在的位置
*/
static S32 _ctx_put_unit(avdm_context_t *ctx, unitpack_t *unitpack)
{
S32 ret = ERROR;
U8 *base = NULL; /* 从该地址往后搜索可用buffer(可能绕圈) */
U32 tmp_len = 0;
U32 unit_len = 0; /* unit需要分配的buffer的长度 */
BOOL block_start = FALSE; /* 当前unit是否为block的起始帧 */
if ((NULL == ctx) || (NULL == unitpack) || (NULL == unitpack->pack_addr[0]) || (0 == unitpack->len))
return ERROR;
#ifdef VIDEO_STREAM_STATUS_CHECK
if (is_local_video_type(ctx))
{
video_stream_status_notify_process(ctx);
}
#endif
pthread_rwlock_wrlock(&ctx->rwlock);
if (is_local_video_type(ctx) || is_network_video_type(ctx))
{
/* I帧作为GOP的起始帧 */
block_start = (unitpack->video_frame_type== TP_FRAME_TYPE_I
#ifdef VIDEO_AVBR_ENABLE
|| unitpack->video_frame_type== TP_FRAME_TYPE_VIRTUAL_I
#endif
);
/* 如果是主码流的I帧,配置全局block_start */
if (AVDM_TYPE_MAIN == ctx->type && block_start)
block_start_write_lock();
}
else if (is_local_audio_type(ctx))
{
if (g_ctx[AVDM_TYPE_MAIN] && g_ctx[AVDM_TYPE_MAIN]->state == CTX_STATE_RUNNING)
{
if (AVDM_BUFFER_IS_EMPTY(g_ctx[AVDM_TYPE_MAIN]))
{
/* 如果主码流还未收帧,丢弃先到的音频帧 */
AVDM_ERROR("drop audio frame when main queue is empty");
goto exit;
}
/* 如果主码流正在运行,让音频GOP与主码流进GOP进行同步 */
block_start_read_with_clear_lock(&block_start);
}
else
{
/* 环上第一帧或者每隔指定秒之后的帧 */
if (AVDM_BUFFER_IS_EMPTY(ctx) ||
((unitpack->pts - ctx->ring->cur_bdesc->head_udesc->unit.pts) >= AVDM_AUDIO_GOP_TIME_SPAN_MICROSECONDS))
block_start = TRUE;
else
block_start = FALSE;
}
}
else if (is_network_audio_type(ctx))
{
/* 环上第一帧或者每隔指定秒之后的帧 */
if (AVDM_BUFFER_IS_EMPTY(ctx) ||
((unitpack->pts - ctx->ring->cur_bdesc->head_udesc->unit.pts) >= AVDM_AUDIO_GOP_TIME_SPAN_MICROSECONDS))
{
block_start = TRUE;
}
else
{
block_start = FALSE;
}
//AVDM_ERROR("unitpack->pts = %lld, block_start = %d", unitpack->pts, block_start);
}
else
{
AVDM_ERROR("type not supported");
ret = ERROR;
goto exit;
}
if (block_start)
{
/* 锁帧老化策略 */
_ctx_aging_walkaround(ctx, unitpack->pts);
/*
* 在为新的block寻找空间之前,先将当前block进行打包处理,
* 否则寻找可用buffer时,当前block和预录block都无法使用,
* 可能会导致内存紧张,实际上最早的预录block可以释放
*/
#ifndef KEEP_REST_P_FRAME
ctx->drop_rest_frame = 0;
#endif
/* 当前block非码流首次收帧 */
if (DESC_STATE_FREE != ctx->ring->cur_bdesc->attr.state)
{
/* 由于音频GOP在主码流I帧时已经打包,该IF分支不会进来 */
if (DESC_STATE_FILLING == ctx->ring->cur_bdesc->attr.state)
{
if (AVDM_TYPE_AUDIO == ctx->type)
{
AVDM_ERROR("audio GOP should already packed");
}
if (AVDM_TYPE_AUDIO_CALL == ctx->type)
{
AVDM_ERROR("audio GOP should already packed");
}
/* 如果这是主码流的I帧,先将音频block打包,让主码流GOP准备好时对应的音频GOP也已经打包完毕 */
if (AVDM_TYPE_MAIN == ctx->type)
{
__sync_pack_audio_block(ctx);
block_start_unlock();
}
/* call: 如果这是avdm_call, 先将音频block打包*/
if (AVDM_TYPE_VIDEO_CALL == ctx->type)
{
__sync_pack_audio_call_block(ctx);
block_start_unlock();
}
/* 将BLOCK打包并放到已完成的环上 */
ret = __pack_block(ctx, unitpack);
if (ret)
AVDM_ERROR("pack block failed");
/* 更新锁定的预录block */
ret = __lock_last_pre_block(ctx);
if (ret)
goto exit;
/* last_used block已经准备好,通知(storage)取GOP */
if (ctx->ring->last_bdesc && (DESC_STATE_OCCUPIED == ctx->ring->last_bdesc->attr.state))
__notify_block_ready(ctx);
}
/* 当前的block指针设为下一个可用的block */
ret = __move_to_next_block(ctx);
if (ret)
goto exit;
#ifdef VIDEO_AVBR_ENABLE
/* AVBR开启时,把真实I帧GOP引用计数加1 */
if (_avbr_get_state()
&& ctx->type == AVDM_TYPE_MAIN)
{
_lock_last_i_frame_block(ctx);
}
#endif
}
else
{
if (AVDM_TYPE_MAIN == ctx->type)
block_start_unlock();
}
/* 当前unit指针已是被使用状态,将其指向下一个可用的unit */
/* warning: 先获取下一个unit描述符再搜索可用空间,否则可用空间如果将刚完成
的GOP释放,cur_udesc实际已经放到了ulist空闲链表状态为FREE,会导致udesc
没有从空闲链表中拿出就被使用 */
if (DESC_STATE_OCCUPIED == ctx->ring->cur_udesc->attr.state)
{
ret = __move_to_next_unit(ctx);
if (ret)
goto exit;
}
if (AVDM_BUFFER_IS_EMPTY(ctx))
base = ctx->buffer;
else
base = ctx->ring->last_bdesc->block.addr + ctx->ring->last_bdesc->block.len;
/* 寻找可用的block内存,如果没有会退而求其次寻找放置I帧的内存,仍然没有则丢帧 */
unit_len = ALIGN(sizeof(FRAME_HEAD_S) + unitpack->len, AVDM_FRAME_ALIGN_SIZE);
ret = __get_available_buffer(ctx, base, ctx->ring->block_max_size, unit_len);
if (ret)
goto exit;
AVDM_ERROR("avdm%d new buffer offset is %#x, available len is %#x, potiental len is %#x",
ctx->type,
(U32)ctx->ring->bbuffer.addr - (U32)ctx->buffer,
ctx->ring->bbuffer.available_len,
ctx->ring->bbuffer.potential_len);
/*
* 释放前一个block到新内存结尾之间覆盖到的描述符及对应内存
* 如果只释放新内存覆盖的内存,可能出现旧buffer夹在新buffer
* 之间的情况,内存无法形成环状难以管理
*/
ret = __free_desc_before_new_buffer(ctx, base, ctx->ring->bbuffer.addr, ctx->ring->bbuffer.available_len);
if (ret)
goto exit;
/* 使用新的内存填充当前unit内容 */
ctx->ring->cur_udesc->unit.addr = ctx->ring->bbuffer.addr;
ctx->ring->cur_udesc->unit.len = unit_len;
ret = __fill_current_unit(ctx, unitpack);
if (ret)
goto exit;
/* 根据当前unit更新当前的block信息 */
__append_unit_to_block(ctx, ctx->ring->cur_bdesc, ctx->ring->cur_udesc, unitpack->video_frame_type);
ctx->ring->cur_bdesc->attr.state = DESC_STATE_FILLING;
/* unit环上最新的已完成unit更新为当前unit */
ctx->ring->last_udesc = ctx->ring->cur_udesc;
/* last_used unit已经准备好,通知取帧 */
__notify_unit_ready(ctx);
#ifdef AVDM_PRINT_TRACE
__avdm_dump(ctx);
#endif
}
else
{
#ifndef KEEP_REST_P_FRAME
/* 若当前P帧前面有过丢弃P帧,则后面的P帧都不再打包 */
if (is_local_video_type(ctx) && ctx->drop_rest_frame)
{
AVDM_ERROR("drop P frame because previous P frame was droped");
ret = ERROR;
goto exit;
}
#endif
/* avdm视频码流第一次收帧为P帧,丢弃 */
if ((is_local_video_type(ctx) || is_network_video_type(ctx)) && AVDM_BUFFER_IS_EMPTY(ctx))
{
AVDM_ERROR("drop P frame when queue is empty");
ret = OK;
goto exit;
}
/* 当前视频码流所在的block不是填充状态,丢弃P帧,一般出现在I帧被丢弃的时候 */
if ((is_local_video_type(ctx) || is_network_video_type(ctx)) && DESC_STATE_FILLING != ctx->ring->cur_bdesc->attr.state)
{
AVDM_ERROR("drop P frame when I frame has been dropped");
ret = OK;
goto exit;
}
/* 当前unit指针已是被使用状态,将其指向下一个可用的unit */
if (DESC_STATE_OCCUPIED == ctx->ring->cur_udesc->attr.state)
{
ret = __move_to_next_unit(ctx);
if (ret)
goto exit;
}
base = ctx->ring->last_udesc->unit.addr + ctx->ring->last_udesc->unit.len;
unit_len = ALIGN(sizeof(FRAME_HEAD_S) + unitpack->len, AVDM_FRAME_ALIGN_SIZE);
if (ctx->ring->bbuffer.available_len < (unit_len + ctx->ring->cur_bdesc->block.len))
{
/* 当前可用的长度不够放置一个P帧(音频帧),更新潜在长度并检查是否足够 */
__update_bbuffer(ctx);
if (ctx->ring->bbuffer.potential_len < (unit_len + ctx->ring->cur_bdesc->block.len))
{
#ifndef KEEP_REST_P_FRAME
/* 丢弃当前block剩下的所有P帧,避免跳帧导致花屏 */
if (is_local_video_type(ctx))
ctx->drop_rest_frame = 1;
#endif
ret = ERROR; //put audio buffer to avdm failed报错主要是因为available_len和potential_len太小导致
goto exit;
}
else
{
/* 释放出新的空间,策略是在block预设最大值范围内尽可能多的释放空间 */
if (ctx->ring->bbuffer.available_len >= ctx->ring->block_max_size)
{
/* 当前可用空间已经不小于block预设最大值,只释放够当前新帧的空间 */
tmp_len = unit_len;
}
else
{
if (ctx->ring->bbuffer.potential_len < ctx->ring->block_max_size)
{
/* 潜在长度比block预设最大值要小,释放潜在长度空间 */
tmp_len = ctx->ring->bbuffer.potential_len - ctx->ring->cur_bdesc->block.len;
}
else
{
/* 潜在长度比block预设最大值要大,只释放到block预设最大值空间 */
tmp_len = ctx->ring->block_max_size - ctx->ring->cur_bdesc->block.len;
}
}
__free_desc_within_buffer(ctx, base, tmp_len);
ctx->ring->bbuffer.available_len = ctx->ring->cur_bdesc->block.len + tmp_len;
}
}
/* 使用新的内存填充当前unit内容 */
ctx->ring->cur_udesc->unit.addr = base;
ctx->ring->cur_udesc->unit.len = unit_len;
ret = __fill_current_unit(ctx, unitpack);
if (ret)
goto exit;
/* 根据当前unit更新当前的block信息 */
__append_unit_to_block(ctx, ctx->ring->cur_bdesc, ctx->ring->cur_udesc, unitpack->video_frame_type);
/* unit环上最新的已完成unit更新为当前unit */
ctx->ring->last_udesc = ctx->ring->cur_udesc;
/* last_used unit已经准备好,通知取帧 */
__notify_unit_ready(ctx);
}
exit:
if (is_local_audio_type(ctx) && (g_ctx[AVDM_TYPE_MAIN] && g_ctx[AVDM_TYPE_MAIN]->state == CTX_STATE_RUNNING))
block_start_unlock();
pthread_rwlock_unlock(&ctx->rwlock);
return ret;
}
为什么log
[2025-10-29 15:14:51] [ERROR] _ctx_attach_next_unit():2573 - [AVDM]Stream 5: Unit Overwrite happened. cursor seq 128, current seq 128, state 0, latest seq 129
[2025-10-29 15:14:51] [ERROR] _ctx_attach_next_unit():2574 - [AVDM]Return lastest unit
[2025-10-29 15:14:51] [ERROR] __pack_block():903 - [AVDM]avdm5 block(index:11,seq:131,unit number:1,buffer offset:0x0,buffer len:1048 Bytes) has been packed
[2025-10-29 15:14:51] [ERROR] _ctx_put_unit():2219 - [AVDM]avdm5 new buffer offset is 0, available len is 0x40000, potiental len is 0x40000
[2025-10-29 15:14:51] [ERROR] __free_a_block():837 - [AVDM]Freed a avdm5 block(index:11,seq:131,unitcnt:1,offset:0x0,len:1048 Bytes) that is never been consumed
[2025-10-29 15:14:51] [ERROR] _ctx_attach_next_unit():2573 - [AVDM]Stream 5: Unit Overwrite happened. cursor seq 129, current seq 129, state 0, latest seq 130
[2025-10-29 15:14:51] [ERROR] _ctx_attach_next_unit():2574 - [AVDM]Return lastest unit
[2025-10-29 15:14:51] [ERROR] __pack_block():903 - [AVDM]avdm5 block(index:12,seq:132,unit number:1,buffer offset:0x0,buffer len:1048 Bytes) has been packed
[2025-10-29 15:14:51] [ERROR] _ctx_put_unit():2219 - [AVDM]avdm5 new buffer offset is 0, available len is 0x40000, potiental len is 0x40000
[2025-10-29 15:14:51] [ERROR] __free_a_block():837 - [AVDM]Freed a avdm5 block(index:12,seq:132,unitcnt:1,offset:0x0,len:1048 Bytes) that is never been consumed
[2025-10-29 15:14:51] [ERROR] _ctx_attach_next_unit():2573 - [AVDM]Stream 5: Unit Overwrite happened. cursor seq 130, current seq 130, state 0, latest seq 131
[2025-10-29 15:14:51] [ERROR] _ctx_attach_next_unit():2574 - [AVDM]Return lastest unit
[2025-10-29 15:14:51] [ERROR] __pack_block():903 - [AVDM]avdm5 block(index:13,seq:133,unit number:1,buffer offset:0x0,buffer len:1048 Bytes) has been packed
[2025-10-29 15:14:51] [ERROR] _ctx_put_unit():2219 - [AVDM]avdm5 new buffer offset is 0, available len is 0x40000, potiental len is 0x40000
[2025-10-29 15:14:51] [ERROR] __free_a_block():837 - [AVDM]Freed a avdm5 block(index:13,seq:133,unitcnt:1,offset:0x0,len:1048 Bytes) that is never been consumed
[2025-10-29 15:14:51] [ERROR] _ctx_attach_next_unit():2573 - [AVDM]Stream 5: Unit Overwrite happened. cursor seq 131, current seq 131, state 0, latest seq 132
[2025-10-29 15:14:51] [ERROR] _ctx_attach_next_unit():2574 - [AVDM]Return lastest unit
[2025-10-29 15:14:52] [ERROR] on_frame_video():448 - [WEBRTC]recv error frame
[2025-10-29 15:14:52] [ERROR] __pack_block():903 - [AVDM]avdm5 block(index:14,seq:134,unit number:1,buffer offset:0x0,buffer len:1048 Bytes) has been packed
[2025-10-29 15:14:52] [ERROR] _ctx_put_unit():2219 - [AVDM]avdm5 new buffer offset is 0, available len is 0x40000, potiental len is 0x40000
[2025-10-29 15:14:52] [ERROR] __free_a_block():837 - [AVDM]Freed a avdm5 block(index:14,seq:134,unitcnt:1,offset:0x0,len:1048 Bytes) that is never been consumed
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2573 - [AVDM]Stream 5: Unit Overwrite happened. cursor seq 132, current seq 132, state 0, latest seq 133
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2574 - [AVDM]Return lastest unit
[2025-10-29 15:14:52] [ERROR] __pack_block():903 - [AVDM]avdm5 block(index:0,seq:135,unit number:1,buffer offset:0x0,buffer len:1048 Bytes) has been packed
[2025-10-29 15:14:52] [ERROR] _ctx_put_unit():2219 - [AVDM]avdm5 new buffer offset is 0, available len is 0x40000, potiental len is 0x40000
[2025-10-29 15:14:52] [ERROR] __free_a_block():837 - [AVDM]Freed a avdm5 block(index:0,seq:135,unitcnt:1,offset:0x0,len:1048 Bytes) that is never been consumed
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2573 - [AVDM]Stream 5: Unit Overwrite happened. cursor seq 133, current seq 133, state 0, latest seq 134
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2574 - [AVDM]Return lastest unit
[2025-10-29 15:14:52] [ERROR] __pack_block():903 - [AVDM]avdm5 block(index:1,seq:136,unit number:1,buffer offset:0x0,buffer len:1048 Bytes) has been packed
[2025-10-29 15:14:52] [ERROR] _ctx_put_unit():2219 - [AVDM]avdm5 new buffer offset is 0, available len is 0x40000, potiental len is 0x40000
[2025-10-29 15:14:52] [ERROR] __free_a_block():837 - [AVDM]Freed a avdm5 block(index:1,seq:136,unitcnt:1,offset:0x0,len:1048 Bytes) that is never been consumed
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2573 - [AVDM]Stream 5: Unit Overwrite happened. cursor seq 134, current seq 134, state 0, latest seq 135
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2574 - [AVDM]Return lastest unit
[2025-10-29 15:14:52] [ERROR] __pack_block():903 - [AVDM]avdm5 block(index:2,seq:137,unit number:1,buffer offset:0x0,buffer len:1048 Bytes) has been packed
[2025-10-29 15:14:52] [ERROR] _ctx_put_unit():2219 - [AVDM]avdm5 new buffer offset is 0, available len is 0x40000, potiental len is 0x40000
[2025-10-29 15:14:52] [ERROR] __free_a_block():837 - [AVDM]Freed a avdm5 block(index:2,seq:137,unitcnt:1,offset:0x0,len:1048 Bytes) that is never been consumed
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2573 - [AVDM]Stream 5: Unit Overwrite happened. cursor seq 135, current seq 135, state 0, latest seq 136
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2574 - [AVDM]Return lastest unit
[2025-10-29 15:14:52] [ERROR] __pack_block():903 - [AVDM]avdm5 block(index:3,seq:138,unit number:1,buffer offset:0x0,buffer len:1048 Bytes) has been packed
[2025-10-29 15:14:52] [ERROR] _ctx_put_unit():2219 - [AVDM]avdm5 new buffer offset is 0, available len is 0x40000, potiental len is 0x40000
[2025-10-29 15:14:52] [ERROR] __free_a_block():837 - [AVDM]Freed a avdm5 block(index:3,seq:138,unitcnt:1,offset:0x0,len:1048 Bytes) that is never been consumed
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2573 - [AVDM]Stream 5: Unit Overwrite happened. cursor seq 136, current seq 136, state 0, latest seq 137
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2574 - [AVDM]Return lastest unit
[2025-10-29 15:14:52] [ERROR] __pack_block():903 - [AVDM]avdm5 block(index:4,seq:139,unit number:1,buffer offset:0x0,buffer len:1048 Bytes) has been packed
[2025-10-29 15:14:52] [ERROR] _ctx_put_unit():2219 - [AVDM]avdm5 new buffer offset is 0, available len is 0x40000, potiental len is 0x40000
[2025-10-29 15:14:52] [ERROR] __free_a_block():837 - [AVDM]Freed a avdm5 block(index:4,seq:139,unitcnt:1,offset:0x0,len:1048 Bytes) that is never been consumed
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2573 - [AVDM]Stream 5: Unit Overwrite happened. cursor seq 137, current seq 137, state 0, latest seq 138
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2574 - [AVDM]Return lastest unit
[2025-10-29 15:14:52] [ERROR] __pack_block():903 - [AVDM]avdm5 block(index:5,seq:140,unit number:1,buffer offset:0x0,buffer len:1048 Bytes) has been packed
[2025-10-29 15:14:52] [ERROR] _ctx_put_unit():2219 - [AVDM]avdm5 new buffer offset is 0, available len is 0x40000, potiental len is 0x40000
[2025-10-29 15:14:52] [ERROR] __free_a_block():837 - [AVDM]Freed a avdm5 block(index:5,seq:140,unitcnt:1,offset:0x0,len:1048 Bytes) that is never been consumed
[2025-10-29 15:14:52] [ERROR] __pack_block():903 - [AVDM]avdm5 block(index:6,seq:141,unit number:1,buffer offset:0x0,buffer len:1048 Bytes) has been packed
[2025-10-29 15:14:52] [ERROR] _ctx_put_unit():2219 - [AVDM]avdm5 new buffer offset is 0, available len is 0x40000, potiental len is 0x40000
[2025-10-29 15:14:52] [ERROR] __free_a_unit():760 - [AVDM]Freed a unit(index:0,seq:139,len:1048 Bytes) that is never been consumed
[2025-10-29 15:14:52] [ERROR] __free_a_block():837 - [AVDM]Freed a avdm5 block(index:6,seq:141,unitcnt:1,offset:0x0,len:1048 Bytes) that is never been consumed
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2573 - [AVDM]Stream 5: Unit Overwrite happened. cursor seq 138, current seq 140, state 2, latest seq 140
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2574 - [AVDM]Return lastest unit
[2025-10-29 15:14:52] [ERROR] __pack_block():903 - [AVDM]avdm5 block(index:7,seq:142,unit number:1,buffer offset:0x0,buffer len:1048 Bytes) has been packed
[2025-10-29 15:14:52] [ERROR] _ctx_put_unit():2219 - [AVDM]avdm5 new buffer offset is 0, available len is 0x40000, potiental len is 0x40000
[2025-10-29 15:14:52] [ERROR] __free_a_block():837 - [AVDM]Freed a avdm5 block(index:7,seq:142,unitcnt:1,offset:0x0,len:1048 Bytes) that is never been consumed
[2025-10-29 15:14:52] [ERROR] _ctx_attach_next_unit():2573 - [AVDM]Stream 5: Unit Overwrite happened. cursor seq 140, current seq 140, state 0, latest seq 141
一直是这样
?
最新发布