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