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