www.pudn.com > ReadingPeopleTracker-1.28.rar > IEEE1394Source.cc


///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//  IEEE1394Source.cc                                                        //
//                                                                           //
//  This program reads and decodes the DV encoded frames                     //
//  from the IEEE1394Adaptor                                                 //
//                                                                           //
//                                                                           //
//  Author    :  Sarah Laval (sl) supervised by Nils T Siebel (nts)          //
//  Created   :  Mon Jun 17 17:32:34 BST 2002                                //
//  Copyright :  The University of Reading                                   //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////



#include    // for exit()
#include 

#include "IEEE1394Source.h"

#include "Grey8Image.h"

namespace ReadingPeopleTracker
{

IEEE1394Source::IEEE1394Source(int the_quality)
{  

    Adaptor = new IEEE1394Adaptor;

    time = new timeval;

    frame_count = 0;
  
    // variables for DV decoding
    decoder = dv_decoder_new(false, false, false);
    // (no add_ntsc_setup, no luma clamping, no chroma clamping)

    // NB: in newer versions of libdv, dv_init is called by dv_decode_new
    dv_init(false, false);       // (no luma clamping, no chroma clamping)

    decoder->quality = the_quality;
    DV_encoded_data = NULL;
}

IEEE1394Source::~IEEE1394Source()
{
    delete Adaptor;

} 

void IEEE1394Source::acquire_DV_frame()
{
    //tell the adaptor to start getting data
    DV_encoded_data = Adaptor->capture_frame(Adaptor->get_channel());
 
    //here Adaptor loops with the hardware
    
    return;
    
}


void IEEE1394Source::DV_decode()
{
  
    dv_parse_header(decoder, DV_encoded_data->current_frame);

    xdim = decoder->width;
    ydim = decoder->height;
    
    // create resulting image if it does not exist
    if (current == NULL)
    	current = new RGB32Image(xdim, ydim);
    else
    {
	// current exists: check dimensions and type
       if ((current->get_image_type() != RGB32)
	   || (current->get_width() != xdim) 
	   || (current->get_height() != ydim))
       {
	   cerror << "IEEE1394Source::DV_decode: "
		  << "Error : consecutive input images have "
		  << "different types/dimensions."
		  << endl;
	   exit(1);
       }
 
       
    }
    
    switch(decoder->system) 
    {
    case e_dv_system_625_50: //for PAL
	decode_image(current);
	break;
	
    default:
	break;
    }

    return;
}

int IEEE1394Source::decode_image(Image *image)
{
    unsigned char *pixels[3];
    int pitches[3];

    // libdv cannot decode into RGB0RGB0... format, only RGBRGB...
    // Hence we will decode into our local buffer
    // decompressed_image_data first, then copy the image data over.

    //
    // 1 - decode DV data into decompressed_image_data buffer:
    //
    pixels[0] = decompressed_image_data;
    pixels[1] = NULL;  // this is unused by libdv
    pixels[2] = NULL;  // this is unused by libdv
    
    //  pitches[0]: offset (in bytes) between lines
    pitches[0] = ABS (image->get_pixel(0,1) - image->get_pixel(0,0));
    pitches[1] = 0;  // this is unused by libdv
    pitches[2] = 0;  // this is unused by libdv
    
    dv_decode_full_frame(decoder, DV_encoded_data->current_frame,
			 e_dv_color_rgb,  // also avaiable: e_dv_color_bgr0
			 pixels, pitches);


    //
    // 2  - copy image data (RGB pixels) over, padding with 0's
    //
    // NB DV thinks in terms of IA_TOP_TO_BOTTOM 
    // see if we need to flip it for the result (*current)
   
    unsigned int row;

    register unsigned int col;
    register unsigned char *rgb_ptr;
    register RGB32pixel *rgba_ptr;
    
    if (Image::image_storage_mode == IA_TOP_TO_BOTTOM)
    {
        // no need to flip the image while converting to 32-bit
	for (row = 0; row < ydim; row++)
	{
	    rgba_ptr = (RGB32pixel *) current->get_pixel(0,row);
	    rgb_ptr = pixels[0] + row * pitches[0];
	    
	    for (col = 0; col < xdim; col++)
	    {
		// see definition of RGB32pixel in RGB32Image.h
		rgba_ptr->red = *(rgb_ptr++);    // R
		rgba_ptr->green = *(rgb_ptr++);  // G
		rgba_ptr->blue = *(rgb_ptr++);   // B
		// not necessary to assign alpha, or is it?
		rgba_ptr->alpha = (unsigned char) 0x00;
		
		rgba_ptr++;
	    }
	}
    }
    else
    {
	// we need to flip the image while converting to 32-bit
	for (row = 0; row < ydim; row++)
	{
	    rgba_ptr = (RGB32pixel *) current->get_pixel(0, ydim - (row+1));
	    rgb_ptr = pixels[0] + row * pitches[0];
	    
	    for (col = 0; col < xdim; col++)
	    {
		// see def'n of RGB32pixel in RGB32Image.h
		rgba_ptr->red = *(rgb_ptr++);    // R
		rgba_ptr->green = *(rgb_ptr++);  // G
		rgba_ptr->blue = *(rgb_ptr++);   // B
		// not necessary to assign alpha, or is it?
		rgba_ptr->alpha = (unsigned char) 0x00;
		
		rgba_ptr++;
	    }
	}
    }
 
    return 0;
}


Image *IEEE1394Source::get_next()
{
    //get the DV-encoded frame 
    acquire_DV_frame();

    //DV-decode it 
    DV_decode();

//#ifdef _BSD_SOURCE
//apparently works anyway?
//    // the following requires the BSD 4.3 gettimeofday()
    
    gettimeofday(time, NULL);
    

    current->set_frame_time_in_ms((time->tv_sec * 1000) + (time->tv_usec / 1000));

// #else
// #error "Please re-implement for your system or use BSD compatability"
// #endif  // ifdef _BSD_SOURCE

    assert (decoder->width == 720);
    assert (decoder->height == 576);

    frame_count++;
    
    return current;

}

} // namespace ReadingPeopleTracker