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