Mercurial > mplayer.hg
changeset 5270:870e932096ff
Support for cropping in mencoder. New options:
-x0, -y0: upper-left corner of rectangle to be cut out
-xsize, -ysize: Size of rectangle to cut out
Cropping is done before scaling.
author | ksorim |
---|---|
date | Sat, 23 Mar 2002 13:13:12 +0000 |
parents | 74eb4d388495 |
children | 81f31373837e |
files | cfg-mencoder.h mencoder.c |
diffstat | 2 files changed, 141 insertions(+), 45 deletions(-) [+] |
line wrap: on
line diff
--- a/cfg-mencoder.h Sat Mar 23 10:47:13 2002 +0000 +++ b/cfg-mencoder.h Sat Mar 23 13:13:12 2002 +0000 @@ -112,6 +112,12 @@ {"x", &vo_w, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, {"y", &vo_h, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, + {"x0", &crop_x0, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, + {"y0", &crop_y0, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, + + {"xsize", &crop_width, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, + {"ysize", &crop_height, CONF_TYPE_INT, CONF_RANGE, 0, 4096, NULL}, + {"mp3file", &mp3_filename, CONF_TYPE_STRING, 0, 0, 0, NULL}, {"ac3file", &ac3_filename, CONF_TYPE_STRING, 0, 0, 0, NULL},
--- a/mencoder.c Sat Mar 23 10:47:13 2002 +0000 +++ b/mencoder.c Sat Mar 23 13:13:12 2002 +0000 @@ -97,7 +97,7 @@ #endif #include <inttypes.h> -#include "../postproc/swscale.h" +#include "postproc/swscale.h" #include "fastmemcpy.h" @@ -208,9 +208,11 @@ int lame_param_ratio=-1; // unset #endif -static int scale_srcW=0; -static int scale_srcH=0; static int vo_w=0, vo_h=0; +static int crop_width, crop_height, crop_x0 = 0, crop_y0 = 0; +static int input_pitch, input_bpp; +static SwsContext* swsContext = NULL; + //-------------------------- config stuff: m_config_t* mconfig; @@ -226,6 +228,7 @@ static int parse_end_at(struct config *conf, const char* param); static uint8_t* flip_upside_down(uint8_t* dst, const uint8_t* src, int width, int height); +static int bits_per_pixel(uint32_t fmt); #include "get_path.c" @@ -269,34 +272,71 @@ static uint32_t draw_slice(uint8_t *src[], int stride[], int w,int h, int x0,int y0){ int y; // printf("draw_slice %dx%d %d;%d\n",w,h,x0,y0); - if(scale_srcW || scale_srcH) + + if(y0 + h < crop_y0) + return 0; + + if(y0 > crop_height + crop_y0) + return 0; + + if(x0 + w < crop_x0) + return 0; + + if(x0 > crop_width + crop_x0) + return 0; + + if(y0 < crop_y0) { + src[0] += stride[0]*(crop_y0 - y0); + src[1] += stride[1]*(crop_y0 - y0)/2; + src[2] += stride[2]*(crop_y0 - y0)/2; + h -= crop_y0 - y0; + y0 = crop_y0; + } + + if(x0 < crop_x0) { + src[0] += crop_x0 - x0; + src[1] += (crop_x0 - x0)/2; + src[2] += (crop_x0 - x0)/2; + w -= crop_x0 - x0; + x0 = crop_x0; + } + + if(y0 + h > crop_y0 + crop_height) + h = crop_y0 + crop_height - y0; + + if(x0 + w > crop_x0 + crop_width) + w = crop_x0 + crop_width - x0; + + if(swsContext) { uint8_t* dstPtr[3]= { - vo_image, - vo_image + vo_w*vo_h*5/4, - vo_image + vo_w*vo_h}; - SwScale_YV12slice(src, stride, y0, h, dstPtr, vo_w, 12, scale_srcW, scale_srcH, vo_w, vo_h); + vo_image, + vo_image + vo_w*vo_h*5/4, + vo_image + vo_w*vo_h}; + int dstStride[3] = {vo_w, vo_w/2, vo_w/2}; + + swsContext->swScale(swsContext, src, stride, y0 - crop_y0, h, dstPtr, dstStride); } else { // copy Y: - for(y=0;y<h;y++){ - unsigned char* s=src[0]+stride[0]*y; - unsigned char* d=vo_image+vo_w*(y0+y)+x0; + for(y = 0; y < h; y++){ + unsigned char* s = src[0] + stride[0]*y; + unsigned char* d = vo_image + vo_w*(y0 - crop_y0 + y); memcpy(d,s,w); } x0>>=1;y0>>=1; w>>=1;h>>=1; // copy U: - for(y=0;y<h;y++){ - unsigned char* s=src[2]+stride[2]*y; - unsigned char* d=vo_image+vo_w*vo_h+(vo_w>>1)*(y0+y)+x0; + for(y = 0; y < h; y++){ + unsigned char* s = src[2] + stride[2]*y; + unsigned char* d = vo_image + vo_w*vo_h + (vo_w>>1)*(y0 - crop_y0/2 + y); memcpy(d,s,w); } // copy V: - for(y=0;y<h;y++){ - unsigned char* s=src[1]+stride[1]*y; - unsigned char* d=vo_image+vo_w*vo_h+vo_w*vo_h/4+(vo_w>>1)*(y0+y)+x0; + for(y = 0; y < h; y++){ + unsigned char* s = src[1] + stride[1]*y; + unsigned char* d = vo_image + vo_w*vo_h + vo_w*vo_h/4 + (vo_w>>1)*(y0 - crop_y0/2 + y); memcpy(d,s,w); } } // !swscaler @@ -304,10 +344,25 @@ } static uint32_t draw_frame(uint8_t *src[]){ + int y; // printf("This function shouldn't be called - report bug!\n"); // later: add YUY2->YV12 conversion here! - vo_image_ptr=src[0]; - return(0); + + if(swsContext) { + uint8_t* src_img = *src + crop_y0*input_pitch + crop_x0*input_bpp/8; + int dstStride = vo_w * input_bpp/8; + + swsContext->swScale(swsContext, &src_img, &input_pitch, 0, crop_height, + &vo_image_ptr, &dstStride); + } + else { + for(y = crop_y0; y < crop_height + crop_y0; y++) + memcpy(&vo_image_ptr[(y - crop_y0)*crop_width*input_bpp/8], + src[0] + y*input_pitch + crop_x0*input_bpp/8, + crop_width*input_bpp/8); + } + + return(0); } static int query_format(unsigned int out_fmt){ @@ -633,30 +688,41 @@ //sh_video->outfmtidx=i; // FIXME!!!!!!!!!!!!!!!!!!! -if((out_fmt==IMGFMT_YV12 || out_fmt==IMGFMT_IYUV || out_fmt==IMGFMT_I420) && - (vo_w!=0 || vo_h!=0)) -{ - scale_srcW= sh_video->disp_w; - scale_srcH= sh_video->disp_h; - if(!vo_w) vo_w=sh_video->disp_w; - if(!vo_h) vo_h=sh_video->disp_h; -} -else -{ - vo_w=sh_video->disp_w; - vo_h=sh_video->disp_h; -} + if(!crop_width) + crop_width = sh_video->disp_w - crop_x0; + if(!crop_height) + crop_height = sh_video->disp_h - crop_y0; + + if(crop_width + crop_x0 > sh_video->disp_w || + crop_height + crop_y0 > sh_video->disp_h) { + printf("Fatal error: x0 + xsize (or y0 + ysize) is larger than the movie.\n"); + return 1; + } + + if(crop_x0 >= sh_video->disp_w || + crop_y0 >= sh_video->disp_h) { + printf("Fatal error: You tried to crop away more than the entire movie!\n"); + return 1; + } -if(out_fmt==IMGFMT_YV12 || out_fmt==IMGFMT_I420 || out_fmt==IMGFMT_IYUV){ - vo_image=malloc(vo_w*vo_h*3/2); - vo_image_ptr=vo_image; -} + printf("x0: %d y0: %d crop_width: %d crop_height: %d\n", crop_x0, crop_y0, crop_width, crop_height); + + if(!vo_w) vo_w = crop_width; + if(!vo_h) vo_h = crop_height; + + if(vo_w != crop_width || vo_h != crop_height) + { + swsContext = getSwsContextFromCmdLine(crop_width, crop_height, out_fmt, vo_w, vo_h, out_fmt); -if (IMGFMT_IS_BGR(out_fmt)) - vo_image_ptr = vo_image = malloc(vo_w*vo_h*IMGFMT_BGR_DEPTH(out_fmt)/8); + if(!swsContext) { + printf("Fatal error: Initialization of software scaler faild.\n"); + return 1; + } + } -if (IMGFMT_IS_RGB(out_fmt)) - vo_image_ptr = vo_image = malloc(vo_w*vo_h*IMGFMT_RGB_DEPTH(out_fmt)/8); + input_bpp = bits_per_pixel(out_fmt); + vo_image_ptr = vo_image = malloc(vo_w*vo_h*input_bpp/8); + input_pitch = sh_video->disp_w*input_bpp/8; } // if(out_video_codec) @@ -700,7 +766,6 @@ // set up video encoder: -SwScale_Init(); #ifdef USE_DVDREAD vo_spudec=spudec_new_scaled(stream->type==STREAMTYPE_DVD?((dvd_priv_t *)(stream->priv))->cur_pgc->palette:NULL, @@ -772,8 +837,8 @@ case VCODEC_RAWRGB: mux_v->bih=malloc(sizeof(BITMAPINFOHEADER)); mux_v->bih->biSize=sizeof(BITMAPINFOHEADER); - mux_v->bih->biWidth=sh_video->disp_w; - mux_v->bih->biHeight=sh_video->disp_h; + mux_v->bih->biWidth=vo_w; + mux_v->bih->biHeight=vo_h; mux_v->bih->biCompression=0; mux_v->bih->biPlanes=1; @@ -1484,8 +1549,8 @@ vo_w*3, vo_h); } else { - yuv2rgb(raw_rgb_buffer, vo_image_ptr, vo_image_ptr + vo_w*vo_h*5/4, - vo_image_ptr + vo_w*vo_h, vo_w, vo_h, vo_w*24/8, vo_w, vo_w/2); + yuv2rgb(raw_rgb_buffer, vo_image_ptr, vo_image_ptr + vo_w*vo_h, + vo_image_ptr + vo_w*vo_h*5/4, vo_w, vo_h, vo_w*24/8, vo_w, vo_w/2); mux_v->buffer = flip_upside_down(raw_rgb_buffer, raw_rgb_buffer, vo_w*3, vo_h); } @@ -1796,3 +1861,28 @@ free(tmp); return dst; } + +/* Bits per pixel for format fmt. Not depth */ +static int bits_per_pixel(uint32_t fmt) +{ + if(IMGFMT_IS_RGB(fmt)) { + if(IMGFMT_RGB_DEPTH(fmt) == 15) + return 16; + else + return IMGFMT_RGB_DEPTH(fmt); + } + else if(IMGFMT_IS_BGR(fmt)) { + if(IMGFMT_BGR_DEPTH(fmt) == 15) + return 16; + else + return IMGFMT_BGR_DEPTH(fmt); + } + else if(fmt==IMGFMT_YV12 || fmt==IMGFMT_I420 || fmt==IMGFMT_IYUV) + return 12; + else if(fmt == IMGFMT_YUY2 || fmt == IMGFMT_UYVY) + return 16; + else { + fprintf(stderr, "Error: bits_per_pixel: Unknown imgfmt: %s\n", vo_format_name(fmt)); + return 0; + } +}