Configuration parameter added "-merger-distance"
[u/mrichter/AliRoot.git] / HLT / TPCLib / HWCFemulator / AliHLTTPCHWCFEmulatorComponent.cxx
1 // $Id$
2 //****************************************************************************
3 //* This file is property of and copyright by the ALICE HLT Project          * 
4 //* ALICE Experiment at CERN, All rights reserved.                           *
5 //*                                                                          *
6 //* Primary Authors: Sergey Gorbunov, Torsten Alt                            *
7 //* Developers:      Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de> *
8 //*                  Torsten Alt <talt@cern.ch>                              *
9 //*                  for The ALICE HLT Project.                              *
10 //*                                                                          *
11 //* Permission to use, copy, modify and distribute this software and its     *
12 //* documentation strictly for non-commercial purposes is hereby granted     *
13 //* without fee, provided that the above copyright notice appears in all     *
14 //* copies and that both the copyright notice and this permission notice     *
15 //* appear in the supporting documentation. The authors make no claims       *
16 //* about the suitability of this software for any purpose. It is            *
17 //* provided "as is" without express or implied warranty.                    *
18 //****************************************************************************
19
20 //  @file   AliHLTTPCHWCFEmulatorComponent.cxx
21 //  @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
22 //  @author Torsten Alt <talt@cern.ch> 
23 //  @brief  HLT Component interface for for FPGA ClusterFinder Emulator for TPC
24 //  @brief  ( see AliHLTTPCHWCFEmulator class )
25 //  @note
26
27
28 #if __GNUC__>= 3
29 using namespace std;
30 #endif
31 #include "AliHLTTPCHWCFEmulatorComponent.h"
32
33 #include "AliHLTTPCDefinitions.h"
34 #include "AliHLTTPCHWCFDataTypes.h"
35 #include "AliHLTTPCClusterMCData.h"
36 #include "AliHLTTPCHWCFData.h"
37
38 #include "AliGRPObject.h"
39 #include "AliCDBEntry.h"
40 #include "AliCDBManager.h"
41 #include "AliRawDataHeader.h"
42 #include <cstdlib>
43 #include <cerrno>
44 #include "TString.h"
45 #include "TObjString.h"
46 #include "TObjArray.h"
47
48
49 #include <sys/time.h>
50 #include "TFile.h"
51
52 AliHLTTPCHWCFEmulatorComponent::AliHLTTPCHWCFEmulatorComponent()
53   :
54   AliHLTProcessor(),
55   fDoDeconvTime(1),
56   fDoDeconvPad(1),
57   fDoMC(1),
58   fDoFlowControl(0),
59   fDoSinglePadSuppression(1),
60   fBypassMerger(0),
61   fClusterLowerLimit(0),
62   fSingleSeqLimit(0),
63   fMergerDistance(3),
64   fDebug(0),
65   fCFSupport(),
66   fCFEmulator(),
67   fBenchmark("TPCHWClusterFinderEmulator")
68 {
69   // see header file for class documentation
70   // or
71   // refer to README to build package
72   // or
73   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
74 }
75
76
77 AliHLTTPCHWCFEmulatorComponent::AliHLTTPCHWCFEmulatorComponent(const AliHLTTPCHWCFEmulatorComponent&)
78   :
79   AliHLTProcessor(),
80   fDoDeconvTime(1),
81   fDoDeconvPad(1),
82   fDoMC(1),
83   fDoFlowControl(0),
84   fDoSinglePadSuppression(1),
85   fBypassMerger(0),
86   fClusterLowerLimit(0),
87   fSingleSeqLimit(0),
88   fMergerDistance(3),
89   fDebug(0),
90   fCFSupport(),
91   fCFEmulator(),
92   fBenchmark("TPCHWClusterFinderEmulator")
93 {
94   // dummy
95 }
96
97 AliHLTTPCHWCFEmulatorComponent& AliHLTTPCHWCFEmulatorComponent::operator=(const AliHLTTPCHWCFEmulatorComponent&)
98 {
99   // dummy
100   return *this;
101 }
102
103 AliHLTTPCHWCFEmulatorComponent::~AliHLTTPCHWCFEmulatorComponent()
104 {
105   // see header file for class documentation
106 }
107
108 // Public functions to implement AliHLTComponent's interface.
109 // These functions are required for the registration process
110
111 const char* AliHLTTPCHWCFEmulatorComponent::GetComponentID()
112 {
113   // see header file for class documentation
114   return "TPCHWClusterFinderEmulator";
115 }
116
117 void AliHLTTPCHWCFEmulatorComponent::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
118 {
119   // see header file for class documentation
120   list.clear();
121   list.push_back( AliHLTTPCDefinitions::fgkUnpackedRawDataType );        
122   list.push_back( kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC );
123 }
124
125 AliHLTComponentDataType AliHLTTPCHWCFEmulatorComponent::GetOutputDataType()
126 {
127   // see header file for class documentation
128   return kAliHLTMultipleDataType;
129 }
130
131 int AliHLTTPCHWCFEmulatorComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
132 {
133   // see header file for class documentation
134   tgtList.clear();
135   tgtList.push_back(AliHLTTPCDefinitions::fgkHWClustersDataType | kAliHLTDataOriginTPC );
136   tgtList.push_back(AliHLTTPCDefinitions::fgkAliHLTDataTypeClusterMCInfo | kAliHLTDataOriginTPC );
137   return tgtList.size();
138 }
139
140
141 void AliHLTTPCHWCFEmulatorComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
142 {
143   // see header file for class documentation
144   // XXX TODO: Find more realistic values.  
145   constBase = 0;
146   inputMultiplier = (6 * 0.4);
147 }
148
149
150 AliHLTComponent* AliHLTTPCHWCFEmulatorComponent::Spawn()
151 {
152   // see header file for class documentation
153   return new AliHLTTPCHWCFEmulatorComponent();
154 }
155
156 void AliHLTTPCHWCFEmulatorComponent::GetOCDBObjectDescription( TMap* const targetMap){
157 // Get a list of OCDB object description needed for the particular component
158   
159   if (!targetMap) return;
160   
161   // OCDB entries for component arguments
162   targetMap->Add(new TObjString("HLT/ConfigTPC/TPCHWClusterFinder"), new TObjString("component arguments, empty at the moment"));
163 }
164
165
166 int AliHLTTPCHWCFEmulatorComponent::DoInit( int argc, const char** argv )
167 {
168   // see header file for class documentation
169
170   TString arguments = "";
171   for ( int i = 0; i < argc; i++ ) {
172     if ( !arguments.IsNull() ) arguments += " ";
173     arguments += argv[i];
174   }
175
176   return Configure( NULL, NULL, arguments.Data()  );
177 }
178
179 int AliHLTTPCHWCFEmulatorComponent::Reconfigure( const char* cdbEntry, const char* chainId )
180 {
181   // Reconfigure the component from OCDB
182
183   return Configure( cdbEntry, chainId, NULL );
184 }
185
186 int AliHLTTPCHWCFEmulatorComponent::ScanConfigurationArgument(int argc, const char** argv)
187 {
188   // see header file for class documentation
189   TString arguments = "";
190   for ( int i = 0; i < argc; i++ ) {
191     if ( !arguments.IsNull() ) arguments += " ";
192     arguments += argv[i];
193   }
194   return ReadConfigurationString(arguments);
195 }
196
197
198
199 void AliHLTTPCHWCFEmulatorComponent::SetDefaultConfiguration()
200 {
201   // Set default configuration for the FPGA ClusterFinder Emulator component
202   // Some parameters can be later overwritten from the OCDB
203
204   fDoDeconvTime = 0;
205   fDoDeconvPad = 0;
206   fDoMC = 1;
207   fDoFlowControl = 0;
208   fDoSinglePadSuppression = 1;
209   fBypassMerger = 0;
210   fClusterLowerLimit = 0;
211   fSingleSeqLimit = 0;
212   fMergerDistance = 3;
213   fDebug = 0;
214   fBenchmark.Reset();
215   fBenchmark.SetTimer(0,"total");
216   fBenchmark.SetTimer(1,"reco");    
217 }
218
219 int AliHLTTPCHWCFEmulatorComponent::ReadConfigurationString(  const char* arguments )
220 {
221   // Set configuration parameters for the FPGA ClusterFinder Emulator component
222   // from the string
223
224   int iResult = 0;
225   if ( !arguments ) return iResult;
226
227   TString allArgs = arguments;
228   TString argument;
229   int bMissingParam = 0;
230
231   TObjArray* pTokens = allArgs.Tokenize( " " );
232
233   int nArgs =  pTokens ? pTokens->GetEntries() : 0;
234
235   for ( int i = 0; i < nArgs; i++ ) {
236     argument = ( ( TObjString* )pTokens->At( i ) )->GetString();
237     if ( argument.IsNull() ) continue;
238
239     if ( argument.CompareTo( "-deconvolute-time" ) == 0 ) {
240       if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
241       fDoDeconvTime  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
242       HLTInfo( "Time deconvolution is set to: %d", fDoDeconvTime );
243       continue;
244     }
245
246     if ( argument.CompareTo( "-deconvolute-pad" ) == 0 ) {
247       if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
248       fDoDeconvPad  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
249       HLTInfo( "Pad deconvolution is set to: %d", fDoDeconvPad );
250       continue;
251     }
252
253     if ( argument.CompareTo( "-deconvolute" ) == 0 ) {
254       if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
255       fDoDeconvTime  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
256       fDoDeconvPad  = fDoDeconvTime;
257       HLTInfo( "Time and pad deconvolution is set to: %d", fDoDeconvPad );
258       continue;
259     }
260  
261     if ( argument.CompareTo( "-do-mc" ) == 0 ) {
262       if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
263       fDoMC  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
264       HLTInfo( "MC processing is set to: %d", fDoMC );
265       continue;
266     }
267
268     if ( argument.CompareTo( "-flow-control" ) == 0 ) {
269       if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
270       fDoFlowControl  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
271       HLTInfo( "Flow control is set to: %d", fDoFlowControl );
272       continue;
273     }
274
275     if ( argument.CompareTo( "-single-pad-suppression" ) == 0 ) {
276       if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
277       fDoSinglePadSuppression  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
278       HLTInfo( "Single pad suppression is set to: %d", fDoSinglePadSuppression );
279       continue;
280     }
281     
282     if ( argument.CompareTo( "-bypass-merger" ) == 0 ) {
283       if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
284       fBypassMerger  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
285       HLTInfo( "Bypassing merger is set to: %d", fBypassMerger );
286       continue;
287     }
288
289     if ( argument.CompareTo( "-cluster-lower-limit" ) == 0 ) {
290       if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
291       fClusterLowerLimit  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
292       HLTInfo( "Cluster lower limit is set to: %d", fClusterLowerLimit );
293       continue;
294     }
295
296     if ( argument.CompareTo( "-single-sequence-limit" ) == 0 ) {
297       if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
298       fSingleSeqLimit  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
299       HLTInfo( "Single sequence limit is set to: %d", fSingleSeqLimit );
300       continue;
301     }
302     
303     if ( argument.CompareTo( "-merger-distance" ) == 0 ) {
304       if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
305       fMergerDistance  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
306       HLTInfo( "Merger distance is set to: %d", fMergerDistance );
307       continue;
308     }
309     
310     if ( argument.CompareTo( "-debug-level" ) == 0 ) {
311       if ( ( bMissingParam = ( ++i >= pTokens->GetEntries() ) ) ) break;
312       fDebug  = ( ( TObjString* )pTokens->At( i ) )->GetString().Atoi();
313       HLTInfo( "Debug level is set to: %d", fDebug );
314       continue;
315     }
316     
317     HLTError( "Unknown option \"%s\"", argument.Data() );
318     iResult = -EINVAL;
319   }
320   delete pTokens;
321
322   if ( bMissingParam ) {
323     HLTError( "Specifier missed for parameter \"%s\"", argument.Data() );
324     iResult = -EINVAL;
325   }
326
327   return iResult;
328 }
329
330
331 int AliHLTTPCHWCFEmulatorComponent::ReadCDBEntry( const char* cdbEntry, const char* chainId )
332 {
333   // Read configuration from OCDB
334
335   const char* defaultNotify = "";
336
337   if ( !cdbEntry ){
338     cdbEntry = "HLT/ConfigTPC/TPCHWClusterFinder";
339     defaultNotify = " (default)";
340     chainId = 0;
341   }
342
343   HLTInfo( "configure from entry \"%s\"%s, chain id %s", cdbEntry, defaultNotify, ( chainId != NULL && chainId[0] != 0 ) ? chainId : "<none>" );
344   AliCDBEntry *pEntry = AliCDBManager::Instance()->Get( cdbEntry );//,GetRunNo());
345   
346   if ( !pEntry ) {
347     HLTError( "cannot fetch object \"%s\" from CDB", cdbEntry );
348     return -EINVAL;
349   }
350
351   TObjString* pString = dynamic_cast<TObjString*>( pEntry->GetObject() );
352
353   if ( !pString ) {
354     HLTError( "configuration object \"%s\" has wrong type, required TObjString", cdbEntry );
355     return -EINVAL;
356   }
357
358   HLTInfo( "received configuration object string: \"%s\"", pString->GetString().Data() );
359
360   return  ReadConfigurationString( pString->GetString().Data() );
361 }
362
363
364 int AliHLTTPCHWCFEmulatorComponent::Configure( const char* cdbEntry, const char* chainId, const char *commandLine )
365 {
366   // Configure the component
367   // There are few levels of configuration,
368   // parameters which are set on one step can be overwritten on the next step
369
370   //* read hard-coded values
371
372   SetDefaultConfiguration();
373
374   //* read the default CDB entry
375
376   int iResult1 = ReadCDBEntry( NULL, chainId );
377
378   //* read the actual CDB entry if required
379
380   int iResult2 = ( cdbEntry ) ? ReadCDBEntry( cdbEntry, chainId ) : 0;
381
382   //* read extra parameters from input (if they are)
383
384   int iResult3 = 0;
385
386   if ( commandLine && commandLine[0] != '\0' ) {
387     HLTInfo( "received configuration string from HLT framework: \"%s\"", commandLine );
388     iResult3 = ReadConfigurationString( commandLine );
389   }
390   
391   if( fDebug>1 ) fCFEmulator.SetDebugLevel( fDebug );
392   else fCFEmulator.SetDebugLevel(0);
393
394   return iResult1 ? iResult1 : ( iResult2 ? iResult2 : iResult3 );
395 }
396
397
398 int AliHLTTPCHWCFEmulatorComponent::DoDeinit()
399 {
400   // see header file for class documentation 
401   return 0;
402 }
403
404
405 int AliHLTTPCHWCFEmulatorComponent::DoEvent( const AliHLTComponentEventData& evtData, 
406                                                         const AliHLTComponentBlockData* blocks, 
407                                                         AliHLTComponentTriggerData& /*trigData*/, AliHLTUInt8_t* outputPtr, 
408                                                         AliHLTUInt32_t& size, 
409                                                         vector<AliHLTComponentBlockData>& outputBlocks )
410 {
411   // see header file for class documentation
412
413   int iResult=0;
414   AliHLTUInt32_t maxSize = size;
415   size = 0;
416   
417   if(!IsDataEvent()){
418     return 0;
419   }
420
421   fBenchmark.StartNewEvent();
422   fBenchmark.Start(0);
423
424   AliHLTUInt32_t configWord1=0, configWord2=0; 
425   AliHLTTPCHWCFEmulator::CreateConfiguration
426     ( fDoDeconvTime, fDoDeconvPad, fDoFlowControl, fDoSinglePadSuppression, fBypassMerger, fClusterLowerLimit, fSingleSeqLimit, fMergerDistance, configWord1, configWord2 );
427
428   for ( unsigned long ndx = 0; ndx < evtData.fBlockCnt; ndx++ )
429     {
430       const AliHLTComponentBlockData* iter = blocks+ndx;
431       
432       if (  iter->fDataType != (kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC) 
433             &&  iter->fDataType != AliHLTTPCDefinitions::fgkUnpackedRawDataType ) continue;
434
435       int slice = AliHLTTPCDefinitions::GetMinSliceNr( *iter );
436       int patch = AliHLTTPCDefinitions::GetMinPatchNr( *iter );
437  
438       const char *str=Form("slice %d patch %d:", slice, patch);
439
440       fBenchmark.AddInput(iter->fSize);
441  
442       if (!iter->fPtr) continue;
443  
444       // create input block for the HW cluster finder
445
446       const AliHLTUInt32_t *rawEvent=0;
447       const AliHLTTPCClusterMCLabel *mcLabels = 0;
448       AliHLTUInt32_t rawEventSize32 = 0;
449       AliHLTUInt32_t nMCLabels = 0;
450
451       if( fCFSupport.CreateRawEvent( iter, rawEvent, rawEventSize32, mcLabels, nMCLabels )<0 ) continue; 
452       if( !fDoMC ){
453         mcLabels = 0;
454         nMCLabels = 0;
455       }
456
457       // book memory for the output
458       
459       AliHLTUInt32_t maxNClusters = rawEventSize32 + 1; // N 32-bit words in input
460       AliHLTUInt32_t clustersSize32 = maxNClusters*AliHLTTPCHWCFData::fgkAliHLTTPCHWClusterSize;
461       AliHLTUInt32_t nOutputMC = maxNClusters;
462
463       AliHLTUInt32_t headerSize = sizeof(AliRawDataHeader);                   
464       AliHLTUInt8_t *outBlock = new AliHLTUInt8_t[ headerSize+clustersSize32*sizeof(AliHLTUInt32_t) ];
465       
466       AliHLTTPCClusterMCData *outMC = reinterpret_cast<AliHLTTPCClusterMCData *>(new AliHLTTPCClusterMCLabel[nOutputMC+1]);
467       
468       if( !outBlock || !outMC ){
469         HLTWarning("%s Not enouth memory!!!", str);
470         delete[] outBlock;
471         delete[] outMC;
472         continue;       
473       }
474       
475       // fill CDH header here, since the HW clusterfinder does not receive it
476       
477       AliRawDataHeader *cdhHeader = reinterpret_cast<AliRawDataHeader*>(iter->fPtr);
478       AliRawDataHeader *outCDHHeader = reinterpret_cast<AliRawDataHeader*>(outBlock);      
479       *outCDHHeader = *cdhHeader;
480       outCDHHeader->fSize = 0xFFFFFFFF;
481
482       AliHLTUInt32_t *outClusters = reinterpret_cast<AliHLTUInt32_t*> (outBlock + headerSize);
483      
484       fBenchmark.Start(1);
485       fCFEmulator.Init
486         ( fCFSupport.GetMapping(slice,patch), configWord1, configWord2 );
487       
488       int err = fCFEmulator.FindClusters( rawEvent, rawEventSize32, 
489                                           outClusters, clustersSize32, 
490                                           mcLabels, nMCLabels,
491                                           outMC );
492       fBenchmark.Stop(1);
493       if( err==-1 ){ HLTWarning("NULL input pointer (warning %d)",err);}
494       else if( err==-2 ){  HLTWarning("No space left in the output buffer (warning %d)",err); }
495       else if( err<0 ){ HLTWarning("HWCF emulator finished with error code %d",err); }
496       if( err<0 ){
497         delete[] outBlock;
498         delete[] outMC;
499         continue;
500       }
501
502       if( fDebug ){
503         int elsize=AliHLTTPCHWCFData::fgkAliHLTTPCHWClusterSize;
504         printf("\nHWCF Emulator: output clusters for slice%d patch %d:\n",slice,patch);
505         for( AliHLTUInt32_t i=0; i<clustersSize32; i+=elsize ){
506           AliHLTUInt32_t *c = outClusters+i;
507           AliHLTUInt32_t flag = (c[0]>>30);       
508           if( flag == 0x3){ //beginning of a cluster
509             int padRow  = (c[0]>>24)&0x3f;
510             int q  = (c[0]&0xFFFFFF)>>6; 
511             double p   = *((AliHLTFloat32_t*)&c[1]);
512             double t  = *((AliHLTFloat32_t*)&c[2]);
513             AliHLTFloat32_t p2 = *((AliHLTFloat32_t*)&c[3]);
514             AliHLTFloat32_t t2 = *((AliHLTFloat32_t*)&c[4]);
515             printf("N: %3d    R: %3d    C: %4d    P:  %7.4f    T:  %8.4f    DP: %6.4f    DT: %6.4f\n", 
516                    i/elsize+1, padRow, q, p, t, sqrt(fabs(p2-p*p)), sqrt(fabs(t2-t*t)));
517
518             if( outMC && outMC->fCount>0 ){
519               printf("        MC: (%3d,%6.1f) (%3d,%6.1f) (%3d,%6.1f)\n",
520                      outMC->fLabels[i/elsize].fClusterID[0].fMCID,outMC->fLabels[i/elsize].fClusterID[0].fWeight,
521                      outMC->fLabels[i/elsize].fClusterID[1].fMCID,outMC->fLabels[i/elsize].fClusterID[1].fWeight,
522                      outMC->fLabels[i/elsize].fClusterID[2].fMCID,outMC->fLabels[i/elsize].fClusterID[2].fWeight
523                      );
524             }
525           }
526         }
527       }
528           
529
530       AliHLTUInt32_t outSize = headerSize + clustersSize32*sizeof(AliHLTUInt32_t);
531       
532       if( size + outSize <= maxSize ){
533         
534         memcpy( outputPtr, outBlock, outSize );
535         
536         AliHLTComponentBlockData bd;
537         FillBlockData( bd );
538         bd.fOffset = size;
539         bd.fSize = outSize;
540         bd.fSpecification = iter->fSpecification;
541         bd.fDataType = AliHLTTPCDefinitions::fgkHWClustersDataType | kAliHLTDataOriginTPC;
542         outputBlocks.push_back( bd );
543         fBenchmark.AddOutput(bd.fSize);
544         size+= bd.fSize;
545         outputPtr+=bd.fSize;
546       } else {
547         HLTWarning( "Output buffer (%db) is too small, required %db", maxSize, size+outSize);
548         iResult=-ENOSPC;
549       }
550
551       if( fDoMC && outMC && outMC->fCount>0 ){
552         int s = sizeof(AliHLTTPCClusterMCData) + outMC->fCount*sizeof(AliHLTTPCClusterMCLabel);
553         if( size + s <= maxSize ){
554           memcpy( outputPtr, outMC, s );                  
555           AliHLTComponentBlockData bdMCInfo;
556           FillBlockData( bdMCInfo );
557           bdMCInfo.fOffset = size;
558           bdMCInfo.fSize = s;
559           bdMCInfo.fSpecification = iter->fSpecification;
560           bdMCInfo.fDataType = AliHLTTPCDefinitions::fgkAliHLTDataTypeClusterMCInfo | kAliHLTDataOriginTPC;
561           outputBlocks.push_back( bdMCInfo );
562           fBenchmark.AddOutput(bdMCInfo.fSize);
563           size+=bdMCInfo.fSize;
564           outputPtr+=bdMCInfo.fSize; 
565         } else {        
566           HLTWarning( "Output buffer (%db) is too small, required %db", maxSize, size+s);
567           iResult=-ENOSPC;          
568         }
569       }
570       
571       delete[] outBlock;
572       delete[] outMC;      
573     }
574   
575   fBenchmark.Stop(0);  
576   HLTInfo(fBenchmark.GetStatistics());
577   return iResult;
578 }
579
580