📄 atmo.cpp
字号:
Atmo_Shutdown(p_filter);#if defined( WIN32 ) if(p_sys->h_AtmoCtrl != NULL) { FreeLibrary(p_sys->h_AtmoCtrl); }#endif delete p_sys->p_atmo_dyndata; delete p_sys->p_atmo_config; vlc_mutex_destroy( &p_sys->filter_lock ); free( p_sys );}/*function stolen from some other videolan source filter ;-)for the moment RGB is OK... but better would be a direct transformationfrom YUV --> HSV*/static inline void yuv_to_rgb( uint8_t *r, uint8_t *g, uint8_t *b, uint8_t y1, uint8_t u1, uint8_t v1 ){ /* macros used for YUV pixel conversions */# define SCALEBITS 10# define ONE_HALF (1 << (SCALEBITS - 1))# define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))# define CLAMP( x ) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (x)); int y, cb, cr, r_add, g_add, b_add; cb = u1 - 128; cr = v1 - 128; r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF; g_add = - FIX(0.34414*255.0/224.0) * cb - FIX(0.71414*255.0/224.0) * cr + ONE_HALF; b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF; y = (y1 - 16) * FIX(255.0/219.0); *r = CLAMP((y + r_add) >> SCALEBITS); *g = CLAMP((y + g_add) >> SCALEBITS); *b = CLAMP((y + b_add) >> SCALEBITS);}/******************************************************************************* ExtractMiniImage_YUV: extract a small image from the picture as 24-bit RGB******************************************************************************** p_sys is a pointer to* p_inpic is the source frame* p_transfer_dest is the target buffer for the picture must be big enough!* (in win32 enviroment this buffer comes from the external DLL where it is* create as "variant array" and returned through the AtmoLockTransferbuffer*/static void ExtractMiniImage_YUV(filter_sys_t *p_sys, picture_t *p_inpic, uint8_t *p_transfer_dest){ int i_col; int i_row; uint8_t *p_src_y; uint8_t *p_src_u; uint8_t *p_src_v; uint8_t *p_rgb_dst_line_red; uint8_t *p_rgb_dst_line_green; uint8_t *p_rgb_dst_line_blue; int i_xpos_y; int i_xpos_u; int i_xpos_v; /* calcute Pointers for Storage of B G R (A) */ p_rgb_dst_line_blue = p_transfer_dest; p_rgb_dst_line_green = p_transfer_dest + 1; p_rgb_dst_line_red = p_transfer_dest + 2 ; int i_row_count = p_sys->i_atmo_height + 1; int i_col_count = p_sys->i_atmo_width + 1; int i_y_row,i_u_row,i_v_row,i_pixel_row; int i_pixel_col; /* these two ugly loops extract the small image - goes it faster? how? the loops are so designed that there is a small border around the extracted image so we wont get column and row - zero from the frame, and not the most right and bottom pixels --- which may be clipped on computers useing TV out - through overscan! TODO: try to find out if the output is clipped through VLC - and try here to ingore the clipped away area for a better result! TODO: performance improvement in InitFilter percalculated the offsets of the lines inside the planes so I can save (i_row_count * 3) 2xMUL and one time DIV the same could be done for the inner loop I think... */ for(i_row = 1; i_row < i_row_count; i_row++) { // calcute the current Lines in the source planes for this outputrow /* Adresscalcuation pointer to plane Length of one pixelrow in bytes calculate row now number */ /* p_inpic->format? transform Pixel row into row of plane... how? simple? fast? good? */ /* compute the source pixel row and respect the active cropping */ i_pixel_row = (i_row * p_sys->i_crop_height) / i_row_count + p_sys->i_crop_y_offset; /* trans for these Pixel row into the row of each plane .. because planesize can differ from image size */ i_y_row = (i_pixel_row * p_inpic->p[Y_PLANE].i_visible_lines) / p_inpic->format.i_visible_height; i_u_row = (i_pixel_row * p_inpic->p[U_PLANE].i_visible_lines) / p_inpic->format.i_visible_height; i_v_row = (i_pixel_row * p_inpic->p[V_PLANE].i_visible_lines) / p_inpic->format.i_visible_height; /* calculate the pointers to the pixeldata for this row in each plane */ p_src_y = p_inpic->p[Y_PLANE].p_pixels + p_inpic->p[Y_PLANE].i_pitch * i_y_row; p_src_u = p_inpic->p[U_PLANE].p_pixels + p_inpic->p[U_PLANE].i_pitch * i_u_row; p_src_v = p_inpic->p[V_PLANE].p_pixels + p_inpic->p[V_PLANE].i_pitch * i_v_row; for(i_col = 1; i_col < i_col_count; i_col++) { i_pixel_col = (i_col * p_sys->i_crop_width) / i_col_count + p_sys->i_crop_x_offset; /* trans for these Pixel row into the row of each plane .. because planesize can differ from image size */ i_xpos_y = (i_pixel_col * p_inpic->p[Y_PLANE].i_visible_pitch) / p_inpic->format.i_visible_width; i_xpos_u = (i_pixel_col * p_inpic->p[U_PLANE].i_visible_pitch) / p_inpic->format.i_visible_width; i_xpos_v = (i_pixel_col * p_inpic->p[V_PLANE].i_visible_pitch) / p_inpic->format.i_visible_width; yuv_to_rgb(p_rgb_dst_line_red, p_rgb_dst_line_green, p_rgb_dst_line_blue, p_src_y[i_xpos_y], p_src_u[i_xpos_u], p_src_v[i_xpos_v]); /* +4 because output image should be RGB32 with dword alignment! */ p_rgb_dst_line_red += 4; p_rgb_dst_line_green += 4; p_rgb_dst_line_blue += 4; } }}/******************************************************************************* SaveBitmap: Saves the content of a transferbuffer as Bitmap to disk******************************************************************************** just for debugging* p_sys -> configuration if Atmo from there the function will get height and* width* p_pixels -> should be the dword aligned BGR(A) image data* psz_filename -> filename where to store*/#if defined(__ATMO_DEBUG__)void SaveBitmap(filter_sys_t *p_sys, uint8_t *p_pixels, char *psz_filename){ /* for debug out only used*/ BITMAPINFO bmp_info; BITMAPFILEHEADER bmp_fileheader; FILE *fp_bitmap; memset(&bmp_info, 0, sizeof(BITMAPINFO)); bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmp_info.bmiHeader.biSizeImage = p_sys->i_atmo_height * p_sys->i_atmo_width * 4; bmp_info.bmiHeader.biCompression = BI_RGB; bmp_info.bmiHeader.biWidth = p_sys->i_atmo_width; bmp_info.bmiHeader.biHeight = -p_sys->i_atmo_height; bmp_info.bmiHeader.biBitCount = 32; bmp_info.bmiHeader.biPlanes = 1; bmp_fileheader.bfReserved1 = 0; bmp_fileheader.bfReserved2 = 0; bmp_fileheader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmp_info.bmiHeader.biSizeImage; bmp_fileheader.bfType = VLC_TWOCC('M','B'); bmp_fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); fp_bitmap = fopen(psz_filename,"wb"); if( fp_bitmap != NULL) { fwrite(&bmp_fileheader, sizeof(BITMAPFILEHEADER), 1, fp_bitmap); fwrite(&bmp_info.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp_bitmap); fwrite(p_pixels, bmp_info.bmiHeader.biSizeImage, 1, fp_bitmap); fclose(fp_bitmap); }}#endif/***************************************************************************** CreateMiniImage: extracts a 64x48 pixel image from the frame* (there is a small border arround thats why the loops starts with one* instead zero) without any interpolation*****************************************************************************/static void CreateMiniImage( filter_t *p_filter, picture_t *p_inpic){ filter_sys_t *p_sys = p_filter->p_sys; /* pointer to RGB Buffer created in external libary as safe array which is locked inside AtmoLockTransferBuffer */ uint8_t *p_transfer = NULL;#if defined( __ATMO_DEBUG__ ) /* for debug out only used*/ char sz_filename[MAX_PATH];#endif /* Lock the before created VarArray (AtmoCreateTransferBuffers) inside my wrapper library and give me a pointer to the buffer! below linux a global buffer may be used and protected with a mutex? */ p_transfer = AtmoLockTransferBuffer(p_filter); if(p_transfer == NULL) { msg_Err( p_filter, "AtmoLight no transferbuffer available. "\ "AtmoLight will be disabled!"); p_sys->b_enabled = false; return; } /* do the call via pointer to function instead of having a case structure here */ p_sys->pf_extract_mini_image(p_sys, p_inpic, p_transfer);#if defined( __ATMO_DEBUG__ ) /* if debugging enabled save every 128th image to disk */ if((p_sys->b_saveframes == true) && (p_sys->sz_framepath[0] != 0 )) { if((p_sys->i_framecounter & 127) == 0) { sprintf(sz_filename,"%satmo_dbg_%06d.bmp",p_sys->sz_framepath, p_sys->i_framecounter); msg_Dbg(p_filter, "SaveFrame %s",sz_filename); SaveBitmap(p_sys, p_transfer, sz_filename); } p_sys->i_framecounter++; }#endif /* show the colors on the wall */ AtmoSendPixelData(p_filter);}/****************************************************************************** Filter: calls the extract method and forwards the incomming picture 1:1***********************************************************************************************************************************************************/static picture_t * Filter( filter_t *p_filter, picture_t *p_pic ){ filter_sys_t *p_sys = p_filter->p_sys; if( !p_pic ) return NULL; if((p_sys->b_enabled == true) && (p_sys->pf_extract_mini_image != NULL) && (p_sys->b_pause_live == false)) { CreateMiniImage(p_filter, p_pic); } return p_pic;}/****************************************************************************** FadeToColorThread: Threadmethod which changes slowly the color* to a target color defined in p_fadethread struct* use for: Fade to Pause Color, and Fade to End Color*****************************************************************************/static void *FadeToColorThread(vlc_object_t *obj){ fadethread_t *p_fadethread = (fadethread_t *)obj; filter_sys_t *p_sys = (filter_sys_t *)p_fadethread->p_filter->p_sys; int i_steps_done = 0; int i_index; int i_pause_red; int i_pause_green; int i_pause_blue; int i_src_red; int i_src_green; int i_src_blue; vlc_thread_ready( p_fadethread ); uint8_t *p_source = NULL; /* initialize AtmoWin for this thread! */ AtmoInitialize(p_fadethread->p_filter , true); uint8_t *p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter ); if(p_transfer != NULL) { /* safe colors as "32bit" Integers to avoid overflows*/ i_pause_red = p_fadethread->ui_red; i_pause_blue = p_fadethread->ui_blue; i_pause_green = p_fadethread->ui_green; /* allocate a temporary buffer for the last send image size less then 15kb */ int i_size = 4 * p_sys->i_atmo_width * p_sys->i_atmo_height; p_source = (uint8_t *)malloc( i_size ); if(p_source != NULL) { /* get a copy of the last transfered image as orign for the fading steps... */ memcpy(p_source, p_transfer, i_size); /* send the same pixel data again... to unlock the buffer! */ AtmoSendPixelData( p_fadethread->p_filter ); while( (vlc_object_alive (p_fadethread)) && (i_steps_done < p_fadethread->i_steps)) { p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -