| 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: pes_scte_127.c $ |
|---|
| 11 | * $brcm_Revision: $ |
|---|
| 12 | * $brcm_Date: $ |
|---|
| 13 | * |
|---|
| 14 | * [File Description:] |
|---|
| 15 | * |
|---|
| 16 | * Revision History: |
|---|
| 17 | * |
|---|
| 18 | ***************************************************************************/ |
|---|
| 19 | #include "pes_scte_127.h" |
|---|
| 20 | |
|---|
| 21 | BDBG_MODULE(pes_scte_127); |
|---|
| 22 | |
|---|
| 23 | #define PES_DATA_LENGTH(buf) (buf[PES_LENGTH_OFFSET]); |
|---|
| 24 | |
|---|
| 25 | #ifdef HOST_BUILD /* for local host PC based verifiction */ |
|---|
| 26 | #define SCTE_127_DATA_ID 0x99 /* SCTE 127 data id */ |
|---|
| 27 | |
|---|
| 28 | #define SCTE_127_DATA_UNIT_ID_AMOL48 0xD0 /* AMOL 48 */ |
|---|
| 29 | #define SCTE_127_DATA_UNIT_ID_AMOL96 0xD1 /* AMOL 96 */ |
|---|
| 30 | #define SCTE_127_DATA_UNIT_ID_NABTS 0xD5 |
|---|
| 31 | #define SCTE_127_DATA_UNIT_ID_TVG2X 0xD6 |
|---|
| 32 | #define SCTE_127_DATA_UNIT_ID_CP 0xD7 /* copy protection */ |
|---|
| 33 | #define SCTE_127_DATA_UNIT_ID_VITC 0xD9 |
|---|
| 34 | |
|---|
| 35 | #define SCTE_127_DATA_UNIT_ID_AMOL48_LEN 7 |
|---|
| 36 | #define SCTE_127_DATA_UNIT_ID_AMOL96_LEN 12 |
|---|
| 37 | #define SCTE_127_DATA_UNIT_ID_NABTS_LEN 35 |
|---|
| 38 | #define SCTE_127_DATA_UNIT_ID_TVG2X_LEN 5 |
|---|
| 39 | #define SCTE_127_DATA_UNIT_ID_CP_LEN 2 |
|---|
| 40 | #define SCTE_127_DATA_UNIT_ID_VITC_LEN 9 |
|---|
| 41 | |
|---|
| 42 | #else |
|---|
| 43 | #include "scte_127.h" |
|---|
| 44 | #endif |
|---|
| 45 | |
|---|
| 46 | #ifdef HOST_BUILD |
|---|
| 47 | void pes_scte_127_parser(uint8_t type, uint8_t *p) |
|---|
| 48 | { |
|---|
| 49 | int i; |
|---|
| 50 | |
|---|
| 51 | switch (type) |
|---|
| 52 | { |
|---|
| 53 | default: |
|---|
| 54 | printf("Unsupported type 0x%2x\n", type); |
|---|
| 55 | return; |
|---|
| 56 | |
|---|
| 57 | case SCTE_127_DATA_UNIT_ID_AMOL48: |
|---|
| 58 | printf("SCTE_127_DATA_UNIT_ID_AMOL48\n"); |
|---|
| 59 | break; |
|---|
| 60 | |
|---|
| 61 | case SCTE_127_DATA_UNIT_ID_AMOL96: |
|---|
| 62 | printf("SCTE_127_DATA_UNIT_ID_AMOL96\n"); |
|---|
| 63 | break; |
|---|
| 64 | |
|---|
| 65 | case SCTE_127_DATA_UNIT_ID_TVG2X: |
|---|
| 66 | printf("SCTE_127_DATA_UNIT_ID_TVG2X\n"); |
|---|
| 67 | break; |
|---|
| 68 | } |
|---|
| 69 | printf("Len = %d\n", *(p + 1)); |
|---|
| 70 | printf("parity = %d\n", ((*(p + 2) >> 5) & 0x1) ? 1 : 0); |
|---|
| 71 | printf("line off= %d\n", (*(p + 2) & 0x1f)); |
|---|
| 72 | for (i = 0; i < (int)(*(p + 1)) - 1; i++) { |
|---|
| 73 | printf("0x%02x ", *(p + 3 + i)); |
|---|
| 74 | } |
|---|
| 75 | printf("\n"); |
|---|
| 76 | } |
|---|
| 77 | #endif |
|---|
| 78 | |
|---|
| 79 | uint8_t *pes_parser(const uint8_t *pes, size_t *size) |
|---|
| 80 | { |
|---|
| 81 | uint32_t private, len; |
|---|
| 82 | uint8_t *p, adaptation_field; |
|---|
| 83 | |
|---|
| 84 | BDBG_MSG(("%s: enter", __func__)); |
|---|
| 85 | |
|---|
| 86 | /* we assume that the size of pes buffer must be 188 or more */ |
|---|
| 87 | CHECK(pes && size); |
|---|
| 88 | |
|---|
| 89 | /* sync byte */ |
|---|
| 90 | if (0x47 != pes[0]) { |
|---|
| 91 | BDBG_ERR(("%s: invalid packet", __func__)); |
|---|
| 92 | return NULL; |
|---|
| 93 | } |
|---|
| 94 | |
|---|
| 95 | adaptation_field = (pes[PES_TRANSPORT_PRIORITY] >> 4) & 0x3; |
|---|
| 96 | /* must be either b01 or b10 per SCTE 127 spec. */ |
|---|
| 97 | if (!(0x01 == adaptation_field || 0x02 == adaptation_field)) { |
|---|
| 98 | BDBG_MSG(("%s: invalid packet (0x%x)", __func__, adaptation_field)); |
|---|
| 99 | *size = 0xff; |
|---|
| 100 | return NULL; |
|---|
| 101 | } |
|---|
| 102 | private = TS_READ_32(&pes[PES_STREAM_ID]); |
|---|
| 103 | if(PES_PRIVATE_START_CODE_ID != private) { |
|---|
| 104 | *size = 0xff; |
|---|
| 105 | BDBG_MSG(("%s: not private", __func__)); |
|---|
| 106 | return NULL; |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | len = PES_DATA_LENGTH(pes); |
|---|
| 110 | /* must be 0x24 per SCTE 127 spec. section 8 */ |
|---|
| 111 | #if 0 |
|---|
| 112 | if (len != 0x24) { |
|---|
| 113 | /* out of spec. */ |
|---|
| 114 | BDBG_WRN(("%s: Warning, len=%d (should be %d)", __func__, len, 0x24)); |
|---|
| 115 | //return NULL; |
|---|
| 116 | } |
|---|
| 117 | #endif |
|---|
| 118 | p = (uint8_t *)pes; |
|---|
| 119 | |
|---|
| 120 | /* skip bytes */ |
|---|
| 121 | *size = PES_LENGTH_OFFSET + 1 + len; |
|---|
| 122 | p += *size; |
|---|
| 123 | |
|---|
| 124 | BDBG_MSG(("%s: leave", __func__)); |
|---|
| 125 | return p; |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | #ifdef HOST_BUILD |
|---|
| 129 | uint8_t pes_data_field_parser(const uint8_t *pdata_id, size_t size) |
|---|
| 130 | { |
|---|
| 131 | uint8_t *p; |
|---|
| 132 | int len = 0; |
|---|
| 133 | uint16_t term; |
|---|
| 134 | /* for debug only */ |
|---|
| 135 | int count = 0; |
|---|
| 136 | |
|---|
| 137 | CHECK(pdata_id && size); |
|---|
| 138 | |
|---|
| 139 | if (SCTE_127_DATA_ID != *pdata_id) { |
|---|
| 140 | BDBG_ERR(("%s: invalid data id (0x%2x)", __func__, *pdata_id)); |
|---|
| 141 | return 0; |
|---|
| 142 | } |
|---|
| 143 | p = (uint8_t *)pdata_id; |
|---|
| 144 | p++; /* skip data id */ |
|---|
| 145 | size--; |
|---|
| 146 | |
|---|
| 147 | do { |
|---|
| 148 | switch ((int)*p) |
|---|
| 149 | { |
|---|
| 150 | default: |
|---|
| 151 | term = TS_READ_16(p) & 0xff00; |
|---|
| 152 | if ((0xff00 == term) || (0xffff == term)) { |
|---|
| 153 | /* terminator, normal */ |
|---|
| 154 | BDBG_MSG(("%s: terminated", __func__)); |
|---|
| 155 | return 1; |
|---|
| 156 | } |
|---|
| 157 | len = (int)*(p + 1); |
|---|
| 158 | if (len >= (size - 2)) { |
|---|
| 159 | BDBG_WRN(("%s: len %d exceed %d", __func__, len, (size - 2))); |
|---|
| 160 | return 0; |
|---|
| 161 | } |
|---|
| 162 | /* not support data type, skip */ |
|---|
| 163 | p += len + 2; |
|---|
| 164 | size -= (len + 2); |
|---|
| 165 | continue; |
|---|
| 166 | |
|---|
| 167 | case SCTE_127_DATA_UNIT_ID_AMOL48: |
|---|
| 168 | len = (int)*(p + 1); |
|---|
| 169 | if (len != SCTE_127_DATA_UNIT_ID_AMOL48_LEN) { |
|---|
| 170 | /* wrong data unit, quit */ |
|---|
| 171 | BDBG_ERR(("%s: invalid AMOL48 data unit size (%d)", __func__, len)); |
|---|
| 172 | return 0; |
|---|
| 173 | } |
|---|
| 174 | break; |
|---|
| 175 | |
|---|
| 176 | case SCTE_127_DATA_UNIT_ID_AMOL96: |
|---|
| 177 | len = (int)*(p + 1); |
|---|
| 178 | if (len != SCTE_127_DATA_UNIT_ID_AMOL96_LEN) { |
|---|
| 179 | /* wrong data unit, quit */ |
|---|
| 180 | BDBG_ERR(("%s: invalid AMOL96 data unit size (%d)", __func__, len)); |
|---|
| 181 | return 0; |
|---|
| 182 | } |
|---|
| 183 | break; |
|---|
| 184 | |
|---|
| 185 | case SCTE_127_DATA_UNIT_ID_TVG2X: |
|---|
| 186 | len = (int)*(p + 1); |
|---|
| 187 | if (len != SCTE_127_DATA_UNIT_ID_TVG2X_LEN) { |
|---|
| 188 | /* wrong data unit, quit */ |
|---|
| 189 | BDBG_ERR(("%s: invalid TVG2X data unit size (%d)", __func__, len)); |
|---|
| 190 | return 0; |
|---|
| 191 | } |
|---|
| 192 | break; |
|---|
| 193 | } |
|---|
| 194 | pes_scte_127_parser(*p, p); |
|---|
| 195 | p++; |
|---|
| 196 | size--; |
|---|
| 197 | p += (len + 1); |
|---|
| 198 | size -= (len + 1); |
|---|
| 199 | count++; |
|---|
| 200 | } while ((size - 2) > 0); |
|---|
| 201 | |
|---|
| 202 | return 0; |
|---|
| 203 | } |
|---|
| 204 | #endif |
|---|