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