117 lines
4.3 KiB
C
Executable File
117 lines
4.3 KiB
C
Executable File
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#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;i<TEST_CNT;i++){
|
|
video_frame *vframe = avframe_create(video_frame, i+10);
|
|
vframe->chn = 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;i<TEST_CNT;i++){
|
|
if (OK == av_ringbuffer_get_frame(v_ring, pcookie, vframe, i+10, 1000)){
|
|
hlogi("1 av_ringbuffer_get_video_frame i:%d seq:%u, size:%u cookie->item->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
|
|
|