📄 ppf_watermark.c
字号:
RMDBGLOG((ENABLE, "Invalid param address!\n")); return RM_ERROR; } /* Most ppf modules will need to handle play/stop commands. We did not add a generic function for this because in the near future the aim is to pass those commands via the input surfaces. So temporarily this is implemented here as a custom command of each ppf module. */ cmd = *(enum ppf_watermark_cmd *)command_param; switch(cmd){ case ppf_watermark_cmd_play: context.state = ppf_watermark_state_play; break; case ppf_watermark_cmd_stop: context.state = ppf_watermark_state_stop; break; } return RM_OK;}/* Video pictures are relased when the associated carbon pictures are released by the display. We cannot release them before because the carbon pictures use the video pictures' chroma buffers.*/static void free_video_pictures(){ RMuint32 i; RMuint32 released = 0; for(i = 0; i < CARBON_PICTURE_COUNT; i++){ struct EMhwlibNewPicture *pic = (struct EMhwlibNewPicture*)context.carbon_pictures[i]; if((context.carbon_pictures_parent[i] != 0) && (gbus_read_uint32(PGBUS, (RMuint32) & (pic->picture_display_status)) == 0)){ struct EMhwlibNewPicture *parent_pic = (struct EMhwlibNewPicture*)context.carbon_pictures_parent[i]; gbus_write_uint32(PGBUS, (RMuint32) & (parent_pic->picture_display_status), 0); context.carbon_pictures_parent[i] = 0; released++; }/* else *//* RMDBGLOG((ENABLE, "no because %ld and %ld\n", (context.carbon_pictures_parent[i] != 0),(gbus_read_uint32(PGBUS, (RMuint32) & (pic->picture_display_status)) == 0) )); */ } }/* Returns the index of an available carbon picture. If the return value is CARBON_PICTURE_COUNT, it means that no pictures are available*/static RMuint32 get_carbon_picture(){ RMuint32 i; for(i = 0; i < CARBON_PICTURE_COUNT; i++){ struct EMhwlibNewPicture *pic = (struct EMhwlibNewPicture*)context.carbon_pictures[i]; if((context.carbon_pictures_parent[i] == 0) && (gbus_read_uint32(PGBUS, (RMuint32) & (pic->picture_display_status)) == 0)){ break; } } return i;}static void copy_luma(struct EMhwlibNewPicture *src_pic, struct EMhwlibNewPicture *dst_pic){ struct GFXEngine_Surface_type surface_param; struct GFXEngine_ColorFormat_type format_param; struct GFXEngine_MoveReplaceRectangle_type move_param; format_param.MainMode = EMhwlibColorMode_LUT_8BPP; format_param.SubMode = EMhwlibColorFormat_32BPP; surface_param.StartAddress = dst_pic->luma_address; surface_param.TotalWidth = dst_pic->luma_total_width; surface_param.Tiled = TRUE; surface_param.SurfaceID = GFX_SURFACE_ID_NX; format_param.SurfaceID = GFX_SURFACE_ID_NX; SEND_GFX_COMMAND(RMGFXEnginePropertyID_Surface, &surface_param, sizeof(surface_param)); SEND_GFX_COMMAND(RMGFXEnginePropertyID_ColorFormat, &format_param, sizeof(format_param)); surface_param.StartAddress = src_pic->luma_address; surface_param.TotalWidth = src_pic->luma_total_width; surface_param.Tiled = TRUE; surface_param.SurfaceID = GFX_SURFACE_ID_Y; format_param.SurfaceID = GFX_SURFACE_ID_Y; SEND_GFX_COMMAND(RMGFXEnginePropertyID_Surface, &surface_param, sizeof(surface_param)); SEND_GFX_COMMAND(RMGFXEnginePropertyID_ColorFormat, &format_param, sizeof(format_param)); move_param.SrcX = 0; move_param.SrcY = 0; move_param.Width = src_pic->luma_position_in_buffer.width; move_param.Height = src_pic->luma_position_in_buffer.height; move_param.Width = RMmin(src_pic->luma_position_in_buffer.width, CARBON_MAX_PIC_WIDTH); move_param.Height = RMmin(src_pic->luma_position_in_buffer.height, CARBON_MAX_PIC_HEIGHT); move_param.DstX = 0; move_param.DstY = 0; move_param.AlphaX = 0; move_param.AlphaY = 0; move_param.Merge = FALSE; SEND_GFX_COMMAND(RMGFXEnginePropertyID_MoveRectangle, &move_param, sizeof(move_param));}/* 1) Get one picture from the video surface 2) Create a picture using a copy of the video picture's luma buffer and the original chroma buffers. 3) Insert that picture into the carbon_output surface*/static RMstatus video_to_carbon(void){ struct GFXEngine_DisplayPicture_type display_pic; struct EMhwlibPictureInfo video_pic; struct EMhwlibNewPicture carbon_pic; RMuint32 carbon_pic_id; RMstatus err; err = EMhwlibExchangeProperty((struct EMhwlib *)pEm, DisplayBlock, RMDisplayBlockPropertyID_PeekNextPicture, &(context.input), sizeof(context.input), &video_pic, sizeof(video_pic)); if((err == RM_OK) && video_pic.PictureAddress){ carbon_pic_id = get_carbon_picture(); if(carbon_pic_id < CARBON_PICTURE_COUNT){ carbon_pic = video_pic.Picture; carbon_pic.luma_address = context.carbon_buffers[carbon_pic_id]; carbon_pic.picture_display_status = 1; gbus_write_data32(PGBUS, context.carbon_pictures[carbon_pic_id], (RMuint32*)&carbon_pic, sizeof(struct EMhwlibNewPicture)/sizeof(RMuint32)); copy_luma(&video_pic.Picture, &carbon_pic); context.carbon_pictures_parent[carbon_pic_id] = video_pic.PictureAddress; display_pic.Surface = context.carbon_output; display_pic.Picture = context.carbon_pictures[carbon_pic_id]; display_pic.Pts = (RMuint64)video_pic.Picture.first_pts_lo | ((RMuint64) video_pic.Picture.first_pts_hi)<<32; SEND_GFX_COMMAND(RMGFXEnginePropertyID_DisplayPicture, &display_pic, sizeof(display_pic)); context.input.emhwlibReserved = video_pic.PictureAddress; err = EMhwlibSetProperty((struct EMhwlib *)pEm, DisplayBlock, RMDisplayBlockPropertyID_AcquirePicture, &(context.input), sizeof(context.input)); } else{ RMDBGLOG((ENABLE, "cant get a carbon picture\n")); return RM_PENDING; } }else{ return RM_PENDING; } return RM_OK;}static void watermark_picture(struct EMhwlibNewPicture *Picture){ RMuint32 x,y,x0,y0,w,h; RMDBGLOG((DISABLE, "luma:%p, luma_width:%08x, frame:%08x, win: %08x:%08x-%08x*%08x\n", Picture->luma_address, Picture->luma_total_width, Picture->frame_count, Picture->luma_position_in_buffer.x, Picture->luma_position_in_buffer.y, Picture->luma_position_in_buffer.width, Picture->luma_position_in_buffer.height)); w = 256; h = 128; x0 = 8; y0 = 8; for(y = y0; y < y0+h; y++) { for(x=x0; x<x0+w; x++) { RMuint32 addr, luma; addr = Picture->luma_address + 128*y + x; addr=Picture->luma_address + (x/128)*4096+(y/32)*Picture->luma_total_width*32+(x%128)+((y%32)*128); luma = gbus_read_uint8(PGBUS, addr); luma = (luma < 128) ? ((luma < 64) ? 32 : 96) : ((luma < 192) ? 160: 224); gbus_write_uint8(PGBUS, addr, luma); } }}/* 1) Get one picture from the carbon surface 2) Modify its luma (watermark it) 3) Insert that picture into the marked_output surface*/static RMstatus carbon_to_marked(){ struct EMhwlibPictureInfo carbon_pic_info; struct EMhwlibSurfaceReader carbon_surface_reader; struct DisplayBlock_InsertPictureInSurfaceFifo_type insert_pic; RMstatus err; carbon_surface_reader.ReaderID = 0; carbon_surface_reader.SurfaceAddress = context.carbon_output; err = EMhwlibExchangeProperty((struct EMhwlib *)pEm, DisplayBlock, RMDisplayBlockPropertyID_PeekNextPicture, &(carbon_surface_reader), sizeof(carbon_surface_reader), &carbon_pic_info, sizeof(carbon_pic_info)); if((err == RM_OK) && carbon_pic_info.PictureAddress){ insert_pic.Surface = context.marked_output; insert_pic.Picture = carbon_pic_info.PictureAddress; watermark_picture(&carbon_pic_info.Picture); err = EMhwlibSetProperty((struct EMhwlib *)pEm, DisplayBlock, RMDisplayBlockPropertyID_InsertPictureInSurfaceFifo, &insert_pic, sizeof(insert_pic)); if(err == RM_OK){ carbon_surface_reader.emhwlibReserved = carbon_pic_info.PictureAddress; err = EMhwlibSetProperty((struct EMhwlib *)pEm, DisplayBlock, RMDisplayBlockPropertyID_AcquirePicture, &(carbon_surface_reader), sizeof(carbon_surface_reader)); } else{ RMDBGLOG((ENABLE, "cannot insert yet, try again later\n")); return RM_PENDING; } }else{ return RM_PENDING; } return RM_OK; }RMstatus watermark_run_filter(RMuint32 data){ RMstatus err; RMuint32 vtc = 0; if(context.input.SurfaceAddress == 0){ RMDBGLOG((PPFDBG, "Not doing anything because no input\n")); goto done; } if((context.carbon_output == 0) || (context.marked_output == 0)){ RMDBGLOG((PPFDBG, "Not doing anything because no output\n")); goto done; } if(context.state == ppf_watermark_state_stop){ RMDBGLOG((PPFDBG, "Not doing anything because on stop mode\n")); goto done; } free_video_pictures(); do{ err = video_to_carbon(); vtc++; }while(err == RM_OK); vtc = 0; do{ err = carbon_to_marked(); vtc++; }while(err == RM_OK); done: { /* hack, this function should get the actual mask that triggered its calling and clear it */ RMuint32 mask = EMHWLIB_DISPLAY_EVENT_ID(DispMainAnalogOut); err = EMhwlibSetProperty((struct EMhwlib *)pEm, DisplayBlock, RMGenericPropertyID_ClearEventMask, &(mask), sizeof(mask)); } return RM_OK;}static RMstatus watermark_init(void){ struct PPFHandle handle = {NULL,}; /* for forward portability */ RMuint32 i; RMstatus err; krua_get_pointers(chip_id, &pE, &pEm); context.input.SurfaceAddress = 0; context.carbon_output = 0; context.gfx_task = 0; context.state = ppf_watermark_state_stop; context.on_display_pics = 0; for(i = 0; i < CARBON_PICTURE_COUNT; i++){ context.carbon_pictures_parent[i] = 0; context.carbon_pictures[i] = 0; context.carbon_buffers[i] = 0; } handle.get_engine_mem = watermark_get_engine_mem; handle.set_engine_mem = watermark_set_engine_mem; handle.get_output_mem = watermark_get_output_mem; handle.set_output_mem = watermark_set_output_mem; handle.get_output = watermark_get_output; handle.set_input = watermark_set_input; handle.set_command = watermark_set_command; RMDBGLOG((ENABLE, "calling register filter\n")); PPFDockRegisterFilter(0, &handle); /* Here we register the watermark_run_filter as a callback function for event EMHWLIB_DISPLAY_EVENT_ID(DispMainAnalogOut). It's possible to register multiple functions to multiple events or the same function to multiple events. The fifth paramater will be passed to the callback function every time it is called. */ RMDBGLOG((ENABLE, "alive so far\n")); err = krua_register_event_callback_as_tasklet((void*)pE, DisplayBlock, EMHWLIB_DISPLAY_EVENT_ID(DispMainAnalogOut), watermark_run_filter, 0, &tasklet_id); if (RMFAILED(err)){ RMDBGLOG((ENABLE, "FAILED to register tasklet\n")); return err; } RMDBGLOG((ENABLE, "alive so far\n")); return RM_OK;}static RMstatus watermark_deinit(void){ RMstatus err; RMDBGLOG((ENABLE, "at watermakr deinit now\n")); err = krua_unregister_event_callback_as_tasklet((void*)pE, tasklet_id); if (RMFAILED(err)){ RMDBGLOG((ENABLE, "FAILED to unregister callback\n")); return err; } return RM_OK;}int init_module(void){ watermark_init(); return 0;}void cleanup_module(void){ watermark_deinit();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -