void FrameWriter::write_frames(VFrame ***frames, int len) { this->frames = frames; this->len = len; set_package_count(len * file->asset->layers); process_packages(); }
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); }