template < typename IN_PORT_TYPE, typename OUT_PORT_TYPE > int copy_bb_base::_forecastAndProcess( bool &eos, typename std::vector< gr_istream< IN_PORT_TYPE > > &istreams , typename std::vector< gr_ostream< OUT_PORT_TYPE > > &ostreams ) { typedef typename std::vector< gr_istream< IN_PORT_TYPE > > _IStreamList; typedef typename std::vector< gr_ostream< OUT_PORT_TYPE > > _OStreamList; typename _OStreamList::iterator ostream; typename _IStreamList::iterator istream = istreams.begin(); int nout = 0; bool dataReady = false; if ( !eos ) { uint64_t max_items_avail = 0; for ( int idx=0 ; istream != istreams.end() && serviceThread->threadRunning() ; idx++, istream++ ) { LOG_TRACE( copy_bb_base, "GET MAX ITEMS: STREAM:"<< idx << " NITEMS/SCALARS:" << istream->nitems() << "/" << istream->_data.size() ); max_items_avail = std::max( istream->nitems(), max_items_avail ); } if ( max_items_avail == 0 ) { LOG_TRACE( copy_bb_base, "DATA CHECK - MAX ITEMS NOUTPUT/MAX_ITEMS:" << noutput_items << "/" << max_items_avail); return -1; } // // calc number of output elements based on input items available // noutput_items = 0; if ( !gr_sptr->fixed_rate() ) { noutput_items = round_down((int32_t) (max_items_avail * gr_sptr->relative_rate()), gr_sptr->output_multiple()); LOG_TRACE( copy_bb_base, " VARIABLE FORECAST NOUTPUT == " << noutput_items ); } else { istream = istreams.begin(); for ( int i=0; istream != istreams.end(); i++, istream++ ) { int t_noutput_items = gr_sptr->fixed_rate_ninput_to_noutput( istream->nitems() ); if ( gr_sptr->output_multiple_set() ) { t_noutput_items = round_up(t_noutput_items, gr_sptr->output_multiple()); } if ( t_noutput_items > 0 ) { if ( noutput_items == 0 ) { noutput_items = t_noutput_items; } if ( t_noutput_items <= noutput_items ) { noutput_items = t_noutput_items; } } } LOG_TRACE( copy_bb_base, " FIXED FORECAST NOUTPUT/output_multiple == " << noutput_items << "/" << gr_sptr->output_multiple()); } // // ask the block how much input they need to produce noutput_items... // if enough data is available to process then set the dataReady flag // int32_t outMultiple = gr_sptr->output_multiple(); while ( !dataReady && noutput_items >= outMultiple ) { // // ask the block how much input they need to produce noutput_items... // gr_sptr->forecast(noutput_items, _ninput_items_required); LOG_TRACE( copy_bb_base, "--> FORECAST IN/OUT " << _ninput_items_required[0] << "/" << noutput_items ); istream = istreams.begin(); uint32_t dr_cnt=0; for ( int idx=0 ; noutput_items > 0 && istream != istreams.end(); idx++, istream++ ) { // check if buffer has enough elements _input_ready[idx] = false; if ( istream->nitems() >= (uint64_t)_ninput_items_required[idx] ) { _input_ready[idx] = true; dr_cnt++; } LOG_TRACE( copy_bb_base, "ISTREAM DATACHECK NELMS/NITEMS/REQ/READY:" << istream->nelems() << "/" << istream->nitems() << "/" << _ninput_items_required[idx] << "/" << _input_ready[idx]); } if ( dr_cnt < istreams.size() ) { if ( outMultiple > 1 ) { noutput_items -= outMultiple; } else { noutput_items /= 2; } } else { dataReady = true; } LOG_TRACE( copy_bb_base, " TRIM FORECAST NOUTPUT/READY " << noutput_items << "/" << dataReady ); } // check if data is ready... if ( !dataReady ) { LOG_TRACE( copy_bb_base, "DATA CHECK - NOT ENOUGH DATA AVAIL/REQ:" << _istreams[0].nitems() << "/" << _ninput_items_required[0] ); return -1; } // reset looping variables int ritems = 0; int nitems = 0; // reset caching vectors _output_items.clear(); _input_items.clear(); _ninput_items.clear(); istream = istreams.begin(); for ( int idx=0 ; istream != istreams.end(); idx++, istream++ ) { // check if the stream is ready if ( !_input_ready[idx] ) { continue; } // get number of items remaining try { ritems = gr_sptr->nitems_read( idx ); } catch(...){ // something bad has happened, we are missing an input stream LOG_ERROR( copy_bb_base, "MISSING INPUT STREAM FOR GR BLOCK, STREAM ID:" << istream->streamID ); return -2; } nitems = istream->nitems() - ritems; LOG_TRACE( copy_bb_base, " ISTREAM: IDX:" << idx << " ITEMS AVAIL/READ/REQ " << nitems << "/" << ritems << "/" << _ninput_items_required[idx] ); if ( nitems >= _ninput_items_required[idx] && nitems > 0 ) { //remove eos checks ...if ( nitems < _ninput_items_required[idx] ) nitems=0; _ninput_items.push_back( nitems ); _input_items.push_back( (const void *) (istream->read_pointer(ritems)) ); } } // // setup output buffer vector based on noutput.. // ostream = ostreams.begin(); for( ; ostream != ostreams.end(); ostream++ ) { ostream->resize(noutput_items); _output_items.push_back((void*)(ostream->write_pointer()) ); } nout=0; if ( _input_items.size() != 0 && serviceThread->threadRunning() ) { LOG_TRACE( copy_bb_base, " CALLING WORK.....N_OUT:" << noutput_items << " N_IN:" << nitems << " ISTREAMS:" << _input_items.size() << " OSTREAMS:" << _output_items.size()); nout = gr_sptr->general_work( noutput_items, _ninput_items, _input_items, _output_items); LOG_TRACE( copy_bb_base, "RETURN WORK ..... N_OUT:" << nout); } // check for stop condition from work method if ( nout < gr_block::WORK_DONE ) { LOG_WARN( copy_bb_base, "WORK RETURNED STOP CONDITION..." << nout ); nout=0; eos = true; } } if (nout != 0 or eos ) { noutput_items = nout; LOG_TRACE( copy_bb_base, " WORK RETURNED: NOUT : " << nout << " EOS:" << eos); ostream = ostreams.begin(); typename IN_PORT_TYPE::dataTransfer *pkt=NULL; for ( int idx=0 ; ostream != ostreams.end(); idx++, ostream++ ) { pkt=NULL; int inputIdx = idx; if ( (size_t)(inputIdx) >= istreams.size() ) { for ( inputIdx= istreams.size()-1; inputIdx > -1; inputIdx--) { if ( istreams[inputIdx].pkt != NULL ) { pkt = istreams[inputIdx].pkt; break; } } } else { pkt = istreams[inputIdx].pkt; } LOG_TRACE( copy_bb_base, "PUSHING DATA ITEMS/STREAM_ID " << ostream->nitems() << "/" << ostream->streamID ); if ( _maintainTimeStamp ) { // set time stamp for output samples based on input time stamp if ( ostream->nelems() == 0 ) { #ifdef TEST_TIME_STAMP LOG_DEBUG( copy_bb_base, "SEED - TS SRI: xdelta:" << std::setprecision(12) << ostream->sri.xdelta ); LOG_DEBUG( copy_bb_base, "OSTREAM WRITE: maint:" << _maintainTimeStamp ); LOG_DEBUG( copy_bb_base, " mode:" << ostream->tstamp.tcmode ); LOG_DEBUG( copy_bb_base, " status:" << ostream->tstamp.tcstatus ); LOG_DEBUG( copy_bb_base, " offset:" << ostream->tstamp.toff ); LOG_DEBUG( copy_bb_base, " whole:" << std::setprecision(10) << ostream->tstamp.twsec ); LOG_DEBUG( copy_bb_base, "SEED - TS frac:" << std::setprecision(12) << ostream->tstamp.tfsec ); #endif ostream->setTimeStamp( pkt->T, _maintainTimeStamp ); } // write out samples, and set next time stamp based on xdelta and noutput_items ostream->write ( noutput_items, eos ); } else { // use incoming packet's time stamp to forward if ( pkt ) { #ifdef TEST_TIME_STAMP LOG_DEBUG( copy_bb_base, "OSTREAM SRI: items/xdelta:" << noutput_items << "/" << std::setprecision(12) << ostream->sri.xdelta ); LOG_DEBUG( copy_bb_base, "PKT - TS maint:" << _maintainTimeStamp ); LOG_DEBUG( copy_bb_base, " mode:" << pkt->T.tcmode ); LOG_DEBUG( copy_bb_base, " status:" << pkt->T.tcstatus ); LOG_DEBUG( copy_bb_base, " offset:" << pkt->T.toff ); LOG_DEBUG( copy_bb_base, " whole:" << std::setprecision(10) << pkt->T.twsec ); LOG_DEBUG( copy_bb_base, "PKT - TS frac:" << std::setprecision(12) << pkt->T.tfsec ); #endif ostream->write( noutput_items, eos, pkt->T ); } else { #ifdef TEST_TIME_STAMP LOG_DEBUG( copy_bb_base, "OSTREAM SRI: items/xdelta:" << noutput_items << "/" << std::setprecision(12) << ostream->sri.xdelta ); LOG_DEBUG( copy_bb_base, "OSTREAM TOD maint:" << _maintainTimeStamp ); LOG_DEBUG( copy_bb_base, " mode:" << ostream->tstamp.tcmode ); LOG_DEBUG( copy_bb_base, " status:" << ostream->tstamp.tcstatus ); LOG_DEBUG( copy_bb_base, " offset:" << ostream->tstamp.toff ); LOG_DEBUG( copy_bb_base, " whole:" << std::setprecision(10) << ostream->tstamp.twsec ); LOG_DEBUG( copy_bb_base, "OSTREAM TOD frac:" << std::setprecision(12) << ostream->tstamp.tfsec ); #endif // use time of day as time stamp ostream->write( noutput_items, eos, _maintainTimeStamp ); } } } // for ostreams } return nout; }
template < typename IN_PORT_TYPE > int tagged_file_sink_b_base::_forecastAndProcess( bool &eos, typename std::vector< gr_istream< IN_PORT_TYPE > > &istreams ) { typedef typename std::vector< gr_istream< IN_PORT_TYPE > > _IStreamList; typename _IStreamList::iterator istream = istreams.begin(); int nout = 0; bool dataReady = false; if ( !eos ) { uint64_t max_items_avail = 0; for ( int idx=0 ; istream != istreams.end() && serviceThread->threadRunning() ; idx++, istream++ ) { LOG_TRACE( tagged_file_sink_b_base, "GET MAX ITEMS: STREAM:" << idx << " NITEMS/SCALARS:" << istream->nitems() << "/" << istream->_data.size() ); max_items_avail = std::max( istream->nitems(), max_items_avail ); } // // calc number of output items to produce // noutput_items = (int) (max_items_avail * gr_sptr->relative_rate ()); noutput_items = round_down (noutput_items, gr_sptr->output_multiple ()); if ( noutput_items <= 0 ) { LOG_TRACE( tagged_file_sink_b_base, "DATA CHECK - MAX ITEMS NOUTPUT/MAX_ITEMS:" << noutput_items << "/" << max_items_avail); return -1; } if ( gr_sptr->fixed_rate() ) { istream = istreams.begin(); for ( int i=0; istream != istreams.end(); i++, istream++ ) { int t_noutput_items = gr_sptr->fixed_rate_ninput_to_noutput( istream->nitems() ); if ( gr_sptr->output_multiple_set() ) { t_noutput_items = round_up(t_noutput_items, gr_sptr->output_multiple()); } if ( t_noutput_items > 0 ) { if ( noutput_items == 0 ) { noutput_items = t_noutput_items; } if ( t_noutput_items <= noutput_items ) { noutput_items = t_noutput_items; } } } LOG_TRACE( tagged_file_sink_b_base, " FIXED FORECAST NOUTPUT/output_multiple == " << noutput_items << "/" << gr_sptr->output_multiple()); } // // ask the block how much input they need to produce noutput_items... // if enough data is available to process then set the dataReady flag // int32_t outMultiple = gr_sptr->output_multiple(); while ( !dataReady && noutput_items >= outMultiple ) { // // ask the block how much input they need to produce noutput_items... // gr_sptr->forecast(noutput_items, _ninput_items_required); LOG_TRACE( tagged_file_sink_b_base, "--> FORECAST IN/OUT " << _ninput_items_required[0] << "/" << noutput_items ); istream = istreams.begin(); uint32_t dr_cnt=0; for ( int idx=0 ; noutput_items > 0 && istream != istreams.end(); idx++, istream++ ) { // check if buffer has enough elements _input_ready[idx] = false; if ( istream->nitems() >= (uint64_t)_ninput_items_required[idx] ) { _input_ready[idx] = true; dr_cnt++; } LOG_TRACE( tagged_file_sink_b_base, "ISTREAM DATACHECK NELMS/NITEMS/REQ/READY:" << istream->nelems() << "/" << istream->nitems() << "/" << _ninput_items_required[idx] << "/" << _input_ready[idx]); } if ( dr_cnt < istreams.size() ) { if ( outMultiple > 1 ) { noutput_items -= outMultiple; } else { noutput_items /= 2; } } else { dataReady = true; } LOG_TRACE( tagged_file_sink_b_base, " TRIM FORECAST NOUTPUT/READY " << noutput_items << "/" << dataReady ); } // check if data is ready... if ( !dataReady ) { LOG_TRACE( tagged_file_sink_b_base, "DATA CHECK - NOT ENOUGH DATA AVAIL/REQ:" << _istreams[0].nitems() << "/" << _ninput_items_required[0] ); return -1; } // reset looping variables int ritems = 0; int nitems = 0; // reset caching vectors _output_items.clear(); _input_items.clear(); _ninput_items.clear(); istream = istreams.begin(); for ( int idx=0 ; istream != istreams.end(); idx++, istream++ ) { // check if the stream is ready if ( !_input_ready[idx] ) continue; // get number of items remaining try { ritems = gr_sptr->nitems_read( idx ); } catch(...){ // something bad has happened, we are missing an input stream LOG_ERROR( tagged_file_sink_b_base, "MISSING INPUT STREAM FOR GR BLOCK, STREAM ID:" << istream->streamID ); return -2; } nitems = istream->nitems() - ritems; LOG_TRACE( tagged_file_sink_b_base, " ISTREAM: IDX:" << idx << " ITEMS AVAIL/READ/REQ " << nitems << "/" << ritems << "/" << _ninput_items_required[idx] ); if ( nitems >= _ninput_items_required[idx] && nitems > 0 ) { //remove eos checks ...if ( nitems < _ninput_items_required[idx] ) nitems=0; _ninput_items.push_back( nitems ); _input_items.push_back( (const void *) (istream->read_pointer(ritems)) ); } } nout=0; if ( _input_items.size() != 0 && serviceThread->threadRunning() ) { LOG_TRACE( tagged_file_sink_b_base, " CALLING WORK.....N_OUT:" << noutput_items << " N_IN:" << nitems << " ISTREAMS:" << _input_items.size() << " OSTREAMS:" << _output_items.size()); nout = gr_sptr->general_work( noutput_items, _ninput_items, _input_items, _output_items); // sink/analyzer patterns do not return items, so consume_each is not called in Gnu Radio BLOCK if ( nout == 0 ) { gr_sptr->consume_each(nitems); } LOG_TRACE( tagged_file_sink_b_base, "RETURN WORK ..... N_OUT:" << nout); } // check for stop condition from work method if ( nout < gr_block::WORK_DONE ) { LOG_WARN( tagged_file_sink_b_base, "WORK RETURNED STOP CONDITION..." << nout ); nout=0; eos = true; } } return nout; }