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
23CamStreamingDeframer::CamStreamingDeframer(CamDevice *device)
24	: CamDeframer(device)
25{
26}
27
28
29CamStreamingDeframer::~CamStreamingDeframer()
30{
31}
32
33
34ssize_t
35CamStreamingDeframer::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