#define CD_COL "31"
#include "CamStreamingDeframer.h"
#include "CamDevice.h"
#include "CamDebug.h"
#include <Autolock.h>
#define MAX_TAG_LEN CAMDEFRAMER_MAX_TAG_LEN
#define MAXFRAMEBUF CAMDEFRAMER_MAX_QUEUED_FRAMES
CamStreamingDeframer::CamStreamingDeframer(CamDevice *device)
: CamDeframer(device)
{
}
CamStreamingDeframer::~CamStreamingDeframer()
{
}
ssize_t
CamStreamingDeframer::Write(const void *buffer, size_t size)
{
int i = -1;
int j;
int end = size;
int which;
const uint8 *buf = (const uint8 *)buffer;
int bufsize = size;
bool detach = false;
bool discard = false;
if (!fCurrentFrame) {
BAutolock l(fLocker);
if (fFrames.CountItems() < MAXFRAMEBUF)
fCurrentFrame = AllocFrame();
else {
PRINT((CH "DROPPED %" B_PRIuSIZE " bytes! "
"(too many queued frames)" CT, size));
return size;
}
}
fMinFrameSize = fDevice->MinRawFrameSize();
fMaxFrameSize = fDevice->MaxRawFrameSize();
if (fInputBuff.Position()) {
fInputBuff.Write(buffer, size);
buf = (uint8 *)fInputBuff.Buffer();
bufsize = fInputBuff.BufferLength();
end = bufsize;
}
if (fState == ST_FRAME) {
off_t position = fCurrentFrame->Position();
if (position + bufsize < 0
|| (size_t)(position + bufsize) < fMinFrameSize) {
fCurrentFrame->Write(buf, bufsize);
fInputBuff.Seek(0LL, SEEK_SET);
fInputBuff.SetSize(0);
return size;
}
}
if (fState == ST_SYNC) {
i = 0;
while ((j = FindSOF(buf+i, bufsize-i, &which)) > -1) {
i += j;
if (fDevice->ValidateStartOfFrameTag(buf+i, fSkipSOFTags))
break;
i++;
}
if (j >= 0) {
PRINT((CH ": SOF[%d] at offset %d" CT, which, i));
int start = i + fSkipSOFTags;
buf += start;
bufsize -= start;
end = bufsize;
fState = ST_FRAME;
}
}
if (fState == ST_FRAME) {
#if 0
int j, k;
i = -1;
k = 0;
while ((j = FindEOF(buf + k, bufsize - k, &which)) > -1) {
k += j;
if (fCurrentFrame->Position()+k >= fMinFrameSize) {
i = k;
break;
}
k++;
if (k >= bufsize)
break;
}
#endif
#if 1
i = 0;
off_t currentFramePosition = fCurrentFrame->Position();
if (currentFramePosition < 0
|| (size_t)currentFramePosition < fMinFrameSize) {
if (currentFramePosition + bufsize > 0
&& (size_t)(currentFramePosition + bufsize) >= fMinFrameSize) {
i = (fMinFrameSize - (size_t)fCurrentFrame->Position());
} else
i = bufsize;
}
PRINT((CH ": checking for EOF; bufsize=%d i=%d" CT, bufsize, i));
if (i + (int)fSkipEOFTags > bufsize) {
end = i;
i = -1;
} else {
PRINT((CH ": EOF? %02x [%02x %02x %02x %02x] %02x" CT, buf[i-1], buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4]));
while ((j = FindEOF(buf + i, bufsize - i, &which)) > -1) {
i += j;
PRINT((CH "| EOF[%d] at offset %d; pos %" B_PRIdOFF CT,
which, i, fCurrentFrame->Position()));
off_t position = fCurrentFrame->Position();
if (position + i >= 0
&& (size_t)(position + i) >= fMaxFrameSize) {
discard = true;
break;
}
if (fDevice->ValidateEndOfFrameTag(buf+i, fSkipEOFTags, fCurrentFrame->Position()+i))
break;
i++;
if (i >= bufsize) {
i = -1;
break;
}
}
if (j < 0)
i = -1;
}
#endif
if (i >= 0) {
PRINT((CH ": EOF[%d] at offset %d" CT, which, i));
end = i;
detach = true;
}
PRINT((CH ": writing %d bytes" CT, end));
if (end <= bufsize)
fCurrentFrame->Write(buf, end);
off_t currentPosition = fCurrentFrame->Position();
if (currentPosition > 0
&& (size_t)currentPosition > fMaxFrameSize) {
fCurrentFrame->SetSize(fMaxFrameSize);
detach = true;
}
if (detach) {
BAutolock f(fLocker);
PRINT((CH ": Detaching a frame "
"(%" B_PRIuSIZE " bytes, end = %d, )" CT,
(size_t)fCurrentFrame->Position(), end));
fCurrentFrame->Seek(0LL, SEEK_SET);
if (discard) {
delete fCurrentFrame;
} else {
fFrames.AddItem(fCurrentFrame);
release_sem(fFrameSem);
}
fCurrentFrame = NULL;
if (fFrames.CountItems() < MAXFRAMEBUF) {
fCurrentFrame = AllocFrame();
}
fState = ST_SYNC;
}
}
#if 0
fInputBuff.Seek(0LL, SEEK_SET);
if (bufsize - end > 0)
fInputBuff.Write(buf+end, bufsize - end);
#endif
BMallocIO m;
m.Write(buf+end, bufsize - end);
fInputBuff.Seek(0LL, SEEK_SET);
if (bufsize - end > 0)
fInputBuff.Write(m.Buffer(), bufsize - end);
fInputBuff.SetSize(bufsize - end);
return size;
}