退而求其次

退而求其次
  朋友有孕在身时,新房墙上,油画换成了俊男美女,天天对着“胎教”,希望宝宝生来就是闭月羞花。产期临近,大夫说脐带缠脖,于是又想只要健康就好,长得再丑也无所谓。[url=http://www.loverank.cn]google排名[/url]一直祈祷,直到听见一声响亮的哭———是个健康的男孩。

  天天对着看,想像着某一天俊朗挺拔的他带着博士帽的样子。[url=http://www.wzqxb.com.cn]网站优化[/url]不到三个月,一个不小心,孩子从床上掉下来,抱去医院路上,当妈的哭个不停,心想千万不要摔坏了头,真要是摔傻了可怎么办。医生看完说没什么大事,不会影响到智力,当妈的又怯怯地问:额头的那一块儿会不会留疤?[url=http://www.boyuchina.com.cn]上海翻译公司[/url]

  孩子十岁,天天被妈妈领着去这个班那个班,当妈的也不断地跟这个比跟那个比,每逢知道孩子的考试成绩总是忍不住感慨一番。孩子突然不明原因发病,检查室外的母亲流着泪祷告:哪怕学习不好,只要他没病就好,病好后我再也不那么逼他了。[url=http://www.zhongguofanyi.com]上海翻译公司[/url]结果只是虚惊,过一段后,孩子还是像以往那样被逼着到处求学。

  大概很多人都是如此,还有退路的时候,就忘了曾经在绝望时许下的心愿。爱情也大抵如此。爱着一个人,开始觉得能爱便是幸福,如果恰好对方也有爱,那便是天下最完美的事;两情相悦后,觉得世上处处都是美丽,但日久便想有爱情的日子面包也要多一些;[url=http://www.justrans.com/sh/index.html]上海翻译公司[/url]在有了足够面包的日子,无论是这一方或是那一方,都可能再有别的要求。

  其实每一个人都在找一个心目中的完美,当不能实现时,退而求其次,再退而求其次,没办法就渐渐的去接受甚至喜欢这个退求来的。[url=http://www.fybest.cn]上海翻译公司[/url]
能够心甘情愿地接受,那未尝不是一种幸福。
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"); } /* 如果这是主码流的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; }这里由于流AVDM_TYPE_MAIN和AVDM_TYPE_VIDEO_CALL不是同步开始有的,这个怎么开始block,是这里代码有问题所以取AVDM_TYPE_audio_CALL音频的时候ring->last_bdesc == NULL,所以ERR_FRAME_NOT_READY报错吗?
10-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值