1*2c9bd703SFrançois Revol /* 2*2c9bd703SFrançois Revol * stream based deframer 3*2c9bd703SFrançois Revol * has a state machine and handles each packet separately. 4*2c9bd703SFrançois Revol * much more complex than the buffering one, and I thought it didn't work, 5*2c9bd703SFrançois Revol * but since I fixed the rest it seems to be working even better without 6*2c9bd703SFrançois Revol * taking the cpu over like the other one. 7*2c9bd703SFrançois Revol */ 8*2c9bd703SFrançois Revol 9*2c9bd703SFrançois Revol #define CD_COL "31" 10*2c9bd703SFrançois Revol #include "CamStreamingDeframer.h" 11*2c9bd703SFrançois Revol #include "CamDevice.h" 12*2c9bd703SFrançois Revol #include "CamDebug.h" 13*2c9bd703SFrançois Revol #include <Autolock.h> 14*2c9bd703SFrançois Revol #define MAX_TAG_LEN CAMDEFRAMER_MAX_TAG_LEN 15*2c9bd703SFrançois Revol #define MAXFRAMEBUF CAMDEFRAMER_MAX_QUEUED_FRAMES 16*2c9bd703SFrançois Revol 17*2c9bd703SFrançois Revol CamStreamingDeframer::CamStreamingDeframer(CamDevice *device) 18*2c9bd703SFrançois Revol : CamDeframer(device) 19*2c9bd703SFrançois Revol { 20*2c9bd703SFrançois Revol } 21*2c9bd703SFrançois Revol 22*2c9bd703SFrançois Revol CamStreamingDeframer::~CamStreamingDeframer() 23*2c9bd703SFrançois Revol { 24*2c9bd703SFrançois Revol } 25*2c9bd703SFrançois Revol 26*2c9bd703SFrançois Revol ssize_t 27*2c9bd703SFrançois Revol CamStreamingDeframer::Write(const void *buffer, size_t size) 28*2c9bd703SFrançois Revol { 29*2c9bd703SFrançois Revol int i = -1; 30*2c9bd703SFrançois Revol int j; 31*2c9bd703SFrançois Revol int end = size; 32*2c9bd703SFrançois Revol int which; 33*2c9bd703SFrançois Revol const uint8 *buf = (const uint8 *)buffer; 34*2c9bd703SFrançois Revol int bufsize = size; 35*2c9bd703SFrançois Revol bool detach = false; 36*2c9bd703SFrançois Revol bool discard = false; 37*2c9bd703SFrançois Revol PRINT((CH "(%p, %d); state=%s framesz=%u queued=%u" CT, buffer, size, (fState==ST_SYNC)?"sync":"frame", (size_t)fCurrentFrame->Position(), (size_t)fInputBuff.Position())); 38*2c9bd703SFrançois Revol if (!fCurrentFrame) { 39*2c9bd703SFrançois Revol BAutolock l(fLocker); 40*2c9bd703SFrançois Revol if (fFrames.CountItems() < MAXFRAMEBUF) 41*2c9bd703SFrançois Revol fCurrentFrame = AllocFrame(); 42*2c9bd703SFrançois Revol else { 43*2c9bd703SFrançois Revol PRINT((CH "DROPPED %d bytes! (too many queued frames)" CT, size)); 44*2c9bd703SFrançois Revol return size; // drop XXX 45*2c9bd703SFrançois Revol } 46*2c9bd703SFrançois Revol } 47*2c9bd703SFrançois Revol 48*2c9bd703SFrançois Revol // update in case resolution changed 49*2c9bd703SFrançois Revol fMinFrameSize = fDevice->MinRawFrameSize(); 50*2c9bd703SFrançois Revol fMaxFrameSize = fDevice->MaxRawFrameSize(); 51*2c9bd703SFrançois Revol 52*2c9bd703SFrançois Revol if (fInputBuff.Position()) { 53*2c9bd703SFrançois Revol // residual data ? append to it 54*2c9bd703SFrançois Revol fInputBuff.Write(buffer, size); 55*2c9bd703SFrançois Revol // and use it as input buf 56*2c9bd703SFrançois Revol buf = (uint8 *)fInputBuff.Buffer(); 57*2c9bd703SFrançois Revol bufsize = fInputBuff.BufferLength(); 58*2c9bd703SFrançois Revol end = bufsize; 59*2c9bd703SFrançois Revol } 60*2c9bd703SFrançois Revol // whole buffer belongs to a frame, simple 61*2c9bd703SFrançois Revol if ((fState == ST_FRAME) && (fCurrentFrame->Position() + bufsize < fMinFrameSize)) { 62*2c9bd703SFrançois Revol // no residual data, and 63*2c9bd703SFrançois Revol fCurrentFrame->Write(buf, bufsize); 64*2c9bd703SFrançois Revol fInputBuff.Seek(0LL, SEEK_SET); 65*2c9bd703SFrançois Revol fInputBuff.SetSize(0); 66*2c9bd703SFrançois Revol return size; 67*2c9bd703SFrançois Revol } 68*2c9bd703SFrançois Revol 69*2c9bd703SFrançois Revol // waiting for a frame... 70*2c9bd703SFrançois Revol if (fState == ST_SYNC) { 71*2c9bd703SFrançois Revol i = 0; 72*2c9bd703SFrançois Revol while ((j = FindSOF(buf+i, bufsize-i, &which)) > -1) { 73*2c9bd703SFrançois Revol i += j; 74*2c9bd703SFrançois Revol if (fDevice->ValidateStartOfFrameTag(buf+i, fSkipSOFTags)) 75*2c9bd703SFrançois Revol break; 76*2c9bd703SFrançois Revol i++; 77*2c9bd703SFrançois Revol } 78*2c9bd703SFrançois Revol // got one 79*2c9bd703SFrançois Revol if (j >= 0) { 80*2c9bd703SFrançois Revol PRINT((CH ": SOF[%d] at offset %d" CT, which, i)); 81*2c9bd703SFranç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])); 82*2c9bd703SFrançois Revol int start = i + fSkipSOFTags; 83*2c9bd703SFrançois Revol buf += start; 84*2c9bd703SFrançois Revol bufsize -= start; 85*2c9bd703SFrançois Revol end = bufsize; 86*2c9bd703SFrançois Revol fState = ST_FRAME; 87*2c9bd703SFrançois Revol } 88*2c9bd703SFrançois Revol } 89*2c9bd703SFrançois Revol 90*2c9bd703SFrançois Revol // check for end of frame 91*2c9bd703SFrançois Revol if (fState == ST_FRAME) { 92*2c9bd703SFrançois Revol #if 0 93*2c9bd703SFrançois Revol int j, k; 94*2c9bd703SFrançois Revol i = -1; 95*2c9bd703SFrançois Revol k = 0; 96*2c9bd703SFrançois Revol while ((j = FindEOF(buf + k, bufsize - k, &which)) > -1) { 97*2c9bd703SFrançois Revol k += j; 98*2c9bd703SFrançois Revol //PRINT((CH "| EOF[%d] at offset %d; pos %Ld" CT, which, k, fCurrentFrame->Position())); 99*2c9bd703SFrançois Revol if (fCurrentFrame->Position()+k >= fMinFrameSize) { 100*2c9bd703SFrançois Revol i = k; 101*2c9bd703SFrançois Revol break; 102*2c9bd703SFrançois Revol } 103*2c9bd703SFrançois Revol k++; 104*2c9bd703SFrançois Revol if (k >= bufsize) 105*2c9bd703SFrançois Revol break; 106*2c9bd703SFrançois Revol } 107*2c9bd703SFrançois Revol #endif 108*2c9bd703SFrançois Revol #if 1 109*2c9bd703SFrançois Revol i = 0; 110*2c9bd703SFrançois Revol if (fCurrentFrame->Position() < fMinFrameSize) { 111*2c9bd703SFrançois Revol if (fCurrentFrame->Position() + bufsize >= fMinFrameSize) 112*2c9bd703SFrançois Revol i = (fMinFrameSize - (size_t)fCurrentFrame->Position()); 113*2c9bd703SFrançois Revol else 114*2c9bd703SFrançois Revol i = bufsize; 115*2c9bd703SFrançois Revol } 116*2c9bd703SFrançois Revol PRINT((CH ": checking for EOF; bufsize=%d i=%d" CT, bufsize, i)); 117*2c9bd703SFrançois Revol 118*2c9bd703SFrançois Revol if (i + fSkipEOFTags > bufsize) { // not enough room to check for EOF, leave it for next time 119*2c9bd703SFrançois Revol end = i; 120*2c9bd703SFrançois Revol i = -1; // don't detach yet 121*2c9bd703SFrançois Revol } else { 122*2c9bd703SFranç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])); 123*2c9bd703SFrançois Revol while ((j = FindEOF(buf + i, bufsize - i, &which)) > -1) { 124*2c9bd703SFrançois Revol i += j; 125*2c9bd703SFrançois Revol PRINT((CH "| EOF[%d] at offset %d; pos %Ld" CT, which, i, fCurrentFrame->Position())); 126*2c9bd703SFrançois Revol if (fCurrentFrame->Position()+i >= fMaxFrameSize) { 127*2c9bd703SFrançois Revol // too big: discard 128*2c9bd703SFrançois Revol //i = -1; 129*2c9bd703SFrançois Revol discard = true; 130*2c9bd703SFrançois Revol break; 131*2c9bd703SFrançois Revol } 132*2c9bd703SFrançois Revol if (fDevice->ValidateEndOfFrameTag(buf+i, fSkipEOFTags, fCurrentFrame->Position()+i)) 133*2c9bd703SFrançois Revol break; 134*2c9bd703SFrançois Revol i++; 135*2c9bd703SFrançois Revol if (i >= bufsize) { 136*2c9bd703SFrançois Revol i = -1; 137*2c9bd703SFrançois Revol break; 138*2c9bd703SFrançois Revol } 139*2c9bd703SFrançois Revol } 140*2c9bd703SFrançois Revol if (j < 0) 141*2c9bd703SFrançois Revol i = -1; 142*2c9bd703SFrançois Revol } 143*2c9bd703SFrançois Revol #endif 144*2c9bd703SFrançois Revol if (i >= 0) { 145*2c9bd703SFrançois Revol PRINT((CH ": EOF[%d] at offset %d" CT, which, i)); 146*2c9bd703SFrançois Revol end = i; 147*2c9bd703SFrançois Revol detach = true; 148*2c9bd703SFrançois Revol } 149*2c9bd703SFrançois Revol PRINT((CH ": writing %d bytes" CT, end)); 150*2c9bd703SFrançois Revol if (end <= bufsize) 151*2c9bd703SFrançois Revol fCurrentFrame->Write(buf, end); 152*2c9bd703SFrançois Revol if (fCurrentFrame->Position() > fMaxFrameSize) { 153*2c9bd703SFrançois Revol fCurrentFrame->SetSize(fMaxFrameSize); 154*2c9bd703SFrançois Revol detach = true; 155*2c9bd703SFrançois Revol } 156*2c9bd703SFrançois Revol if (detach) { 157*2c9bd703SFrançois Revol BAutolock f(fLocker); 158*2c9bd703SFrançois Revol PRINT((CH ": Detaching a frame (%d bytes, end = %d, )" CT, (size_t)fCurrentFrame->Position(), end)); 159*2c9bd703SFrançois Revol fCurrentFrame->Seek(0LL, SEEK_SET); 160*2c9bd703SFrançois Revol if (discard) { 161*2c9bd703SFrançois Revol delete fCurrentFrame; 162*2c9bd703SFrançois Revol } else { 163*2c9bd703SFrançois Revol fFrames.AddItem(fCurrentFrame); 164*2c9bd703SFrançois Revol release_sem(fFrameSem); 165*2c9bd703SFrançois Revol } 166*2c9bd703SFrançois Revol fCurrentFrame = NULL; 167*2c9bd703SFrançois Revol if (fFrames.CountItems() < MAXFRAMEBUF) { 168*2c9bd703SFrançois Revol fCurrentFrame = AllocFrame(); 169*2c9bd703SFrançois Revol } 170*2c9bd703SFrançois Revol fState = ST_SYNC; 171*2c9bd703SFrançois Revol } 172*2c9bd703SFrançois Revol } 173*2c9bd703SFrançois Revol 174*2c9bd703SFrançois Revol 175*2c9bd703SFrançois Revol 176*2c9bd703SFrançois Revol 177*2c9bd703SFrançois Revol // put the remainder in input buff, discarding old data 178*2c9bd703SFrançois Revol #if 0 179*2c9bd703SFrançois Revol fInputBuff.Seek(0LL, SEEK_SET); 180*2c9bd703SFrançois Revol if (bufsize - end > 0) 181*2c9bd703SFrançois Revol fInputBuff.Write(buf+end, bufsize - end); 182*2c9bd703SFrançois Revol #endif 183*2c9bd703SFrançois Revol BMallocIO m; 184*2c9bd703SFrançois Revol m.Write(buf+end, bufsize - end); 185*2c9bd703SFrançois Revol fInputBuff.Seek(0LL, SEEK_SET); 186*2c9bd703SFrançois Revol if (bufsize - end > 0) 187*2c9bd703SFrançois Revol fInputBuff.Write(m.Buffer(), bufsize - end); 188*2c9bd703SFrançois Revol fInputBuff.SetSize(bufsize - end); 189*2c9bd703SFrançois Revol return size; 190*2c9bd703SFrançois Revol } 191*2c9bd703SFrançois Revol 192