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 24 CamBufferingDeframer::CamBufferingDeframer(CamDevice *device) 25 : CamDeframer(device), 26 fInputBuffIndex(0) 27 { 28 } 29 30 31 CamBufferingDeframer::~CamBufferingDeframer() 32 { 33 } 34 35 36 ssize_t 37 CamBufferingDeframer::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 116 size_t 117 CamBufferingDeframer::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