#include #include #include #include "list.h" #include "av_ringbuffer.h" #include "iot_math.h" /* * 不用移动rb->read指针, 只是复制出来 * 尽可能减少数据的复制, 如只为了判断类型时只要复制结构体 */ static int32_t av_ringbuffer_get_frame_locked(ringbuffer *rb, ring_item *item, void *to, int8_t size){ const int32_t end_pos = (item->pos + size) - (rb->buffer + rb->capacity); if (end_pos <= 0){ memcpy(to, item->pos, size); }else{ memcpy(to, item->pos, size - end_pos); memcpy(to + size - end_pos, rb->buffer, end_pos); } } #if 0 uint32_t av_ringbuffer_get_video_frame(ringbuffer *rb, av_cookie *cookie, video_frame *to, uint32_t max_len, uint32_t timeout){ int32_t ret = NG; ring_item *item = NULL; hmutex_lock(&rb->mutex); if (!list_empty(&rb->list[RING_LIST_USING])){ if (cookie->item && /* 正常情况直接获取下一个帧, 否则进入后面的异常情况去搜索 */ (cookie->item->seq > rb->last_drop_seq || rb->last_drop_seq == UINT32_MAX) && cookie->item->seq < ringbuffer_get_lastseq_locked(rb)) {/* 直接获取下一个*/ item = list_entry(cookie->item->link.next, ring_item, link); }else if (cookie->dir == LATEST_IFRAME){/*直播查找最新的关键帧*/ struct list_head *pos, *n; list_for_each_prev_safe(pos, n, &rb->list[RING_LIST_USING]) { ring_item* tmp_item = list_entry(pos, ring_item, link); av_ringbuffer_get_frame_locked(rb, tmp_item, to, sizeof(video_frame)); if((to->type & FRAME_TYPE_IFRAME) && (!cookie->item || tmp_item->seq >= cookie->item->seq)){ item = tmp_item; break; } } }else{/* dir = NEXT_IFRAME 查找比cookie->item新的关键帧, 如oss, 又不想丢太多 */ struct list_head *pos, *n; list_for_each_safe(pos, n, &rb->list[RING_LIST_USING]) { ring_item* tmp_item = list_entry(pos, ring_item, link); av_ringbuffer_get_frame_locked(rb, tmp_item, to, sizeof(video_frame)); if((to->type & FRAME_TYPE_IFRAME) && (!cookie->item || tmp_item->seq >= cookie->item->seq) /*&& (to->ts >= cookie->startPTS)*/) {/*头一个, 或者 下一个*/ item = tmp_item; break; } } } } hmutex_unlock(&rb->mutex); if ( item ) { cookie->item = item; av_ringbuffer_get_frame_locked(rb, item, to, sizeof(video_frame) + item->size); //hlogd("av_ringbuffer_get_video_frame %u %X %u\n", cookie->item->seq, rb->last_drop_seq, ringbuffer_get_lastseq_locked(rb)); ret = OK; } else { ret = NG; if (timeout) { if ( hsem_wait_for(&rb->sem, timeout) ){ /* 没有数据,调用端再重新call */ /* 正常, 收到了sem, 有新的av帧送入 */ } else { /* 超时没收到 sem */ } } } return ret; } #endif #if 1 void av_ringbuffer_test() { hlogi("test_av_ringbuffer\n"); #define TEST_CNT (10) av_ringbuffer *v_ring = av_ringbuffer_init(3*1024*1024); int i; for(i=0;ichn = 0; vframe->type = i % 15 == 0 ? FRAME_TYPE_IFRAME : FRAME_TYPE_PBFRAME; vframe->format = VIDEO_FORMAT_H264; vframe->seq = i; sprintf(vframe->data, "im %d", i); if (!av_ringbuffer_put(v_ring, vframe, vframe->data)){ hlogi("av_ringbuffer_put err:%u read:%p\n", vframe->size); } free(vframe); } hlogi("av_ringbuffer_put\n"); av_ringbuffer_dump(v_ring); av_cookie cookie = {0}; cookie.dir = NEXT_IFRAME; av_cookie *pcookie = &cookie; video_frame *vframe = (video_frame*)calloc(1, sizeof(video_frame)+MAX_VFRAME_SIZE); for(i=0;iitem->seq:%u data:%s\n", i, vframe->seq, vframe->size, cookie.item->seq, vframe->data); }else{ hlogi("1 av_ringbuffer_get_video_frame err:%d\n", i); //break; } } free(vframe); hlogi("test_av_ringbuffer end\n"); } #endif