3rdparty/licenseReport: Add seperate LGPL checks
[haiku.git] / src / add-ons / media / media-add-ons / usb_webcam / CamBufferingDeframer.cpp
blobb2d2ddd84bb3813073662ff6e0e091e43794fe85
1 /*
2 * Copyright 2004-2008, François Revol, <revol@free.fr>.
3 * Distributed under the terms of the MIT License.
4 */
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 :^)
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
21 #define IB fInputBuffs[fInputBuffIndex]
24 CamBufferingDeframer::CamBufferingDeframer(CamDevice *device)
25 : CamDeframer(device),
26 fInputBuffIndex(0)
31 CamBufferingDeframer::~CamBufferingDeframer()
36 ssize_t
37 CamBufferingDeframer::Write(const void *buffer, size_t size)
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();
49 PRINT((CH "(%p, %d), IB: %d" CT, buffer, size, IB.BufferLength()));
51 if (l < (int)(fMinFrameSize + fSkipSOFTags + fSkipEOFTags))
52 return size; // not enough data anyway
54 if (!fCurrentFrame) {
55 BAutolock l(fLocker);
56 if (fFrames.CountItems() < MAXFRAMEBUF)
57 fCurrentFrame = AllocFrame();
58 else {
59 PRINT((CH "DROPPED %d bytes! (too many queued frames)" CT, size));
60 return size; // drop XXX
64 for (s = 0; (l - s > (int)fMinFrameSize) && ((i = FindSOF(b + s, l - fMinFrameSize - s, &which)) > -1); s++) {
65 s += i;
66 if ((int)(s + fSkipSOFTags + fMinFrameSize + fSkipEOFTags) > l)
67 break;
68 if (!fDevice->ValidateStartOfFrameTag(b + s, fSkipSOFTags))
69 continue;
71 PRINT((CH ": SOF[%d] at offset %d" CT, which, s));
72 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]));
74 for (e = s + fSkipSOFTags + fMinFrameSize;
75 ((e <= (int)(s + fSkipSOFTags + fMaxFrameSize)) &&
76 (e < l) && ((i = 0*FindEOF(b + e, l - e, &which)) > -1));
77 e++) {
78 e += i;
80 //PRINT((CH ": EOF[%d] at offset %d" CT, which, s));
81 if (!fDevice->ValidateEndOfFrameTag(b + e, fSkipEOFTags, e - s - fSkipSOFTags))
82 continue;
86 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]));
88 // we have one!
89 s += fSkipSOFTags;
91 // fill it
92 fCurrentFrame->Write(b + s, e - s);
94 // queue it
95 BAutolock f(fLocker);
96 PRINT((CH ": Detaching a frame (%d bytes, %d to %d / %d)" CT, (size_t)fCurrentFrame->Position(), s, e, l));
97 fCurrentFrame->Seek(0LL, SEEK_SET);
98 fFrames.AddItem(fCurrentFrame);
99 release_sem(fFrameSem);
100 // next Write() will allocate a new one
101 fCurrentFrame = NULL;
102 // discard the frame and everything before it.
103 DiscardFromInput(e + fSkipEOFTags);
105 return size;
108 return size;
112 size_t
113 CamBufferingDeframer::DiscardFromInput(size_t size)
115 int next = (fInputBuffIndex+1)%2;
116 PRINT((CH ": %d bytes of %d from buffs[%d] (%d left)" CT, size, IB.BufferLength(), fInputBuffIndex, IB.BufferLength() - size));
117 fInputBuffs[next].Seek(0LL, SEEK_SET);
118 fInputBuffs[next].SetSize(0);
119 uint8 *buff = (uint8 *)IB.Buffer();
120 if (IB.BufferLength() > size) {
121 buff += size;
122 fInputBuffs[next].Write(buff, IB.BufferLength() - size);
124 IB.Seek(0LL, SEEK_SET);
125 IB.SetSize(0);
126 fInputBuffIndex = next;
127 return size;