12c9bd703SFrançois Revol /* 22c9bd703SFrançois Revol * stream based deframer 32c9bd703SFrançois Revol * has a state machine and handles each packet separately. 42c9bd703SFrançois Revol * much more complex than the buffering one, and I thought it didn't work, 52c9bd703SFrançois Revol * but since I fixed the rest it seems to be working even better without 62c9bd703SFrançois Revol * taking the cpu over like the other one. 72c9bd703SFrançois Revol */ 82c9bd703SFrançois Revol 92c9bd703SFrançois Revol #define CD_COL "31" 102c9bd703SFrançois Revol #include "CamStreamingDeframer.h" 112c9bd703SFrançois Revol #include "CamDevice.h" 122c9bd703SFrançois Revol #include "CamDebug.h" 132c9bd703SFrançois Revol #include <Autolock.h> 142c9bd703SFrançois Revol #define MAX_TAG_LEN CAMDEFRAMER_MAX_TAG_LEN 152c9bd703SFrançois Revol #define MAXFRAMEBUF CAMDEFRAMER_MAX_QUEUED_FRAMES 162c9bd703SFrançois Revol 172c9bd703SFrançois Revol CamStreamingDeframer::CamStreamingDeframer(CamDevice *device) 182c9bd703SFrançois Revol : CamDeframer(device) 192c9bd703SFrançois Revol { 202c9bd703SFrançois Revol } 212c9bd703SFrançois Revol 222c9bd703SFrançois Revol CamStreamingDeframer::~CamStreamingDeframer() 232c9bd703SFrançois Revol { 242c9bd703SFrançois Revol } 252c9bd703SFrançois Revol 262c9bd703SFrançois Revol ssize_t 272c9bd703SFrançois Revol CamStreamingDeframer::Write(const void *buffer, size_t size) 282c9bd703SFrançois Revol { 292c9bd703SFrançois Revol int i = -1; 302c9bd703SFrançois Revol int j; 312c9bd703SFrançois Revol int end = size; 322c9bd703SFrançois Revol int which; 332c9bd703SFrançois Revol const uint8 *buf = (const uint8 *)buffer; 342c9bd703SFrançois Revol int bufsize = size; 352c9bd703SFrançois Revol bool detach = false; 362c9bd703SFrançois Revol bool discard = false; 377f2c1e80SFranç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())); 382c9bd703SFrançois Revol if (!fCurrentFrame) { 392c9bd703SFrançois Revol BAutolock l(fLocker); 402c9bd703SFrançois Revol if (fFrames.CountItems() < MAXFRAMEBUF) 412c9bd703SFrançois Revol fCurrentFrame = AllocFrame(); 422c9bd703SFrançois Revol else { 432c9bd703SFrançois Revol PRINT((CH "DROPPED %d bytes! (too many queued frames)" CT, size)); 442c9bd703SFrançois Revol return size; // drop XXX 452c9bd703SFrançois Revol } 462c9bd703SFrançois Revol } 472c9bd703SFrançois Revol 482c9bd703SFrançois Revol // update in case resolution changed 492c9bd703SFrançois Revol fMinFrameSize = fDevice->MinRawFrameSize(); 502c9bd703SFrançois Revol fMaxFrameSize = fDevice->MaxRawFrameSize(); 512c9bd703SFrançois Revol 522c9bd703SFrançois Revol if (fInputBuff.Position()) { 532c9bd703SFrançois Revol // residual data ? append to it 542c9bd703SFrançois Revol fInputBuff.Write(buffer, size); 552c9bd703SFrançois Revol // and use it as input buf 562c9bd703SFrançois Revol buf = (uint8 *)fInputBuff.Buffer(); 572c9bd703SFrançois Revol bufsize = fInputBuff.BufferLength(); 582c9bd703SFrançois Revol end = bufsize; 592c9bd703SFrançois Revol } 602c9bd703SFrançois Revol // whole buffer belongs to a frame, simple 612c9bd703SFrançois Revol if ((fState == ST_FRAME) && (fCurrentFrame->Position() + bufsize < fMinFrameSize)) { 622c9bd703SFrançois Revol // no residual data, and 632c9bd703SFrançois Revol fCurrentFrame->Write(buf, bufsize); 642c9bd703SFrançois Revol fInputBuff.Seek(0LL, SEEK_SET); 652c9bd703SFrançois Revol fInputBuff.SetSize(0); 662c9bd703SFrançois Revol return size; 672c9bd703SFrançois Revol } 682c9bd703SFrançois Revol 692c9bd703SFrançois Revol // waiting for a frame... 702c9bd703SFrançois Revol if (fState == ST_SYNC) { 712c9bd703SFrançois Revol i = 0; 722c9bd703SFrançois Revol while ((j = FindSOF(buf+i, bufsize-i, &which)) > -1) { 732c9bd703SFrançois Revol i += j; 742c9bd703SFrançois Revol if (fDevice->ValidateStartOfFrameTag(buf+i, fSkipSOFTags)) 752c9bd703SFrançois Revol break; 762c9bd703SFrançois Revol i++; 772c9bd703SFrançois Revol } 782c9bd703SFrançois Revol // got one 792c9bd703SFrançois Revol if (j >= 0) { 802c9bd703SFrançois Revol PRINT((CH ": SOF[%d] at offset %d" CT, which, i)); 812c9bd703SFranç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])); 822c9bd703SFrançois Revol int start = i + fSkipSOFTags; 832c9bd703SFrançois Revol buf += start; 842c9bd703SFrançois Revol bufsize -= start; 852c9bd703SFrançois Revol end = bufsize; 862c9bd703SFrançois Revol fState = ST_FRAME; 872c9bd703SFrançois Revol } 882c9bd703SFrançois Revol } 892c9bd703SFrançois Revol 902c9bd703SFrançois Revol // check for end of frame 912c9bd703SFrançois Revol if (fState == ST_FRAME) { 922c9bd703SFrançois Revol #if 0 932c9bd703SFrançois Revol int j, k; 942c9bd703SFrançois Revol i = -1; 952c9bd703SFrançois Revol k = 0; 962c9bd703SFrançois Revol while ((j = FindEOF(buf + k, bufsize - k, &which)) > -1) { 972c9bd703SFrançois Revol k += j; 982c9bd703SFrançois Revol //PRINT((CH "| EOF[%d] at offset %d; pos %Ld" CT, which, k, fCurrentFrame->Position())); 992c9bd703SFrançois Revol if (fCurrentFrame->Position()+k >= fMinFrameSize) { 1002c9bd703SFrançois Revol i = k; 1012c9bd703SFrançois Revol break; 1022c9bd703SFrançois Revol } 1032c9bd703SFrançois Revol k++; 1042c9bd703SFrançois Revol if (k >= bufsize) 1052c9bd703SFrançois Revol break; 1062c9bd703SFrançois Revol } 1072c9bd703SFrançois Revol #endif 1082c9bd703SFrançois Revol #if 1 1092c9bd703SFrançois Revol i = 0; 1102c9bd703SFrançois Revol if (fCurrentFrame->Position() < fMinFrameSize) { 1112c9bd703SFrançois Revol if (fCurrentFrame->Position() + bufsize >= fMinFrameSize) 1122c9bd703SFrançois Revol i = (fMinFrameSize - (size_t)fCurrentFrame->Position()); 1132c9bd703SFrançois Revol else 1142c9bd703SFrançois Revol i = bufsize; 1152c9bd703SFrançois Revol } 1162c9bd703SFrançois Revol PRINT((CH ": checking for EOF; bufsize=%d i=%d" CT, bufsize, i)); 1172c9bd703SFrançois Revol 118*e53032e5SFrançois Revol if (i + (int)fSkipEOFTags > bufsize) { // not enough room to check for EOF, leave it for next time 1192c9bd703SFrançois Revol end = i; 1202c9bd703SFrançois Revol i = -1; // don't detach yet 1212c9bd703SFrançois Revol } else { 1222c9bd703SFranç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])); 1232c9bd703SFrançois Revol while ((j = FindEOF(buf + i, bufsize - i, &which)) > -1) { 1242c9bd703SFrançois Revol i += j; 1252c9bd703SFrançois Revol PRINT((CH "| EOF[%d] at offset %d; pos %Ld" CT, which, i, fCurrentFrame->Position())); 1262c9bd703SFrançois Revol if (fCurrentFrame->Position()+i >= fMaxFrameSize) { 1272c9bd703SFrançois Revol // too big: discard 1282c9bd703SFrançois Revol //i = -1; 1292c9bd703SFrançois Revol discard = true; 1302c9bd703SFrançois Revol break; 1312c9bd703SFrançois Revol } 1322c9bd703SFrançois Revol if (fDevice->ValidateEndOfFrameTag(buf+i, fSkipEOFTags, fCurrentFrame->Position()+i)) 1332c9bd703SFrançois Revol break; 1342c9bd703SFrançois Revol i++; 1352c9bd703SFrançois Revol if (i >= bufsize) { 1362c9bd703SFrançois Revol i = -1; 1372c9bd703SFrançois Revol break; 1382c9bd703SFrançois Revol } 1392c9bd703SFrançois Revol } 1402c9bd703SFrançois Revol if (j < 0) 1412c9bd703SFrançois Revol i = -1; 1422c9bd703SFrançois Revol } 1432c9bd703SFrançois Revol #endif 1442c9bd703SFrançois Revol if (i >= 0) { 1452c9bd703SFrançois Revol PRINT((CH ": EOF[%d] at offset %d" CT, which, i)); 1462c9bd703SFrançois Revol end = i; 1472c9bd703SFrançois Revol detach = true; 1482c9bd703SFrançois Revol } 1492c9bd703SFrançois Revol PRINT((CH ": writing %d bytes" CT, end)); 1502c9bd703SFrançois Revol if (end <= bufsize) 1512c9bd703SFrançois Revol fCurrentFrame->Write(buf, end); 1522c9bd703SFrançois Revol if (fCurrentFrame->Position() > fMaxFrameSize) { 1532c9bd703SFrançois Revol fCurrentFrame->SetSize(fMaxFrameSize); 1542c9bd703SFrançois Revol detach = true; 1552c9bd703SFrançois Revol } 1562c9bd703SFrançois Revol if (detach) { 1572c9bd703SFrançois Revol BAutolock f(fLocker); 1582c9bd703SFrançois Revol PRINT((CH ": Detaching a frame (%d bytes, end = %d, )" CT, (size_t)fCurrentFrame->Position(), end)); 1592c9bd703SFrançois Revol fCurrentFrame->Seek(0LL, SEEK_SET); 1602c9bd703SFrançois Revol if (discard) { 1612c9bd703SFrançois Revol delete fCurrentFrame; 1622c9bd703SFrançois Revol } else { 1632c9bd703SFrançois Revol fFrames.AddItem(fCurrentFrame); 1642c9bd703SFrançois Revol release_sem(fFrameSem); 1652c9bd703SFrançois Revol } 1662c9bd703SFrançois Revol fCurrentFrame = NULL; 1672c9bd703SFrançois Revol if (fFrames.CountItems() < MAXFRAMEBUF) { 1682c9bd703SFrançois Revol fCurrentFrame = AllocFrame(); 1692c9bd703SFrançois Revol } 1702c9bd703SFrançois Revol fState = ST_SYNC; 1712c9bd703SFrançois Revol } 1722c9bd703SFrançois Revol } 1732c9bd703SFrançois Revol 1742c9bd703SFrançois Revol 1752c9bd703SFrançois Revol 1762c9bd703SFrançois Revol 1772c9bd703SFrançois Revol // put the remainder in input buff, discarding old data 1782c9bd703SFrançois Revol #if 0 1792c9bd703SFrançois Revol fInputBuff.Seek(0LL, SEEK_SET); 1802c9bd703SFrançois Revol if (bufsize - end > 0) 1812c9bd703SFrançois Revol fInputBuff.Write(buf+end, bufsize - end); 1822c9bd703SFrançois Revol #endif 1832c9bd703SFrançois Revol BMallocIO m; 1842c9bd703SFrançois Revol m.Write(buf+end, bufsize - end); 1852c9bd703SFrançois Revol fInputBuff.Seek(0LL, SEEK_SET); 1862c9bd703SFrançois Revol if (bufsize - end > 0) 1872c9bd703SFrançois Revol fInputBuff.Write(m.Buffer(), bufsize - end); 1882c9bd703SFrançois Revol fInputBuff.SetSize(bufsize - end); 1892c9bd703SFrançois Revol return size; 1902c9bd703SFrançois Revol } 1912c9bd703SFrançois Revol 192