화면 비율 조절하기
Video 재생시에 화면 비율(16:9 또는 4:3) 에서 각 4 가지의 모드를 조절하기 위한 내용을 담고 있다. 7020 의 경우 아래의 4가지 모드를 지원한다.
- letter-box
- pan and scan
- combined
- ignore
각 모드마다, 특징이 있다. 자세한 것은 stvid application datasheet 를 참고하기 바란다.
직면한 문제
Video 재생 도중에, 위의 4 가지 중 하나로 출력 모드를 바꿔야 하는데, 제대로 바뀌지 않는다.
한가지 힌트가 될 만한 것은 DACS1000 의 경우에는 제대로 동작하는 것이다. 하지만, DACS100 의 경우에는 5517 자체에서 Video 를 재생하기 때문에 세팅이 다를 수 있었다.
또한 7020stem_j 역시 scenario02 에서 4 가지 모드가 제대로 동작하였다.
해결 방법
DACS1000 과 DACS5000 모두 Video 모드를 바꾸기 위해서 'STVID_SetDisplayAspectRatioConversion()' 함수를 제공하고 있었다.
| 모드 | 설명 |
| 1 | pan and scan |
| 2 | letter box |
| 4 | combinded |
| 8 | ignore |
DACS1000 의 경우
src/system/vid.c 에서 다음과 같이 함수를 선언했다.
ST_ErrorCode_t VID_SetRatioConversion(U32 mode) // mode 는 위의 표를 참조
{
ST_ErrorCode_t ST_ErrorCode;
ST_ErrorCode = STVID_SetDisplayAspectRatioConversion(VID_ViewPortHandle, mode);
if (ST_ErrorCode != ST_NO_ERROR)
{
STTBX_Print(("VID_SetDisplayAspectRatioConversion()=%s\n", GetErrorText(ST_ErrorCode) ));
}
}
그리고 나서, src/ui/ui_system.c 에서 아래와 같이 추가해 주었다.
void NonMenuMsgProcessing(U8 inputKey)
{
U8 keyValue=0;
setTimer(10,EndUi,NULL);
switch(inputKey)
{
case ZERO_KEY:
keyValue=0;
DigitProcesser(keyValue);
break;
case ONE_KEY:
keyValue=1;
DigitProcesser(keyValue);
break;
case TWO_KEY:
keyValue=2;
DigitProcesser(keyValue);
break;
case THREE_KEY:
keyValue=3;
DigitProcesser(keyValue);
break;
case FOUR_KEY:
keyValue=4;
DigitProcesser(keyValue);
break;
case FIVE_KEY:
keyValue=5;
DigitProcesser(keyValue);
break;
case SIX_KEY:
keyValue=6;
DigitProcesser(keyValue);
break;
case SEVEN_KEY:
keyValue=7;
DigitProcesser(keyValue);
break;
case EIGHT_KEY:
keyValue=8;
DigitProcesser(keyValue);
break;
case NINE_KEY:
keyValue=9;
DigitProcesser(keyValue);
break;
case UP_KEY:
digitInput=FALSE;
CONFIRM_CHANNEL(ChUpMode);
break;
case DOWN_KEY:
digitInput=FALSE;
CONFIRM_CHANNEL(ChDnMode);
break;
case OK_KEY:
digitInput=FALSE;
if(inputValue==0)
{
EndUi();
if(pMainWindow==pOriginWindow)
{
pMainWindow=pTestWindow;
}
else
{
pMainWindow=pOriginWindow;
}
}
else
CONFIRM_CHANNEL(ChInMode);
break;
case RIGHT_KEY:
// clearTimer(EndInput);
Update_Data();
avVolumeControl(TRUE, &volpercentage);
// if(preMode != curMode) {
Fill_Rect(150, SCREEN_HEIGHT-100, 410, 29, 22);
Fill_Rect(156, SCREEN_HEIGHT-97, 400, 24, 1);
Put_Draw(120, SCREEN_HEIGHT-100, 40); // volume icon
// }
Fill_Rect(156, SCREEN_HEIGHT-97, (U16)volpercentage*4, 24, 162);
// setTimer(UI_TIMEOUT/2,EndUi,NULL);
// curMode=NoneMode;
break;
case LEFT_KEY:
// clearTimer(EndInput);
Update_Data();
//AUD_SetAttenuation(((100 - volpercentage)*76)/100);
avVolumeControl(FALSE, &volpercentage);
// if(preMode != curMode) {
Fill_Rect(150, SCREEN_HEIGHT-100, 410, 29, 22);
Fill_Rect(156, SCREEN_HEIGHT-97, 400, 24, 1);
Put_Draw(120, SCREEN_HEIGHT-100, 40); // volume icon
// }
HideRegion(155, SCREEN_HEIGHT-98, 400, 26, 1);
Fill_Rect(156, SCREEN_HEIGHT-97, (U16)volpercentage*4, 24, 162);
// setTimer(UI_TIMEOUT,EndUi,NULL);
// curMode=NoneMode;
break;
case MUTE_KEY:
//clearTimer(CloseMenu);
Update_Data();
if(isAudMute == TRUE) {
isAudMute=FALSE;
AUD_Mute(isAudMute);
Put_Draw(SCREEN_WIDTH/2-15, 300, 43); // speaker_off
} else {
isAudMute=TRUE;
AUD_Mute(isAudMute);
Put_Draw(SCREEN_WIDTH/2-15, 300, 44); // speaker_on
}
// setTimer(UI_TIMEOUT, EndUi, NULL);
// curMode=NoneMode;
break;
case RED_KEY: // 추가한 부분
// STVID_SetDisplayAspectRatioConversion(VID_ViewPortHandle, 1);
VID_SetRatioConversion(1);
break;
case GREEN_KEY: // 추가한 부분
// STVID_SetDisplayAspectRatioConversion(VID_ViewPortHandle, 2);
VID_SetRatioConversion(2);
break;
case YELLOW_KEY: // 추가한 부분
// STVID_SetDisplayAspectRatioConversion(VID_ViewPortHandle, 4);
VID_SetRatioConversion(4);
break;
case BLUE_KEY: // 추가한 부분
// STVID_SetDisplayAspectRatioConversion(VID_ViewPortHandle, 8);
VID_SetRatioConversion(8);
break;
default:
digitInput=FALSE;
break;
}
}
리모콘의 특정 키에 맵핑을 시켰다.
DACS1000 의 경우에는 위의 과정만으로도, 원하는 Video 모드를 얻을 수 있었다.
DAC5000 의 경우
처음에는 앞에서의 DACS1000 과 같이 했지만, 각 모드를 바꿀 때마다 아주 미세한 변화만 있을 뿐 바뀌지 않았다.
이외에도 Window_mode 를 AUTO_MATIC 으로 바꿔주어야 했다.
일단 먼저, src/ui/vidutils.c 에서 함수를 만든다.
void SET_AUTOMODE(void)
{
STVID_WindowParams_t WinParams = {STVID_WIN_ALIGN_TOP_HCENTRE,STVID_WIN_SIZE_DONT_CARE};
STVID_SetOutputWindowMode(VID_ViewPortHandle, TRUE, &WinParams); // TRUE 를 유의해서 보기 바란다
}
이번에는 src/system/vid.c 에서 함수를 추가한다.
ST_ErrorCode_t VID_SetRatioConversion(U32 mode)
{
ST_ErrorCode_t ST_ErrorCode;
ST_ErrorCode = STVID_SetDisplayAspectRatioConversion(VID_ViewPortHandle, mode);
if(ST_ErrorCode != ST_NO_ERROR)
{
printf("VID_SetRatioConversion Error\n");
}
}
이제 리모콘 키와 맵핑시키면 된다.
void NonMenuMsgProcessing(U8 inputKey)
{
U8 keyValue=0,result;
U16 major,minor;
U16 tempString[10];
setTimer(UI_TIMEOUT-270,EndUi,NULL);
switch(inputKey)
{
case ZERO_KEY:
keyValue=0;
DigitProcesser(keyValue);
break;
case ONE_KEY:
keyValue=1;
DigitProcesser(keyValue);
break;
case TWO_KEY:
keyValue=2;
DigitProcesser(keyValue);
break;
case THREE_KEY:
keyValue=3;
DigitProcesser(keyValue);
break;
case FOUR_KEY:
keyValue=4;
DigitProcesser(keyValue);
break;
case FIVE_KEY:
keyValue=5;
DigitProcesser(keyValue);
break;
case SIX_KEY:
keyValue=6;
DigitProcesser(keyValue);
break;
case SEVEN_KEY:
keyValue=7;
DigitProcesser(keyValue);
break;
case EIGHT_KEY:
keyValue=8;
DigitProcesser(keyValue);
break;
case NINE_KEY:
keyValue=9;
DigitProcesser(keyValue);
break;
case UP_KEY:
digitInput=FALSE;
CONFIRM_CHANNEL(ChUpMode);
break;
case DOWN_KEY:
digitInput=FALSE;
CONFIRM_CHANNEL(ChDnMode);
break;
case OK_KEY:
digitInput=FALSE;
MAJOR=TRUE;
if(inputValue==0)
{
EndUi();
if(pMainWindow==pOriginWindow)
{
pMainWindow=pTestWindow;
}
else
{
pMainWindow=pOriginWindow;
}
}
else
{
ChannnelChange(inMajor,inMinor);
inMajor=0;
inMinor=0;
bStartChInput=FALSE;
MAJOR=TRUE;
digitInput=FALSE;
bDashInput=FALSE;
clearTimer(TimeupChannelChange);
}
break;
case RIGHT_KEY:
// clearTimer(EndInput);
// Update_Data();
avVolumeControl(TRUE, &volpercentage);
// if(preMode != curMode) {
if((prevKey==RIGHT_KEY)||(prevKey==LEFT_KEY))
{
// Fill_Rect(156, SCREEN_HEIGHT-97, 400, 24, 1);
// Fill_Rect(156, SCREEN_HEIGHT-97, (U16)volpercentage*4, 24, 162);
ReDrawVolumeControl(volpercentage);
}
else
{
DrawVolumeControl(volpercentage);
/* Fill_Rect(150, SCREEN_HEIGHT-100, 410, 29, 22);
Fill_Rect(156, SCREEN_HEIGHT-97, 400, 24, 1);
Put_Draw(120, SCREEN_HEIGHT-100, 40); // volume icon
Fill_Rect(156, SCREEN_HEIGHT-97, (U16)volpercentage*4, 24, 162);*/
}
// setTimer(UI_TIMEOUT/2,EndUi,NULL);
// curMode=NoneMode;
UpdateWindow();
break;
case LEFT_KEY:
// clearTimer(EndInput);
// Update_Data();
//AUD_SetAttenuation(((100 - volpercentage)*76)/100);
avVolumeControl(FALSE, &volpercentage);
// if(preMode != curMode) {
if((prevKey==RIGHT_KEY)||(prevKey==LEFT_KEY))
{
// Fill_Rect(156, SCREEN_HEIGHT-97, 400, 24, 1);
// Fill_Rect(156, SCREEN_HEIGHT-97, (U16)volpercentage*4, 24, 162);
ReDrawVolumeControl(volpercentage);
}
else
{
/* Fill_Rect(150, SCREEN_HEIGHT-100, 410, 29, 22);
Fill_Rect(156, SCREEN_HEIGHT-97, 400, 24, 1);
Put_Draw(120, SCREEN_HEIGHT-100, 40); // volume icon
Fill_Rect(156, SCREEN_HEIGHT-97, (U16)volpercentage*4, 24, 162);*/
DrawVolumeControl(volpercentage);
}
// UpdateWindow();
// setTimer(UI_TIMEOUT,EndUi,NULL);
// curMode=NoneMode;
break;
case MUTE_KEY:
//clearTimer(CloseMenu);
// Update_Data();
if(isAudMute == TRUE) {
isAudMute=FALSE;
AUD_Mute(isAudMute);
Put_Draw(120, SCREEN_HEIGHT-100, 26); // speaker_off
} else {
isAudMute=TRUE;
AUD_Mute(isAudMute);
Put_Draw(120, SCREEN_HEIGHT-100, 25); // speaker_on
}
// setTimer(UI_TIMEOUT, EndUi, NULL);
// curMode=NoneMode;
break;
case HELP_KEY:
if(bHelpEnable)
{
bHelpEnable=FALSE;
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,100,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage_helpoff,10,10);
}
else
{
bHelpEnable=TRUE;
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,100,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage_helpon,10,10);
}
break;
case MAJOR_MINOR_BAR:
if(digitInput)
{
MAJOR=FALSE;
bDashInput=TRUE;
}
OutputChannelNumber(inMajor,inMinor);
break;
case INFO_KEY:
if(bActiveInfoWindow)
{
ClearWindow();
bActiveInfoWindow=FALSE;
}
else
{
DrawChInfomationWindow();
bActiveInfoWindow=TRUE;
}
break;
case MUILTI_LANG_KEY:
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,250,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage,10,10);
break;
/* case TIME_KEY:
//Fill_RectBasicTrans(300,800,200,50,2);
//PrintText(U32 x, U32 y, U8 * letter, U32 f_color, U32 b_color)
break;*/
/* case SOUND_KEY:
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,250,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage,10,10);
//Fill_RectBasicTrans(300,800,200,50,2);
//PrintText(U32 x, U32 y, U8 * letter, U32 f_color, U32 b_color)
break;*/
case FLASHBACK_KEY:
BackChannnelChange();
break;
case CHANNEL_ADD:
//pMessage_channeladd
if((currentMajor!=0)&&(currentMinor!=0))
{
/* if(CheckCurrentChannelInfo())
{
}*/
printf("Edit ch %d-%d\n",currentMajor,currentMinor);
result=CheckChannel(currentMajor,currentMinor,HIDE_STATE);
if(result==2)
{
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,200,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage_liked_channel,10,10);
}
else if(result)
{
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,80,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage_channeladd,10,10);
}
else
{
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,80,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage_channeldel,10,10);
}
}
break;
case RATIO_KEY:
/* result=vidToggleVideMode();
if(result==2)
{
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,50,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage_video_wide,10,10);
}
else if(result==3)
{
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,50,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage_video_normal,10,10);
}
else
{
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,50,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage_video_exten,10,10);
}*/
tempString[0]=pMessage_book_sleep[0];
tempString[1]=pMessage_book_sleep[1];
tempString[2]=pMessage_book_sleep[2];
tempString[3]=pMessage_book_sleep[3];
tempString[4]=0x0020;
SleepPowerOnMin+=10;
if(SleepPowerOnMin==60)
{
SleepPowerOnMin=0;
bEnableSleepOff=TRUE;
tempString[5]=0xaebc;
tempString[6]=0xc9d0;
tempString[7]=0;
}
else
{
bEnableSleepOff=TRUE;
tempString[5]=SleepPowerOnMin/10+48;
tempString[6]='0';
tempString[7]=0xbd84;
tempString[8]=0;
}
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,120,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)tempString,10,10);
break;
//선호
case FAVORITE_ADD_KEY:
//pMessage_channeladd
if((currentMajor!=0)&&(currentMinor!=0))
{
/* if(CheckCurrentChannelInfo())
{
}*/
result=CheckChannel(currentMajor,currentMinor,FAV_STATE);
if(result==2)
{
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,200,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage_delete_channel,10,10);
}
else if(result)
{
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,80,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage_like_delete,10,10);
}
else
{
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,80,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage_like_regist,10,10);
}
}
break;
case EPG_KEY:
SetKeyAction(pChCurInfoWindow, 2,MENU_KEY, CloseInputInfoWindow);
NewWindow(pChCurInfoWindow);
break;
case DIGITAL_CAPTION:
Fill_RectBasicTrans(MESSAGE_BOX_X,MESSAGE_BOX_Y,250,20,SUB_BG);
PrintUnicode(MESSAGE_X,MESSAGE_Y,(U16*)pMessage,10,10);
break;
case FAVORITE_PLAY_KEY:
CONFIRM_CHANNEL(FavChMode);
break;
case EXIT_KEY:
EndUi();
break;
case RED_KEY: // 추가한 부분
SET_AUTOMODE();
VID_SetRatioConversion(1);
break;
case GREEN_KEY: // 추가한 부분
SET_AUTOMODE();
VID_SetRatioConversion(2);
break;
case YELLOW_KEY: // 추가한 부분
SET_AUTOMODE();
VID_SetRatioConversion(4);
break;
case BLUE_KEY: // 추가한 부분
SET_AUTOMODE();
VID_SetRatioConversion(8);
break;
default:
digitInput=FALSE;
break;
}
}
결론
Video 를 재생하기 전에, window mode 와 ratio 를 바꿀 수 있는 함수를 통해 원하는 모드로 변경가능하다.