예제 #1
0
void FrameWriter::write_frames(VFrame ***frames, int len)
{
	this->frames = frames;
	this->len = len;
	set_package_count(len * file->asset->layers);

	process_packages();
}
예제 #2
0
void MotionScan::scan_frame(VFrame *previous_frame,
	VFrame *current_frame,
	int global_range_w,
	int global_range_h,
	int global_block_w,
	int global_block_h,
	double block_x,
	double block_y,
	int frame_type,
	int tracking_type,
	int action_type,
	int horizontal_only,
	int vertical_only,
	int source_position,
	int total_steps,
	int total_dx,
	int total_dy,
	int global_origin_x,
	int global_origin_y)
{
	this->previous_frame_arg = previous_frame;
	this->current_frame_arg = current_frame;
	this->horizontal_only = horizontal_only;
	this->vertical_only = vertical_only;
	this->previous_frame = previous_frame_arg;
	this->current_frame = current_frame_arg;
	this->global_origin_x = global_origin_x;
	this->global_origin_y = global_origin_y;
	subpixel = 0;

	cache.remove_all_objects();

// Single macroblock
	int w = current_frame->get_w();
	int h = current_frame->get_h();

// Initial search parameters
	int scan_w = w * global_range_w / 100;
	int scan_h = h * global_range_h / 100;
	int block_w = w * global_block_w / 100;
	int block_h = h * global_block_h / 100;

// Location of block in previous frame
	block_x1 = (int)(w * block_x / 100 - block_w / 2);
	block_y1 = (int)(h * block_y / 100 - block_h / 2);
	block_x2 = (int)(w * block_x / 100 + block_w / 2);
	block_y2 = (int)(h * block_y / 100 + block_h / 2);

// Offset to location of previous block.  This offset needn't be very accurate
// since it's the offset of the previous image and current image we want.
	if(frame_type == MotionScan::TRACK_PREVIOUS)
	{
		block_x1 += total_dx / OVERSAMPLE;
		block_y1 += total_dy / OVERSAMPLE;
		block_x2 += total_dx / OVERSAMPLE;
		block_y2 += total_dy / OVERSAMPLE;
	}

	skip = 0;

	switch(tracking_type)
	{
// Don't calculate
		case MotionScan::NO_CALCULATE:
			dx_result = 0;
			dy_result = 0;
			skip = 1;
			break;

		case MotionScan::LOAD:
		{
// Load result from disk
			char string[BCTEXTLEN];
			sprintf(string, "%s%06d", 
				MOTION_FILE, 
				source_position);
//printf("MotionScan::scan_frame %d %s\n", __LINE__, string);
			FILE *input = fopen(string, "r");
			if(input)
			{
				int temp = fscanf(input, 
					"%d %d", 
					&dx_result,
					&dy_result);
// HACK
//dx_result *= 2;
//dy_result *= 2;
//printf("MotionScan::scan_frame %d %d %d\n", __LINE__, dx_result, dy_result);
				fclose(input);
				skip = 1;
			}
			break;
		}

// Scan from scratch
		default:
			skip = 0;
			break;
	}

	if(!skip && test_match)
	{
		if(previous_frame->data_matches(current_frame))
		{
printf("MotionScan::scan_frame: data matches. skipping.\n");
			dx_result = 0;
			dy_result = 0;
			skip = 1;
		}
	}

// Perform scan
	if(!skip)
	{
//printf("MotionScan::scan_frame %d\n", __LINE__);
// Location of block in current frame
		int origin_offset_x = this->global_origin_x * w / 100;
		int origin_offset_y = this->global_origin_y * h / 100;
		int x_result = block_x1 + origin_offset_x;
		int y_result = block_y1 + origin_offset_y;

// printf("MotionScan::scan_frame 1 %d %d %d %d %d %d %d %d\n",
// block_x1 + block_w / 2,
// block_y1 + block_h / 2,
// block_w,
// block_h,
// block_x1,
// block_y1,
// block_x2,
// block_y2);

		while(1)
		{
// Cache needs to be cleared if downsampling is used because the sums of 
// different downsamplings can't be compared.
// Subpixel never uses the cache.
//			cache.remove_all_objects();
			scan_x1 = x_result - scan_w / 2;
			scan_y1 = y_result - scan_h / 2;
			scan_x2 = x_result + scan_w / 2;
			scan_y2 = y_result + scan_h / 2;



// Zero out requested values
			if(horizontal_only)
			{
				scan_y1 = block_y1;
				scan_y2 = block_y1 + 1;
			}
			if(vertical_only)
			{
				scan_x1 = block_x1;
				scan_x2 = block_x1 + 1;
			}

// printf("MotionScan::scan_frame 1 %d %d %d %d %d %d %d %d\n",
// block_x1,
// block_y1,
// block_x2,
// block_y2,
// scan_x1,
// scan_y1,
// scan_x2,
// scan_y2);
// Clamp the block coords before the scan so we get useful scan coords.
			clamp_scan(w, 
				h, 
				&block_x1,
				&block_y1,
				&block_x2,
				&block_y2,
				&scan_x1,
				&scan_y1,
				&scan_x2,
				&scan_y2,
				0);
// printf("MotionScan::scan_frame 1 %d block_x1=%d block_y1=%d block_x2=%d block_y2=%d\n	 scan_x1=%d scan_y1=%d scan_x2=%d scan_y2=%d\n    x_result=%d y_result=%d\n", 
// __LINE__,
// block_x1,
// block_y1,
// block_x2,
// block_y2,
// scan_x1, 
// scan_y1, 
// scan_x2, 
// scan_y2, 
// x_result, 
// y_result);


// Give up if invalid coords.
			if(scan_y2 <= scan_y1 ||
				scan_x2 <= scan_x1 ||
				block_x2 <= block_x1 ||
				block_y2 <= block_y1)
				break;

// For subpixel, the top row and left column are skipped
			if(subpixel)
			{

//printf("MotionScan::scan_frame %d %d %d\n", __LINE__, x_result, y_result);
// Scan every subpixel in a 2 pixel * 2 pixel square
				total_pixels = (2 * OVERSAMPLE) * (2 * OVERSAMPLE);

				this->total_steps = total_pixels;
// These aren't used in subpixel
				this->x_steps = OVERSAMPLE * 2;
				this->y_steps = OVERSAMPLE * 2;

				set_package_count(this->total_steps);
				process_packages();

// Get least difference
				int64_t min_difference = -1;
				for(int i = 0; i < get_total_packages(); i++)
				{
					MotionScanPackage *pkg = (MotionScanPackage*)get_package(i);
//printf("MotionScan::scan_frame %d search_x=%d search_y=%d sub_x=%d sub_y=%d diff1=%lld diff2=%lld\n", 
//__LINE__, pkg->search_x, pkg->search_y, pkg->sub_x, pkg->sub_y, pkg->difference1, pkg->difference2);
					if(pkg->difference1 < min_difference || min_difference == -1)
					{
						min_difference = pkg->difference1;

// The sub coords are 1 pixel up & left of the block coords
						x_result = pkg->search_x * OVERSAMPLE + pkg->sub_x;
						y_result = pkg->search_y * OVERSAMPLE + pkg->sub_y;


// Fill in results
						dx_result = block_x1 * OVERSAMPLE - x_result;
						dy_result = block_y1 * OVERSAMPLE - y_result;
//printf("MotionScan::scan_frame %d dx_result=%d dy_result=%d diff=%lld\n", 
//__LINE__, dx_result, dy_result, min_difference);
					}

					if(pkg->difference2 < min_difference)
					{
						min_difference = pkg->difference2;

						x_result = pkg->search_x * OVERSAMPLE - pkg->sub_x;
						y_result = pkg->search_y * OVERSAMPLE - pkg->sub_y;

						dx_result = block_x1 * OVERSAMPLE - x_result;
						dy_result = block_y1 * OVERSAMPLE - y_result;
//printf("MotionScan::scan_frame %d dx_result=%d dy_result=%d diff=%lld\n", 
//__LINE__, dx_result, dy_result, min_difference);
					}
				}

				break;
			}
			else
// Single pixel
			{
				total_pixels = (scan_x2 - scan_x1) * (scan_y2 - scan_y1);
				this->total_steps = MIN(total_steps, total_pixels);

				if(this->total_steps == total_pixels)
				{
					x_steps = scan_x2 - scan_x1;
					y_steps = scan_y2 - scan_y1;
				}
				else
				{
					x_steps = (int)sqrt(this->total_steps);
					y_steps = (int)sqrt(this->total_steps);
				}

// Use downsampled images
// 				if(scan_x2 - scan_x1 > x_steps * 4 ||
// 					scan_y2 - scan_y1 > y_steps * 4)
// 				{
// printf("MotionScan::scan_frame %d total_pixels=%d total_steps=%d x_steps=%d y_steps=%d x y steps=%d\n",
// __LINE__,
// total_pixels,
// total_steps,
// x_steps,
// y_steps,
// x_steps * y_steps);
// 
// 					if(!downsampled_previous ||
// 						!downsampled_previous->equivalent(previous_frame_arg))
// 					{
// 						delete downsampled_previous;
// 						downsampled_previous = new VFrame(*previous_frame_arg);
// 					}
// 
// 					if(!downsampled_current ||
// 						!downsampled_current->equivalent(current_frame_arg))
// 					{
// 						delete downsampled_current;
// 						downsampled_current = new VFrame(*current_frame_arg);
// 					}
// 
// 
// 					if(!downsample)
// 						downsample = new DownSampleServer(get_total_clients(), 
// 							get_total_clients());
// 					downsample->process_frame(downsampled_previous, 
// 						previous_frame_arg, 
// 						1, 
// 						1, 
// 						1, 
// 						1,
// 						(scan_y2 - scan_y1) / y_steps,
// 						(scan_x2 - scan_x1) / x_steps,
// 						0,
// 						0);
// 					downsample->process_frame(downsampled_current, 
// 						current_frame_arg, 
// 						1, 
// 						1, 
// 						1, 
// 						1,
// 						(scan_y2 - scan_y1) / y_steps,
// 						(scan_x2 - scan_x1) / x_steps,
// 						0,
// 						0);
// 					this->previous_frame = downsampled_previous;
// 					this->current_frame = downsampled_current;
// 				}





// printf("MotionScan::scan_frame %d this->total_steps=%d\n", 
// __LINE__, 
// this->total_steps);


				set_package_count(this->total_steps);
				process_packages();

// Get least difference
				int64_t min_difference = -1;
				for(int i = 0; i < get_total_packages(); i++)
				{
					MotionScanPackage *pkg = (MotionScanPackage*)get_package(i);
//printf("MotionScan::scan_frame %d search_x=%d search_y=%d sub_x=%d sub_y=%d diff1=%lld diff2=%lld\n", 
//__LINE__, pkg->search_x, pkg->search_y, pkg->sub_x, pkg->sub_y, pkg->difference1, pkg->difference2);
					if(pkg->difference1 < min_difference || min_difference == -1)
					{
						min_difference = pkg->difference1;
						x_result = pkg->search_x;
						y_result = pkg->search_y;
						x_result *= OVERSAMPLE;
						y_result *= OVERSAMPLE;
//printf("MotionScan::scan_frame %d x_result=%d y_result=%d diff=%lld\n", 
//__LINE__, block_x1 * OVERSAMPLE - x_result, block_y1 * OVERSAMPLE - y_result, pkg->difference1);
					}
				}


// If a new search is required, rescale results back to pixels.
				if(this->total_steps >= total_pixels)
				{
// Single pixel accuracy reached.  Now do exhaustive subpixel search.
					if(action_type == MotionScan::STABILIZE ||
						action_type == MotionScan::TRACK ||
						action_type == MotionScan::NOTHING)
					{
//printf("MotionScan::scan_frame %d %d %d\n", __LINE__, x_result, y_result);
						x_result /= OVERSAMPLE;
						y_result /= OVERSAMPLE;
						scan_w = 2;
						scan_h = 2;
						subpixel = 1;
					}
					else
					{
// Fill in results and quit
						dx_result = block_x1 * OVERSAMPLE - x_result;
						dy_result = block_y1 * OVERSAMPLE - y_result;
//printf("MotionScan::scan_frame %d %d %d\n", __LINE__, dx_result, dy_result);
						break;
					}
				}
				else
// Reduce scan area and try again
				{
					scan_w = (scan_x2 - scan_x1) / 2;
					scan_h = (scan_y2 - scan_y1) / 2;
					x_result /= OVERSAMPLE;
					y_result /= OVERSAMPLE;
				}
			}
		}

		dx_result *= -1;
		dy_result *= -1;
	}
//printf("MotionScan::scan_frame %d\n", __LINE__);


	if(vertical_only) dx_result = 0;
	if(horizontal_only) dy_result = 0;



// Write results
	if(tracking_type == MotionScan::SAVE)
	{
		char string[BCTEXTLEN];
		sprintf(string, 
			"%s%06d", 
			MOTION_FILE, 
			source_position);
		FILE *output = fopen(string, "w");
		if(output)
		{
			fprintf(output, 
				"%d %d\n",
				dx_result,
				dy_result);
			fclose(output);
		}
		else
		{
			printf("MotionScan::scan_frame %d: save coordinate failed", __LINE__);
		}
	}

// printf("MotionScan::scan_frame %d dx=%.2f dy=%.2f\n", 
// __LINE__,
// (float)this->dx_result / OVERSAMPLE,
// (float)this->dy_result / OVERSAMPLE);
}