Originally committed as revision 888 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -79,6 +79,10 @@ static AVInputFormat *file_iformat; | |||||
| static AVOutputFormat *file_oformat; | static AVOutputFormat *file_oformat; | ||||
| static int frame_width = 160; | static int frame_width = 160; | ||||
| static int frame_height = 128; | static int frame_height = 128; | ||||
| static int frame_topBand = 0; | |||||
| static int frame_bottomBand = 0; | |||||
| static int frame_leftBand = 0; | |||||
| static int frame_rightBand = 0; | |||||
| static int frame_rate = 25 * FRAME_RATE_BASE; | static int frame_rate = 25 * FRAME_RATE_BASE; | ||||
| static int video_bit_rate = 200*1000; | static int video_bit_rate = 200*1000; | ||||
| static int video_bit_rate_tolerance = 4000*1000; | static int video_bit_rate_tolerance = 4000*1000; | ||||
| @@ -821,9 +825,11 @@ static int av_encode(AVFormatContext **output_files, | |||||
| ost->pict_tmp.linesize[1] = codec->width / 2; | ost->pict_tmp.linesize[1] = codec->width / 2; | ||||
| ost->pict_tmp.linesize[2] = codec->width / 2; | ost->pict_tmp.linesize[2] = codec->width / 2; | ||||
| ost->img_resample_ctx = img_resample_init( | |||||
| ost->img_resample_ctx = img_resample_full_init( | |||||
| ost->st->codec.width, ost->st->codec.height, | ost->st->codec.width, ost->st->codec.height, | ||||
| ist->st->codec.width, ist->st->codec.height); | |||||
| ist->st->codec.width, ist->st->codec.height, | |||||
| frame_topBand, frame_bottomBand, | |||||
| frame_leftBand, frame_rightBand); | |||||
| } | } | ||||
| ost->encoding_needed = 1; | ost->encoding_needed = 1; | ||||
| ist->decoding_needed = 1; | ist->decoding_needed = 1; | ||||
| @@ -1382,6 +1388,79 @@ void opt_frame_rate(const char *arg) | |||||
| frame_rate = (int)(strtod(arg, 0) * FRAME_RATE_BASE); | frame_rate = (int)(strtod(arg, 0) * FRAME_RATE_BASE); | ||||
| } | } | ||||
| void opt_frame_crop_top(const char *arg) | |||||
| { | |||||
| frame_topBand = atoi(arg); | |||||
| if (frame_topBand < 0) { | |||||
| fprintf(stderr, "Incorrect top crop size\n"); | |||||
| exit(1); | |||||
| } | |||||
| if ((frame_topBand % 2) != 0) { | |||||
| fprintf(stderr, "Top crop size must be a multiple of 2\n"); | |||||
| exit(1); | |||||
| } | |||||
| if ((frame_topBand) >= frame_height){ | |||||
| fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n"); | |||||
| exit(1); | |||||
| } | |||||
| frame_height -= frame_topBand; | |||||
| } | |||||
| void opt_frame_crop_bottom(const char *arg) | |||||
| { | |||||
| frame_bottomBand = atoi(arg); | |||||
| if (frame_bottomBand < 0) { | |||||
| fprintf(stderr, "Incorrect bottom crop size\n"); | |||||
| exit(1); | |||||
| } | |||||
| if ((frame_bottomBand % 2) != 0) { | |||||
| fprintf(stderr, "Bottom crop size must be a multiple of 2\n"); | |||||
| exit(1); | |||||
| } | |||||
| if ((frame_bottomBand) >= frame_height){ | |||||
| fprintf(stderr, "Vertical crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n"); | |||||
| exit(1); | |||||
| } | |||||
| frame_height -= frame_bottomBand; | |||||
| } | |||||
| void opt_frame_crop_left(const char *arg) | |||||
| { | |||||
| frame_leftBand = atoi(arg); | |||||
| if (frame_leftBand < 0) { | |||||
| fprintf(stderr, "Incorrect left crop size\n"); | |||||
| exit(1); | |||||
| } | |||||
| if ((frame_leftBand % 2) != 0) { | |||||
| fprintf(stderr, "Left crop size must be a multiple of 2\n"); | |||||
| exit(1); | |||||
| } | |||||
| if ((frame_leftBand) >= frame_width){ | |||||
| fprintf(stderr, "Horizontal crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n"); | |||||
| exit(1); | |||||
| } | |||||
| frame_width -= frame_leftBand; | |||||
| } | |||||
| void opt_frame_crop_right(const char *arg) | |||||
| { | |||||
| frame_rightBand = atoi(arg); | |||||
| if (frame_rightBand < 0) { | |||||
| fprintf(stderr, "Incorrect right crop size\n"); | |||||
| exit(1); | |||||
| } | |||||
| if ((frame_rightBand % 2) != 0) { | |||||
| fprintf(stderr, "Right crop size must be a multiple of 2\n"); | |||||
| exit(1); | |||||
| } | |||||
| if ((frame_rightBand) >= frame_width){ | |||||
| fprintf(stderr, "Horizontal crop dimensions are outside the range of the original image.\nRemember to crop first and scale second.\n"); | |||||
| exit(1); | |||||
| } | |||||
| frame_width -= frame_rightBand; | |||||
| } | |||||
| void opt_frame_size(const char *arg) | void opt_frame_size(const char *arg) | ||||
| { | { | ||||
| parse_image_size(&frame_width, &frame_height, arg); | parse_image_size(&frame_width, &frame_height, arg); | ||||
| @@ -2135,6 +2214,10 @@ const OptionDef options[] = { | |||||
| { "b", HAS_ARG, {(void*)opt_video_bitrate}, "set video bitrate (in kbit/s)", "bitrate" }, | { "b", HAS_ARG, {(void*)opt_video_bitrate}, "set video bitrate (in kbit/s)", "bitrate" }, | ||||
| { "r", HAS_ARG, {(void*)opt_frame_rate}, "set frame rate (in Hz)", "rate" }, | { "r", HAS_ARG, {(void*)opt_frame_rate}, "set frame rate (in Hz)", "rate" }, | ||||
| { "s", HAS_ARG, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" }, | { "s", HAS_ARG, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" }, | ||||
| { "croptop", HAS_ARG, {(void*)opt_frame_crop_top}, "set top crop band size (in pixels)", "size" }, | |||||
| { "cropbottom", HAS_ARG, {(void*)opt_frame_crop_bottom}, "set bottom crop band size (in pixels)", "size" }, | |||||
| { "cropleft", HAS_ARG, {(void*)opt_frame_crop_left}, "set left crop band size (in pixels)", "size" }, | |||||
| { "cropright", HAS_ARG, {(void*)opt_frame_crop_right}, "set right crop band size (in pixels)", "size" }, | |||||
| { "g", HAS_ARG | OPT_EXPERT, {(void*)opt_gop_size}, "set the group of picture size", "gop_size" }, | { "g", HAS_ARG | OPT_EXPERT, {(void*)opt_gop_size}, "set the group of picture size", "gop_size" }, | ||||
| { "intra", OPT_BOOL | OPT_EXPERT, {(void*)&intra_only}, "use only intra frames"}, | { "intra", OPT_BOOL | OPT_EXPERT, {(void*)&intra_only}, "use only intra frames"}, | ||||
| { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" }, | { "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" }, | ||||
| @@ -463,6 +463,12 @@ typedef struct ImgReSampleContext ImgReSampleContext; | |||||
| ImgReSampleContext *img_resample_init(int output_width, int output_height, | ImgReSampleContext *img_resample_init(int output_width, int output_height, | ||||
| int input_width, int input_height); | int input_width, int input_height); | ||||
| ImgReSampleContext *img_resample_full_init(int owidth, int oheight, | |||||
| int iwidth, int iheight, | |||||
| int topBand, int bottomBand, | |||||
| int leftBand, int rightBand); | |||||
| void img_resample(ImgReSampleContext *s, | void img_resample(ImgReSampleContext *s, | ||||
| AVPicture *output, AVPicture *input); | AVPicture *output, AVPicture *input); | ||||
| @@ -30,6 +30,7 @@ | |||||
| #define NB_PHASES (1 << PHASE_BITS) | #define NB_PHASES (1 << PHASE_BITS) | ||||
| #define NB_TAPS 4 | #define NB_TAPS 4 | ||||
| #define FCENTER 1 /* index of the center of the filter */ | #define FCENTER 1 /* index of the center of the filter */ | ||||
| //#define TEST 1 /* Test it */ | |||||
| #define POS_FRAC_BITS 16 | #define POS_FRAC_BITS 16 | ||||
| #define POS_FRAC (1 << POS_FRAC_BITS) | #define POS_FRAC (1 << POS_FRAC_BITS) | ||||
| @@ -39,7 +40,7 @@ | |||||
| #define LINE_BUF_HEIGHT (NB_TAPS * 4) | #define LINE_BUF_HEIGHT (NB_TAPS * 4) | ||||
| struct ImgReSampleContext { | struct ImgReSampleContext { | ||||
| int iwidth, iheight, owidth, oheight; | |||||
| int iwidth, iheight, owidth, oheight, topBand, bottomBand, leftBand, rightBand; | |||||
| int h_incr, v_incr; | int h_incr, v_incr; | ||||
| INT16 h_filters[NB_PHASES][NB_TAPS] __align8; /* horizontal filters */ | INT16 h_filters[NB_PHASES][NB_TAPS] __align8; /* horizontal filters */ | ||||
| INT16 v_filters[NB_PHASES][NB_TAPS] __align8; /* vertical filters */ | INT16 v_filters[NB_PHASES][NB_TAPS] __align8; /* vertical filters */ | ||||
| @@ -353,8 +354,8 @@ static void component_resample(ImgReSampleContext *s, | |||||
| if (++ring_y >= LINE_BUF_HEIGHT + NB_TAPS) | if (++ring_y >= LINE_BUF_HEIGHT + NB_TAPS) | ||||
| ring_y = NB_TAPS; | ring_y = NB_TAPS; | ||||
| last_src_y++; | last_src_y++; | ||||
| /* handle limit conditions : replicate line (slighly | |||||
| inefficient because we filter multiple times */ | |||||
| /* handle limit conditions : replicate line (slightly | |||||
| inefficient because we filter multiple times) */ | |||||
| y1 = last_src_y; | y1 = last_src_y; | ||||
| if (y1 < 0) { | if (y1 < 0) { | ||||
| y1 = 0; | y1 = 0; | ||||
| @@ -427,6 +428,14 @@ static void build_filter(INT16 *filter, float factor) | |||||
| ImgReSampleContext *img_resample_init(int owidth, int oheight, | ImgReSampleContext *img_resample_init(int owidth, int oheight, | ||||
| int iwidth, int iheight) | int iwidth, int iheight) | ||||
| { | |||||
| return img_resample_full_init(owidth, oheight, iwidth, iheight, 0, 0, 0, 0); | |||||
| } | |||||
| ImgReSampleContext *img_resample_full_init(int owidth, int oheight, | |||||
| int iwidth, int iheight, | |||||
| int topBand, int bottomBand, | |||||
| int leftBand, int rightBand) | |||||
| { | { | ||||
| ImgReSampleContext *s; | ImgReSampleContext *s; | ||||
| @@ -441,12 +450,16 @@ ImgReSampleContext *img_resample_init(int owidth, int oheight, | |||||
| s->oheight = oheight; | s->oheight = oheight; | ||||
| s->iwidth = iwidth; | s->iwidth = iwidth; | ||||
| s->iheight = iheight; | s->iheight = iheight; | ||||
| s->topBand = topBand; | |||||
| s->bottomBand = bottomBand; | |||||
| s->leftBand = leftBand; | |||||
| s->rightBand = rightBand; | |||||
| s->h_incr = (iwidth * POS_FRAC) / owidth; | |||||
| s->v_incr = (iheight * POS_FRAC) / oheight; | |||||
| s->h_incr = ((iwidth - leftBand - rightBand) * POS_FRAC) / owidth; | |||||
| s->v_incr = ((iheight - topBand - bottomBand) * POS_FRAC) / oheight; | |||||
| build_filter(&s->h_filters[0][0], (float)owidth / (float)iwidth); | |||||
| build_filter(&s->v_filters[0][0], (float)oheight / (float)iheight); | |||||
| build_filter(&s->h_filters[0][0], (float) owidth / (float) (iwidth - leftBand - rightBand)); | |||||
| build_filter(&s->v_filters[0][0], (float) oheight / (float) (iheight - topBand - bottomBand)); | |||||
| return s; | return s; | ||||
| fail: | fail: | ||||
| @@ -463,8 +476,9 @@ void img_resample(ImgReSampleContext *s, | |||||
| shift = (i == 0) ? 0 : 1; | shift = (i == 0) ? 0 : 1; | ||||
| component_resample(s, output->data[i], output->linesize[i], | component_resample(s, output->data[i], output->linesize[i], | ||||
| s->owidth >> shift, s->oheight >> shift, | s->owidth >> shift, s->oheight >> shift, | ||||
| input->data[i], input->linesize[i], | |||||
| s->iwidth >> shift, s->iheight >> shift); | |||||
| input->data[i] + (input->linesize[i] * (s->topBand >> shift)) + (s->leftBand >> shift), | |||||
| input->linesize[i], ((s->iwidth - s->leftBand - s->rightBand) >> shift), | |||||
| (s->iheight - s->topBand - s->bottomBand) >> shift); | |||||
| } | } | ||||
| } | } | ||||
| @@ -484,6 +498,13 @@ void *av_mallocz(int size) | |||||
| return ptr; | return ptr; | ||||
| } | } | ||||
| void av_free(void *ptr) | |||||
| { | |||||
| /* XXX: this test should not be needed on most libcs */ | |||||
| if (ptr) | |||||
| free(ptr); | |||||
| } | |||||
| /* input */ | /* input */ | ||||
| #define XSIZE 256 | #define XSIZE 256 | ||||
| #define YSIZE 256 | #define YSIZE 256 | ||||
| @@ -569,19 +590,19 @@ int main(int argc, char **argv) | |||||
| } else { | } else { | ||||
| v = ((x + y - XSIZE) * 255) / XSIZE; | v = ((x + y - XSIZE) * 255) / XSIZE; | ||||
| } | } | ||||
| img[y * XSIZE + x] = v; | |||||
| img[(YSIZE - y) * XSIZE + (XSIZE - x)] = v; | |||||
| } | } | ||||
| } | } | ||||
| save_pgm("/tmp/in.pgm", img, XSIZE, YSIZE); | save_pgm("/tmp/in.pgm", img, XSIZE, YSIZE); | ||||
| for(i=0;i<sizeof(factors)/sizeof(float);i++) { | for(i=0;i<sizeof(factors)/sizeof(float);i++) { | ||||
| fact = factors[i]; | fact = factors[i]; | ||||
| xsize = (int)(XSIZE * fact); | xsize = (int)(XSIZE * fact); | ||||
| ysize = (int)(YSIZE * fact); | |||||
| s = img_resample_init(xsize, ysize, XSIZE, YSIZE); | |||||
| ysize = (int)((YSIZE - 100) * fact); | |||||
| s = img_resample_full_init(xsize, ysize, XSIZE, YSIZE, 50 ,50); | |||||
| printf("Factor=%0.2f\n", fact); | printf("Factor=%0.2f\n", fact); | ||||
| dump_filter(&s->h_filters[0][0]); | dump_filter(&s->h_filters[0][0]); | ||||
| component_resample(s, img1, xsize, xsize, ysize, | component_resample(s, img1, xsize, xsize, ysize, | ||||
| img, XSIZE, XSIZE, YSIZE); | |||||
| img + 50 * XSIZE, XSIZE, XSIZE, YSIZE - 100); | |||||
| img_resample_close(s); | img_resample_close(s); | ||||
| sprintf(buf, "/tmp/out%d.pgm", i); | sprintf(buf, "/tmp/out%d.pgm", i); | ||||