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