# HG changeset patch # User Alexey Osipov <si...@lerlan.ru> # Date 1310724114 -25200 # Branch stabilize_optimize # Node ID a988634e1d2b94aab2babbeb8df8ce0a2b77e311 # Parent 3ae3c32787846be1052b20f862914b0dc8817a2d Remove extra whitespace at end of lines to apply next patches.
diff -r 3ae3c3278784 -r a988634e1d2b filter/stabilize/filter_stabilize.c --- a/filter/stabilize/filter_stabilize.c Fri Jul 15 16:50:12 2011 +0700 +++ b/filter/stabilize/filter_stabilize.c Fri Jul 15 17:01:54 2011 +0700 @@ -2,28 +2,28 @@ * filter_stabilize.c * * Copyright (C) Georg Martius - June 2007 - * georg dot martius at web dot de + * georg dot martius at web dot de * * This file is part of transcode, a video stream processing tool - * + * * transcode is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. - * + * * transcode is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* Typical call: - * transcode -V -J stabilize=shakiness=5:show=1,preview + * transcode -V -J stabilize=shakiness=5:show=1,preview * -i inp.mpeg -y null,null -o dummy * all parameters are optional */ @@ -46,7 +46,7 @@ TC_MODULE_FEATURE_FILTER|TC_MODULE_FEATURE_VIDEO #define MOD_FLAGS \ TC_MODULE_FLAG_RECONFIGURABLE | TC_MODULE_FLAG_DELAY - + #include "transcode.h" #include "filter.h" #include "libtc/libtc.h" @@ -90,11 +90,11 @@ TCList* transs; Field* fields; - + /* Options */ /* maximum number of pixels we expect the shift of subsequent frames */ - int maxshift; + int maxshift; int stepsize; // stepsize of field transformation detection int allowmax; // 1 if maximal shift is allowed int algo; // algorithm to use @@ -103,15 +103,15 @@ int field_size; // size = min(sd->width, sd->height)/10; int field_rows; // number of rows /* if 1 and 2 then the fields and transforms are shown in the frames */ - int show; + int show; /* measurement fields with lower contrast are discarded */ - double contrast_threshold; + double contrast_threshold; /* maximal difference in angles of fields */ double maxanglevariation; /* meta parameter for maxshift and fieldsize between 1 and 10 */ - int shakiness; + int shakiness; int accuracy; // meta parameter for number of fields between 1 and 10 - + int t; char* result; FILE* f; @@ -119,11 +119,11 @@ char conf_str[TC_BUF_MIN]; } StabData; -/* type for a function that calculates the transformation of a certain field +/* type for a function that calculates the transformation of a certain field */ typedef Transform (*calcFieldTransFunc)(StabData*, const Field*, int); -/* type for a function that calculates the contrast of a certain field +/* type for a function that calculates the contrast of a certain field */ typedef double (*contrastSubImgFunc)(StabData* sd, const Field* field); @@ -131,7 +131,7 @@ "Overview:\n" " Generates a file with relative transform information\n" " (translation, rotation) about subsequent frames." - " See also transform.\n" + " See also transform.\n" "Options\n" " 'result' path to the file used to write the transforms\n" " (def:inputfile.stab)\n" @@ -149,14 +149,14 @@ " 'help' print this help message\n"; int initFields(StabData* sd); -double compareImg(unsigned char* I1, unsigned char* I2, +double compareImg(unsigned char* I1, unsigned char* I2, int width, int height, int bytesPerPixel, int d_x, int d_y); -double compareSubImg(unsigned char* const I1, unsigned char* const I2, - const Field* field, +double compareSubImg(unsigned char* const I1, unsigned char* const I2, + const Field* field, int width, int height, int bytesPerPixel,int d_x,int d_y); double contrastSubImgYUV(StabData* sd, const Field* field); double contrastSubImgRGB(StabData* sd, const Field* field); -double contrastSubImg(unsigned char* const I, const Field* field, +double contrastSubImg(unsigned char* const I, const Field* field, int width, int height, int bytesPerPixel); int cmp_contrast_idx(const void *ci1, const void* ci2); TCList* selectfields(StabData* sd, contrastSubImgFunc contrastfunc); @@ -165,9 +165,9 @@ Transform calcShiftYUVSimple(StabData* sd); double calcAngle(StabData* sd, Field* field, Transform* t, int center_x, int center_y); -Transform calcFieldTransYUV(StabData* sd, const Field* field, +Transform calcFieldTransYUV(StabData* sd, const Field* field, int fieldnum); -Transform calcFieldTransRGB(StabData* sd, const Field* field, +Transform calcFieldTransRGB(StabData* sd, const Field* field, int fieldnum); Transform calcTransFields(StabData* sd, calcFieldTransFunc fieldfunc, contrastSubImgFunc contrastfunc); @@ -176,7 +176,7 @@ void drawFieldScanArea(StabData* sd, const Field* field, const Transform* t); void drawField(StabData* sd, const Field* field, const Transform* t); void drawFieldTrans(StabData* sd, const Field* field, const Transform* t); -void drawBox(unsigned char* I, int width, int height, int bytesPerPixel, +void drawBox(unsigned char* I, int width, int height, int bytesPerPixel, int x, int y, int sizex, int sizey, unsigned char color); void addTrans(StabData* sd, Transform sl); @@ -191,7 +191,7 @@ /** initialise measurement fields on the frame. - The size of the fields and the maxshift is used to + The size of the fields and the maxshift is used to calculate an optimal distribution in the frame. */ int initFields(StabData* sd) @@ -202,7 +202,7 @@ // make sure that the remaining rows have the same length sd->field_num = rows*cols; sd->field_rows = rows; - // tc_log_msg(MOD_NAME, "field setup: rows: %i cols: %i Total: %i fields", + // tc_log_msg(MOD_NAME, "field setup: rows: %i cols: %i Total: %i fields", // rows, cols, sd->field_num); if (!(sd->fields = tc_malloc(sizeof(Field) * sd->field_num))) { @@ -234,13 +234,13 @@ \param d_x shift in x direction \param d_y shift in y direction */ -double compareImg(unsigned char* I1, unsigned char* I2, +double compareImg(unsigned char* I1, unsigned char* I2, int width, int height, int bytesPerPixel, int d_x, int d_y) { int i, j; unsigned char* p1 = NULL; unsigned char* p2 = NULL; - long int sum = 0; + long int sum = 0; int effectWidth = width - abs(d_x); int effectHeight = height - abs(d_y); @@ -256,47 +256,47 @@ for (i = 0; i < effectHeight; i++) { p1 = I1; p2 = I2; - if (d_y > 0 ){ + if (d_y > 0 ){ p1 += (i + d_y) * width * bytesPerPixel; p2 += i * width * bytesPerPixel; } else { p1 += i * width * bytesPerPixel; p2 += (i - d_y) * width * bytesPerPixel; } - if (d_x > 0) { + if (d_x > 0) { p1 += d_x * bytesPerPixel; } else { - p2 -= d_x * bytesPerPixel; + p2 -= d_x * bytesPerPixel; } // TODO: use some mmx or sse stuff here for (j = 0; j < effectWidth * bytesPerPixel; j++) { /* debugging code continued */ /* fwrite(p1,1,1,pic1);fwrite(p1,1,1,pic1);fwrite(p1,1,1,pic1); - fwrite(p2,1,1,pic2);fwrite(p2,1,1,pic2);fwrite(p2,1,1,pic2); + fwrite(p2,1,1,pic2);fwrite(p2,1,1,pic2);fwrite(p2,1,1,pic2); */ sum += abs((int)*p1 - (int)*p2); p1++; - p2++; + p2++; } } /* fclose(pic1); - fclose(pic2); + fclose(pic2); */ return sum/((double) effectWidth * effectHeight * bytesPerPixel); } /** - compares a small part of two given images + compares a small part of two given images and returns the average absolute difference. - Field center, size and shift have to be choosen, + Field center, size and shift have to be choosen, so that no clipping is required - - \param field Field specifies position(center) and size of subimage + + \param field Field specifies position(center) and size of subimage \param d_x shift in x direction - \param d_y shift in y direction + \param d_y shift in y direction */ -double compareSubImg(unsigned char* const I1, unsigned char* const I2, - const Field* field, +double compareSubImg(unsigned char* const I1, unsigned char* const I2, + const Field* field, int width, int height, int bytesPerPixel, int d_x, int d_y) { int k, j; @@ -312,7 +312,7 @@ for (k = 0; k < field->size * bytesPerPixel; k++) { sum += abs((int)*p1 - (int)*p2); p1++; - p2++; + p2++; } p1 += (width - field->size) * bytesPerPixel; p2 += (width - field->size) * bytesPerPixel; @@ -325,27 +325,27 @@ return contrastSubImg(sd->curr,field,sd->width,sd->height,1); } -/** - \see contrastSubImg three times called with bytesPerPixel=3 - for all channels +/** + \see contrastSubImg three times called with bytesPerPixel=3 + for all channels */ double contrastSubImgRGB(StabData* sd, const Field* field){ unsigned char* const I = sd->curr; - return ( contrastSubImg(I, field,sd->width,sd->height,3) + return ( contrastSubImg(I, field,sd->width,sd->height,3) + contrastSubImg(I+1,field,sd->width,sd->height,3) + contrastSubImg(I+2,field,sd->width,sd->height,3))/3; } /** calculates Michelson-contrast in the given small part of the given image - - \param I pointer to framebuffer - \param field Field specifies position(center) and size of subimage + + \param I pointer to framebuffer + \param field Field specifies position(center) and size of subimage \param width width of frame \param height height of frame \param bytesPerPixel calc contrast for only for first channel */ -double contrastSubImg(unsigned char* const I, const Field* field, +double contrastSubImg(unsigned char* const I, const Field* field, int width, int height, int bytesPerPixel) { int k, j; @@ -376,23 +376,23 @@ { int x = 0, y = 0; int i, j; - double minerror = 1e20; + double minerror = 1e20; for (i = -sd->maxshift; i <= sd->maxshift; i++) { for (j = -sd->maxshift; j <= sd->maxshift; j++) { - double error = compareImg(sd->curr, sd->prev, + double error = compareImg(sd->curr, sd->prev, sd->width, sd->height, 3, i, j); if (error < minerror) { minerror = error; x = i; y = j; - } + } } - } + } return new_transform(x, y, 0, 0, 0); } -/** tries to register current frame onto previous frame. +/** tries to register current frame onto previous frame. (only the luminance is used) This is the most simple algorithm: shift images to all possible positions and calc summed error @@ -412,17 +412,17 @@ #endif // we only use the luminance part of the image - Y_c = sd->curr; + Y_c = sd->curr; // Cb_c = sd->curr + sd->width*sd->height; //Cr_c = sd->curr + 5*sd->width*sd->height/4; - Y_p = sd->prev; + Y_p = sd->prev; //Cb_p = sd->prev + sd->width*sd->height; //Cr_p = sd->prev + 5*sd->width*sd->height/4; - double minerror = 1e20; + double minerror = 1e20; for (i = -sd->maxshift; i <= sd->maxshift; i++) { for (j = -sd->maxshift; j <= sd->maxshift; j++) { - double error = compareImg(Y_c, Y_p, + double error = compareImg(Y_c, Y_p, sd->width, sd->height, 1, i, j); #ifdef STABVERBOSE fprintf(f, "%i %i %f\n", i, j, error); @@ -431,9 +431,9 @@ minerror = error; x = i; y = j; - } + } } - } + } #ifdef STABVERBOSE fclose(f); tc_log_msg(MOD_NAME, "Minerror: %f\n", minerror); @@ -443,23 +443,23 @@ -/* calculates rotation angle for the given transform and +/* calculates rotation angle for the given transform and * field with respect to the given center-point */ -double calcAngle(StabData* sd, Field* field, Transform* t, +double calcAngle(StabData* sd, Field* field, Transform* t, int center_x, int center_y) { - // we better ignore fields that are to close to the rotation center + // we better ignore fields that are to close to the rotation center if (abs(field->x - center_x) + abs(field->y - center_y) < sd->maxshift) { return 0; } else { - // double r = sqrt(field->x*field->x + field->y*field->y); + // double r = sqrt(field->x*field->x + field->y*field->y); double a1 = atan2(field->y - center_y, field->x - center_x); - double a2 = atan2(field->y - center_y + t->y, + double a2 = atan2(field->y - center_y + t->y, field->x - center_x + t->x); double diff = a2 - a1; - return (diff>M_PI) ? diff - 2*M_PI - : ( (diff<-M_PI) ? diff + 2*M_PI : diff); + return (diff>M_PI) ? diff - 2*M_PI + : ( (diff<-M_PI) ? diff + 2*M_PI : diff); } } @@ -482,65 +482,65 @@ /* return t; */ /* } */ #ifdef STABVERBOSE - // printf("%i %i %f\n", sd->t, fieldnum, contr); + // printf("%i %i %f\n", sd->t, fieldnum, contr); FILE *f = NULL; char buffer[32]; tc_snprintf(buffer, sizeof(buffer), "f%04i_%02i.dat", sd->t, fieldnum); f = fopen(buffer, "w"); fprintf(f, "# splot \"%s\"\n", buffer); -#endif +#endif - double minerror = 1e10; + double minerror = 1e10; double error = 1e10; for (i = -sd->maxshift; i <= sd->maxshift; i += sd->stepsize) { for (j = -sd->maxshift; j <= sd->maxshift; j += sd->stepsize) { - error = compareSubImg(Y_c, Y_p, field, + error = compareSubImg(Y_c, Y_p, field, sd->width, sd->height, 1, i, j); #ifdef STABVERBOSE fprintf(f, "%i %i %f\n", i, j, error); -#endif +#endif if (error < minerror) { minerror = error; tx = i; ty = j; - } + } } } if (sd->stepsize > 1) { // make fine grain check around the best match int txc=tx; // save the shifts - int tyc=ty; + int tyc=ty; int r = sd->stepsize - 1; for (i = txc - r; i <= txc + r; i += 1) { for (j = tyc - r; j <= tyc + r; j += 1) { - if (i == txc && j == tyc) + if (i == txc && j == tyc) continue; //no need to check this since already done - error = compareSubImg(Y_c, Y_p, field, + error = compareSubImg(Y_c, Y_p, field, sd->width, sd->height, 1, i, j); -#ifdef STABVERBOSE +#ifdef STABVERBOSE fprintf(f, "%i %i %f\n", i, j, error); -#endif +#endif if (error < minerror){ minerror = error; tx = i; ty = j; - } + } } } } -#ifdef STABVERBOSE - fclose(f); +#ifdef STABVERBOSE + fclose(f); tc_log_msg(MOD_NAME, "Minerror: %f\n", minerror); #endif if (!sd->allowmax && fabs(tx) >= sd->maxshift+sd->stepsize) { -#ifdef STABVERBOSE +#ifdef STABVERBOSE tc_log_msg(MOD_NAME, "maximal x shift "); #endif tx = 0; } if (!sd->allowmax && fabs(ty) == sd->maxshift+sd->stepsize) { -#ifdef STABVERBOSE +#ifdef STABVERBOSE tc_log_msg(MOD_NAME, "maximal y shift "); #endif ty = 0; @@ -551,7 +551,7 @@ return t; } -/* calculates the optimal transformation for one field in RGB +/* calculates the optimal transformation for one field in RGB * slower than the YUV version because it uses all three color channels */ Transform calcFieldTransRGB(StabData* sd, const Field* field, int fieldnum) @@ -559,28 +559,28 @@ Transform t = null_transform(); uint8_t *I_c = sd->curr, *I_p = sd->prev; int i, j; - - double minerror = 1e20; + + double minerror = 1e20; for (i = -sd->maxshift; i <= sd->maxshift; i += 2) { - for (j=-sd->maxshift; j <= sd->maxshift; j += 2) { - double error = compareSubImg(I_c, I_p, field, + for (j=-sd->maxshift; j <= sd->maxshift; j += 2) { + double error = compareSubImg(I_c, I_p, field, sd->width, sd->height, 3, i, j); if (error < minerror) { minerror = error; t.x = i; t.y = j; - } + } } } for (i = t.x - 1; i <= t.x + 1; i += 2) { for (j = -t.y - 1; j <= t.y + 1; j += 2) { - double error = compareSubImg(I_c, I_p, field, + double error = compareSubImg(I_c, I_p, field, sd->width, sd->height, 3, i, j); if (error < minerror) { minerror = error; t.x = i; t.y = j; - } + } } } if (!sd->allowmax && fabs(t.x) == sd->maxshift) { @@ -592,8 +592,8 @@ return t; } -/* compares contrast_idx structures respect to the contrast - (for sort function) +/* compares contrast_idx structures respect to the contrast + (for sort function) */ int cmp_contrast_idx(const void *ci1, const void* ci2) { @@ -610,7 +610,7 @@ int i,j; TCList* goodflds = tc_list_new(0); contrast_idx *ci = tc_malloc(sizeof(contrast_idx) * sd->field_num); - + // we split all fields into row+1 segments and take from each segment // the best fields int numsegms = (sd->field_rows+1); @@ -619,12 +619,12 @@ contrast_idx *ci_segms = tc_malloc(sizeof(contrast_idx) * sd->field_num); int remaining = 0; // calculate contrast for each field - for (i = 0; i < sd->field_num; i++) { + for (i = 0; i < sd->field_num; i++) { ci[i].contrast = contrastfunc(sd, &sd->fields[i]); ci[i].index=i; if(ci[i].contrast < sd->contrast_threshold) ci[i].contrast = 0; // else printf("%i %lf\n", ci[i].index, ci[i].contrast); - } + } memcpy(ci_segms, ci, sizeof(contrast_idx) * sd->field_num); // get best fields from each segment @@ -635,34 +635,34 @@ //printf("Segment: %i: %i-%i\n", i, startindex, endindex); // sort within segment - qsort(ci_segms+startindex, endindex-startindex, - sizeof(contrast_idx), cmp_contrast_idx); + qsort(ci_segms+startindex, endindex-startindex, + sizeof(contrast_idx), cmp_contrast_idx); // take maxfields/numsegms for(j=0; j<sd->maxfields/numsegms; j++){ if(startindex+j >= endindex) continue; - // printf("%i %lf\n", ci_segms[startindex+j].index, + // printf("%i %lf\n", ci_segms[startindex+j].index, // ci_segms[startindex+j].contrast); - if(ci_segms[startindex+j].contrast > 0){ + if(ci_segms[startindex+j].contrast > 0){ tc_list_append_dup(goodflds, &ci[ci_segms[startindex+j].index], sizeof(contrast_idx)); // don't consider them in the later selection process - ci_segms[startindex+j].contrast=0; - } + ci_segms[startindex+j].contrast=0; + } } } // check whether enough fields are selected // printf("Phase2: %i\n", tc_list_size(goodflds)); - remaining = sd->maxfields - tc_list_size(goodflds); + remaining = sd->maxfields - tc_list_size(goodflds); if(remaining > 0){ // take the remaining from the leftovers - qsort(ci_segms, sd->field_num, + qsort(ci_segms, sd->field_num, sizeof(contrast_idx), cmp_contrast_idx); for(j=0; j < remaining; j++){ if(ci_segms[j].contrast > 0){ - tc_list_append_dup(goodflds, &ci_segms[j], sizeof(contrast_idx)); - } + tc_list_append_dup(goodflds, &ci_segms[j], sizeof(contrast_idx)); + } } - } + } // printf("Ende: %i\n", tc_list_size(goodflds)); tc_free(ci); tc_free(ci_segms); @@ -671,11 +671,11 @@ -/* tries to register current frame onto previous frame. +/* tries to register current frame onto previous frame. * Algorithm: * check all fields for vertical and horizontal transformation * use minimal difference of all possible positions - * discards fields with low contrast + * discards fields with low contrast * select maxfields field according to their contrast * calculate shift as cleaned mean of all remaining fields * calculate rotation angle of each field in respect to center of fields @@ -698,16 +698,16 @@ file = fopen(buffer, "w"); fprintf(file, "# plot \"%s\" w l, \"\" every 2:1:0\n", buffer); #endif - + TCList* goodflds = selectfields(sd, contrastfunc); - // use all "good" fields and calculate optimal match to previous frame + // use all "good" fields and calculate optimal match to previous frame contrast_idx* f; while((f = (contrast_idx*)tc_list_pop(goodflds,0)) != 0){ int i = f->index; t = fieldfunc(sd, &sd->fields[i], i); // e.g. calcFieldTransYUV #ifdef STABVERBOSE - fprintf(file, "%i %i\n%f %f %i\n \n\n", sd->fields[i].x, sd->fields[i].y, + fprintf(file, "%i %i\n%f %f %i\n \n\n", sd->fields[i].x, sd->fields[i].y, sd->fields[i].x + t.x, sd->fields[i].y + t.y, t.extra); #endif if (t.extra != -1){ // ignore if extra == -1 (unused at the moment) @@ -719,37 +719,37 @@ tc_list_fini(goodflds); t = null_transform(); - num_trans = index; // amount of transforms we actually have + num_trans = index; // amount of transforms we actually have if (num_trans < 1) { tc_log_warn(MOD_NAME, "too low contrast! No field remains.\n \ (no translations are detected in frame %i)", sd->t); return t; } - + int center_x = 0; int center_y = 0; // calc center point of all remaining fields for (i = 0; i < num_trans; i++) { center_x += fs[i]->x; - center_y += fs[i]->y; - } + center_y += fs[i]->y; + } center_x /= num_trans; - center_y /= num_trans; - + center_y /= num_trans; + if (sd->show){ // draw fields and transforms into frame. - // this has to be done one after another to handle possible overlap + // this has to be done one after another to handle possible overlap if (sd->show > 1) { for (i = 0; i < num_trans; i++) - drawFieldScanArea(sd, fs[i], &ts[i]); + drawFieldScanArea(sd, fs[i], &ts[i]); } for (i = 0; i < num_trans; i++) - drawField(sd, fs[i], &ts[i]); + drawField(sd, fs[i], &ts[i]); for (i = 0; i < num_trans; i++) - drawFieldTrans(sd, fs[i], &ts[i]); - } + drawFieldTrans(sd, fs[i], &ts[i]); + } /* median over all transforms t= median_xy_transform(ts, sd->field_num);*/ - // cleaned mean + // cleaned mean t = cleanmean_xy_transform(ts, num_trans); // substract avg @@ -759,8 +759,8 @@ // figure out angle if (sd->field_num < 6) { // the angle calculation is inaccurate for 5 and less fields - t.alpha = 0; - } else { + t.alpha = 0; + } else { for (i = 0; i < num_trans; i++) { angles[i] = calcAngle(sd, fs[i], &ts[i], center_x, center_y); } @@ -768,7 +768,7 @@ t.alpha = -cleanmean(angles, num_trans, &min, &max); if(max-min>sd->maxanglevariation){ t.alpha=0; - tc_log_info(MOD_NAME, "too large variation in angle(%f)\n", + tc_log_info(MOD_NAME, "too large variation in angle(%f)\n", max-min); } } @@ -776,8 +776,8 @@ double p_x = (center_x - sd->width/2); double p_y = (center_y - sd->height/2); t.x += (cos(t.alpha)-1)*p_x - sin(t.alpha)*p_y; - t.y += sin(t.alpha)*p_x + (cos(t.alpha)-1)*p_y; - + t.y += sin(t.alpha)*p_x + (cos(t.alpha)-1)*p_y; + #ifdef STABVERBOSE fclose(file); #endif @@ -788,15 +788,15 @@ void drawFieldScanArea(StabData* sd, const Field* field, const Transform* t){ if(!sd->vob->im_v_codec == CODEC_YUV) return; - drawBox(sd->curr, sd->width, sd->height, 1, field->x, field->y, - field->size+2*sd->maxshift, field->size+2*sd->maxshift, 80); + drawBox(sd->curr, sd->width, sd->height, 1, field->x, field->y, + field->size+2*sd->maxshift, field->size+2*sd->maxshift, 80); } /** draws the field */ void drawField(StabData* sd, const Field* field, const Transform* t){ if(!sd->vob->im_v_codec == CODEC_YUV) return; - drawBox(sd->curr, sd->width, sd->height, 1, field->x, field->y, + drawBox(sd->curr, sd->width, sd->height, 1, field->x, field->y, field->size, field->size, t->extra == -1 ? 100 : 40); } @@ -804,20 +804,20 @@ void drawFieldTrans(StabData* sd, const Field* field, const Transform* t){ if(!sd->vob->im_v_codec == CODEC_YUV) return; - drawBox(sd->curr, sd->width, sd->height, 1, + drawBox(sd->curr, sd->width, sd->height, 1, field->x, field->y, 5, 5, 128); // draw center - drawBox(sd->curr, sd->width, sd->height, 1, + drawBox(sd->curr, sd->width, sd->height, 1, field->x + t->x, field->y + t->y, 8, 8, 250); // draw translation } /** * draws a box at the given position x,y (center) in the given color - (the same for all channels) + (the same for all channels) */ -void drawBox(unsigned char* I, int width, int height, int bytesPerPixel, +void drawBox(unsigned char* I, int width, int height, int bytesPerPixel, int x, int y, int sizex, int sizey, unsigned char color){ - - unsigned char* p = NULL; + + unsigned char* p = NULL; int j,k; p = I + ((x - sizex/2) + (y - sizey/2)*width)*bytesPerPixel; for (j = 0; j < sizey; j++){ @@ -907,17 +907,17 @@ */ static int stabilize_configure(TCModuleInstance *self, const char *options, vob_t *vob) -{ +{ StabData *sd = NULL; TC_MODULE_SELF_CHECK(self, "configure"); char* filenamecopy, *filebasename; sd = self->userdata; - /* sd->framesize = sd->vob->im_v_width * MAX_PLANES * + /* sd->framesize = sd->vob->im_v_width * MAX_PLANES * sizeof(char) * 2 * sd->vob->im_v_height * 2; */ - sd->framesize = sd->vob->im_v_size; - sd->prev = tc_zalloc(sd->framesize); + sd->framesize = sd->vob->im_v_size; + sd->prev = tc_zalloc(sd->framesize); if (!sd->prev) { tc_log_error(MOD_NAME, "malloc failed"); return TC_ERROR; @@ -929,7 +929,7 @@ sd->hasSeenOneFrame = 0; sd->transs = 0; - + // Options sd->stepsize = 6; sd->allowmax = 0; @@ -949,11 +949,11 @@ sd->shakiness = 4; sd->field_size = TC_MIN(sd->width, sd->height)/12; sd->show = 0; - sd->contrast_threshold = 0.3; + sd->contrast_threshold = 0.3; sd->maxanglevariation = 1; - - if (options != NULL) { - // for some reason this plugin is called in the old fashion + + if (options != NULL) { + // for some reason this plugin is called in the old fashion // (not with inspect). Anyway we support both ways of getting help. if(optstr_lookup(options, "help")) { tc_log_info(MOD_NAME,stabilize_help); @@ -972,9 +972,9 @@ sd->accuracy = TC_MIN(15,TC_MAX(1,sd->accuracy)); if(sd->accuracy < sd->shakiness/2){ tc_log_info(MOD_NAME, "accuracy should not be lower than shakiness/2"); - sd->accuracy = sd->shakiness/2; + sd->accuracy = sd->shakiness/2; } - + if (verbose) { tc_log_info(MOD_NAME, "Image Stabilization Settings:"); tc_log_info(MOD_NAME, " shakiness = %d", sd->shakiness); @@ -989,10 +989,10 @@ // shift and size: shakiness 1: height/40; 10: height/4 sd->maxshift = TC_MAX(4,(TC_MIN(sd->width, sd->height)*sd->shakiness)/40); sd->field_size = TC_MAX(4,(TC_MIN(sd->width, sd->height)*sd->shakiness)/40); - - tc_log_info(MOD_NAME, "Fieldsize: %i, Maximal translation: %i pixel", + + tc_log_info(MOD_NAME, "Fieldsize: %i, Maximal translation: %i pixel", sd->field_size, sd->maxshift); - if (sd->algo==1) { + if (sd->algo==1) { // initialize measurement fields. field_num is set here. if (!initFields(sd)) { return TC_ERROR; @@ -1005,14 +1005,14 @@ if (sd->f == NULL) { tc_log_error(MOD_NAME, "cannot open result file %s!\n", sd->result); return TC_ERROR; - } + } if (sd->show) sd->currcopy = tc_zalloc(sd->framesize); /* load unsharp filter to smooth the frames. This allows larger stepsize.*/ char unsharp_param[128]; int masksize = TC_MIN(13,sd->stepsize*1.8); // only works up to 13. - sprintf(unsharp_param,"luma=-1:luma_matrix=%ix%i:pre=1", + sprintf(unsharp_param,"luma=-1:luma_matrix=%ix%i:pre=1", masksize, masksize); if (!tc_filter_add("unsharp", unsharp_param)) { tc_log_warn(MOD_NAME, "cannot load unsharp filter!"); @@ -1027,26 +1027,26 @@ * See tcmodule-data.h for function details. */ -static int stabilize_filter_video(TCModuleInstance *self, +static int stabilize_filter_video(TCModuleInstance *self, vframe_list_t *frame) { StabData *sd = NULL; - + TC_MODULE_SELF_CHECK(self, "filter_video"); TC_MODULE_SELF_CHECK(frame, "filter_video"); - - sd = self->userdata; + + sd = self->userdata; if(sd->show) // save the buffer to restore at the end for prev memcpy(sd->currcopy, frame->video_buf, sd->framesize); - + if (sd->hasSeenOneFrame) { sd->curr = frame->video_buf; if (sd->vob->im_v_codec == CODEC_RGB) { if (sd->algo == 0) addTrans(sd, calcShiftRGBSimple(sd)); else if (sd->algo == 1) - addTrans(sd, calcTransFields(sd, calcFieldTransRGB, + addTrans(sd, calcTransFields(sd, calcFieldTransRGB, contrastSubImgRGB)); } else if (sd->vob->im_v_codec == CODEC_YUV) { if (sd->algo == 0) @@ -1063,7 +1063,7 @@ sd->hasSeenOneFrame = 1; addTrans(sd, null_transform()); } - + if(!sd->show) { // copy current frame to prev for next frame comparison memcpy(sd->prev, frame->video_buf, sd->framesize); } else { // use the copy because we changed the original frame @@ -1089,7 +1089,7 @@ struct iterdata ID; ID.counter = 0; ID.f = sd->f; - // write parameters as comments to file + // write parameters as comments to file fprintf(sd->f, "# accuracy = %d\n", sd->accuracy); fprintf(sd->f, "# shakiness = %d\n", sd->shakiness); fprintf(sd->f, "# stepsize = %d\n", sd->stepsize); @@ -1100,7 +1100,7 @@ fprintf(sd->f, "# Transforms\n#C FrameNr x y alpha zoom extra\n"); // and all transforms tc_list_foreach(sd->transs, stabilize_dump_trans, &ID); - + fclose(sd->f); sd->f = NULL; } @@ -1133,7 +1133,7 @@ const char *param, const char **value) { StabData *sd = NULL; - + TC_MODULE_SELF_CHECK(self, "inspect"); TC_MODULE_SELF_CHECK(param, "inspect"); TC_MODULE_SELF_CHECK(value, "inspect"); @@ -1143,7 +1143,7 @@ *value = stabilize_help; } CHECKPARAM("shakiness","shakiness=%d", sd->shakiness); - CHECKPARAM("accuracy", "accuracy=%d", sd->accuracy); + CHECKPARAM("accuracy", "accuracy=%d", sd->accuracy); CHECKPARAM("stepsize", "stepsize=%d", sd->stepsize); CHECKPARAM("allowmax", "allowmax=%d", sd->allowmax); CHECKPARAM("algo", "algo=%d", sd->algo); @@ -1151,13 +1151,13 @@ return TC_OK; } -static const TCCodecID stabilize_codecs_in[] = { - TC_CODEC_YUV420P, TC_CODEC_YUV422P, TC_CODEC_RGB, TC_CODEC_ERROR +static const TCCodecID stabilize_codecs_in[] = { + TC_CODEC_YUV420P, TC_CODEC_YUV422P, TC_CODEC_RGB, TC_CODEC_ERROR }; -static const TCCodecID stabilize_codecs_out[] = { - TC_CODEC_YUV420P, TC_CODEC_YUV422P, TC_CODEC_RGB, TC_CODEC_ERROR +static const TCCodecID stabilize_codecs_out[] = { + TC_CODEC_YUV420P, TC_CODEC_YUV422P, TC_CODEC_RGB, TC_CODEC_ERROR }; -TC_MODULE_FILTER_FORMATS(stabilize); +TC_MODULE_FILTER_FORMATS(stabilize); TC_MODULE_INFO(stabilize);