这几天在工作中遇到一个问题:
从网络中接收数据,数据量很大,大概在每秒钟10MB左右,也可以说是视频YUV数据的传输。当接收到这些数据后再将这些数据进行编码。
在这个接收和传入编码的过程中不能进行大数据量的拷贝工作,(原因我们都知道,拷贝这么多的数量在ARM上会占用太多的资源),对此我写了一个队列来完成该事情。
由于是YUV图像数据,每帧的大小都是定值,所分配的内存空间大小也都一致。我暂且将我的队列大小定为25个,因为一秒的PAL帧是25左右。另外我分配了多分配两个内存(这两个很重要):其中一个作为第一个从网络上接收的数据存放用,另一个作为第一个出队列用。在这里可能说的不够清楚。-----意思很简单,为了不进行大数据量的拷贝工作,我只进行内存地址的交换。
原理:每次进队列的操作是:保存进入队列的地址,返回一个新的没有使用的地址
每次出队列的操作是:保存一个使用过的地址,返回一个队列中存放的地址。
具体看代码:
进队列的操作:
MS_INT32 enqueue_sq_yuv(YUV_FRAME *e)
{ //e插入队尾作为新元素
//lock_pend(1,SYS_FOREVER);
YUV_FRAME tmp;
memcpy (&tmp,e,sizeof(YUV_FRAME));
if(q == NULL)
{
printf("ERROR:sqqueue_yuv not create/n");
return MD_FAILED;
}
lock(lockHandleYuv);
if ((q->rear + 1) % DEF_MAX_QUEUES_SIZE_YUV == q->front)
{
memcpy(e,&(q->base[q->rear]),sizeof(YUV_FRAME));
q->front = (q->front + 1) % DEF_MAX_QUEUES_SIZE_YUV;
//printf("WARN: sqqueue_yuv is fulling q->rear[%d]/n",q->rear);
//lock_post(1);
//unlock(lockHandleYuv);
//return MD_FAILED;
}else
{
memcpy(e,&(q->base[q->rear]),sizeof(YUV_FRAME));
//printf("INFO: sqqueue_yuv isn't full q->front[%d] q->rear[%d]/n",q->front,q->rear);
}
//q->base[q->rear] = e;
memcpy(&(q->base[q->rear]),&tmp,sizeof(YUV_FRAME));
q->rear = (q->rear + 1) % DEF_MAX_QUEUES_SIZE_YUV;
//lock_post(1);
unlock(lockHandleYuv);
return MD_OK;
}
出队列的操作:
MS_INT32 dequeue_sq_yuv( YUV_FRAME *e)
{ //出队,返回首元素e的值
//lock_pend(1,SYS_FOREVER);
YUV_FRAME tmp;
memcpy (&tmp,e,sizeof(YUV_FRAME));
if(q == NULL)
{
printf("ERROR: dequeue_sq_yuv sqqueue_yuv not create/n");
return MD_FAILED;
}
lock(lockHandleYuv);
if (q->front == q->rear)
{
//lock_post(1);
unlock(lockHandleYuv);
//printf("WARN: dequeue_sq_yuv sqqueue_yuv is empty q->rear[%d]/n",q->rear);
return MD_FAILED;
}else
{
//printf("INFO: dequeue_sq_yuv sqqueue_yuv isn't empty q->front[%d] q->rear)[%d]/n",q->front,q->rear);
}
//*e = q->base[q->front];
memcpy(e,&(q->base[q->front]),sizeof(YUV_FRAME));
if(0)
{
e->data = tmp.data;
memcpy(e->data,q->base[q->front].data,704*576*3/2);
}else
{
memcpy(&(q->base[q->front]),&tmp,sizeof(YUV_FRAME));
}
q->front = (q->front + 1) % DEF_MAX_QUEUES_SIZE_YUV;
//lock_post(1);
unlock(lockHandleYuv);
return MD_OK;
}
经过上面的进队和出队便可以进行操作使用。下面是完整的代码
#ifndef _YUV_QUEUES_H_
#define _YUV_QUEUES_H_
#include "C2Htype.h"
#define DEF_MAX_QUEUES_SIZE_YUV 10
typedef struct strYUV_FRAME{
MS_INT32 *pflag;
MU_INT32 *data;
MS_INT32 resave[2];
}YUV_FRAME;
typedef struct {
YUV_FRAME *base;
MS_INT32 front;
MS_INT32 rear;
} sqqueue_yuv;
MS_INT32 initqueue_sq_yuv( void ) ;//初始化队列
MS_INT32 enqueue_sq_yuv(YUV_FRAME* e) ;//??en,??de
MS_INT32 dequeue_sq_yuv(YUV_FRAME *e) ;//??e
MS_INT32 queuelength_sq_yuv( void ); //??
MS_INT32 deletequeue_sq_yuv(void) ;//???
MS_INT32 CreatQueue_yuv(MS_INT32 bufSize);
MS_INT32 DestroyQueue_yuv(MS_INT32 bufSize);
#endif
#include "../include/yuv_queues.h"
static sqqueue_yuv *q = NULL;
static M_HANDLE lockHandleYuv = NULL;
MS_INT32 initqueue_sq_yuv(void)
{ //初始化顺序队
q = (sqqueue_yuv *) MM_calloc(sizeof(sqqueue_yuv),0,4);//
q->base = (YUV_FRAME *) MM_alloc(DEF_MAX_QUEUES_SIZE_YUV * sizeof (YUV_FRAME),4);
memset(q->base,0,DEF_MAX_QUEUES_SIZE_YUV * sizeof (YUV_FRAME));
if (!q->base)
return MD_FAILED; //存储分配失败
q->front = q->rear = 0;
CreatLock(&lockHandleYuv);
if(lockHandleYuv==NULL)
{
printf("ERROR: initqueue_sq_yuv->CreatLock error/n");
deletequeue_sq_yuv();
return MD_FAILED;
}
printf("OK: Create sqqueue_yuv is %08x ,Create Lock is %08x/n",(MU_INT32)q,(MU_INT32)lockHandleYuv);
return MD_OK;
}
MS_INT32 enqueue_sq_yuv(YUV_FRAME *e)
{ //e插入队尾作为新元素
//lock_pend(1,SYS_FOREVER);
YUV_FRAME tmp;
memcpy (&tmp,e,sizeof(YUV_FRAME));
if(q == NULL)
{
printf("ERROR:sqqueue_yuv not create/n");
return MD_FAILED;
}
lock(lockHandleYuv);
if ((q->rear + 1) % DEF_MAX_QUEUES_SIZE_YUV == q->front)
{
memcpy(e,&(q->base[q->rear]),sizeof(YUV_FRAME));
q->front = (q->front + 1) % DEF_MAX_QUEUES_SIZE_YUV;
//printf("WARN: sqqueue_yuv is fulling q->rear[%d]/n",q->rear);
//lock_post(1);
//unlock(lockHandleYuv);
//return MD_FAILED;
}else
{
memcpy(e,&(q->base[q->rear]),sizeof(YUV_FRAME));
//printf("INFO: sqqueue_yuv isn't full q->front[%d] q->rear[%d]/n",q->front,q->rear);
}
//q->base[q->rear] = e;
memcpy(&(q->base[q->rear]),&tmp,sizeof(YUV_FRAME));
q->rear = (q->rear + 1) % DEF_MAX_QUEUES_SIZE_YUV;
//lock_post(1);
unlock(lockHandleYuv);
return MD_OK;
}
MS_INT32 dequeue_sq_yuv( YUV_FRAME *e)
{ //出队,返回首元素e的值
//lock_pend(1,SYS_FOREVER);
YUV_FRAME tmp;
memcpy (&tmp,e,sizeof(YUV_FRAME));
if(q == NULL)
{
printf("ERROR: dequeue_sq_yuv sqqueue_yuv not create/n");
return MD_FAILED;
}
lock(lockHandleYuv);
if (q->front == q->rear)
{
//lock_post(1);
unlock(lockHandleYuv);
//printf("WARN: dequeue_sq_yuv sqqueue_yuv is empty q->rear[%d]/n",q->rear);
return MD_FAILED;
}else
{
//printf("INFO: dequeue_sq_yuv sqqueue_yuv isn't empty q->front[%d] q->rear)[%d]/n",q->front,q->rear);
}
//*e = q->base[q->front];
memcpy(e,&(q->base[q->front]),sizeof(YUV_FRAME));
if(0)
{
e->data = tmp.data;
memcpy(e->data,q->base[q->front].data,704*576*3/2);
}else
{
memcpy(&(q->base[q->front]),&tmp,sizeof(YUV_FRAME));
}
q->front = (q->front + 1) % DEF_MAX_QUEUES_SIZE_YUV;
//lock_post(1);
unlock(lockHandleYuv);
return MD_OK;
}
MS_INT32 queuelength_sq_yuv(void) //求对长
{
return (q->rear - q->front + DEF_MAX_QUEUES_SIZE_YUV) % DEF_MAX_QUEUES_SIZE_YUV;
}
MS_INT32 deletequeue_sq_yuv(void) //删除
{
if (q != NULL)
{
if(NULL != q->base)
MM_free(q->base,DEF_MAX_QUEUES_SIZE_YUV * sizeof (YUV_FRAME));
MM_free(q,sizeof(sqqueue_yuv));
q = NULL;
}
return MD_OK;
}
MS_INT32 CreatQueue_yuv(MS_INT32 bufSize)
{
MU_INT32 i;
YUV_FRAME tFrame;
memset(&tFrame,0,sizeof(YUV_FRAME));
tFrame.data = (MU_INT32 *) MM_alloc(bufSize,4);
if(tFrame.data == NULL)
{
printf("ERROR:CreatQueue_yuv error/n");
return MD_FAILED;
}
initqueue_sq_yuv();
for(i =0;i < DEF_MAX_QUEUES_SIZE_YUV;i++)
{
if(tFrame.data == NULL)
{
tFrame.data = (MU_INT32 *) MM_alloc(bufSize,4);
if(tFrame.data == NULL)
{
printf("ERROR:CreatQueue_yuv %d error/n",i);
return MD_FAILED;
}else
{
//printf("CreatQueue_yuv %d:%08x/n",i,tFrame.data);
}
}else
{
//printf("CreatQueue_yuv had %d:%08x/n",i,tFrame.data);
}
enqueue_sq_yuv(&tFrame);
}
return MD_OK;
}
MS_INT32 DestroyQueue_yuv(MS_INT32 bufSize)
{
MU_INT32 rtn,i;
YUV_FRAME tFrame;
memset(&tFrame,0,sizeof(YUV_FRAME));
if(q == NULL)
{
printf("ERROR:sqqueue_yuv not create/n");
return MD_FAILED;
}
for(i =0;i < DEF_MAX_QUEUES_SIZE_YUV;i++)
{
rtn = dequeue_sq_yuv(&tFrame);
if(rtn == MD_FAILED)
continue;
if(tFrame.data != NULL)
{
//printf("INFO:delete %d tFrame.data 0x%08x/n",i,tFrame.data);
MM_free(tFrame.data,bufSize);
tFrame.data = NULL;
}
}
deletequeue_sq_yuv() ;
printf("OK: DestroyQueue_yuv ok/n");
return MD_OK;
}