1/*
2 * Copyright 2004-2008, Fran��ois Revol, <revol@free.fr>.
3 * Distributed under the terms of the MIT License.
4 */
5
6/*
7 * buffer based deframer
8 * buffers all packet until it finds a complete frame.
9 * simpler than StreamingDeframer, but doesn't work any better
10 * and hogs the cpu intermitently :^)
11 */
12
13#define CD_COL "31"
14#include "CamBufferingDeframer.h"
15#include "CamDevice.h"
16#include "CamDebug.h"
17#include <Autolock.h>
18#define MAX_TAG_LEN CAMDEFRAMER_MAX_TAG_LEN
19#define MAXFRAMEBUF CAMDEFRAMER_MAX_QUEUED_FRAMES
20
21#define IB fInputBuffs[fInputBuffIndex]
22
23
24CamBufferingDeframer::CamBufferingDeframer(CamDevice *device)
25	: CamDeframer(device),
26	fInputBuffIndex(0)
27{
28}
29
30
31CamBufferingDeframer::~CamBufferingDeframer()
32{
33}
34
35
36ssize_t
37CamBufferingDeframer::Write(const void *buffer, size_t size)
38{
39	uint8 *b;
40	int l;
41	int i, s, e;
42	int which;
43	fMinFrameSize = fDevice->MinRawFrameSize();
44	fMaxFrameSize = fDevice->MaxRawFrameSize();
45	IB.Write(buffer, size);
46	b = (uint8 *)IB.Buffer();
47	l = IB.BufferLength();
48
49	PRINT((CH "(%p, %" B_PRIuSIZE "), IB: %" B_PRIuSIZE CT, buffer, size,
50		IB.BufferLength()));
51
52	if (l < (int)(fMinFrameSize + fSkipSOFTags + fSkipEOFTags))
53		return size; // not enough data anyway
54
55	if (!fCurrentFrame) {
56		BAutolock l(fLocker);
57		if (fFrames.CountItems() < MAXFRAMEBUF)
58			fCurrentFrame = AllocFrame();
59		else {
60			PRINT((CH "DROPPED %" B_PRIuSIZE " bytes! "
61				"(too many queued frames)" CT, size));
62			return size; // drop XXX
63		}
64	}
65
66	for (s = 0; (l - s > (int)fMinFrameSize) && ((i = FindSOF(b + s, l - fMinFrameSize - s, &which)) > -1); s++) {
67		s += i;
68		if ((int)(s + fSkipSOFTags + fMinFrameSize + fSkipEOFTags) > l)
69			break;
70		if (!fDevice->ValidateStartOfFrameTag(b + s, fSkipSOFTags))
71			continue;
72
73		PRINT((CH ": SOF[%d] at offset %d" CT, which, s));
74		PRINT((CH ": SOF: ... %02x %02x %02x %02x %02x %02x" CT, b[s+6], b[s+7], b[s+8], b[s+9], b[s+10], b[s+11]));
75
76		for (e = s + fSkipSOFTags + fMinFrameSize;
77			 ((e <= (int)(s + fSkipSOFTags + fMaxFrameSize)) &&
78			  (e < l) && ((i = 0*FindEOF(b + e, l - e, &which)) > -1));
79			 e++) {
80			e += i;
81
82			//PRINT((CH ": EOF[%d] at offset %d" CT, which, s));
83			if (!fDevice->ValidateEndOfFrameTag(b + e, fSkipEOFTags, e - s - fSkipSOFTags))
84				continue;
85
86
87
88		PRINT((CH ": SOF= ... %02x %02x %02x %02x %02x %02x" CT, b[s+6], b[s+7], b[s+8], b[s+9], b[s+10], b[s+11]));
89
90			// we have one!
91			s += fSkipSOFTags;
92
93			// fill it
94			fCurrentFrame->Write(b + s, e - s);
95
96			// queue it
97			BAutolock f(fLocker);
98			PRINT((CH ": Detaching a frame (%" B_PRIuSIZE " bytes, "
99				"%d to %d / %d)" CT, (size_t)fCurrentFrame->Position(),
100				s, e, l));
101			fCurrentFrame->Seek(0LL, SEEK_SET);
102			fFrames.AddItem(fCurrentFrame);
103			release_sem(fFrameSem);
104			// next Write() will allocate a new one
105			fCurrentFrame = NULL;
106			// discard the frame and everything before it.
107			DiscardFromInput(e + fSkipEOFTags);
108
109			return size;
110		}
111	}
112	return size;
113}
114
115
116size_t
117CamBufferingDeframer::DiscardFromInput(size_t size)
118{
119	int next = (fInputBuffIndex+1)%2;
120	PRINT((CH ": %" B_PRIuSIZE " bytes of %" B_PRIuSIZE " from buffs[%d] "
121		"(%" B_PRIuSIZE " left)" CT,
122		size, IB.BufferLength(), fInputBuffIndex, IB.BufferLength() - size));
123	fInputBuffs[next].Seek(0LL, SEEK_SET);
124	fInputBuffs[next].SetSize(0);
125	uint8 *buff = (uint8 *)IB.Buffer();
126	if (IB.BufferLength() > size) {
127		buff += size;
128		fInputBuffs[next].Write(buff, IB.BufferLength() - size);
129	}
130	IB.Seek(0LL, SEEK_SET);
131	IB.SetSize(0);
132	fInputBuffIndex = next;
133	return size;
134}
135