| 1 | /*************************************************************************** |
|---|
| 2 | * Copyright (c) 2012, Broadcom Corporation |
|---|
| 3 | * All Rights Reserved |
|---|
| 4 | * Confidential Property of Broadcom Corporation |
|---|
| 5 | * |
|---|
| 6 | * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE |
|---|
| 7 | * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR |
|---|
| 8 | * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. |
|---|
| 9 | * |
|---|
| 10 | * $brcm_Workfile: $ |
|---|
| 11 | * $brcm_Revision: $ |
|---|
| 12 | * $brcm_Date: $ |
|---|
| 13 | * |
|---|
| 14 | * Module Description: |
|---|
| 15 | * |
|---|
| 16 | * Revision History: |
|---|
| 17 | * |
|---|
| 18 | * $brcm_Log: $ |
|---|
| 19 | * |
|---|
| 20 | ***************************************************************************/ |
|---|
| 21 | |
|---|
| 22 | #include "nexus_platform.h" |
|---|
| 23 | |
|---|
| 24 | #include "nexus_video_decoder.h" |
|---|
| 25 | #include "nexus_video_window.h" |
|---|
| 26 | #include "nexus_stc_channel.h" |
|---|
| 27 | #include "nexus_timebase.h" |
|---|
| 28 | #include "nexus_display.h" |
|---|
| 29 | #include "nexus_display_vbi.h" |
|---|
| 30 | #include "nexus_core_utils.h" |
|---|
| 31 | #include "nexus_video_window.h" |
|---|
| 32 | #include "nexus_video_decoder_userdata.h" |
|---|
| 33 | #include "nexus_video_input_vbi.h" |
|---|
| 34 | #include "nexus_video_decoder_trick.h" |
|---|
| 35 | |
|---|
| 36 | #include "bstd.h" |
|---|
| 37 | #include "bkni.h" |
|---|
| 38 | #include "ts_psi.h" |
|---|
| 39 | #include "bavc.h" |
|---|
| 40 | |
|---|
| 41 | #include "bsettop.h" |
|---|
| 42 | #include "bsettop_stream_n_priv.h" |
|---|
| 43 | #include "bsettop_display_n_priv.h" |
|---|
| 44 | #include "xds_ctrl.h" |
|---|
| 45 | |
|---|
| 46 | BDBG_MODULE(bdecode); |
|---|
| 47 | |
|---|
| 48 | #define MAX_TRIPLETS 0x1F |
|---|
| 49 | |
|---|
| 50 | struct bdecode { |
|---|
| 51 | NEXUS_VideoDecoderHandle videoDecoder; |
|---|
| 52 | |
|---|
| 53 | /* following two members are from bdisplay_t when opening bdecode_window_open */ |
|---|
| 54 | NEXUS_DisplayHandle display[eBDISPLAY_ID_MAX]; |
|---|
| 55 | NEXUS_VideoWindowHandle window[eBDISPLAY_ID_MAX]; |
|---|
| 56 | |
|---|
| 57 | bool video_decoding; |
|---|
| 58 | bstream_info_t *p_stream_info; |
|---|
| 59 | bstream_t stream; |
|---|
| 60 | |
|---|
| 61 | bdecode_config config; |
|---|
| 62 | bdecode_status status; |
|---|
| 63 | |
|---|
| 64 | unsigned int start_ticks; |
|---|
| 65 | bool seq_pending; |
|---|
| 66 | bool first_pts_pending; |
|---|
| 67 | bool b708cc; |
|---|
| 68 | |
|---|
| 69 | NEXUS_ClosedCaptionData captionData[MAX_TRIPLETS]; |
|---|
| 70 | unsigned char triplets[MAX_TRIPLETS*3]; |
|---|
| 71 | BKNI_EventHandle wdEvent; |
|---|
| 72 | |
|---|
| 73 | bool bypass_tsm; /* flag to bypass TSM mode if video is H.264 to show video as long as got the GOP */ |
|---|
| 74 | xds_ctrl_t xds_ctrl; |
|---|
| 75 | }; |
|---|
| 76 | |
|---|
| 77 | static struct bdecode s_decode; |
|---|
| 78 | |
|---|
| 79 | bool g_disable_fcc = false; |
|---|
| 80 | static void bdecode_first_pts_passed_cb(void *context, int param); |
|---|
| 81 | static void bdecode_stream_changed_cb(void *context, int param); |
|---|
| 82 | static void bdecode_userdata_ready(void *context, int param); |
|---|
| 83 | static void bdecode_first_pts_cb(void *context, int param); |
|---|
| 84 | |
|---|
| 85 | extern NEXUS_DisplayHandle bdisplay_p_get_handle(bdisplay_t display, int id); |
|---|
| 86 | extern NEXUS_VideoWindowHandle bdisplay_p_get_window(bdisplay_t display, int index); |
|---|
| 87 | extern bresult bdisplay_vbi_clear_cc(void); |
|---|
| 88 | |
|---|
| 89 | /* |
|---|
| 90 | * Summary: |
|---|
| 91 | * Open a decode engine. |
|---|
| 92 | * Description: |
|---|
| 93 | **/ |
|---|
| 94 | bdecode_t bdecode_open(bobject_t decode_id) |
|---|
| 95 | { |
|---|
| 96 | NEXUS_VideoDecoderSettings videoSettings; |
|---|
| 97 | NEXUS_VideoInputVbiSettings vbiSettings; |
|---|
| 98 | |
|---|
| 99 | BSTD_UNUSED(decode_id); |
|---|
| 100 | |
|---|
| 101 | BKNI_Memset(&s_decode, 0, sizeof(struct bdecode)); |
|---|
| 102 | |
|---|
| 103 | s_decode.videoDecoder = NEXUS_VideoDecoder_Open(0, NULL); |
|---|
| 104 | |
|---|
| 105 | NEXUS_VideoDecoder_GetSettings(s_decode.videoDecoder, &videoSettings); |
|---|
| 106 | videoSettings.channelChangeMode = NEXUS_VideoDecoder_ChannelChangeMode_eHoldUntilFirstPicture; |
|---|
| 107 | |
|---|
| 108 | videoSettings.firstPtsPassed.callback = bdecode_first_pts_passed_cb; |
|---|
| 109 | videoSettings.firstPtsPassed.context = &s_decode; |
|---|
| 110 | |
|---|
| 111 | videoSettings.firstPts.callback = bdecode_first_pts_cb; |
|---|
| 112 | videoSettings.firstPts.context = &s_decode; |
|---|
| 113 | |
|---|
| 114 | videoSettings.streamChanged.callback = bdecode_stream_changed_cb; |
|---|
| 115 | videoSettings.streamChanged.context = &s_decode; |
|---|
| 116 | NEXUS_VideoDecoder_SetSettings(s_decode.videoDecoder, &videoSettings); |
|---|
| 117 | |
|---|
| 118 | NEXUS_VideoInput_GetVbiSettings(NEXUS_VideoDecoder_GetConnector(s_decode.videoDecoder), &vbiSettings); |
|---|
| 119 | vbiSettings.closedCaptionEnabled = true; |
|---|
| 120 | vbiSettings.closedCaptionBufferSize = 200; |
|---|
| 121 | vbiSettings.closedCaptionDataReady.callback = bdecode_userdata_ready; |
|---|
| 122 | vbiSettings.closedCaptionDataReady.context = &s_decode; |
|---|
| 123 | NEXUS_VideoInput_SetVbiSettings(NEXUS_VideoDecoder_GetConnector(s_decode.videoDecoder), &vbiSettings); |
|---|
| 124 | bstream_init(s_decode.videoDecoder); |
|---|
| 125 | xds_ctrl_init(&s_decode.xds_ctrl); |
|---|
| 126 | return (&s_decode); |
|---|
| 127 | } |
|---|
| 128 | |
|---|
| 129 | /* |
|---|
| 130 | * Summary: |
|---|
| 131 | * Close a decode engine. |
|---|
| 132 | * Description: |
|---|
| 133 | * The decode should be stopped before closing. After closing, the bdecode_t handle is invalid |
|---|
| 134 | */ |
|---|
| 135 | void bdecode_close( |
|---|
| 136 | bdecode_t decode /* handle returned by bdecode_open */ |
|---|
| 137 | ) |
|---|
| 138 | { |
|---|
| 139 | int i; |
|---|
| 140 | BDBG_ASSERT(decode); |
|---|
| 141 | |
|---|
| 142 | |
|---|
| 143 | if (decode->videoDecoder) |
|---|
| 144 | NEXUS_VideoDecoder_Close(decode->videoDecoder); |
|---|
| 145 | |
|---|
| 146 | for (i=0; i<eBDISPLAY_ID_MAX; i++) { |
|---|
| 147 | NEXUS_VideoWindow_Close(decode->window[i]); |
|---|
| 148 | } |
|---|
| 149 | return; |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | /* |
|---|
| 153 | * Summary: |
|---|
| 154 | * Start decoding a stream. |
|---|
| 155 | **/ |
|---|
| 156 | bresult bdecode_start( |
|---|
| 157 | bdecode_t decode, /* handle returned by bdecode_open */ |
|---|
| 158 | bstream_t p_stream, /* source for the decode, either analog or digital */ |
|---|
| 159 | bdecode_window_t window /* window to render decode <= not used */ |
|---|
| 160 | ) |
|---|
| 161 | { |
|---|
| 162 | bstream_status status; |
|---|
| 163 | NEXUS_TimebaseSettings timebaseSettings; |
|---|
| 164 | NEXUS_VideoDecoderSettings vsettings; |
|---|
| 165 | |
|---|
| 166 | BSTD_UNUSED(window); |
|---|
| 167 | BDBG_ASSERT(p_stream); |
|---|
| 168 | |
|---|
| 169 | #ifdef CONFIG_EIA_708 |
|---|
| 170 | decode->b708cc = false; |
|---|
| 171 | #endif |
|---|
| 172 | decode->stream = p_stream; |
|---|
| 173 | |
|---|
| 174 | bstream_get_status(p_stream, &status); |
|---|
| 175 | if (status.mpeg.video[0].pid == 0) { |
|---|
| 176 | BDBG_WRN(("%s (0x%04x)", __FUNCTION__, status.mpeg.video[0].pid)); |
|---|
| 177 | return eBAPP_RESULT_FAILURE; |
|---|
| 178 | } |
|---|
| 179 | |
|---|
| 180 | if (decode->video_decoding) { |
|---|
| 181 | BDBG_WRN(("%s (0x%04x) video is already decoding", __FUNCTION__, status.mpeg.video[0].pid)); |
|---|
| 182 | return eBAPP_RESULT_FAILURE; |
|---|
| 183 | } |
|---|
| 184 | |
|---|
| 185 | decode->p_stream_info = bstream_get_info(p_stream); |
|---|
| 186 | if (!decode->p_stream_info) { |
|---|
| 187 | BDBG_WRN(("%s invalid nexus handles", __FUNCTION__)); |
|---|
| 188 | return eBAPP_RESULT_FAILURE; |
|---|
| 189 | } |
|---|
| 190 | |
|---|
| 191 | BDBG_ASSERT(decode->p_stream_info->videoPidChannel); |
|---|
| 192 | BDBG_ASSERT(decode->p_stream_info->stcChannel); |
|---|
| 193 | |
|---|
| 194 | NEXUS_VideoDecoder_GetDefaultStartSettings(&(decode->p_stream_info->decodeSettings)); |
|---|
| 195 | decode->p_stream_info->decodeSettings.codec = status.mpeg.video[0].format; |
|---|
| 196 | decode->p_stream_info->decodeSettings.pidChannel = decode->p_stream_info->videoPidChannel; |
|---|
| 197 | decode->p_stream_info->decodeSettings.stcChannel = decode->p_stream_info->stcChannel; |
|---|
| 198 | decode->p_stream_info->decodeSettings.prerollRate = 1; |
|---|
| 199 | |
|---|
| 200 | NEXUS_Timebase_GetSettings(NEXUS_Timebase_e0, &timebaseSettings); |
|---|
| 201 | timebaseSettings.sourceType = NEXUS_TimebaseSourceType_ePcr; |
|---|
| 202 | timebaseSettings.sourceSettings.pcr.pidChannel = decode->p_stream_info->pcrPidChannel; |
|---|
| 203 | timebaseSettings.sourceSettings.pcr.maxPcrError = 0xFF; |
|---|
| 204 | timebaseSettings.sourceSettings.pcr.trackRange = NEXUS_TimebaseTrackRange_e61ppm; |
|---|
| 205 | NEXUS_Timebase_SetSettings(NEXUS_Timebase_e0, &timebaseSettings); |
|---|
| 206 | |
|---|
| 207 | NEXUS_VideoDecoder_GetSettings(decode->videoDecoder, &vsettings); |
|---|
| 208 | vsettings.channelChangeMode = NEXUS_VideoDecoder_ChannelChangeMode_eHoldUntilTsmLock; |
|---|
| 209 | NEXUS_VideoDecoder_SetSettings(decode->videoDecoder, &vsettings); |
|---|
| 210 | |
|---|
| 211 | if (status.mpeg.video[0].format == NEXUS_VideoCodec_eH264) { |
|---|
| 212 | NEXUS_VideoDecoderTrickState trick; |
|---|
| 213 | NEXUS_VideoDecoder_GetTrickState(decode->videoDecoder, &trick); |
|---|
| 214 | trick.tsmEnabled = NEXUS_TsmMode_eDisabled; |
|---|
| 215 | NEXUS_VideoDecoder_SetTrickState(decode->videoDecoder, &trick); |
|---|
| 216 | decode->bypass_tsm = true; |
|---|
| 217 | } |
|---|
| 218 | decode->config.channel_change = 1; |
|---|
| 219 | NEXUS_VideoDecoder_StartDecodeWithPrimer(decode->videoDecoder, decode->p_stream_info->primerHandle); |
|---|
| 220 | decode->video_decoding = true; |
|---|
| 221 | |
|---|
| 222 | decode->status.bVideoDecoding = true; |
|---|
| 223 | decode->first_pts_pending = true; |
|---|
| 224 | decode->start_ticks = bos_getticks(); |
|---|
| 225 | |
|---|
| 226 | NEXUS_VideoInput_FlushClosedCaption(NEXUS_VideoDecoder_GetConnector(decode->videoDecoder)); |
|---|
| 227 | decode->b708cc = false; |
|---|
| 228 | |
|---|
| 229 | return b_ok; |
|---|
| 230 | } |
|---|
| 231 | |
|---|
| 232 | /* |
|---|
| 233 | * Summary: |
|---|
| 234 | * Stop decoding a stream. |
|---|
| 235 | * Description: |
|---|
| 236 | * The stream remains valid after decode is stopped. Decode could be restarted |
|---|
| 237 | * without retuning or restarting playback. |
|---|
| 238 | **/ |
|---|
| 239 | void bdecode_stop( |
|---|
| 240 | bdecode_t decode /* handle returned by bdecode_open */ |
|---|
| 241 | ) |
|---|
| 242 | { |
|---|
| 243 | if (!decode->video_decoding) |
|---|
| 244 | return; |
|---|
| 245 | |
|---|
| 246 | BDBG_ASSERT(decode->p_stream_info); |
|---|
| 247 | BDBG_ASSERT(decode->p_stream_info->primerHandle); |
|---|
| 248 | |
|---|
| 249 | NEXUS_VideoDecoder_Stop(decode->videoDecoder); |
|---|
| 250 | NEXUS_VideoDecoder_StartPrimer(decode->videoDecoder, decode->p_stream_info->primerHandle, &(decode->p_stream_info->decodeSettings)); |
|---|
| 251 | decode->video_decoding = false; |
|---|
| 252 | } |
|---|
| 253 | |
|---|
| 254 | /* |
|---|
| 255 | * Summary: |
|---|
| 256 | * Get the status of the decoder and current source. |
|---|
| 257 | */ |
|---|
| 258 | bresult bdecode_get_status( |
|---|
| 259 | bdecode_t decode, /* handle returned by bdecode_open */ |
|---|
| 260 | bdecode_status *status /* [out] status to be populated */ |
|---|
| 261 | ) |
|---|
| 262 | { |
|---|
| 263 | NEXUS_VideoDecoderStatus nstatus; |
|---|
| 264 | NEXUS_VideoDecoderStreamInformation streamInfo; |
|---|
| 265 | |
|---|
| 266 | bstream_status stream_status; |
|---|
| 267 | |
|---|
| 268 | BDBG_ASSERT(decode); |
|---|
| 269 | BDBG_ASSERT(status); |
|---|
| 270 | |
|---|
| 271 | NEXUS_VideoDecoder_GetStatus(decode->videoDecoder, &nstatus); |
|---|
| 272 | NEXUS_VideoDecoder_GetStreamInformation(decode->videoDecoder, &streamInfo); |
|---|
| 273 | |
|---|
| 274 | if (decode->stream) |
|---|
| 275 | bstream_get_status(decode->stream, &stream_status); |
|---|
| 276 | else |
|---|
| 277 | BKNI_Memset(&stream_status, 0, sizeof(bstream_status)); |
|---|
| 278 | |
|---|
| 279 | status->source_width = nstatus.source.width; |
|---|
| 280 | status->source_height = nstatus.source.height; |
|---|
| 281 | status->display_width = nstatus.display.width; |
|---|
| 282 | status->display_height = nstatus.display.height; |
|---|
| 283 | status->video_fifo_depth = nstatus.fifoDepth; |
|---|
| 284 | status->video_fifo_size = nstatus.fifoSize; |
|---|
| 285 | status->video_pts = nstatus.pts; |
|---|
| 286 | status->video_stc = nstatus.pts + nstatus.ptsStcDifference; |
|---|
| 287 | status->video_pts_error = 0; /*TODO: see VideoDecoder_P_GetStatus_Avd. ptsInfo.uiPCROffset. */ |
|---|
| 288 | status->video_aspect_ratio = streamInfo.aspectRatio; /* need to be covnerted */ |
|---|
| 289 | status->video_format = nstatus.format; /* need to be converted */ |
|---|
| 290 | status->video_framerate = nstatus.frameRate; /* need to be converted */ |
|---|
| 291 | status->first_pts_ticks = decode->status.first_pts_ticks; |
|---|
| 292 | status->first_pts_cnt = decode->status.first_pts_cnt; |
|---|
| 293 | status->seq_ticks = decode->status.seq_ticks; |
|---|
| 294 | status->hPanScan = streamInfo.horizontalPanScan; |
|---|
| 295 | status->vPanScan = streamInfo.verticalPanScan; |
|---|
| 296 | status->watchdog_cnt = nstatus.numWatchdogs; |
|---|
| 297 | status->pts_err_cnt = nstatus.ptsErrorCount; |
|---|
| 298 | status->req_stc_cnt = decode->status.req_stc_cnt; |
|---|
| 299 | status->offset_cnt = 0; /* TODO:: ePtsStcOffset, NEXUS_VideoDecoder_P_PtsStcOffset_isr */ |
|---|
| 300 | status->pic_info_cnt = 0; /* TODO::ePictureParameters, NEXUS_VideoDecoder_P_PictureParams_isr */ |
|---|
| 301 | status->TSM_Mode = !nstatus.tsm; |
|---|
| 302 | status->decode_err_cnt = nstatus.numDecodeErrors; |
|---|
| 303 | status->decoder_drop_cnt = nstatus.numDecodeDrops; |
|---|
| 304 | status->display_drop_cnt = nstatus.numDisplayDrops; |
|---|
| 305 | status->pic_received = nstatus.numPicturesReceived; |
|---|
| 306 | status->underflow_cnt = nstatus.numDisplayUnderflows; |
|---|
| 307 | status->bStreamProgressive = !(nstatus.interlaced); |
|---|
| 308 | #if 0 |
|---|
| 309 | status->bitRate = |
|---|
| 310 | status.bPCR_Lock = |
|---|
| 311 | #endif |
|---|
| 312 | status->bVideoDecoding = decode->status.bVideoDecoding; |
|---|
| 313 | status->profile = nstatus.protocolProfile; |
|---|
| 314 | status->level = nstatus.protocolLevel; |
|---|
| 315 | status->bFrameProgressive = !nstatus.interlaced; |
|---|
| 316 | status->xvdch_status = nstatus.avdStatusBlock; |
|---|
| 317 | status->vPID = stream_status.mpeg.video[0].pid; |
|---|
| 318 | status->pcrPID = stream_status.mpeg.pcr_pid; |
|---|
| 319 | |
|---|
| 320 | return b_ok; |
|---|
| 321 | } |
|---|
| 322 | |
|---|
| 323 | bresult bdecode_window_get(bdecode_window_t window, bdecode_window_settings *settings) |
|---|
| 324 | { |
|---|
| 325 | NEXUS_VideoWindowSettings windowSettings; |
|---|
| 326 | int id = (int)window; |
|---|
| 327 | NEXUS_VideoWindowHandle handle = s_decode.window[id]; |
|---|
| 328 | |
|---|
| 329 | NEXUS_VideoWindow_GetSettings(handle, &windowSettings); |
|---|
| 330 | settings->position.x = windowSettings.position.x; |
|---|
| 331 | settings->position.y = windowSettings.position.y; |
|---|
| 332 | settings->position.width = windowSettings.position.width; |
|---|
| 333 | settings->position.height = windowSettings.position.height; |
|---|
| 334 | #if HAS_HDMI |
|---|
| 335 | if (id == eBDISPLAY_HDMI) |
|---|
| 336 | { |
|---|
| 337 | NEXUS_VideoFormatInfo vinfo; |
|---|
| 338 | NEXUS_DisplaySettings dispSettings; |
|---|
| 339 | NEXUS_Display_GetSettings(s_decode.display[id], &dispSettings); |
|---|
| 340 | NEXUS_VideoFormat_GetInfo(dispSettings.format, &vinfo); |
|---|
| 341 | settings->def_position.x = settings->def_position.y = 0; |
|---|
| 342 | settings->def_position.width = vinfo.digitalWidth; |
|---|
| 343 | settings->def_position.height = vinfo.digitalHeight; |
|---|
| 344 | } |
|---|
| 345 | else |
|---|
| 346 | #endif |
|---|
| 347 | { |
|---|
| 348 | settings->def_position.x = windowSettings.clipBase.x; |
|---|
| 349 | settings->def_position.y = windowSettings.clipBase.y; |
|---|
| 350 | settings->def_position.width = windowSettings.clipBase.width; |
|---|
| 351 | settings->def_position.height = windowSettings.clipBase.height; |
|---|
| 352 | } |
|---|
| 353 | return b_ok; |
|---|
| 354 | } |
|---|
| 355 | |
|---|
| 356 | bresult bdecode_window_set(bdecode_window_t window, bdecode_window_settings *settings) |
|---|
| 357 | { |
|---|
| 358 | NEXUS_VideoWindowSettings windowSettings; |
|---|
| 359 | NEXUS_VideoWindowHandle handle = s_decode.window[(int)window]; |
|---|
| 360 | |
|---|
| 361 | BDBG_ASSERT(settings); |
|---|
| 362 | |
|---|
| 363 | NEXUS_VideoWindow_GetSettings(handle, &windowSettings); |
|---|
| 364 | windowSettings.position.x = settings->position.x; |
|---|
| 365 | windowSettings.position.y = settings->position.y; |
|---|
| 366 | windowSettings.position.width = settings->position.width; |
|---|
| 367 | windowSettings.position.height = settings->position.height; |
|---|
| 368 | NEXUS_VideoWindow_SetSettings(handle, &windowSettings); |
|---|
| 369 | NEXUS_DisplayModule_SetUpdateMode(NEXUS_DisplayUpdateMode_eAuto); |
|---|
| 370 | return b_ok; |
|---|
| 371 | } |
|---|
| 372 | |
|---|
| 373 | bresult bdecode_window_preset(bdecode_window_t window, bdecode_window_settings *settings) |
|---|
| 374 | { |
|---|
| 375 | NEXUS_VideoWindowSettings windowSettings; |
|---|
| 376 | NEXUS_VideoWindowHandle handle = s_decode.window[(int)window]; |
|---|
| 377 | |
|---|
| 378 | BDBG_ASSERT(settings); |
|---|
| 379 | |
|---|
| 380 | NEXUS_DisplayModule_SetUpdateMode(NEXUS_DisplayUpdateMode_eManual); |
|---|
| 381 | NEXUS_VideoWindow_GetSettings(handle, &windowSettings); |
|---|
| 382 | windowSettings.position.x = settings->position.x; |
|---|
| 383 | windowSettings.position.y = settings->position.y; |
|---|
| 384 | windowSettings.position.width = settings->position.width; |
|---|
| 385 | windowSettings.position.height = settings->position.height; |
|---|
| 386 | NEXUS_VideoWindow_SetSettings(handle, &windowSettings); |
|---|
| 387 | return b_ok; |
|---|
| 388 | } |
|---|
| 389 | |
|---|
| 390 | #define B_MAX_VBI_CC_COUNT 32 /* required by VBI lib */ |
|---|
| 391 | static void bdecode_userdata_ready(void *context, int param) |
|---|
| 392 | { |
|---|
| 393 | bdecode_t decode = (bdecode_t)context; |
|---|
| 394 | NEXUS_VideoDecoderHandle videoDecoder = decode->videoDecoder; |
|---|
| 395 | NEXUS_Error rc; |
|---|
| 396 | uint32_t numEntries, numValidEntries, i, size; |
|---|
| 397 | uint8_t *buffer; |
|---|
| 398 | |
|---|
| 399 | BSTD_UNUSED(param); |
|---|
| 400 | |
|---|
| 401 | NEXUS_VideoInput_ReadClosedCaption(NEXUS_VideoDecoder_GetConnector(videoDecoder), decode->captionData, MAX_TRIPLETS, &numEntries); |
|---|
| 402 | if (!decode->config.cc_enabled) return; |
|---|
| 403 | |
|---|
| 404 | for (i=0, numValidEntries = 0; i<numEntries; i++) |
|---|
| 405 | { |
|---|
| 406 | if ((decode->captionData[i].field > 3) || decode->captionData[i].noData) continue; |
|---|
| 407 | |
|---|
| 408 | if ((decode->captionData[i].field & 0x2)==0x2) { /* 708 CC */ |
|---|
| 409 | /* primary CC is 708 */ |
|---|
| 410 | if ((i!=(numEntries-1)) && ((decode->captionData[i+1].field & 0x2) == 0x2) && (decode->b708cc == false)) { |
|---|
| 411 | BDBG_WRN(("Switch to 708CC mode")); |
|---|
| 412 | numValidEntries = 0; |
|---|
| 413 | decode->b708cc = true; |
|---|
| 414 | } |
|---|
| 415 | } |
|---|
| 416 | else if (decode->b708cc) { |
|---|
| 417 | continue; |
|---|
| 418 | } |
|---|
| 419 | |
|---|
| 420 | if (!decode->captionData[i].noData) { |
|---|
| 421 | decode->triplets[numValidEntries] = decode->captionData[i].field; |
|---|
| 422 | decode->triplets[numValidEntries+1] = decode->captionData[i].data[0]; |
|---|
| 423 | decode->triplets[numValidEntries+2] = decode->captionData[i].data[1]; |
|---|
| 424 | numValidEntries+=3; |
|---|
| 425 | } |
|---|
| 426 | } |
|---|
| 427 | if (decode->config.cc_callback && decode->config.cc_enabled && numValidEntries>0) { |
|---|
| 428 | decode->config.cc_callback((unsigned char *)decode->triplets, numValidEntries, decode->b708cc?false:true); |
|---|
| 429 | } |
|---|
| 430 | } |
|---|
| 431 | |
|---|
| 432 | /* |
|---|
| 433 | * Summary: |
|---|
| 434 | * Get the config for the decoder. |
|---|
| 435 | */ |
|---|
| 436 | void bdecode_get_config( |
|---|
| 437 | bdecode_t decode, /* handle returned by bdecode_open */ |
|---|
| 438 | bdecode_config *cfg /* [out] configuration structure to be populated */ |
|---|
| 439 | ) |
|---|
| 440 | { |
|---|
| 441 | unsigned int flags; |
|---|
| 442 | flags = bos_enter_critical(); |
|---|
| 443 | *cfg = decode->config; |
|---|
| 444 | bos_exit_critical(flags); |
|---|
| 445 | } |
|---|
| 446 | |
|---|
| 447 | /* |
|---|
| 448 | * Summary: |
|---|
| 449 | * Set the config for the decoder. |
|---|
| 450 | */ |
|---|
| 451 | void bdecode_set_config( |
|---|
| 452 | bdecode_t decode, /* handle returned by bdecode_open */ |
|---|
| 453 | bdecode_config *cfg /*configuration */ |
|---|
| 454 | ) |
|---|
| 455 | { |
|---|
| 456 | NEXUS_VideoDecoderSettings settings; |
|---|
| 457 | |
|---|
| 458 | NEXUS_VideoDecoder_GetSettings(decode->videoDecoder, &settings); |
|---|
| 459 | if (cfg->mute != settings.mute) { |
|---|
| 460 | settings.mute = cfg->mute; |
|---|
| 461 | } |
|---|
| 462 | if ((cfg->channel_change != decode->config.channel_change) && !(cfg->channel_change&decode->config.channel_change)) |
|---|
| 463 | { |
|---|
| 464 | switch (cfg->channel_change) { |
|---|
| 465 | case 0: settings.channelChangeMode = NEXUS_VideoDecoder_ChannelChangeMode_eMute; break; |
|---|
| 466 | case 1: settings.channelChangeMode = NEXUS_VideoDecoder_ChannelChangeMode_eHoldUntilTsmLock; break; |
|---|
| 467 | case 2: settings.channelChangeMode = NEXUS_VideoDecoder_ChannelChangeMode_eMuteUntilFirstPicture; break; |
|---|
| 468 | default: break; |
|---|
| 469 | } |
|---|
| 470 | } |
|---|
| 471 | NEXUS_VideoDecoder_SetSettings(decode->videoDecoder, &settings); |
|---|
| 472 | |
|---|
| 473 | xds_ctrl_set_cb(&decode->xds_ctrl, (xds_callback_t)cfg->xds_callback); |
|---|
| 474 | |
|---|
| 475 | if (!decode->config.block_vbi && cfg->block_vbi) { |
|---|
| 476 | #ifdef CONFIG_EIA_708 |
|---|
| 477 | bdisplay_vbi_clear_cc(); |
|---|
| 478 | #endif |
|---|
| 479 | } |
|---|
| 480 | |
|---|
| 481 | decode->config = *cfg; |
|---|
| 482 | return; |
|---|
| 483 | } |
|---|
| 484 | |
|---|
| 485 | bdecode_window_t bdecode_window_open(int id, bdisplay_t display) |
|---|
| 486 | { |
|---|
| 487 | NEXUS_DisplayVbiSettings displayVbiSettings; |
|---|
| 488 | |
|---|
| 489 | s_decode.display[id] = bdisplay_p_get_handle(display, id); |
|---|
| 490 | s_decode.window[id] = bdisplay_p_get_window(display, id); |
|---|
| 491 | |
|---|
| 492 | /* always enable CC routing on SD path */ |
|---|
| 493 | if (id == eBDISPLAY_COMPOSITE) { |
|---|
| 494 | NEXUS_Display_GetVbiSettings(s_decode.display[id], &displayVbiSettings); |
|---|
| 495 | displayVbiSettings.vbiSource = NEXUS_VideoDecoder_GetConnector(s_decode.videoDecoder); |
|---|
| 496 | displayVbiSettings.closedCaptionRouting = true; |
|---|
| 497 | displayVbiSettings.closedCaptionEnabled = true; |
|---|
| 498 | NEXUS_Display_SetVbiSettings(s_decode.display[id], &displayVbiSettings); |
|---|
| 499 | } |
|---|
| 500 | NEXUS_VideoWindow_AddInput(s_decode.window[id], NEXUS_VideoDecoder_GetConnector(s_decode.videoDecoder)); |
|---|
| 501 | return (bdecode_window_t)id; |
|---|
| 502 | } |
|---|
| 503 | |
|---|
| 504 | static void bdecode_first_pts_passed_cb(void *context, int param) |
|---|
| 505 | { |
|---|
| 506 | bdecode_t decode = (bdecode_t)context; |
|---|
| 507 | |
|---|
| 508 | BSTD_UNUSED(param); |
|---|
| 509 | |
|---|
| 510 | decode->status.first_pts_cnt++; |
|---|
| 511 | if (decode->first_pts_pending) |
|---|
| 512 | { |
|---|
| 513 | decode->status.first_pts_ticks = bos_getticks()-decode->start_ticks; |
|---|
| 514 | if (decode->config.first_pts_callback) |
|---|
| 515 | decode->config.first_pts_callback(); |
|---|
| 516 | } |
|---|
| 517 | } |
|---|
| 518 | |
|---|
| 519 | static void bdecode_stream_changed_cb(void *context, int param) |
|---|
| 520 | { |
|---|
| 521 | bdecode_t decode = (bdecode_t)context; |
|---|
| 522 | |
|---|
| 523 | BSTD_UNUSED(param); |
|---|
| 524 | if (decode->seq_pending) |
|---|
| 525 | { |
|---|
| 526 | decode->seq_pending = false; |
|---|
| 527 | decode->status.seq_ticks = bos_getticks()-decode->start_ticks; |
|---|
| 528 | if (decode->config.seq_hdr_callback) |
|---|
| 529 | decode->config.seq_hdr_callback(); |
|---|
| 530 | } |
|---|
| 531 | if (decode->bypass_tsm) { |
|---|
| 532 | NEXUS_VideoDecoderTrickState trick; |
|---|
| 533 | NEXUS_VideoDecoder_GetTrickState(decode->videoDecoder, &trick); |
|---|
| 534 | trick.tsmEnabled = NEXUS_TsmMode_eEnabled; |
|---|
| 535 | NEXUS_VideoDecoder_SetTrickState(decode->videoDecoder, &trick); |
|---|
| 536 | decode->bypass_tsm = false; |
|---|
| 537 | } |
|---|
| 538 | } |
|---|
| 539 | |
|---|
| 540 | static void bdecode_first_pts_cb(void *context, int param) |
|---|
| 541 | { |
|---|
| 542 | bdecode_t decode = (bdecode_t)context; |
|---|
| 543 | BSTD_UNUSED(param); |
|---|
| 544 | |
|---|
| 545 | decode->status.req_stc_cnt++; |
|---|
| 546 | } |
|---|
| 547 | |
|---|
| 548 | void bsettop_pvt(void) |
|---|
| 549 | { |
|---|
| 550 | } |
|---|
| 551 | |
|---|
| 552 | const bsettop_av_stream_type_t s_video_stream_types[] = |
|---|
| 553 | { |
|---|
| 554 | { TS_PSI_ST_13818_2_Video, BAVC_VideoCompressionStd_eMPEG2, 0,"MPEG-2"}, |
|---|
| 555 | { TS_PSI_ST_ATSC_Video, BAVC_VideoCompressionStd_eMPEG2, 0,"MPEG-2"}, |
|---|
| 556 | { TS_PSI_ST_AVS_Video, BAVC_VideoCompressionStd_eAVS, 0,"AVS"}, |
|---|
| 557 | { TS_PSI_ST_14496_10_Video, BAVC_VideoCompressionStd_eH264, 0,"H.264"}, |
|---|
| 558 | { TS_PSI_ST_SMPTE_VC1, BAVC_VideoCompressionStd_eVC1, 0,"VC1"}, |
|---|
| 559 | { TS_PSI_ST_14496_2_Video, BAVC_VideoCompressionStd_eMPEG4Part2, 0,"MP4p2"} |
|---|
| 560 | }; |
|---|
| 561 | const int s_video_stream_types_num = sizeof(s_video_stream_types)/sizeof(s_video_stream_types[0]); |
|---|
| 562 | |
|---|
| 563 | /** |
|---|
| 564 | * Summary: |
|---|
| 565 | * Supported video format. Returns NULL if stream_type (from PMT) not supported. |
|---|
| 566 | * **/ |
|---|
| 567 | bsettop_av_stream_type_t *bdecode_supported_video(unsigned char stream_type) |
|---|
| 568 | { |
|---|
| 569 | int i; |
|---|
| 570 | for (i = 0; i < s_video_stream_types_num; ++i) |
|---|
| 571 | { |
|---|
| 572 | if (stream_type == s_video_stream_types[i].format) |
|---|
| 573 | { |
|---|
| 574 | BDBG_MSG(("Video format[0x%02x]: %s\n",s_video_stream_types[i].format,s_video_stream_types[i].format_name)); |
|---|
| 575 | return(bsettop_av_stream_type_t*)&s_video_stream_types[i]; |
|---|
| 576 | } |
|---|
| 577 | } |
|---|
| 578 | BDBG_MSG(("Unsupported Video format[0x%02x]\n",stream_type)); |
|---|
| 579 | return NULL; |
|---|
| 580 | } |
|---|
| 581 | |
|---|