📄 rmsoftmixer.c
字号:
/***************************************** Copyright © 2001-2003 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential*****************************************/#include "../include/rmsoftmixer.h"#if 0#define RMSMXDBG ENABLE#else#define RMSMXDBG DISABLE#endif#define MAX_SLOTS 16#define TIMEOUT_US 1000#define SMX_BUFFER_COUNT 3#define SEND_GFX_COMMAND(smx_handle, propertyID, value) \{ \ RMstatus err; \ RMuint32 n; \ n = 5; \ do{ \ err = RUASetProperty(smx_handle->pRUA, smx_handle->gfx_id, propertyID, &value, sizeof(value), 0); \ if ((err == RM_PENDING)) { \ struct RUAEvent evt; \ evt.ModuleID = smx_handle->gfx_id; \ evt.Mask = RUAEVENT_COMMANDCOMPLETION; \ RMDBGLOG((ENABLE, "Can't send command to command fifo\n" )); \ while (RUAWaitForMultipleEvents(smx_handle->pRUA, &evt, 1, TIMEOUT_US, NULL) != RM_OK); \ } \ n--; \ }while((n>0) && (err == RM_PENDING)); \ \ if (err != RM_OK) { \ RMDBGLOG((ENABLE, "Can't send command to command fifo\n" )); \ return err; \ } \ \}struct smx_slot{ RMbool active; RMuint32 decoder; RMuint32 stc; RMuint32 tir; RMuint32 draw_border; struct VideoDecoder_NextPicture_type new_pic; struct VideoDecoder_NextPicture_type current_pic; struct rmsmx_window current_window; RMbool starved;}; struct _RMsmx{ struct DCC *pDCC; struct RUA *pRUA; RMuint32 canvas_buffer[SMX_BUFFER_COUNT]; /*address to canvas buffers */ RMuint32 canvas_picture[SMX_BUFFER_COUNT]; /*address to pictures, needed for gfx engine sync */ RMuint32 canvas_index; RMuint32 canvas_surface; RMuint32 canvas_color; RMuint32 canvas_width; RMuint32 canvas_height; RMuint32 canvas_dirty; struct DCCVideoSource *canvas_source; RMuint32 gfx_id; RMuint32 gfx_cached_buf; RMuint32 gfx_uncached_buf; struct smx_slot slots[MAX_SLOTS];};static inline RMstatus smx_set_picture(RMsmx smx, struct EMhwlibNewPicture *pic, RMuint32 slot);static inline RMstatus smx_open_gfx(RMsmx smx, struct DCCOSDProfile *canvas_profile);static RMstatus smx_clear_buffers(RMsmx smx);static RMstatus smx_disconnect(RMsmx smx, RMuint32 slot){ RMstatus err; if(smx->slots[slot].active){ if(smx->slots[slot].current_pic.PictureAddress){ err = RUASetProperty(smx->pRUA, smx->slots[slot].decoder, RMVideoDecoderPropertyID_ReleasePicture, &(smx->slots[slot].current_pic.PictureAddress), sizeof(smx->slots[slot].current_pic.PictureAddress), 0); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot release picture\n")); } smx->slots[slot].current_pic.PictureAddress = 0; } err = RMSMXFlushSlot(smx, slot); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot flush slot %d\n", slot)); return err; } smx->slots[slot].active = FALSE; err = RUASetProperty(smx->pRUA, smx->slots[slot].decoder, RMVideoDecoderPropertyID_DisconnectReader, NULL, 0, 0); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot disconnect reader %\n", err)); return err; } } return RM_OK;}RM_EXTERN_C RMsmx RMSMXOpen(struct rmsmx_config *config){ RMsmx smx; struct EMhwlibDisplayWindow window; enum EMhwlibMixerSourceState state; RMstatus err; RMuint32 scaler, src_index, mixer; RMuint32 slot, i; RMbool enable; RMuint32 canvas_alpha = 0x80; struct EMhwlibNonLinearScalingMode nonlinearmode = {0,0}; struct EMhwlibBlackStripMode blackstrip = {0,0}; struct EMhwlibCutStripMode cutstrip = {0,0}; /* allocate handle */ if(config == NULL) { RMDBGLOG((RMSMXDBG, "Cannot open RMSMX : config == NULL\n")); return NULL; } smx = (RMsmx)RMMalloc(sizeof(struct _RMsmx)); if(!smx){ RMDBGLOG((RMSMXDBG, "Could not allocate smx handler\n")); return NULL; } /* initialize handle */ smx->pDCC = config->pDCC; smx->pRUA = config->pRUA; smx->canvas_index = 0; smx->canvas_width = config->canvas_profile.Width; smx->canvas_height = config->canvas_profile.Height; smx->canvas_color = config->canvas_color; for(slot = 0; slot < MAX_SLOTS; slot++){ smx->slots[slot].active = FALSE; smx->slots[slot].current_pic.PictureAddress = 0; smx->slots[slot].new_pic.PictureAddress = 0; smx->slots[slot].current_window.width = 0; smx->slots[slot].starved = TRUE; } err = smx_open_gfx(smx, &(config->canvas_profile)); if (RMFAILED(err)){ RMDBGLOG((ENABLE, "Error opening gfx engine : %d\n",err)); return NULL; } /* create an osd */ scaler = config->canvas_scaler; mixer = DispMainMixer; window.X = 2048; window.Y = 2048; window.Width = 4096; window.Height = 4096; window.XPositionMode = EMhwlibDisplayWindowPositionMode_FrontEdgeToCenter; window.YPositionMode = EMhwlibDisplayWindowPositionMode_FrontEdgeToCenter; window.XMode = EMhwlibDisplayWindowValueMode_Relative; window.YMode = EMhwlibDisplayWindowValueMode_Relative; window.WidthMode = EMhwlibDisplayWindowValueMode_Relative; window.HeightMode = EMhwlibDisplayWindowValueMode_Relative; err = DCCOpenMultiplePictureOSDVideoSource(smx->pDCC, &(config->canvas_profile), SMX_BUFFER_COUNT, &(smx->canvas_source), NULL); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot open OSD surface %d\n", err)); return NULL; } err = DCCGetOSDSurfaceInfo(smx->pDCC, smx->canvas_source, NULL, &(smx->canvas_surface), NULL); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get canvas surface info %d\n", err)); return NULL; } for(i = 0; i < SMX_BUFFER_COUNT; i++){ err = DCCGetOSDPictureInfo(smx->canvas_source, i, &(smx->canvas_picture[i]), &(smx->canvas_buffer[i]), NULL, NULL, NULL); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get picture info %d\n", err)); return NULL; } } while ((err = RUASetProperty(smx->pRUA, scaler, RMGenericPropertyID_NonLinearScalingMode, &nonlinearmode, sizeof(nonlinearmode), 0)) == RM_PENDING); if (RMFAILED(err) && (err != RM_INVALIDMODE)) { RMDBGLOG((ENABLE, "Error setting current scaler non-linear selection %d\n", err)); return NULL; } while ((err = RUASetProperty(smx->pRUA, scaler, RMGenericPropertyID_BlackStripMode, &blackstrip, sizeof(blackstrip), 0)) == RM_PENDING); if (RMFAILED(err) && (err != RM_INVALIDMODE)) { RMDBGLOG((ENABLE, "Error setting current scaler blackstrip mode %d\n", err)); return NULL; } while ((err = RUASetProperty(smx->pRUA, scaler, RMGenericPropertyID_CutStripMode, &cutstrip, sizeof(cutstrip), 0)) == RM_PENDING); if (RMFAILED(err) && (err != RM_INVALIDMODE)) { RMDBGLOG((ENABLE, "Error setting current scaler cutstrip mode %d\n", err)); return NULL; } enable = TRUE; err = RUASetProperty(smx->pRUA, scaler, RMGenericPropertyID_Enable, &enable, sizeof(enable), 0); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot enable scaler\n")); return NULL; } while( (err = RUASetProperty(smx->pRUA, scaler, RMGenericPropertyID_Alpha0, &(canvas_alpha), sizeof(canvas_alpha), 0)) == RM_PENDING); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot set the alpha value on the scaler\n")); } while ((err = RUASetProperty(smx->pRUA, scaler, RMGenericPropertyID_ScalerInputWindow, &(window), sizeof(window), 0)) == RM_PENDING); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot set scaler input window on OSD surface %d\n", err)); if(err == RM_ERROR){ /* when scaler == DispVideoPlane, RUA will return RM_NOT_FOUND */ return NULL; } } err = RUAExchangeProperty(smx->pRUA, mixer, RMGenericPropertyID_MixerSourceIndex, &scaler, sizeof(scaler), &src_index, sizeof(src_index)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get scaler index\n")); return NULL; } mixer = EMHWLIB_TARGET_MODULE(mixer, 0, src_index); state = EMhwlibMixerSourceState_Master; while((err = RUASetProperty(smx->pRUA, mixer, RMGenericPropertyID_MixerSourceState, &state, sizeof(state), 0)) == RM_PENDING); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot set scaler's state on mixer\n")); return NULL; } while ((err = RUASetProperty(smx->pRUA, mixer, RMGenericPropertyID_MixerSourceWindow, &(window), sizeof(window), 0)) == RM_PENDING); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot set scaler output window %d\n", err)); return NULL; } while ((err = RUASetProperty(smx->pRUA, mixer, RMGenericPropertyID_Validate, NULL, 0, 0)) == RM_PENDING); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot Validate mixer\n")); return NULL; } /*clear both buffers */ smx_clear_buffers(smx); err = DCCSetSurfaceSource(smx->pDCC, scaler, smx->canvas_source); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot set the surface source %d\n", err)); return NULL; } return smx;}RMstatus RMSMXClose(RMsmx smx){ RMuint32 close_profile = 0; RMuint32 slot; for(slot = 0; slot < MAX_SLOTS; slot++){ smx_disconnect(smx, slot); } SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_Close, close_profile); if (smx->gfx_cached_buf) RUAFree(smx->pRUA, smx->gfx_cached_buf); if (smx->gfx_uncached_buf) RUAFree(smx->pRUA, smx->gfx_uncached_buf); DCCCloseVideoSource(smx->canvas_source); RMFree(smx); return RM_OK;}RMstatus RMSMXSetInputSource(RMsmx smx, struct rmsmx_source *source, RMuint32 slot){ RMuint32 surface, stc_tir; RMstatus err; struct DisplayBlock_SurfaceInfo_out_type surface_info; struct GFXEngine_ColorFormat_type format_param; RMuint32 r2, r1; if(source == NULL){ smx_disconnect(smx,slot); return RM_OK; } err = RUAGetProperty(smx->pRUA, source->decoder_id, RMGenericPropertyID_Surface, &(surface), sizeof(surface)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get surface adress\n" )); return err; } RUAExchangeProperty(smx->pRUA, DisplayBlock, RMDisplayBlockPropertyID_SurfaceInfo, &(surface), sizeof(surface), &surface_info, sizeof(surface_info)); /* returns RM_ERROR for video surfaces */ err = RUAGetProperty(smx->pRUA, source->stc_id, RMSTCPropertyID_VideoTimeResolution, &stc_tir, sizeof(stc_tir)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get stc resolution\n" )); return err; } format_param.SurfaceID = GFX_SURFACE_ID_Z; format_param.MainMode = surface_info.ColorMode; format_param.SubMode = surface_info.ColorFormat; format_param.SamplingMode = surface_info.SamplingMode; format_param.ColorSpace = surface_info.ColorSpace; SEND_GFX_COMMAND(smx, RMGFXEnginePropertyID_ColorFormat, format_param); r1 = 0; err = RUAExchangeProperty(smx->pRUA, source->decoder_id, RMVideoDecoderPropertyID_ConnectReader, &r1, sizeof(r1), &r2, sizeof(r2)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot connect reader to video surface\n")); return err; } smx->slots[slot].active = TRUE; smx->slots[slot].decoder = EMHWLIB_TARGET_MODULE(EMHWLIB_MODULE_CATEGORY(source->decoder_id), EMHWLIB_MODULE_INDEX(source->decoder_id), r2); smx->slots[slot].stc = source->stc_id; smx->slots[slot].tir = stc_tir; RMDBGLOG((ENABLE, "stc resolution %ld\n", stc_tir )); return RM_OK;}RMstatus RMSMXGetSlotStatus(RMsmx smx, struct rmsmx_slot_status *status, RMuint32 slot){ status->starved = smx->slots[slot].starved; if(smx->slots[slot].current_pic.PictureAddress){ status->displayed_pts = smx->slots[slot].current_pic.Picture.first_pts_hi; status->displayed_pts <<= 32; status->displayed_pts = smx->slots[slot].current_pic.Picture.first_pts_lo; } else return RM_ERROR; return RM_OK;}RMstatus RMSMXRefresh(RMsmx smx){ RMstatus err; RMuint32 slot = 0; RMuint64 stc; RMuint64 pts; RMbool empty_queue = FALSE; struct GFXEngine_Surface_type surface_param; struct GFXEngine_DisplayPicture_type display_pic; /* The eraser process is performed by the GFX engine via the wait_picture command *//* err = RUASetProperty(smx->pRUA, DisplayBlock, RMDisplayBlockPropertyID_ErasePicturesInSurfaceFifo, *//* &(smx->canvas_surface), sizeof(smx->canvas_surface), 0); *//* if (RMFAILED(err)) { */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -