이벤트는 무엇인가?
우리가 흔히 이벤트라 하면, 뭔가 특별한 것을 생각한다. 일반적으로 이벤트라는 것은 뭔가 어떤 특별한 뭔가를 의미한다.
ST 에서 각 디바이스마다 이벤트가 발생하도록 지원하고 있다.
각 디바이스의 application datasheet 를 보면, 관련 api들을 제공한다. 이런 이벤트 중에서는 정상 동작을 할 때, 발생하는 것이 있는 반면에 에러가 났을 때 발생하는 것이 있다.
이럴 때 이벤트를 봐라?
7020 ATSC 모듈이 A/V play 도중에 멈추는 현상이 있었다. 프로그램을 돌려본 결과, 채널 스캔을 하고 5 초를 넘기지 못했다.
기존의 보드 회로와 거의 같았기 때문에, 하드웨어는 거의 의심하지 않았다.
소프트웨어 쪽에서 알아 볼 수 있는 방법은 어떤 이벤트가 발생하고 멈추는 지 보는 것이 전부였다. 프로그램 역시, 예전 보드때와 동일했기 때문에 특별히 이상하다고 생각하진 않았다. 그렇다고 손 놓고 있을 수는 없으니, 별 수 없지 않는가?
이벤트 동작하게 하기
처음 7020 brick source 의 경우, 많은 이벤트가 동작하도록 세팅되어 있었다. 그래서 실행시킬 때, 화면 가득 이벤트 메세지가 출력되었다. 하지만, DAC5000 으로 옮겨 오면서, 불필요한 이벤트를 주석처리 했다. 이벤트에 대한 설정은 system/event.c 파일에 지정하고 있다.
우선 나는 A/V 와 관련있는 stpti, stvid 의 이벤트 함수를 등록 해제해야 했다.
stvid 에는 아래 표와 같은 이벤트 함수를 제공하고 있다.
이벤트 이름 | 설명 |
---|---|
STVID_DATA_OVERFLOW_EVT | Bit buffer level of occupancy reached the upper threshold. |
STVID_DATA_UNDERFLOW_EVT | Bit buffer level of occupancy reached the lower threshold. |
STVID_SPEED_DRIFT_THRESHOLD_EVT | The real current speed is drifting compared to the requested speed. |
STVID_STOPPED_EVT | Driver is now stopped, the last byte of data has been decoded. |
STVID_DATA_ERROR_EVT | A bad incoming data stream has been detected. |
STVID_NEW_PICTURE_DECODED_EVT | A new picture has just been decoded. |
STVID_PICTURE_DECODING_ERROR_EVT | The video driver has detected error(s) when decoding a picture. |
STVID_PROVIDED_DATA_TO_BE_INJECTED_EVT | Some data is provided by the video driver, which requiresto be injected by the application. |
STVID_SEQUENCE_INFO_EVT | Next sequence found in bit buffer has new information. |
STVID_USER_DATA_EVT | User data information are found in the decoded stream. |
STVID_DISPLAY_NEW_FRAME_EVT | A new picture will be displayed on the next VSYNC. |
STVID_NEW_PICTURE_TO_BE_DISPLAYED_EVT | A new picture will be displayed on the next VSYNC. |
STVID_ASPECT_RATIO_CHANGE_EVT | Next picture to be displayed (on next VSYNC) has a new aspect ratio compared to the previous displayed picture. |
STVID_FRAME_RATE_CHANGE_EVT | Next picture to be displayed (on next VSYNC) has a new frame rate information compared to the previous displayed picture. |
STVID_SCAN_TYPE_CHANGE_EVT | Next picture to be displayed (on next VSYNC) has a new scan type compared to the previous displayed picture. |
STVID_RESOLUTION_CHANGE_EVT | Next picture to be displayed (on next VSYNC) has a new resolution compared to the previous displayed picture. |
STVID_DIGINPUT_WIN_CHANGE_EVT | The digital input driver (stvin) needs to change its windows. |
STVID_IMPOSSIBLE_WITH_MEM_PROFILE_EVT | An action, with the current memory profile, cannot be performed. |
STVID_BACK_TO_SYNC_EVT | Video is synchronised again. |
STVID_OUT_OF_SYNC_EVT | Video lost synchronisation. |
STVID_SYNCHRO_EVT | The requested action of synchronization has been completed or time out occurred. |
많은 이벤트 함수들 중에서, STVID_RESOLUTION_CHANGE_EVT 를 등록해보겠다. event.c 파일에다 특정 이벤트를 등록해두면, 나중에 이벤트가 발생했을 때, 등록할 때 지정해 둔 함수가 실행이 된다. 이 때 거의 대부분 함수는 printf 이다.
우선 event.c 파일을 보자! 등록하는 형식이 다른 이벤트를 등록할 때도 동일하기 때문에 몇 군데만 바꿔주면 된다.
DevSubscribeParams.NotifyCallback = (STEVT_DeviceCallbackProc_t)RESOLUTION_CHANGE_EVT; // 이벤트 발생시 수행될 함수 ST_ErrorCode = STEVT_SubscribeDeviceEvent(EVT_Handle[0], VID_DeviceName, (STEVT_EventConstant_t)STVID_RESOLUTION_CHANGE_EVT, &DevSubscribeParams); // 등록할 이벤트 함수 지정 if (ST_ErrorCode != ST_NO_ERROR) { printf("DataErrMessage=%s\n", GetErrorText(ST_ErrorCode) ); return( ST_ErrorCode ); }
다음은 위의 이벤트가 발생할 때 호출되는 함수에 대한 정의이다.
void RESOLUTION_CHANGE_EVT( STEVT_CallReason_t Reason, const ST_DeviceName_t RegistrantName, STEVT_EventConstant_t Event, const void *EventData, const void *SubscriberData_p) { STVID_PictureParams_t *pictureType; pictureType=(STVID_PictureParams_t*)EventData; printf("STVID_RESOLUTION_CHANGE_EVT!\n"); printf("Width=%d, height=%d\n",pictureType->Width,pictureType->Height); }
구조체가 좀 복잡하게 나열되어 있지만, 결국은 printf 문이다.
이번에는 stpti 에 대한 이벤트를 등록해보겠다. stpti 의 경우는 앞의 stvid 와는 약간 다르다.
우선 event.c 에 이벤트를 등록하기전에, stpti_setup() 에서 STPTI_EnableErrorEvent() 함수로 이벤트를 enable 시켜야 한다.
아래는 system/stpti.c 이다.
ST_ErrorCode = STPTI_EnableErrorEvent(PTI_DeviceName, STPTI_EVENT_BUFFER_OVERFLOW_EVT); // enable 시킬 이벤트 함수 지정 if (ST_ErrorCode != ST_ERROR_FEATURE_NOT_SUPPORTED ) { // printf("PTI_EnableErrorEvent(OVERFLOW)=%s\n", GetErrorText(ST_ErrorCode) ); if (ST_ErrorCode != ST_NO_ERROR) return( ST_ErrorCode ); ST_ErrorCode = STPTI_EnableErrorEvent(PTI_DeviceName, STPTI_EVENT_CC_ERROR_EVT); // printf("PTI_EnableErrorEvent(CC)=%s\n", GetErrorText(ST_ErrorCode) ); if (ST_ErrorCode != ST_NO_ERROR) return( ST_ErrorCode ); ST_ErrorCode = STPTI_EnableErrorEvent(PTI_DeviceName, STPTI_EVENT_INTERRUPT_FAIL_EVT); // printf("PTI_EnableErrorEvent(CC)=%s\n", GetErrorText(ST_ErrorCode) ); if (ST_ErrorCode != ST_NO_ERROR) return( ST_ErrorCode );
그리고 나서, 이제는 event.c 에 stvid 와 같은 방법으로 등록해주면 된다.
DevSubscribeParams.NotifyCallback = (STEVT_DeviceCallbackProc_t)EVENT_PACKET_ERROR_EVT; ST_ErrorCode = STEVT_SubscribeDeviceEvent(EVT_Handle[0], PTI_DeviceName, (STEVT_EventConstant_t)STPTI_EVENT_PACKET_ERROR_EVT, &DevSubscribeParams); if (ST_ErrorCode != ST_NO_ERROR) { printf("NewPictureDecordErrMessage=%s\n", GetErrorText(ST_ErrorCode) ); return( ST_ErrorCode ); }
아래는 STPTI_EVENT_PACKET_ERROR_EVT 이벤트에 대한 호출 함수이다.
void EVENT_PACKET_ERROR_EVT() { printf("STPTI_EVENT_PACKET_ERROR_EVT!\n"); }
마치면서
현재 DAC5000 의 경우 event.c 를 보면, 대부분의 이벤트가 주석처리 되어 있다. 필요에 따라서 주석을 풀어서 등록이 가능하다.