12c9bd703SFrançois Revol /*
2a1830cbdSFrançois Revol * Copyright 2004-2008, François Revol, <revol@free.fr>.
3a1830cbdSFrançois Revol * Distributed under the terms of the MIT License.
4a1830cbdSFrançois Revol */
5a1830cbdSFrançois Revol
6a1830cbdSFrançois Revol /*
72c9bd703SFrançois Revol * stream based deframer
82c9bd703SFrançois Revol * has a state machine and handles each packet separately.
92c9bd703SFrançois Revol * much more complex than the buffering one, and I thought it didn't work,
102c9bd703SFrançois Revol * but since I fixed the rest it seems to be working even better without
112c9bd703SFrançois Revol * taking the cpu over like the other one.
122c9bd703SFrançois Revol */
132c9bd703SFrançois Revol
142c9bd703SFrançois Revol #define CD_COL "31"
152c9bd703SFrançois Revol #include "CamStreamingDeframer.h"
162c9bd703SFrançois Revol #include "CamDevice.h"
172c9bd703SFrançois Revol #include "CamDebug.h"
182c9bd703SFrançois Revol #include <Autolock.h>
192c9bd703SFrançois Revol #define MAX_TAG_LEN CAMDEFRAMER_MAX_TAG_LEN
202c9bd703SFrançois Revol #define MAXFRAMEBUF CAMDEFRAMER_MAX_QUEUED_FRAMES
212c9bd703SFrançois Revol
2274b3713aSFrançois Revol
CamStreamingDeframer(CamDevice * device)232c9bd703SFrançois Revol CamStreamingDeframer::CamStreamingDeframer(CamDevice *device)
242c9bd703SFrançois Revol : CamDeframer(device)
252c9bd703SFrançois Revol {
262c9bd703SFrançois Revol }
272c9bd703SFrançois Revol
2874b3713aSFrançois Revol
~CamStreamingDeframer()292c9bd703SFrançois Revol CamStreamingDeframer::~CamStreamingDeframer()
302c9bd703SFrançois Revol {
312c9bd703SFrançois Revol }
322c9bd703SFrançois Revol
3374b3713aSFrançois Revol
342c9bd703SFrançois Revol ssize_t
Write(const void * buffer,size_t size)352c9bd703SFrançois Revol CamStreamingDeframer::Write(const void *buffer, size_t size)
362c9bd703SFrançois Revol {
372c9bd703SFrançois Revol int i = -1;
382c9bd703SFrançois Revol int j;
392c9bd703SFrançois Revol int end = size;
402c9bd703SFrançois Revol int which;
412c9bd703SFrançois Revol const uint8 *buf = (const uint8 *)buffer;
422c9bd703SFrançois Revol int bufsize = size;
432c9bd703SFrançois Revol bool detach = false;
442c9bd703SFrançois Revol bool discard = false;
45a486abdcSFrançois Revol //PRINT((CH "(%p, %d); state=%s framesz=%u queued=%u" CT, buffer, size, (fState==ST_SYNC)?"sync":"frame", (size_t)(fCurrentFrame?(fCurrentFrame->Position()):-1), (size_t)fInputBuff.Position()));
462c9bd703SFrançois Revol if (!fCurrentFrame) {
472c9bd703SFrançois Revol BAutolock l(fLocker);
482c9bd703SFrançois Revol if (fFrames.CountItems() < MAXFRAMEBUF)
492c9bd703SFrançois Revol fCurrentFrame = AllocFrame();
502c9bd703SFrançois Revol else {
51edb48467SMurai Takashi PRINT((CH "DROPPED %" B_PRIuSIZE " bytes! "
52edb48467SMurai Takashi "(too many queued frames)" CT, size));
532c9bd703SFrançois Revol return size; // drop XXX
542c9bd703SFrançois Revol }
552c9bd703SFrançois Revol }
562c9bd703SFrançois Revol
572c9bd703SFrançois Revol // update in case resolution changed
582c9bd703SFrançois Revol fMinFrameSize = fDevice->MinRawFrameSize();
592c9bd703SFrançois Revol fMaxFrameSize = fDevice->MaxRawFrameSize();
602c9bd703SFrançois Revol
612c9bd703SFrançois Revol if (fInputBuff.Position()) {
622c9bd703SFrançois Revol // residual data ? append to it
632c9bd703SFrançois Revol fInputBuff.Write(buffer, size);
642c9bd703SFrançois Revol // and use it as input buf
652c9bd703SFrançois Revol buf = (uint8 *)fInputBuff.Buffer();
662c9bd703SFrançois Revol bufsize = fInputBuff.BufferLength();
672c9bd703SFrançois Revol end = bufsize;
682c9bd703SFrançois Revol }
692c9bd703SFrançois Revol // whole buffer belongs to a frame, simple
70628ddb27SFranck LeCodeur if (fState == ST_FRAME) {
71628ddb27SFranck LeCodeur off_t position = fCurrentFrame->Position();
72628ddb27SFranck LeCodeur if (position + bufsize < 0
73628ddb27SFranck LeCodeur || (size_t)(position + bufsize) < fMinFrameSize) {
742c9bd703SFrançois Revol // no residual data, and
752c9bd703SFrançois Revol fCurrentFrame->Write(buf, bufsize);
762c9bd703SFrançois Revol fInputBuff.Seek(0LL, SEEK_SET);
772c9bd703SFrançois Revol fInputBuff.SetSize(0);
782c9bd703SFrançois Revol return size;
792c9bd703SFrançois Revol }
80628ddb27SFranck LeCodeur }
812c9bd703SFrançois Revol
822c9bd703SFrançois Revol // waiting for a frame...
832c9bd703SFrançois Revol if (fState == ST_SYNC) {
842c9bd703SFrançois Revol i = 0;
852c9bd703SFrançois Revol while ((j = FindSOF(buf+i, bufsize-i, &which)) > -1) {
862c9bd703SFrançois Revol i += j;
872c9bd703SFrançois Revol if (fDevice->ValidateStartOfFrameTag(buf+i, fSkipSOFTags))
882c9bd703SFrançois Revol break;
892c9bd703SFrançois Revol i++;
902c9bd703SFrançois Revol }
912c9bd703SFrançois Revol // got one
922c9bd703SFrançois Revol if (j >= 0) {
932c9bd703SFrançois Revol PRINT((CH ": SOF[%d] at offset %d" CT, which, i));
942c9bd703SFrançois Revol //PRINT((CH ": SOF: ... %02x %02x %02x %02x %02x %02x" CT, buf[i+6], buf[i+7], buf[i+8], buf[i+9], buf[i+10], buf[i+11]));
952c9bd703SFrançois Revol int start = i + fSkipSOFTags;
962c9bd703SFrançois Revol buf += start;
972c9bd703SFrançois Revol bufsize -= start;
982c9bd703SFrançois Revol end = bufsize;
992c9bd703SFrançois Revol fState = ST_FRAME;
1002c9bd703SFrançois Revol }
1012c9bd703SFrançois Revol }
1022c9bd703SFrançois Revol
1032c9bd703SFrançois Revol // check for end of frame
1042c9bd703SFrançois Revol if (fState == ST_FRAME) {
1052c9bd703SFrançois Revol #if 0
1062c9bd703SFrançois Revol int j, k;
1072c9bd703SFrançois Revol i = -1;
1082c9bd703SFrançois Revol k = 0;
1092c9bd703SFrançois Revol while ((j = FindEOF(buf + k, bufsize - k, &which)) > -1) {
1102c9bd703SFrançois Revol k += j;
111*425ac1b6SAlexander von Gluck IV //PRINT((CH "| EOF[%d] at offset %d; pos %lld" CT, which, k, fCurrentFrame->Position()));
1122c9bd703SFrançois Revol if (fCurrentFrame->Position()+k >= fMinFrameSize) {
1132c9bd703SFrançois Revol i = k;
1142c9bd703SFrançois Revol break;
1152c9bd703SFrançois Revol }
1162c9bd703SFrançois Revol k++;
1172c9bd703SFrançois Revol if (k >= bufsize)
1182c9bd703SFrançois Revol break;
1192c9bd703SFrançois Revol }
1202c9bd703SFrançois Revol #endif
1212c9bd703SFrançois Revol #if 1
1222c9bd703SFrançois Revol i = 0;
123628ddb27SFranck LeCodeur off_t currentFramePosition = fCurrentFrame->Position();
124628ddb27SFranck LeCodeur if (currentFramePosition < 0
125628ddb27SFranck LeCodeur || (size_t)currentFramePosition < fMinFrameSize) {
126628ddb27SFranck LeCodeur if (currentFramePosition + bufsize > 0
127628ddb27SFranck LeCodeur && (size_t)(currentFramePosition + bufsize) >= fMinFrameSize) {
1282c9bd703SFrançois Revol i = (fMinFrameSize - (size_t)fCurrentFrame->Position());
129628ddb27SFranck LeCodeur } else
1302c9bd703SFrançois Revol i = bufsize;
1312c9bd703SFrançois Revol }
1322c9bd703SFrançois Revol PRINT((CH ": checking for EOF; bufsize=%d i=%d" CT, bufsize, i));
1332c9bd703SFrançois Revol
134e53032e5SFrançois Revol if (i + (int)fSkipEOFTags > bufsize) { // not enough room to check for EOF, leave it for next time
1352c9bd703SFrançois Revol end = i;
1362c9bd703SFrançois Revol i = -1; // don't detach yet
1372c9bd703SFrançois Revol } else {
1382c9bd703SFrançois Revol 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]));
1392c9bd703SFrançois Revol while ((j = FindEOF(buf + i, bufsize - i, &which)) > -1) {
1402c9bd703SFrançois Revol i += j;
141edb48467SMurai Takashi PRINT((CH "| EOF[%d] at offset %d; pos %" B_PRIdOFF CT,
142edb48467SMurai Takashi which, i, fCurrentFrame->Position()));
143628ddb27SFranck LeCodeur off_t position = fCurrentFrame->Position();
144628ddb27SFranck LeCodeur if (position + i >= 0
145628ddb27SFranck LeCodeur && (size_t)(position + i) >= fMaxFrameSize) {
1462c9bd703SFrançois Revol // too big: discard
1472c9bd703SFrançois Revol //i = -1;
1482c9bd703SFrançois Revol discard = true;
1492c9bd703SFrançois Revol break;
1502c9bd703SFrançois Revol }
1512c9bd703SFrançois Revol if (fDevice->ValidateEndOfFrameTag(buf+i, fSkipEOFTags, fCurrentFrame->Position()+i))
1522c9bd703SFrançois Revol break;
1532c9bd703SFrançois Revol i++;
1542c9bd703SFrançois Revol if (i >= bufsize) {
1552c9bd703SFrançois Revol i = -1;
1562c9bd703SFrançois Revol break;
1572c9bd703SFrançois Revol }
1582c9bd703SFrançois Revol }
1592c9bd703SFrançois Revol if (j < 0)
1602c9bd703SFrançois Revol i = -1;
1612c9bd703SFrançois Revol }
1622c9bd703SFrançois Revol #endif
1632c9bd703SFrançois Revol if (i >= 0) {
1642c9bd703SFrançois Revol PRINT((CH ": EOF[%d] at offset %d" CT, which, i));
1652c9bd703SFrançois Revol end = i;
1662c9bd703SFrançois Revol detach = true;
1672c9bd703SFrançois Revol }
1682c9bd703SFrançois Revol PRINT((CH ": writing %d bytes" CT, end));
1692c9bd703SFrançois Revol if (end <= bufsize)
1702c9bd703SFrançois Revol fCurrentFrame->Write(buf, end);
171628ddb27SFranck LeCodeur off_t currentPosition = fCurrentFrame->Position();
172628ddb27SFranck LeCodeur if (currentPosition > 0
173628ddb27SFranck LeCodeur && (size_t)currentPosition > fMaxFrameSize) {
1742c9bd703SFrançois Revol fCurrentFrame->SetSize(fMaxFrameSize);
1752c9bd703SFrançois Revol detach = true;
1762c9bd703SFrançois Revol }
1772c9bd703SFrançois Revol if (detach) {
1782c9bd703SFrançois Revol BAutolock f(fLocker);
179edb48467SMurai Takashi PRINT((CH ": Detaching a frame "
180edb48467SMurai Takashi "(%" B_PRIuSIZE " bytes, end = %d, )" CT,
181edb48467SMurai Takashi (size_t)fCurrentFrame->Position(), end));
1822c9bd703SFrançois Revol fCurrentFrame->Seek(0LL, SEEK_SET);
1832c9bd703SFrançois Revol if (discard) {
1842c9bd703SFrançois Revol delete fCurrentFrame;
1852c9bd703SFrançois Revol } else {
1862c9bd703SFrançois Revol fFrames.AddItem(fCurrentFrame);
1872c9bd703SFrançois Revol release_sem(fFrameSem);
1882c9bd703SFrançois Revol }
1892c9bd703SFrançois Revol fCurrentFrame = NULL;
1902c9bd703SFrançois Revol if (fFrames.CountItems() < MAXFRAMEBUF) {
1912c9bd703SFrançois Revol fCurrentFrame = AllocFrame();
1922c9bd703SFrançois Revol }
1932c9bd703SFrançois Revol fState = ST_SYNC;
1942c9bd703SFrançois Revol }
1952c9bd703SFrançois Revol }
1962c9bd703SFrançois Revol
1972c9bd703SFrançois Revol
1982c9bd703SFrançois Revol
1992c9bd703SFrançois Revol
2002c9bd703SFrançois Revol // put the remainder in input buff, discarding old data
2012c9bd703SFrançois Revol #if 0
2022c9bd703SFrançois Revol fInputBuff.Seek(0LL, SEEK_SET);
2032c9bd703SFrançois Revol if (bufsize - end > 0)
2042c9bd703SFrançois Revol fInputBuff.Write(buf+end, bufsize - end);
2052c9bd703SFrançois Revol #endif
2062c9bd703SFrançois Revol BMallocIO m;
2072c9bd703SFrançois Revol m.Write(buf+end, bufsize - end);
2082c9bd703SFrançois Revol fInputBuff.Seek(0LL, SEEK_SET);
2092c9bd703SFrançois Revol if (bufsize - end > 0)
2102c9bd703SFrançois Revol fInputBuff.Write(m.Buffer(), bufsize - end);
2112c9bd703SFrançois Revol fInputBuff.SetSize(bufsize - end);
2122c9bd703SFrançois Revol return size;
2132c9bd703SFrançois Revol }
214