683 lines
17 KiB
C++
Executable File
683 lines
17 KiB
C++
Executable File
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include "streamManager.h"
|
|
#include "log.h"
|
|
|
|
|
|
typedef struct STREAMFIFO
|
|
{
|
|
StreamFrame* pFrames;
|
|
int nMaxFrameNum;
|
|
int nValidFrameNum;
|
|
int nReadPos;
|
|
int nWritePos;
|
|
int nFlushPos;
|
|
}StreamFifo;
|
|
|
|
typedef struct STREAMMANAGERCONTEXT
|
|
{
|
|
pthread_mutex_t mutex;
|
|
int nMaxBufferSize;
|
|
int nValidDataSize;
|
|
int nStreamID;
|
|
StreamFifo streamFifo;
|
|
char* pMem;
|
|
int nMemSize;
|
|
char *lostBaby;
|
|
}StreamManagerCtx;
|
|
|
|
/*
|
|
**********************************************************************
|
|
* StreamManagerCreate
|
|
*
|
|
*Description: Create Stream Manager module.
|
|
*
|
|
*Arguments : nMaxBufferSize max stream buffer size.
|
|
*Arguments : nMaxFrameNum max stream frame count.
|
|
*Arguments : nStreamId the ID value to identify which stream
|
|
* this streamBufferManager belong to.
|
|
*
|
|
*Return : result
|
|
* = NULL; failed;
|
|
* != NULL; StreamManager handler.
|
|
*
|
|
*Summary :
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
StreamManager* StreamManagerCreate(int nMaxBufferSize, int nMaxFrameNum, int nStreamID)
|
|
{
|
|
StreamManagerCtx* p;
|
|
int i;
|
|
int ret;
|
|
|
|
if(nMaxBufferSize <= 0)
|
|
return NULL;
|
|
|
|
p = (StreamManagerCtx *)malloc(sizeof(StreamManagerCtx));
|
|
if(p == NULL)
|
|
{
|
|
loge("can not allocate memory for stream manager.");
|
|
return NULL;
|
|
}
|
|
memset(p, 0, sizeof(StreamManagerCtx));
|
|
|
|
p->streamFifo.pFrames = (StreamFrame*)malloc(nMaxFrameNum * sizeof(StreamFrame));
|
|
if(p->streamFifo.pFrames == NULL)
|
|
{
|
|
loge("can not allocate memory for stream manager.");
|
|
free(p);
|
|
return NULL;
|
|
}
|
|
memset(p->streamFifo.pFrames, 0, nMaxFrameNum * sizeof(StreamFrame));
|
|
|
|
pthread_mutex_init(&p->mutex, NULL);
|
|
p->nMaxBufferSize = nMaxBufferSize;
|
|
p->nValidDataSize = 0;
|
|
|
|
p->streamFifo.nMaxFrameNum = nMaxFrameNum;
|
|
p->streamFifo.nValidFrameNum = 0;
|
|
p->streamFifo.nReadPos = 0;
|
|
p->streamFifo.nWritePos = 0;
|
|
p->streamFifo.nFlushPos = 0;
|
|
p->nStreamID = nStreamID;
|
|
|
|
return (StreamManager*)p;
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************
|
|
* StreamManagerDestroy
|
|
*
|
|
*Description: Destroy Stream Manager module, free resource.
|
|
*
|
|
*Arguments : pSm Created by StreamManagerCreate function.
|
|
*
|
|
*Return : NULL
|
|
*
|
|
*Summary :
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
void StreamManagerDestroy(StreamManager* pSm)
|
|
{
|
|
StreamManagerCtx* p;
|
|
StreamFrame* pFrame;
|
|
StreamFrame* pFrames;
|
|
int nMaxFrameNum;
|
|
int nValidFrameNum;
|
|
int nReadPos;
|
|
|
|
p = (StreamManagerCtx*)pSm;
|
|
|
|
if(p != NULL)
|
|
{
|
|
pthread_mutex_destroy(&p->mutex);
|
|
|
|
pFrames = p->streamFifo.pFrames;
|
|
nMaxFrameNum = p->streamFifo.nMaxFrameNum;
|
|
nValidFrameNum = p->streamFifo.nValidFrameNum;
|
|
nReadPos = p->streamFifo.nReadPos;
|
|
|
|
while(nValidFrameNum > 0)
|
|
{
|
|
pFrame = &pFrames[nReadPos];
|
|
if(pFrame->pData != NULL)
|
|
free(pFrame->pData);
|
|
nValidFrameNum--;
|
|
nReadPos++;
|
|
if(nReadPos >= nMaxFrameNum)
|
|
nReadPos = 0;
|
|
}
|
|
|
|
if(pFrames != NULL)
|
|
free(pFrames);
|
|
|
|
if(p->pMem != NULL)
|
|
free(p->pMem);
|
|
|
|
free(p);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************
|
|
* StreamManagerReset
|
|
*
|
|
*Description: Reset Stream Manager module.
|
|
*
|
|
*Arguments : pSm Created by StreamManagerCreate function.
|
|
*
|
|
*Return : NULL
|
|
*
|
|
*Summary : If succeed, Stream Manager module will be resumed to initial state,
|
|
* stream data will be discarded.
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
void StreamManagerReset(StreamManager* pSm)
|
|
{
|
|
StreamManagerCtx* p;
|
|
StreamFrame* pFrame;
|
|
StreamFrame* pFrames;
|
|
int nMaxFrameNum;
|
|
int nValidFrameNum;
|
|
int nReadPos;
|
|
|
|
p = (StreamManagerCtx*)pSm;
|
|
|
|
if(p == NULL)
|
|
{
|
|
loge("pSm == NULL.");
|
|
return;
|
|
}
|
|
|
|
pthread_mutex_lock(&p->mutex);
|
|
|
|
pFrames = p->streamFifo.pFrames;
|
|
nMaxFrameNum = p->streamFifo.nMaxFrameNum;
|
|
nValidFrameNum = p->streamFifo.nValidFrameNum;
|
|
nReadPos = p->streamFifo.nReadPos;
|
|
|
|
while(nValidFrameNum > 0)
|
|
{
|
|
pFrame = &pFrames[nReadPos];
|
|
if(pFrame->pData != NULL)
|
|
free(pFrame->pData);
|
|
nValidFrameNum--;
|
|
nReadPos++;
|
|
if(nReadPos >= nMaxFrameNum)
|
|
nReadPos = 0;
|
|
}
|
|
|
|
if(p->pMem != NULL)
|
|
{
|
|
loge("memory leak,,,, the guy not return... '%p'", p->pMem);
|
|
p->lostBaby = p->pMem;
|
|
// free(p->pMem);
|
|
p->pMem = NULL;
|
|
p->nMemSize = 0;
|
|
}
|
|
|
|
p->nValidDataSize = 0;
|
|
p->streamFifo.nReadPos = 0;
|
|
p->streamFifo.nWritePos = 0;
|
|
p->streamFifo.nFlushPos = 0;
|
|
p->streamFifo.nValidFrameNum = 0;
|
|
pthread_mutex_unlock(&p->mutex);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************
|
|
* StreamManagerBufferSize
|
|
*
|
|
*Description: Get the StreamManager buffer size.
|
|
*
|
|
*Arguments : pSm Created by StreamManagerCreate function.
|
|
*
|
|
*Return : The size of StreamManager buffer, in Bytes.
|
|
*
|
|
*Summary : The size is set when create StreamManager.
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
int StreamManagerBufferSize(StreamManager* pSm)
|
|
{
|
|
StreamManagerCtx* p;
|
|
p = (StreamManagerCtx*)pSm;
|
|
|
|
if(p == NULL)
|
|
{
|
|
loge("pSm == NULL.");
|
|
return 0;
|
|
}
|
|
|
|
return p->nMaxBufferSize;
|
|
}
|
|
|
|
/*
|
|
**********************************************************************
|
|
* StreamManagerStreamFrameNum
|
|
*
|
|
*Description: Get the total frames of undecoded stream data.
|
|
*
|
|
*Arguments : pSm Created by StreamManagerCreate function.
|
|
*
|
|
*Return : The frames of undecoded stream data.
|
|
*
|
|
*Summary :
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
int StreamManagerStreamFrameNum(StreamManager* pSm)
|
|
{
|
|
StreamManagerCtx* p;
|
|
p = (StreamManagerCtx*)pSm;
|
|
|
|
if(p == NULL)
|
|
{
|
|
loge("pSm == NULL.");
|
|
return 0;
|
|
}
|
|
|
|
return p->streamFifo.nValidFrameNum;
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************
|
|
* StreamManagerStreamDataSize
|
|
*
|
|
*Description: Get the total size of undecoded data.
|
|
*
|
|
*Arguments : pSm Created by StreamManagerCreate function.
|
|
*
|
|
*Return : The total size of undecoded stream data, in bytes.
|
|
*
|
|
*Summary :
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
int StreamManagerStreamDataSize(StreamManager* pSm)
|
|
{
|
|
StreamManagerCtx* p;
|
|
p = (StreamManagerCtx*)pSm;
|
|
|
|
if(p == NULL)
|
|
{
|
|
loge("pSm == NULL.");
|
|
return 0;
|
|
}
|
|
|
|
return p->nValidDataSize;
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************
|
|
* StreamManagerRequestBuffer
|
|
*
|
|
*Description: Request buffer from sbm module.
|
|
*
|
|
*Arguments : pSm Created by StreamManagerCreate function;
|
|
* nRequireSize the required size, in bytes;
|
|
* ppBuf store the requested buffer address;
|
|
* pBufSize store the requested buffer size.
|
|
*
|
|
*Return : result;
|
|
* = 0; succeeded;
|
|
* = -1; failed.
|
|
*
|
|
*Summary : SBM buffer is cyclic, if the buffer turns around, there will be 2 blocks.
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
int StreamManagerRequestBuffer(StreamManager* pSm, int nRequireSize, char** ppBuf, int* pBufSize)
|
|
{
|
|
StreamManagerCtx* p;
|
|
|
|
p = (StreamManagerCtx*)pSm;
|
|
|
|
if (p == NULL || ppBuf == NULL || pBufSize == NULL)
|
|
{
|
|
loge("input error.");
|
|
return -1;
|
|
}
|
|
|
|
pthread_mutex_lock(&p->mutex);
|
|
|
|
if (p->streamFifo.nValidFrameNum >= p->streamFifo.nMaxFrameNum)
|
|
{
|
|
logv("nValidFrameNum >= nMaxFrameNum.");
|
|
pthread_mutex_unlock(&p->mutex);
|
|
*ppBuf = NULL;
|
|
*pBufSize = 0;
|
|
return -1;
|
|
}
|
|
|
|
if (p->nValidDataSize >= p->nMaxBufferSize)
|
|
{
|
|
//change to logv, it is not an error.
|
|
logw("no free buffer.");
|
|
usleep(100000); /* buffer full, wait 100ms... */
|
|
pthread_mutex_unlock(&p->mutex);
|
|
*ppBuf = NULL;
|
|
*pBufSize = 0;
|
|
return -1;
|
|
}
|
|
|
|
if (p->pMem != NULL)
|
|
{
|
|
logw("you not payback last buffer, not bollow now...");
|
|
usleep(100000); /* buffer full, wait 100ms... */
|
|
return -1;
|
|
/*
|
|
if (p->nMemSize == nRequireSize)
|
|
{
|
|
*ppBuf = p->pMem;
|
|
*pBufSize = p->nMemSize;
|
|
pthread_mutex_unlock(&p->mutex);
|
|
return 0;
|
|
}
|
|
|
|
free(p->pMem);
|
|
p->nMemSize = 0;
|
|
*/
|
|
}
|
|
|
|
p->pMem = (char*)malloc(nRequireSize);
|
|
if(p->pMem != NULL)
|
|
{
|
|
p->nMemSize = nRequireSize;
|
|
*ppBuf = p->pMem;
|
|
*pBufSize = p->nMemSize;
|
|
pthread_mutex_unlock(&p->mutex);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
loge("allocate memory fail.");
|
|
pthread_mutex_unlock(&p->mutex);
|
|
*ppBuf = NULL;
|
|
*pBufSize = 0;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************
|
|
* StreamManagerAddStream
|
|
*
|
|
*Description: Add one frame stream to StreamManager module.
|
|
*
|
|
*Arguments : pSm Created by StreamManagerCreate function;
|
|
* pDataInfo the stream info need to be added.
|
|
*
|
|
*Return : result;
|
|
* = 0; succeeded;
|
|
* = -1; failed.
|
|
*
|
|
*Summary :
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
int StreamManagerAddStream(StreamManager* pSm, StreamFrame* pStreamFrame)
|
|
{
|
|
|
|
int nWritePos;
|
|
char* pNewWriteAddr;
|
|
StreamManagerCtx* p;
|
|
|
|
p = (StreamManagerCtx*)pSm;
|
|
|
|
if(p == NULL || pStreamFrame == NULL)
|
|
{
|
|
loge("input error.");
|
|
return -1;
|
|
}
|
|
|
|
pthread_mutex_lock(&p->mutex);
|
|
|
|
if(p->streamFifo.nValidFrameNum >= p->streamFifo.nMaxFrameNum)
|
|
{
|
|
loge("nValidFrameNum > nMaxFrameNum.");
|
|
pthread_mutex_unlock(&p->mutex);
|
|
return -1;
|
|
}
|
|
|
|
if(p->pMem != pStreamFrame->pData || p->nMemSize < pStreamFrame->nLength)
|
|
{
|
|
loge("stream buffer not match. (%p :%d) (%p :%d)", p->pMem, p->nMemSize, pStreamFrame->pData, pStreamFrame->nLength);
|
|
if (p->lostBaby == pStreamFrame->pData)
|
|
{
|
|
logw("found the lost baby, free now.'%p'", pStreamFrame->pData);
|
|
free(pStreamFrame->pData);
|
|
}
|
|
pthread_mutex_unlock(&p->mutex);
|
|
return -1;
|
|
}
|
|
|
|
nWritePos = p->streamFifo.nWritePos;
|
|
memcpy(&p->streamFifo.pFrames[nWritePos], pStreamFrame, sizeof(StreamFrame));
|
|
nWritePos++;
|
|
if(nWritePos >= p->streamFifo.nMaxFrameNum)
|
|
nWritePos = 0;
|
|
|
|
p->streamFifo.nWritePos = nWritePos;
|
|
p->streamFifo.nValidFrameNum++;
|
|
p->nValidDataSize += pStreamFrame->nLength;
|
|
|
|
p->pMem = NULL;
|
|
p->nMemSize = 0;
|
|
|
|
pthread_mutex_unlock(&p->mutex);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************
|
|
* StreamManagerRequestStream
|
|
*
|
|
*Description: Request one frame stream data from sbm module to decoder.
|
|
*
|
|
*Arguments : pSm Created by StreamManagerCreate function;
|
|
*
|
|
*Return : The stream information.
|
|
*
|
|
*Summary : The stream data obeys FIFO rule.
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
StreamFrame* StreamManagerRequestStream(StreamManager* pSm)
|
|
{
|
|
StreamFrame* pStreamFrame;
|
|
StreamManagerCtx* p;
|
|
|
|
p = (StreamManagerCtx*)pSm;
|
|
|
|
if(p == NULL )
|
|
{
|
|
loge("pSm == NULL.");
|
|
return NULL;
|
|
}
|
|
|
|
pthread_mutex_lock(&p->mutex);
|
|
|
|
if(p->streamFifo.nValidFrameNum == 0)
|
|
{
|
|
loge("nValidFrameNum == 0.");
|
|
pthread_mutex_unlock(&p->mutex);
|
|
return NULL;
|
|
}
|
|
|
|
pStreamFrame = &p->streamFifo.pFrames[p->streamFifo.nReadPos];
|
|
|
|
p->streamFifo.nReadPos++;
|
|
if(p->streamFifo.nReadPos >= p->streamFifo.nMaxFrameNum)
|
|
p->streamFifo.nReadPos = 0;
|
|
|
|
pthread_mutex_unlock(&p->mutex);
|
|
|
|
return pStreamFrame;
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************
|
|
* StreamManagerGetFrameInfo
|
|
*
|
|
*Description: get the frame information of the specific frame.
|
|
*
|
|
*Arguments : pSm Created by StreamManagerCreate function;
|
|
* nFrameIndex the frame index start counted from the first
|
|
* valid frame.
|
|
*
|
|
*Return : The stream information.
|
|
*
|
|
*Summary : The stream data obeys FIFO rule.
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
StreamFrame* StreamManagerGetFrameInfo(StreamManager* pSm, int nFrameIndex)
|
|
{
|
|
StreamFrame* pStreamFrame;
|
|
int nPos;
|
|
StreamManagerCtx* p;
|
|
|
|
p = (StreamManagerCtx*)pSm;
|
|
|
|
if(p == NULL )
|
|
{
|
|
loge("pSm == NULL.");
|
|
return NULL;
|
|
}
|
|
|
|
pthread_mutex_lock(&p->mutex);
|
|
|
|
if(nFrameIndex < 0 || nFrameIndex >= p->streamFifo.nValidFrameNum)
|
|
{
|
|
pthread_mutex_unlock(&p->mutex);
|
|
return NULL;
|
|
}
|
|
|
|
nPos = p->streamFifo.nReadPos + nFrameIndex;
|
|
if(nPos >= p->streamFifo.nMaxFrameNum)
|
|
nPos -= p->streamFifo.nMaxFrameNum;
|
|
|
|
pStreamFrame = &p->streamFifo.pFrames[nPos];
|
|
|
|
pthread_mutex_unlock(&p->mutex);
|
|
|
|
return pStreamFrame;
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************
|
|
* StreamManagerReturnStream
|
|
*
|
|
*Description: Return one undecoded frame to StreamManager module.
|
|
*
|
|
*Arguments : pSm Created by StreamManagerCreate function;
|
|
* pStreamFrame the stream info need to be returned.
|
|
*
|
|
*Return : result;
|
|
* = 0; succeeded;
|
|
* = -1; failed.
|
|
*
|
|
*Summary : After returned, the stream data's sequence is the same as before.
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
int StreamManagerReturnStream(StreamManager* pSm, StreamFrame* pStreamFrame)
|
|
{
|
|
int nReadPos;
|
|
StreamManagerCtx* p;
|
|
|
|
p = (StreamManagerCtx*)pSm;
|
|
|
|
if(p == NULL || pStreamFrame == NULL)
|
|
{
|
|
loge("input error.");
|
|
return -1;
|
|
}
|
|
|
|
pthread_mutex_lock(&p->mutex);
|
|
|
|
if(p->streamFifo.nValidFrameNum == 0)
|
|
{
|
|
loge("nValidFrameNum == 0.");
|
|
pthread_mutex_unlock(&p->mutex);
|
|
return -1;
|
|
}
|
|
nReadPos = p->streamFifo.nReadPos;
|
|
nReadPos--;
|
|
if(nReadPos < 0)
|
|
nReadPos = p->streamFifo.nMaxFrameNum - 1;
|
|
|
|
if(pStreamFrame != &p->streamFifo.pFrames[nReadPos])
|
|
{
|
|
loge("wrong frame sequence.");
|
|
abort();
|
|
}
|
|
|
|
p->streamFifo.pFrames[nReadPos] = *pStreamFrame;
|
|
p->streamFifo.nReadPos = nReadPos;
|
|
|
|
pthread_mutex_unlock(&p->mutex);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************
|
|
* StreamManagerFlushStream
|
|
*
|
|
*Description: Flush one frame which is requested from StreamManager.
|
|
*
|
|
*Arguments : pSm Created by StreamManagerCreate function;
|
|
* pStreamFrame the stream info need to be flushed.
|
|
*
|
|
*Return : result;
|
|
* = 0; succeeded;
|
|
* = -1; failed.
|
|
*
|
|
*Summary : After flushed, the buffer can be used to store new stream.
|
|
*
|
|
**********************************************************************
|
|
*/
|
|
int StreamManagerFlushStream(StreamManager* pSm, StreamFrame* pStreamFrame)
|
|
{
|
|
int nFlushPos;
|
|
StreamManagerCtx* p;
|
|
|
|
p = (StreamManagerCtx*)pSm;
|
|
|
|
if(p == NULL)
|
|
{
|
|
loge("pSm == NULL.");
|
|
return -1;
|
|
}
|
|
|
|
pthread_mutex_lock(&p->mutex);
|
|
|
|
if(p->streamFifo.nValidFrameNum == 0)
|
|
{
|
|
loge("no valid frame.");
|
|
pthread_mutex_unlock(&p->mutex);
|
|
return -1;
|
|
}
|
|
|
|
nFlushPos = p->streamFifo.nFlushPos;
|
|
if(pStreamFrame != &p->streamFifo.pFrames[nFlushPos])
|
|
{
|
|
loge("flush frame not match.");
|
|
pthread_mutex_unlock(&p->mutex);
|
|
return -1;
|
|
}
|
|
|
|
if(pStreamFrame->pData != NULL)
|
|
free(pStreamFrame->pData);
|
|
|
|
nFlushPos++;
|
|
if(nFlushPos >= p->streamFifo.nMaxFrameNum)
|
|
nFlushPos = 0;
|
|
|
|
p->streamFifo.nValidFrameNum--;
|
|
p->nValidDataSize -= pStreamFrame->nLength;
|
|
p->streamFifo.nFlushPos = nFlushPos;
|
|
pthread_mutex_unlock(&p->mutex);
|
|
return 0;
|
|
}
|