xref: /haiku/src/add-ons/media/media-add-ons/usb_webcam/CamBufferingDeframer.cpp (revision edb484677944d3243760cea487fc8c9dbbd032eb)
12c9bd703SFrançois Revol /*
2a1830cbdSFrançois Revol  * Copyright 2004-2008, François Revol, <revol@free.fr>.
3a1830cbdSFrançois Revol  * Distributed under the terms of the MIT License.
4a1830cbdSFrançois Revol  */
5a1830cbdSFrançois Revol 
6a1830cbdSFrançois Revol /*
72c9bd703SFrançois Revol  * buffer based deframer
82c9bd703SFrançois Revol  * buffers all packet until it finds a complete frame.
92c9bd703SFrançois Revol  * simpler than StreamingDeframer, but doesn't work any better
102c9bd703SFrançois Revol  * and hogs the cpu intermitently :^)
112c9bd703SFrançois Revol  */
122c9bd703SFrançois Revol 
132c9bd703SFrançois Revol #define CD_COL "31"
142c9bd703SFrançois Revol #include "CamBufferingDeframer.h"
152c9bd703SFrançois Revol #include "CamDevice.h"
162c9bd703SFrançois Revol #include "CamDebug.h"
172c9bd703SFrançois Revol #include <Autolock.h>
182c9bd703SFrançois Revol #define MAX_TAG_LEN CAMDEFRAMER_MAX_TAG_LEN
192c9bd703SFrançois Revol #define MAXFRAMEBUF CAMDEFRAMER_MAX_QUEUED_FRAMES
202c9bd703SFrançois Revol 
212c9bd703SFrançois Revol #define IB fInputBuffs[fInputBuffIndex]
222c9bd703SFrançois Revol 
2374b3713aSFrançois Revol 
CamBufferingDeframer(CamDevice * device)242c9bd703SFrançois Revol CamBufferingDeframer::CamBufferingDeframer(CamDevice *device)
252c9bd703SFrançois Revol 	: CamDeframer(device),
262c9bd703SFrançois Revol 	fInputBuffIndex(0)
272c9bd703SFrançois Revol {
282c9bd703SFrançois Revol }
292c9bd703SFrançois Revol 
3074b3713aSFrançois Revol 
~CamBufferingDeframer()312c9bd703SFrançois Revol CamBufferingDeframer::~CamBufferingDeframer()
322c9bd703SFrançois Revol {
332c9bd703SFrançois Revol }
342c9bd703SFrançois Revol 
3574b3713aSFrançois Revol 
362c9bd703SFrançois Revol ssize_t
Write(const void * buffer,size_t size)372c9bd703SFrançois Revol CamBufferingDeframer::Write(const void *buffer, size_t size)
382c9bd703SFrançois Revol {
392c9bd703SFrançois Revol 	uint8 *b;
402c9bd703SFrançois Revol 	int l;
412c9bd703SFrançois Revol 	int i, s, e;
422c9bd703SFrançois Revol 	int which;
432c9bd703SFrançois Revol 	fMinFrameSize = fDevice->MinRawFrameSize();
442c9bd703SFrançois Revol 	fMaxFrameSize = fDevice->MaxRawFrameSize();
452c9bd703SFrançois Revol 	IB.Write(buffer, size);
462c9bd703SFrançois Revol 	b = (uint8 *)IB.Buffer();
472c9bd703SFrançois Revol 	l = IB.BufferLength();
482c9bd703SFrançois Revol 
49*edb48467SMurai Takashi 	PRINT((CH "(%p, %" B_PRIuSIZE "), IB: %" B_PRIuSIZE CT, buffer, size,
50*edb48467SMurai Takashi 		IB.BufferLength()));
512c9bd703SFrançois Revol 
52e53032e5SFrançois Revol 	if (l < (int)(fMinFrameSize + fSkipSOFTags + fSkipEOFTags))
532c9bd703SFrançois Revol 		return size; // not enough data anyway
542c9bd703SFrançois Revol 
552c9bd703SFrançois Revol 	if (!fCurrentFrame) {
562c9bd703SFrançois Revol 		BAutolock l(fLocker);
572c9bd703SFrançois Revol 		if (fFrames.CountItems() < MAXFRAMEBUF)
582c9bd703SFrançois Revol 			fCurrentFrame = AllocFrame();
592c9bd703SFrançois Revol 		else {
60*edb48467SMurai Takashi 			PRINT((CH "DROPPED %" B_PRIuSIZE " bytes! "
61*edb48467SMurai Takashi 				"(too many queued frames)" CT, size));
622c9bd703SFrançois Revol 			return size; // drop XXX
632c9bd703SFrançois Revol 		}
642c9bd703SFrançois Revol 	}
652c9bd703SFrançois Revol 
66e53032e5SFrançois Revol 	for (s = 0; (l - s > (int)fMinFrameSize) && ((i = FindSOF(b + s, l - fMinFrameSize - s, &which)) > -1); s++) {
672c9bd703SFrançois Revol 		s += i;
68e53032e5SFrançois Revol 		if ((int)(s + fSkipSOFTags + fMinFrameSize + fSkipEOFTags) > l)
692c9bd703SFrançois Revol 			break;
702c9bd703SFrançois Revol 		if (!fDevice->ValidateStartOfFrameTag(b + s, fSkipSOFTags))
712c9bd703SFrançois Revol 			continue;
722c9bd703SFrançois Revol 
732c9bd703SFrançois Revol 		PRINT((CH ": SOF[%d] at offset %d" CT, which, s));
742c9bd703SFranç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]));
752c9bd703SFrançois Revol 
762c9bd703SFrançois Revol 		for (e = s + fSkipSOFTags + fMinFrameSize;
77e53032e5SFrançois Revol 			 ((e <= (int)(s + fSkipSOFTags + fMaxFrameSize)) &&
782c9bd703SFrançois Revol 			  (e < l) && ((i = 0*FindEOF(b + e, l - e, &which)) > -1));
792c9bd703SFrançois Revol 			 e++) {
802c9bd703SFrançois Revol 			e += i;
812c9bd703SFrançois Revol 
822c9bd703SFrançois Revol 			//PRINT((CH ": EOF[%d] at offset %d" CT, which, s));
832c9bd703SFrançois Revol 			if (!fDevice->ValidateEndOfFrameTag(b + e, fSkipEOFTags, e - s - fSkipSOFTags))
842c9bd703SFrançois Revol 				continue;
852c9bd703SFrançois Revol 
862c9bd703SFrançois Revol 
872c9bd703SFrançois Revol 
882c9bd703SFranç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]));
892c9bd703SFrançois Revol 
902c9bd703SFrançois Revol 			// we have one!
912c9bd703SFrançois Revol 			s += fSkipSOFTags;
922c9bd703SFrançois Revol 
932c9bd703SFrançois Revol 			// fill it
942c9bd703SFrançois Revol 			fCurrentFrame->Write(b + s, e - s);
952c9bd703SFrançois Revol 
962c9bd703SFrançois Revol 			// queue it
972c9bd703SFrançois Revol 			BAutolock f(fLocker);
98*edb48467SMurai Takashi 			PRINT((CH ": Detaching a frame (%" B_PRIuSIZE " bytes, "
99*edb48467SMurai Takashi 				"%d to %d / %d)" CT, (size_t)fCurrentFrame->Position(),
100*edb48467SMurai Takashi 				s, e, l));
1012c9bd703SFrançois Revol 			fCurrentFrame->Seek(0LL, SEEK_SET);
1022c9bd703SFrançois Revol 			fFrames.AddItem(fCurrentFrame);
1032c9bd703SFrançois Revol 			release_sem(fFrameSem);
1042c9bd703SFrançois Revol 			// next Write() will allocate a new one
1052c9bd703SFrançois Revol 			fCurrentFrame = NULL;
1062c9bd703SFrançois Revol 			// discard the frame and everything before it.
1072c9bd703SFrançois Revol 			DiscardFromInput(e + fSkipEOFTags);
1082c9bd703SFrançois Revol 
1092c9bd703SFrançois Revol 			return size;
1102c9bd703SFrançois Revol 		}
1112c9bd703SFrançois Revol 	}
1122c9bd703SFrançois Revol 	return size;
1132c9bd703SFrançois Revol }
1142c9bd703SFrançois Revol 
11574b3713aSFrançois Revol 
1162c9bd703SFrançois Revol size_t
DiscardFromInput(size_t size)1172c9bd703SFrançois Revol CamBufferingDeframer::DiscardFromInput(size_t size)
1182c9bd703SFrançois Revol {
1192c9bd703SFrançois Revol 	int next = (fInputBuffIndex+1)%2;
120*edb48467SMurai Takashi 	PRINT((CH ": %" B_PRIuSIZE " bytes of %" B_PRIuSIZE " from buffs[%d] "
121*edb48467SMurai Takashi 		"(%" B_PRIuSIZE " left)" CT,
122*edb48467SMurai Takashi 		size, IB.BufferLength(), fInputBuffIndex, IB.BufferLength() - size));
1232c9bd703SFrançois Revol 	fInputBuffs[next].Seek(0LL, SEEK_SET);
1242c9bd703SFrançois Revol 	fInputBuffs[next].SetSize(0);
1252c9bd703SFrançois Revol 	uint8 *buff = (uint8 *)IB.Buffer();
1262c9bd703SFrançois Revol 	if (IB.BufferLength() > size) {
1272c9bd703SFrançois Revol 		buff += size;
1282c9bd703SFrançois Revol 		fInputBuffs[next].Write(buff, IB.BufferLength() - size);
1292c9bd703SFrançois Revol 	}
1302c9bd703SFrançois Revol 	IB.Seek(0LL, SEEK_SET);
1312c9bd703SFrançois Revol 	IB.SetSize(0);
1322c9bd703SFrançois Revol 	fInputBuffIndex = next;
133e53032e5SFrançois Revol 	return size;
1342c9bd703SFrançois Revol }
135