?? spu.c
字號:
#include <stdio.h>#include <stdlib.h>#include <string.h>#define ALLOW_OS_CODE 1#include <sys/types.h>#include "../samples/common.h"#include "../samples/command_ids.h"#include "rmlocalremote.h"#include "../rmremoteapi/include/rmremoteapi.h"#include "../rmrtk/include/rmrtk.h"/* #### Begin CARDEA code #### */#include "rmupnp/rmlibwmdrmnd/include/ms_cardea.h"/* #### End CARDEA code #### */#include "mono.h"/* proof of concept, the implementation of subtitles may change */#define MAX_COLS 30#define MAX_ROWS 3#define SUBTITLEDBG DISABLEvoid clear_subtitles(void);void show_subtitles(RMuint8 *string);RMstatus init_subtitle_engine(void);RMstatus insert_string_into_subtitle_buffer(RMuint8 *string);void clear_subtitle_buffer(void);extern struct dcc_context dcc_info;extern struct mono_context mono_opt;extern RMbool osd_enabled;RMbool popWordfromString(RMuint8 *string, RMuint32 sLen, RMuint8 *word, RMuint32 *index);void pushWordintoString(RMuint8 **string, RMuint8 *word);struct subtitles_context{ RMuint32 maxCharsPerRow; RtkPoint cursor; RtkPoint top_left; RtkRect char_size; RtkRect active_area; RtkProp text_props; RMuint8 text_buffer[MAX_ROWS][MAX_COLS]; RMuint32 lastValidRowIndex; RMbool subtitles_initialised; RMbool disable_subtitles; RtkRect last_rect;};static struct subtitles_context subTContext = {0,}; /* in order for this init to work, the first element of the structure shall not be another structure, but a RMuint32 for example (otherwise gcc complains) *//* this is the Subtitle callback */void RMSubtitleCallback(RMuint8 *string, RMuint64 pts, RMbool usePTS){ if (subTContext.disable_subtitles) return; if (!osd_enabled) { osd_enabled = TRUE; if (mono_opt.osd_source) {#if 0 RMstatus err; err = DCCSetSurfaceSource(dcc_info.pDCC, mono_opt.osd_scaler, mono_opt.osd_source); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot set the surface source %d\n", err)); return; }#else DCCEnableVideoSource(mono_opt.osd_source, TRUE);#endif } else { subTContext.disable_subtitles = TRUE; return; } } if (!subTContext.subtitles_initialised) { RMstatus status; status = init_subtitle_engine(); if (status != RM_OK) { subTContext.disable_subtitles = TRUE; return; } subTContext.subtitles_initialised = TRUE; } if (!usePTS) { // for now, only this case is treated if (strlen((const char *)string) == 0) clear_subtitles(); else show_subtitles(string); } return;}void clear_subtitles(void){ RMFRTKClearScreen(mono_opt.rtk); clear_subtitle_buffer(); RMDBGLOG((SUBTITLEDBG, ">> clear subtitles\n")); return;}void show_subtitles(RMuint8 *string){ RMuint32 i; insert_string_into_subtitle_buffer(string); for (i = 0; i <= subTContext.lastValidRowIndex; i++) { RtkPoint cursor; RMuint32 y; y = subTContext.top_left.y + ((MAX_ROWS - 1 - subTContext.lastValidRowIndex) * subTContext.char_size.height); cursor.x = subTContext.top_left.x; cursor.y = y + (i * subTContext.char_size.height); RMFRTKDrawString(mono_opt.rtk, (RMascii *)subTContext.text_buffer[i], &cursor, &(subTContext.text_props), &(subTContext.last_rect)); } RMDBGLOG((SUBTITLEDBG, ">>> show: '%s'\n", string)); return;}RMstatus init_subtitle_engine(void){ if (!mono_opt.rtk) return RM_ERROR; subTContext.active_area.x = 0; subTContext.active_area.y = 0; RMFRTKGetOsdDimension(mono_opt.rtk, &(subTContext.active_area.width), &(subTContext.active_area.height), NULL); RMFRTKClearScreen(mono_opt.rtk); { // reload font, use a monospaced font for subtitles RMnonAscii *naname = RMnonAsciiFromAscii("VeraMono.ttf"); RMFRTKLoadFontFile( mono_opt.rtk, naname); RMFreeNonAscii(naname); } subTContext.text_props.fgColor = 0xffffffff; subTContext.text_props.bgColor = 0x80000000; subTContext.text_props.scale = subTContext.active_area.width / 30; // ?? RMFRTKGetCharSize(mono_opt.rtk, 'M', &(subTContext.text_props), &(subTContext.char_size)); if((subTContext.active_area.width < MAX_COLS * subTContext.char_size.width) || (subTContext.active_area.height < MAX_ROWS * subTContext.char_size.height)) { RMDBGLOG((ENABLE, "decrease the size of the font or the number of chars\n" "\tarea(%lu x %lu), char(%lu x %lu), textarea(%lu x %lu)\n", subTContext.active_area.width, subTContext.active_area.height, subTContext.char_size.width, subTContext.char_size.height, MAX_COLS, MAX_ROWS)); return RM_ERROR; } subTContext.top_left.x = (subTContext.active_area.width - MAX_COLS * subTContext.char_size.width) / 2; subTContext.top_left.y = ((subTContext.active_area.height * 0.8) - (MAX_ROWS - 1) * subTContext.char_size.height); subTContext.maxCharsPerRow = subTContext.active_area.width / subTContext.char_size.width; RMDBGLOG((ENABLE, "\t>>> OSDArea(%lu x %lu), charArea(%lu x %lu), textArea(%lu x %lu), maxChars %lu, topleft(%lu, %lu)\n", subTContext.active_area.width, subTContext.active_area.height, subTContext.char_size.width, subTContext.char_size.height, MAX_COLS, MAX_ROWS, subTContext.maxCharsPerRow, subTContext.top_left.x, subTContext.top_left.y)); return RM_OK;}RMstatus insert_string_into_subtitle_buffer(RMuint8 *string){ RMuint32 sLen = strlen((const char *)string); RMuint32 i = 0, j = 0; RMuint8 word[32]; RMuint32 partialLen; RMuint32 wLen; RMuint8 *buffer; RMbool lastWord = FALSE; while (1) { lastWord = popWordfromString(string, sLen, word, &i); i++; partialLen = strlen((const char *)subTContext.text_buffer[j]); wLen = strlen((const char *)word); if (partialLen + wLen + 1 > (MAX_COLS-1)) j++; buffer = subTContext.text_buffer[j]; pushWordintoString(&buffer, word); if ((lastWord) || (j > MAX_ROWS)) break; } for(i = 0; i <= j; i++) RMDBGLOG((SUBTITLEDBG, "*********** '%s'\n", subTContext.text_buffer[i])); subTContext.lastValidRowIndex = j; return RM_OK;}void clear_subtitle_buffer(void){ RMuint32 i, j; for (i = 0; i < MAX_ROWS; i++) for (j = 0; j < MAX_COLS; j++) subTContext.text_buffer[i][j] = '\0'; return;}RMbool popWordfromString(RMuint8 *string, RMuint32 sLen, RMuint8 *word, RMuint32 *index){ RMuint32 i = *index, j = 0; RMuint32 wLen; RMbool wordEnd = FALSE; while (1) { word[j] = string[i+j]; j++; if (string[i+j] == ' ') { wordEnd = TRUE; break; } if (i+j > sLen) break; }; word[j] = '\0'; wLen = strlen((const char *)word); *index = i + wLen; RMDBGLOG((SUBTITLEDBG, "pop: word '%s' from string '%s', slen %lu, wlen %lu, new string '%s'\n", word, string, sLen, wLen, (string + *index))); if (wordEnd) return FALSE; return TRUE;}void pushWordintoString(RMuint8 **string, RMuint8 *word){ RMuint32 sLen = strlen((const char *)*string); RMuint32 wLen = strlen((const char *)word); RMuint32 i = 0; RMuint8 *buffer = *string; if (sLen != 0) { buffer[sLen] = ' '; sLen++; } for (i = 0; i < wLen; i++) buffer[i+sLen] = word[i]; buffer[i+sLen] = '\0'; *string = *string + wLen; RMDBGLOG((SUBTITLEDBG, "push: word '%s', new string '%s', slen %lu, wlen %lu\n", word, buffer, sLen, wLen)); return;}/* END subtitle implementation *//* begin SPU implementation */RMstatus RMInitDoubleBufferOSD(RMuint32 *moduleID, struct DCCOSDProfile osdProfile, struct OSDdoubleBuffer *doubleBuffer){ enum EMhwlibMixerSourceState state; RMuint32 mixer, scaler, src_index, mixer_src; struct EMhwlibDisplayWindow window; RMuint32 val; RMuint32 pic_luma_addr[2], pic_addr[2], pic_luma_size[2], surface_addr; RMuint8 *buf_map; RMuint32 buf_addr, buf_size; RMstatus err; RMDBGLOG((ENABLE, "init doubleBuffer OSD, size %lu x %lu\n", osdProfile.Width, osdProfile.Height)); mixer = EMHWLIB_MODULE(DispMainMixer, 0); scaler = EMHWLIB_MODULE(DispGFXMultiScaler,0); /* set a NULL surface, this will force a full register update when next surface is set */ err = DCCSetSurfaceSource(dcc_info.pDCC, scaler, NULL); if (RMFAILED(err)) { fprintf(stderr, "Cannot unset gfx scaler's surface\n"); return err; } err = RUAExchangeProperty(dcc_info.pRUA, mixer, RMGenericPropertyID_MixerSourceIndex, &scaler, sizeof(scaler), &src_index, sizeof(src_index)); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot get scaler index\n")); return err; } mixer_src = EMHWLIB_TARGET_MODULE(mixer, 0 , src_index); state = EMhwlibMixerSourceState_Master; window.X = 0; window.Y = 0; window.Width = 4096; window.Height = 4096; window.XPositionMode = EMhwlibDisplayWindowPositionMode_FrontEdgeToBorder; window.YPositionMode = EMhwlibDisplayWindowPositionMode_FrontEdgeToBorder; window.XMode = EMhwlibDisplayWindowValueMode_Relative; window.YMode = EMhwlibDisplayWindowValueMode_Relative; window.WidthMode = EMhwlibDisplayWindowValueMode_Relative; window.HeightMode = EMhwlibDisplayWindowValueMode_Relative; RUASetProperty(dcc_info.pRUA, mixer_src, RMGenericPropertyID_MixerSourceWindow, &window, sizeof(window), 0); window.X = 0; window.Y = 0; window.Width = 4096; window.Height = 4096; window.XPositionMode = EMhwlibDisplayWindowPositionMode_FrontEdgeToBorder; window.YPositionMode = EMhwlibDisplayWindowPositionMode_FrontEdgeToBorder; window.XMode = EMhwlibDisplayWindowValueMode_Relative; window.YMode = EMhwlibDisplayWindowValueMode_Relative; window.WidthMode = EMhwlibDisplayWindowValueMode_Relative; window.HeightMode = EMhwlibDisplayWindowValueMode_Relative; RUASetProperty(dcc_info.pRUA, scaler, RMGenericPropertyID_ScalerInputWindow, &window, sizeof(window), 0); while((err = RUASetProperty(dcc_info.pRUA, mixer_src, RMGenericPropertyID_MixerSourceState, &state, sizeof(state), 0))==RM_PENDING); if (RMFAILED(err)) { RMDBGLOG((ENABLE, "Cannot set scaler's state on mixer\n")); return err; } while ((err = RUASetProperty(dcc_info.pRUA, mixer, RMGenericPropertyID_Validate, NULL, 0, 0)) == RM_PENDING); if (RMFAILED(err)) { fprintf(stderr, "Cannot validate mixer\n"); return err; } while ((err = RUASetProperty(dcc_info.pRUA, scaler, RMGenericPropertyID_Validate, NULL, 0, 0)) == RM_PENDING); if (RMFAILED(err)) { fprintf(stderr, "Cannot validate mixer\n"); return err; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -