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) && (fCurrentFrame->Position() + bufsize < fMinFrameSize)) { 71 // no residual data, and 72 fCurrentFrame->Write(buf, bufsize); 73 fInputBuff.Seek(0LL, SEEK_SET); 74 fInputBuff.SetSize(0); 75 return size; 76 } 77 78 // waiting for a frame... 79 if (fState == ST_SYNC) { 80 i = 0; 81 while ((j = FindSOF(buf+i, bufsize-i, &which)) > -1) { 82 i += j; 83 if (fDevice->ValidateStartOfFrameTag(buf+i, fSkipSOFTags)) 84 break; 85 i++; 86 } 87 // got one 88 if (j >= 0) { 89 PRINT((CH ": SOF[%d] at offset %d" CT, which, i)); 90 //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])); 91 int start = i + fSkipSOFTags; 92 buf += start; 93 bufsize -= start; 94 end = bufsize; 95 fState = ST_FRAME; 96 } 97 } 98 99 // check for end of frame 100 if (fState == ST_FRAME) { 101 #if 0 102 int j, k; 103 i = -1; 104 k = 0; 105 while ((j = FindEOF(buf + k, bufsize - k, &which)) > -1) { 106 k += j; 107 //PRINT((CH "| EOF[%d] at offset %d; pos %Ld" CT, which, k, fCurrentFrame->Position())); 108 if (fCurrentFrame->Position()+k >= fMinFrameSize) { 109 i = k; 110 break; 111 } 112 k++; 113 if (k >= bufsize) 114 break; 115 } 116 #endif 117 #if 1 118 i = 0; 119 if (fCurrentFrame->Position() < fMinFrameSize) { 120 if (fCurrentFrame->Position() + bufsize >= fMinFrameSize) 121 i = (fMinFrameSize - (size_t)fCurrentFrame->Position()); 122 else 123 i = bufsize; 124 } 125 PRINT((CH ": checking for EOF; bufsize=%d i=%d" CT, bufsize, i)); 126 127 if (i + (int)fSkipEOFTags > bufsize) { // not enough room to check for EOF, leave it for next time 128 end = i; 129 i = -1; // don't detach yet 130 } else { 131 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])); 132 while ((j = FindEOF(buf + i, bufsize - i, &which)) > -1) { 133 i += j; 134 PRINT((CH "| EOF[%d] at offset %d; pos %" B_PRIdOFF CT, 135 which, i, fCurrentFrame->Position())); 136 if (fCurrentFrame->Position()+i >= fMaxFrameSize) { 137 // too big: discard 138 //i = -1; 139 discard = true; 140 break; 141 } 142 if (fDevice->ValidateEndOfFrameTag(buf+i, fSkipEOFTags, fCurrentFrame->Position()+i)) 143 break; 144 i++; 145 if (i >= bufsize) { 146 i = -1; 147 break; 148 } 149 } 150 if (j < 0) 151 i = -1; 152 } 153 #endif 154 if (i >= 0) { 155 PRINT((CH ": EOF[%d] at offset %d" CT, which, i)); 156 end = i; 157 detach = true; 158 } 159 PRINT((CH ": writing %d bytes" CT, end)); 160 if (end <= bufsize) 161 fCurrentFrame->Write(buf, end); 162 if (fCurrentFrame->Position() > fMaxFrameSize) { 163 fCurrentFrame->SetSize(fMaxFrameSize); 164 detach = true; 165 } 166 if (detach) { 167 BAutolock f(fLocker); 168 PRINT((CH ": Detaching a frame " 169 "(%" B_PRIuSIZE " bytes, end = %d, )" CT, 170 (size_t)fCurrentFrame->Position(), end)); 171 fCurrentFrame->Seek(0LL, SEEK_SET); 172 if (discard) { 173 delete fCurrentFrame; 174 } else { 175 fFrames.AddItem(fCurrentFrame); 176 release_sem(fFrameSem); 177 } 178 fCurrentFrame = NULL; 179 if (fFrames.CountItems() < MAXFRAMEBUF) { 180 fCurrentFrame = AllocFrame(); 181 } 182 fState = ST_SYNC; 183 } 184 } 185 186 187 188 189 // put the remainder in input buff, discarding old data 190 #if 0 191 fInputBuff.Seek(0LL, SEEK_SET); 192 if (bufsize - end > 0) 193 fInputBuff.Write(buf+end, bufsize - end); 194 #endif 195 BMallocIO m; 196 m.Write(buf+end, bufsize - end); 197 fInputBuff.Seek(0LL, SEEK_SET); 198 if (bufsize - end > 0) 199 fInputBuff.Write(m.Buffer(), bufsize - end); 200 fInputBuff.SetSize(bufsize - end); 201 return size; 202 } 203