/*************************************************************************** * Copyright (c) 2008, Broadcom Corporation * All Rights Reserved * Confidential Property of Broadcom Corporation * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * $brcm_Workfile: $ * $brcm_Revision: $ * $brcm_Date: $ * * Module Description: * * Revision History: * * $brcm_Log: $ * ***************************************************************************/ #include "scte_18.h" #include "bstd.h" #include "bkni.h" BDBG_MODULE(scte_18); #ifndef SCTE_ASSERT #define SCTE_ASSERT(expr) { \ if (!expr) \ printf("%s failed at %s:%d\n",#expr, __FILE__, __LINE__); \ } #endif /* * This function is used to initialize scte 18 object * * Parameters: * NONE * * Returns: * pointer to scte_18 if success * NULL otherwise */ pscte_18_handle scte_18_init(void) { pscte_18_handle pscte_18; BDBG_MSG(("%s: enter", __func__)); pscte_18 = (pscte_18_handle)malloc(sizeof(scte_18_handle)); if (NULL == pscte_18) { BDBG_ERR(("%s: no memory", __func__)); return NULL; } memset(pscte_18, 0, sizeof(scte_18_handle)); pscte_18->pMsg = malloc(TS_SCTE_18_MAX_TABLE_SIZE); if (!pscte_18->pMsg) { BDBG_ERR(("%s: out of memory", __func__)); free(pscte_18); return NULL; } if (b_ok != bos_create_mutex(&pscte_18->mutex)) { free(pscte_18->pMsg); free(pscte_18); pscte_18 = NULL; BDBG_ERR(("%s: create mutex failed", __func__)); return NULL; } BDBG_MSG(("%s: leave", __func__)); return pscte_18; } /* * This function is used to de-initialize scte 18 object initialize before * * Parameters: * pointer to scte 18 handle * * Returns: * NONE */ void scte_18_deinit(pscte_18_handle pscte_18) { BDBG_WRN(("%s: enter", __func__)); if (!pscte_18) { BDBG_MSG(("%s: null pointer", __func__)); return; } if (pscte_18->pMsg) free(pscte_18->pMsg); bos_delete_mutex(&pscte_18->mutex); free(pscte_18); BDBG_MSG(("%s: leave", __func__)); } /* * acqurie scte 18 channels if required * * Parameters: * pscte_18[in] pointer to scte 18 handler * which[in] bitmap for process audio and/or text * * Returns: * NONE */ void scte_18_acquire(pscte_18_handle pscte_18, int which) { BDBG_WRN(("%s: enter, which=0x2x\n", __func__, which)); if (SCTE_18_ACQ_AUDIO & which) { /* re-acquire oritinal channel if interrupted */ /* replace audio with referenced override track */ } if (SCTE_18_ACQ_TEXT & which) { if (pscte_18->details_OOB_source_ID) { /*RLQ, note currently we don't present alert text to user, but rather switch to given channel directly */ /* if text available? */ } } /* finish audio or wait alert_message_time_remaining seconds */ pscte_18->alert_in_progress = 1; /* set in progress flag */ BDBG_WRN(("%s: leave", __func__)); } /* * process scte 18 data * * Parameters: * pscte_18[in] pointer to scte 18 handler * pkt[in] pointer to the SCTE 18 data packet * size[in] length of data * * Returns: * length of byts passed * 0 if no data is found */ int scte_18_process(pscte_18_handle pscte_18, unsigned char *pkt, int size) { TS_SCTE_18_header *pHdr; BDBG_MSG(("%s: enter", __func__)); if (!pscte_18 || !pkt) { BDBG_WRN(("%s: null ptr", __func__)); return 1; } pHdr = &pscte_18->header; memset(pHdr, 0, sizeof(TS_SCTE_18_header)); if (0 == TS_SCTE_18_getSectionHeader(pkt, size, pHdr)) { #ifdef SCTE_DBG static int first = 0; /* current test stream doesn't change EAS, so we will print at least one to show EAS decoding */ if (!first) { TS_SCTE_18_DumpPacket(pkt, pHdr); first = 1; } #endif /* check if we want to process it */ if (pscte_18->sequence_number == pHdr->sequence_number) { /* done */ BDBG_WRN(("%s: repeat EAS packet, sequence number %d, skip", __func__, pHdr->sequence_number)); return 1; } /* TODO check current service in exception list */ if (pHdr->alert_priority < SCTE_18_ALERT_PRIORITY) { BDBG_WRN(("%s: skip alert priority %d", __func__, pHdr->alert_priority)); } if (pscte_18->alert_in_progress) { if (pscte_18->EAS_event_ID != pHdr->EAS_event_ID) { /* stop any text scroll in progress, in our case, there is no need */ } } else { if (pscte_18->EAS_event_ID == pHdr->EAS_event_ID) { BDBG_WRN(("%s: duplicated EAS packet", __func__)); } } /* update alert_message_time_remaning */ pscte_18->alert_message_time_remaining = pHdr->alert_message_time_remaining; /* keep some important data for later use */ pscte_18->sequence_number = pHdr->sequence_number; pscte_18->alert_priority = pHdr->alert_priority; /* TODO */ /* remember original source ID for switch back */ //pscte_18->original_source_ID = /* remember original audio source ID for switch back */ //pscte_18->original_audio_source_ID = pscte_18->details_OOB_source_ID = pHdr->details_OOB_source_ID; pscte_18->audio_OOB_source_ID = pHdr->audio_OOB_source_ID; pscte_18->event_start_time = pHdr->event_start_time; pscte_18->event_duration = pHdr->event_duration; /* requires audio ? */ if (SCTE_18_ALERT_NEED_AUDIO > pHdr->alert_priority) { /* audio desired? */ } if (pscte_18->audio_OOB_source_ID) { scte_18_acquire(pscte_18, SCTE_18_ACQ_AUDIO | SCTE_18_ACQ_TEXT); } else { if (pscte_18->details_OOB_source_ID) { scte_18_acquire(pscte_18, SCTE_18_ACQ_TEXT); } } } else { BDBG_WRN(("Invalid packet\n")); } BDBG_MSG(("%s: leave", __func__)); return 0; }