| 1 | /*************************************************************************** |
|---|
| 2 | * Copyright (c) 2008, 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 | #include "scte_18.h" |
|---|
| 22 | #include "bstd.h" |
|---|
| 23 | #include "bkni.h" |
|---|
| 24 | |
|---|
| 25 | BDBG_MODULE(scte_18); |
|---|
| 26 | |
|---|
| 27 | #ifndef SCTE_ASSERT |
|---|
| 28 | #define SCTE_ASSERT(expr) { \ |
|---|
| 29 | if (!expr) \ |
|---|
| 30 | printf("%s failed at %s:%d\n",#expr, __FILE__, __LINE__); \ |
|---|
| 31 | } |
|---|
| 32 | #endif |
|---|
| 33 | |
|---|
| 34 | /* |
|---|
| 35 | * This function is used to initialize scte 18 object |
|---|
| 36 | * |
|---|
| 37 | * Parameters: |
|---|
| 38 | * NONE |
|---|
| 39 | * |
|---|
| 40 | * Returns: |
|---|
| 41 | * pointer to scte_18 if success |
|---|
| 42 | * NULL otherwise |
|---|
| 43 | */ |
|---|
| 44 | pscte_18_handle scte_18_init(void) |
|---|
| 45 | { |
|---|
| 46 | pscte_18_handle pscte_18; |
|---|
| 47 | |
|---|
| 48 | BDBG_MSG(("%s: enter", __func__)); |
|---|
| 49 | |
|---|
| 50 | pscte_18 = (pscte_18_handle)malloc(sizeof(scte_18_handle)); |
|---|
| 51 | if (NULL == pscte_18) |
|---|
| 52 | { |
|---|
| 53 | BDBG_ERR(("%s: no memory", __func__)); |
|---|
| 54 | return NULL; |
|---|
| 55 | } |
|---|
| 56 | memset(pscte_18, 0, sizeof(scte_18_handle)); |
|---|
| 57 | |
|---|
| 58 | pscte_18->pMsg = malloc(TS_SCTE_18_MAX_TABLE_SIZE); |
|---|
| 59 | if (!pscte_18->pMsg) |
|---|
| 60 | { |
|---|
| 61 | BDBG_ERR(("%s: out of memory", __func__)); |
|---|
| 62 | free(pscte_18); |
|---|
| 63 | return NULL; |
|---|
| 64 | } |
|---|
| 65 | |
|---|
| 66 | if (b_ok != bos_create_mutex(&pscte_18->mutex)) |
|---|
| 67 | { |
|---|
| 68 | free(pscte_18->pMsg); |
|---|
| 69 | free(pscte_18); |
|---|
| 70 | pscte_18 = NULL; |
|---|
| 71 | BDBG_ERR(("%s: create mutex failed", __func__)); |
|---|
| 72 | return NULL; |
|---|
| 73 | } |
|---|
| 74 | |
|---|
| 75 | |
|---|
| 76 | BDBG_MSG(("%s: leave", __func__)); |
|---|
| 77 | return pscte_18; |
|---|
| 78 | } |
|---|
| 79 | |
|---|
| 80 | /* |
|---|
| 81 | * This function is used to de-initialize scte 18 object initialize before |
|---|
| 82 | * |
|---|
| 83 | * Parameters: |
|---|
| 84 | * pointer to scte 18 handle |
|---|
| 85 | * |
|---|
| 86 | * Returns: |
|---|
| 87 | * NONE |
|---|
| 88 | */ |
|---|
| 89 | void scte_18_deinit(pscte_18_handle pscte_18) |
|---|
| 90 | { |
|---|
| 91 | BDBG_WRN(("%s: enter", __func__)); |
|---|
| 92 | |
|---|
| 93 | if (!pscte_18) |
|---|
| 94 | { |
|---|
| 95 | BDBG_MSG(("%s: null pointer", __func__)); |
|---|
| 96 | return; |
|---|
| 97 | } |
|---|
| 98 | if (pscte_18->pMsg) |
|---|
| 99 | free(pscte_18->pMsg); |
|---|
| 100 | |
|---|
| 101 | bos_delete_mutex(&pscte_18->mutex); |
|---|
| 102 | free(pscte_18); |
|---|
| 103 | |
|---|
| 104 | BDBG_MSG(("%s: leave", __func__)); |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | /* |
|---|
| 108 | * acqurie scte 18 channels if required |
|---|
| 109 | * |
|---|
| 110 | * Parameters: |
|---|
| 111 | * pscte_18[in] pointer to scte 18 handler |
|---|
| 112 | * which[in] bitmap for process audio and/or text |
|---|
| 113 | * |
|---|
| 114 | * Returns: |
|---|
| 115 | * NONE |
|---|
| 116 | */ |
|---|
| 117 | void scte_18_acquire(pscte_18_handle pscte_18, int which) |
|---|
| 118 | { |
|---|
| 119 | BDBG_WRN(("%s: enter, which=0x2x\n", __func__, which)); |
|---|
| 120 | if (SCTE_18_ACQ_AUDIO & which) |
|---|
| 121 | { |
|---|
| 122 | /* re-acquire oritinal channel if interrupted */ |
|---|
| 123 | /* replace audio with referenced override track */ |
|---|
| 124 | } |
|---|
| 125 | if (SCTE_18_ACQ_TEXT & which) |
|---|
| 126 | { |
|---|
| 127 | if (pscte_18->details_OOB_source_ID) |
|---|
| 128 | { |
|---|
| 129 | /*RLQ, note currently we don't present alert text to user, but rather switch to given channel directly */ |
|---|
| 130 | /* if text available? */ |
|---|
| 131 | } |
|---|
| 132 | } |
|---|
| 133 | /* finish audio or wait alert_message_time_remaining seconds */ |
|---|
| 134 | pscte_18->alert_in_progress = 1; /* set in progress flag */ |
|---|
| 135 | BDBG_WRN(("%s: leave", __func__)); |
|---|
| 136 | } |
|---|
| 137 | |
|---|
| 138 | /* |
|---|
| 139 | * process scte 18 data |
|---|
| 140 | * |
|---|
| 141 | * Parameters: |
|---|
| 142 | * pscte_18[in] pointer to scte 18 handler |
|---|
| 143 | * pkt[in] pointer to the SCTE 18 data packet |
|---|
| 144 | * size[in] length of data |
|---|
| 145 | * |
|---|
| 146 | * Returns: |
|---|
| 147 | * length of byts passed |
|---|
| 148 | * 0 if no data is found |
|---|
| 149 | */ |
|---|
| 150 | int scte_18_process(pscte_18_handle pscte_18, unsigned char *pkt, int size) |
|---|
| 151 | { |
|---|
| 152 | TS_SCTE_18_header *pHdr; |
|---|
| 153 | |
|---|
| 154 | BDBG_MSG(("%s: enter", __func__)); |
|---|
| 155 | |
|---|
| 156 | if (!pscte_18 || !pkt) |
|---|
| 157 | { |
|---|
| 158 | BDBG_WRN(("%s: null ptr", __func__)); |
|---|
| 159 | return 1; |
|---|
| 160 | } |
|---|
| 161 | |
|---|
| 162 | pHdr = &pscte_18->header; |
|---|
| 163 | memset(pHdr, 0, sizeof(TS_SCTE_18_header)); |
|---|
| 164 | if (0 == TS_SCTE_18_getSectionHeader(pkt, size, pHdr)) |
|---|
| 165 | { |
|---|
| 166 | #ifdef SCTE_DBG |
|---|
| 167 | static int first = 0; |
|---|
| 168 | |
|---|
| 169 | /* current test stream doesn't change EAS, so we will print at least one to show EAS decoding */ |
|---|
| 170 | if (!first) { |
|---|
| 171 | TS_SCTE_18_DumpPacket(pkt, pHdr); |
|---|
| 172 | first = 1; |
|---|
| 173 | } |
|---|
| 174 | #endif |
|---|
| 175 | /* check if we want to process it */ |
|---|
| 176 | if (pscte_18->sequence_number == pHdr->sequence_number) |
|---|
| 177 | { |
|---|
| 178 | /* done */ |
|---|
| 179 | BDBG_WRN(("%s: repeat EAS packet, sequence number %d, skip", __func__, pHdr->sequence_number)); |
|---|
| 180 | return 1; |
|---|
| 181 | } |
|---|
| 182 | /* TODO check current service in exception list */ |
|---|
| 183 | if (pHdr->alert_priority < SCTE_18_ALERT_PRIORITY) |
|---|
| 184 | { |
|---|
| 185 | BDBG_WRN(("%s: skip alert priority %d", __func__, pHdr->alert_priority)); |
|---|
| 186 | } |
|---|
| 187 | if (pscte_18->alert_in_progress) |
|---|
| 188 | { |
|---|
| 189 | if (pscte_18->EAS_event_ID != pHdr->EAS_event_ID) |
|---|
| 190 | { |
|---|
| 191 | /* stop any text scroll in progress, in our case, there is no need */ |
|---|
| 192 | } |
|---|
| 193 | } |
|---|
| 194 | else |
|---|
| 195 | { |
|---|
| 196 | if (pscte_18->EAS_event_ID == pHdr->EAS_event_ID) |
|---|
| 197 | { |
|---|
| 198 | BDBG_WRN(("%s: duplicated EAS packet", __func__)); |
|---|
| 199 | } |
|---|
| 200 | } |
|---|
| 201 | /* update alert_message_time_remaning */ |
|---|
| 202 | pscte_18->alert_message_time_remaining = pHdr->alert_message_time_remaining; |
|---|
| 203 | |
|---|
| 204 | /* keep some important data for later use */ |
|---|
| 205 | pscte_18->sequence_number = pHdr->sequence_number; |
|---|
| 206 | pscte_18->alert_priority = pHdr->alert_priority; |
|---|
| 207 | /* TODO */ |
|---|
| 208 | /* remember original source ID for switch back */ |
|---|
| 209 | //pscte_18->original_source_ID = |
|---|
| 210 | /* remember original audio source ID for switch back */ |
|---|
| 211 | //pscte_18->original_audio_source_ID = |
|---|
| 212 | pscte_18->details_OOB_source_ID = pHdr->details_OOB_source_ID; |
|---|
| 213 | pscte_18->audio_OOB_source_ID = pHdr->audio_OOB_source_ID; |
|---|
| 214 | pscte_18->event_start_time = pHdr->event_start_time; |
|---|
| 215 | pscte_18->event_duration = pHdr->event_duration; |
|---|
| 216 | |
|---|
| 217 | /* requires audio ? */ |
|---|
| 218 | if (SCTE_18_ALERT_NEED_AUDIO > pHdr->alert_priority) |
|---|
| 219 | { |
|---|
| 220 | /* audio desired? */ |
|---|
| 221 | } |
|---|
| 222 | if (pscte_18->audio_OOB_source_ID) |
|---|
| 223 | { |
|---|
| 224 | scte_18_acquire(pscte_18, SCTE_18_ACQ_AUDIO | SCTE_18_ACQ_TEXT); |
|---|
| 225 | } |
|---|
| 226 | else |
|---|
| 227 | { |
|---|
| 228 | if (pscte_18->details_OOB_source_ID) |
|---|
| 229 | { |
|---|
| 230 | scte_18_acquire(pscte_18, SCTE_18_ACQ_TEXT); |
|---|
| 231 | } |
|---|
| 232 | } |
|---|
| 233 | } |
|---|
| 234 | else |
|---|
| 235 | { |
|---|
| 236 | BDBG_WRN(("Invalid packet\n")); |
|---|
| 237 | } |
|---|
| 238 | |
|---|
| 239 | BDBG_MSG(("%s: leave", __func__)); |
|---|
| 240 | |
|---|
| 241 | return 0; |
|---|
| 242 | } |
|---|
| 243 | |
|---|