Пример #1
0
/***********************************************************************************************

    Basic functionality:

        The service function is called by the serviceThread object (of type ProcessThread).
        This call happens immediately after the previous call if the return value for
        the previous call was NORMAL.
        If the return value for the previous call was NOOP, then the serviceThread waits
        an amount of time defined in the serviceThread's constructor.
        
    SRI:
        To create a StreamSRI object, use the following code:
                std::string stream_id = "testStream";
                BULKIO::StreamSRI sri = bulkio::sri::create(stream_id);

	Time:
	    To create a PrecisionUTCTime object, use the following code:
                BULKIO::PrecisionUTCTime tstamp = bulkio::time::utils::now();

        
    Ports:

        Data is passed to the serviceFunction through the getPacket call (BULKIO only).
        The dataTransfer class is a port-specific class, so each port implementing the
        BULKIO interface will have its own type-specific dataTransfer.

        The argument to the getPacket function is a floating point number that specifies
        the time to wait in seconds. A zero value is non-blocking. A negative value
        is blocking.  Constants have been defined for these values, bulkio::Const::BLOCKING and
        bulkio::Const::NON_BLOCKING.

        Each received dataTransfer is owned by serviceFunction and *MUST* be
        explicitly deallocated.

        To send data using a BULKIO interface, a convenience interface has been added 
        that takes a std::vector as the data input

        NOTE: If you have a BULKIO dataSDDS port, you must manually call 
              "port->updateStats()" to update the port statistics when appropriate.

        Example:
            // this example assumes that the component has two ports:
            //  A provides (input) port of type bulkio::InShortPort called short_in
            //  A uses (output) port of type bulkio::OutFloatPort called float_out
            // The mapping between the port and the class is found
            // in the component base class header file

            bulkio::InShortPort::dataTransfer *tmp = short_in->getPacket(bulkio::Const::BLOCKING);
            if (not tmp) { // No data is available
                return NOOP;
            }

            std::vector<float> outputData;
            outputData.resize(tmp->dataBuffer.size());
            for (unsigned int i=0; i<tmp->dataBuffer.size(); i++) {
                outputData[i] = (float)tmp->dataBuffer[i];
            }

            // NOTE: You must make at least one valid pushSRI call
            if (tmp->sriChanged) {
                float_out->pushSRI(tmp->SRI);
            }
            float_out->pushPacket(outputData, tmp->T, tmp->EOS, tmp->streamID);

            delete tmp; // IMPORTANT: MUST RELEASE THE RECEIVED DATA BLOCK
            return NORMAL;

        If working with complex data (i.e., the "mode" on the SRI is set to
        true), the std::vector passed from/to BulkIO can be typecast to/from
        std::vector< std::complex<dataType> >.  For example, for short data:

            bulkio::InShortPort::dataTransfer *tmp = myInput->getPacket(bulkio::Const::BLOCKING);
            std::vector<std::complex<short> >* intermediate = (std::vector<std::complex<short> >*) &(tmp->dataBuffer);
            // do work here
            std::vector<short>* output = (std::vector<short>*) intermediate;
            myOutput->pushPacket(*output, tmp->T, tmp->EOS, tmp->streamID);

        Interactions with non-BULKIO ports are left up to the component developer's discretion

    Properties:
        
        Properties are accessed directly as member variables. For example, if the
        property name is "baudRate", it may be accessed within member functions as
        "baudRate". Unnamed properties are given a generated name of the form
        "prop_n", where "n" is the ordinal number of the property in the PRF file.
        Property types are mapped to the nearest C++ type, (e.g. "string" becomes
        "std::string"). All generated properties are declared in the base class
        (fastfilter_base).
    
        Simple sequence properties are mapped to "std::vector" of the simple type.
        Struct properties, if used, are mapped to C++ structs defined in the
        generated file "struct_props.h". Field names are taken from the name in
        the properties file; if no name is given, a generated name of the form
        "field_n" is used, where "n" is the ordinal number of the field.
        
        Example:
            // This example makes use of the following Properties:
            //  - A float value called scaleValue
            //  - A boolean called scaleInput
              
            if (scaleInput) {
                dataOut[i] = dataIn[i] * scaleValue;
            } else {
                dataOut[i] = dataIn[i];
            }
            
        A callback method can be associated with a property so that the method is
        called each time the property value changes.  This is done by calling 
        setPropertyChangeListener(<property name>, this, &fastfilter_i::<callback method>)
        in the constructor.
            
        Example:
            // This example makes use of the following Properties:
            //  - A float value called scaleValue
            
        //Add to fastfilter.cpp
        fastfilter_i::fastfilter_i(const char *uuid, const char *label) :
            fastfilter_base(uuid, label)
        {
            setPropertyChangeListener("scaleValue", this, &fastfilter_i::scaleChanged);
        }

        void fastfilter_i::scaleChanged(const std::string& id){
            std::cout << "scaleChanged scaleValue " << scaleValue << std::endl;
        }
            
        //Add to fastfilter.h
        void scaleChanged(const std::string&);
        
        
************************************************************************************************/
int fastfilter_i::serviceFunction()
{
    bulkio::InFloatPort::dataTransfer *tmp = dataFloat_in->getPacket(bulkio::Const::BLOCKING);
	if (not tmp) { // No data is available
		return NOOP;
	}

	if (tmp->inputQueueFlushed)
	{
		LOG_WARN(fastfilter_i, "input queue flushed - data has been thrown on the floor.  flushing internal buffers");
		//flush all our processor states if the queue flushed
		boost::mutex::scoped_lock lock(filterLock_);
		for (map_type::iterator i = filters_.begin(); i!=filters_.end(); i++)
			i->second.filter->flush();
	}
	bool updateSRI = tmp->sriChanged;
    float fs = 1.0/tmp->SRI.xdelta;
	{
		boost::mutex::scoped_lock lock(filterLock_);
		map_type::iterator i = filters_.find(tmp->streamID);
		firfilter* filter;
		if (i==filters_.end())
		{
			//this is a new stream - need to create a new filter & wrapper
			LOG_DEBUG(fastfilter_i, "creating new filter for streamID "<<tmp->streamID);
			if (manualTaps_)
			{
				LOG_DEBUG(fastfilter_i, "using manual taps ");
				bool real, complex;
				getManualTaps(real,complex);
				if (real)
					filter = new firfilter(fftSize, realOut, complexOut, realTaps_);
				else if(complex)
					filter = new firfilter(fftSize, realOut, complexOut, complexTaps_);
				else
				{
					LOG_WARN(fastfilter_i, "state error - using manual taps with no filter provided.  This shouldn't really happen");
					if (updateSRI)
						dataFloat_out->pushSRI(tmp->SRI);
					dataFloat_out->pushPacket(tmp->dataBuffer, tmp->T, tmp->EOS, tmp->streamID);
					delete tmp;
					return NORMAL;
				}
				updateSRI = true;
			}
			else
			{
				LOG_DEBUG(fastfilter_i, "using filter designer");
				correlationMode=false;
				if (filterProps.filterComplex)
				{
					designTaps(complexTaps_, fs);
					filter = new firfilter(fftSize, realOut, complexOut, complexTaps_);
				}
				else
				{
					designTaps(realTaps_, fs);
					filter = new firfilter(fftSize, realOut, complexOut, realTaps_);
				}
			}
			map_type::value_type filterWrapperMap(tmp->streamID, FilterWrapper());
			i = filters_.insert(filters_.end(),filterWrapperMap);
			i->second.setParams(fs,filter);
		}
		else
			//get the filter we have used before
			filter = i->second.filter;

		//if we are in design mode and the sample rate has changed - redesign and apply our filter
		if (!manualTaps_ && i->second.hasSampleRateChanged(fs))
		{
			if (filterProps.filterComplex)
			{
				designTaps(complexTaps_, fs);
				filter->setTaps(complexTaps_);
			}
			else
			{
				designTaps(realTaps_, fs);
				filter->setTaps(realTaps_);
			}
		}

		//now process the data
		if (tmp->SRI.mode==1)
		{
			//data is complex
			//run the filter
			std::vector<std::complex<float> >* cxData = (std::vector<std::complex<float> >*) &(tmp->dataBuffer);
			filter->newComplexData(*cxData);
		}
		else
		{
			//data is real
			//run the filter
			filter->newRealData(tmp->dataBuffer);
			//we might have a single complex frame if the previous data was complex and there were
			//complex data still in the filter taps
			if (!complexOut.empty())
			{
				//update the mode to true for the complex fame and force an sri push
				tmp->SRI.mode=1;
				updateSRI = true;
			}
		}
	    if (tmp->EOS)
	    {
	    	//if we have an eos - remove the wrapper from the container
	    	filters_.erase(i);
	    }
	}

	//to do -- adjust time stamps appropriately on all these output pushes
    // NOTE: You must make at least one valid pushSRI call
    if (updateSRI) {
    	dataFloat_out->pushSRI(tmp->SRI);
    }
    if (!complexOut.empty())
    {
    	std::vector<float>* tmpRealOut = (std::vector<float>*) &(complexOut);
    	dataFloat_out->pushPacket(*tmpRealOut, tmp->T, tmp->EOS, tmp->streamID);
    }
    if (!realOut.empty())
    {
    	//case we we forced a push on real data from previous complex data
    	//need to force our sri back to real and push another sri
    	if (updateSRI && tmp->SRI.mode==1)
    	{
    		//change mode back to 0 and send another sri with our real output
    		tmp->SRI.mode=0;
    		dataFloat_out->pushSRI(tmp->SRI);
    	}
    	dataFloat_out->pushPacket(realOut, tmp->T, tmp->EOS, tmp->streamID);
    }
    delete tmp; // IMPORTANT: MUST RELEASE THE RECEIVED DATA BLOCK
    return NORMAL;
}
Пример #2
0
// Host code
int main(int argc, char** argv)
{
    ParseArguments(argc, argv);
	
	float s_SobelMatrix[25];  
	s_SobelMatrix[0] = 1;
	s_SobelMatrix[1] = 2;
	s_SobelMatrix[2]= 0;
	s_SobelMatrix[3] = -2;
	s_SobelMatrix[4] = -1;
	s_SobelMatrix[5] = 4;
	s_SobelMatrix[6] = 8;
	s_SobelMatrix[7] = 0;
	s_SobelMatrix[8] = -8;
	s_SobelMatrix[9] = -4;
	s_SobelMatrix[10] = 6;
	s_SobelMatrix[11] = 12;
	s_SobelMatrix[12] = 0;
	s_SobelMatrix[13] = -12;
	s_SobelMatrix[14] = -6;
	s_SobelMatrix[15] = 4;
	s_SobelMatrix[16] = 8; 
	s_SobelMatrix[17] = 0;
	s_SobelMatrix[18] = -8;
	s_SobelMatrix[19] =-4;
	s_SobelMatrix[20] =1;
	s_SobelMatrix[21] =2;
	s_SobelMatrix[22] =0;
	s_SobelMatrix[23] =-2;
	s_SobelMatrix[24] =-1;
	
    unsigned char *palete = NULL;
    unsigned char *data = NULL, *out = NULL;
    PPMImage *input_image=NULL, *output_image=NULL;
    output_image = (PPMImage *)malloc(sizeof(PPMImage));
    input_image = readPPM(PPMInFileL);
    printf("Running %s filter\n", Filter);
    out = (unsigned char *)malloc();

    printf("Computing the CPU output\n");
    printf("Image details: %d by %d = %d , imagesize = %d\n", input_image->x, input_image->y, input_image->x * input_image->y, input_image->x * input_image->y);
    
	cutilCheckError(cutStartTimer(time_CPU));
	if(FilterMode == SOBEL_FILTER){
	printf("Running Sobel\n");
	CPU_Sobel(intput_image->data, output_image, input_image->x, input_image->y);
	}
	else if(FilterMode == HIGH_BOOST_FILTER){
	printf("Running boost\n");
	CPU_Boost(data, out, dib.width, dib.height);
	}
	cutilCheckError(cutStopTimer(time_CPU));
	if(FilterMode == SOBEL_FILTER || FilterMode == SOBEL_FILTER5)
    BitMapWrite("CPU_sobel.bmp", &bmp, &dib, out, palete);
	
	else if(FilterMode == AVERAGE_FILTER)
	BitMapWrite("CPU_average.bmp", &bmp, &dib, out, palete);
	
	else if(FilterMode == HIGH_BOOST_FILTER)
	BitMapWrite("CPU_boost.bmp", &bmp, &dib, out, palete);
	
    printf("Done with CPU output\n");
	printf("CPU execution time %f \n", cutGetTimerValue(time_CPU));
	
	
    printf("Allocating %d bytes for image \n", dib.image_size);
	
    cutilSafeCall( cudaMalloc( (void **)&d_In, dib.image_size*sizeof(unsigned char)) );
    cutilSafeCall( cudaMalloc( (void **)&d_Out, dib.image_size*sizeof(unsigned char)) );
    
	// creating space for filter matrix
	cutilSafeCall( cudaMalloc( (void **)&sobel_matrix, 25*sizeof(float)) );
	
	cutilCheckError(cutStartTimer(time_mem));
	
	cudaMemcpy(d_In, data, dib.image_size*sizeof(unsigned char), cudaMemcpyHostToDevice);
	
	cudaMemcpy(sobel_matrix, s_SobelMatrix, 25*sizeof(float), cudaMemcpyHostToDevice);
	
	cutilCheckError(cutStopTimer(time_mem));
    
	FilterWrapper(data, dib.width, dib.height);

    // Copy image back to host
	
	cutilCheckError(cutStartTimer(time_mem));
    cudaMemcpy(out, d_Out, dib.image_size*sizeof(unsigned char), cudaMemcpyDeviceToHost);
	cutilCheckError(cutStopTimer(time_mem));
	
	printf("GPU execution time %f Memtime %f \n", cutGetTimerValue(time_GPU), cutGetTimerValue(time_mem));
    printf("Total GPU = %f \n", (cutGetTimerValue(time_GPU) + cutGetTimerValue(time_mem)));
	// Write output image   
    BitMapWrite(BMPOutFile, &bmp, &dib, out, palete);

    Cleanup();
}