3rdparty/licenseReport: Add seperate LGPL checks
[haiku.git] / src / add-ons / media / media-add-ons / usb_webcam / CamStreamingDeframer.cpp
blobcf3975a639b7e4e8e2366cd161e1a390189447bb
1 /*
2 * Copyright 2004-2008, François Revol, <revol@free.fr>.
3 * Distributed under the terms of the MIT License.
4 */
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.
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
23 CamStreamingDeframer::CamStreamingDeframer(CamDevice *device)
24 : CamDeframer(device)
29 CamStreamingDeframer::~CamStreamingDeframer()
34 ssize_t
35 CamStreamingDeframer::Write(const void *buffer, size_t size)
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
56 // update in case resolution changed
57 fMinFrameSize = fDevice->MinRawFrameSize();
58 fMaxFrameSize = fDevice->MaxRawFrameSize();
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;
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;
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++;
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;
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;
111 k++;
112 if (k >= bufsize)
113 break;
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;
124 PRINT((CH ": checking for EOF; bufsize=%d i=%d" CT, bufsize, i));
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;
140 if (fDevice->ValidateEndOfFrameTag(buf+i, fSkipEOFTags, fCurrentFrame->Position()+i))
141 break;
142 i++;
143 if (i >= bufsize) {
144 i = -1;
145 break;
148 if (j < 0)
149 i = -1;
151 #endif
152 if (i >= 0) {
153 PRINT((CH ": EOF[%d] at offset %d" CT, which, i));
154 end = i;
155 detach = true;
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;
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);
174 fCurrentFrame = NULL;
175 if (fFrames.CountItems() < MAXFRAMEBUF) {
176 fCurrentFrame = AllocFrame();
178 fState = ST_SYNC;
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;