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