1 /***************************************************************************** 2 * Copyright (C) 2013-2020 MulticoreWare, Inc 3 * 4 * Authors: Steve Borho <steve@borho.org> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. 19 * 20 * This program is also available under a commercial proprietary license. 21 * For more information, contact us at license @ x265.com. 22 *****************************************************************************/ 23 24 #ifndef X265_SEI_H 25 #define X265_SEI_H 26 27 #include "common.h" 28 #include "bitstream.h" 29 #include "slice.h" 30 #include "nal.h" 31 #include "md5.h" 32 33 namespace X265_NS { 34 // private namespace 35 36 class SEI : public SyntaxElementWriter 37 { 38 public: 39 /* SEI users call writeSEImessages() to marshal an SEI to a bitstream. 40 * The writeSEImessages() method calls writeSEI() which encodes the header */ 41 void writeSEImessages(Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list, int isNested); 42 void setSize(uint32_t size); 43 static char* base64Decode(char encodedString[], int base64EncodeLength); ~SEI()44 virtual ~SEI() {} 45 protected: 46 SEIPayloadType m_payloadType; 47 uint32_t m_payloadSize; 48 virtual void writeSEI(const SPS&) = 0; 49 void writeByteAlign(); 50 }; 51 52 //seongnam.oh@samsung.com :: for the Creative Intent Meta Data Encoding 53 class SEIuserDataRegistered : public SEI 54 { 55 public: SEIuserDataRegistered()56 SEIuserDataRegistered() 57 { 58 m_payloadType = USER_DATA_REGISTERED_ITU_T_T35; 59 m_payloadSize = 0; 60 } 61 62 uint8_t *m_userData; 63 64 // daniel.vt@samsung.com :: for the Creative Intent Meta Data Encoding ( seongnam.oh@samsung.com ) writeSEI(const SPS &)65 void writeSEI(const SPS&) 66 { 67 if (!m_userData) 68 return; 69 70 uint32_t i = 0; 71 for (; i < m_payloadSize; ++i) 72 WRITE_CODE(m_userData[i], 8, "creative_intent_metadata"); 73 } 74 }; 75 76 static const uint32_t ISO_IEC_11578_LEN = 16; 77 78 class SEIuserDataUnregistered : public SEI 79 { 80 public: SEIuserDataUnregistered()81 SEIuserDataUnregistered() : m_userData(NULL) 82 { 83 m_payloadType = USER_DATA_UNREGISTERED; 84 m_payloadSize = 0; 85 } 86 static const uint8_t m_uuid_iso_iec_11578[ISO_IEC_11578_LEN]; 87 uint8_t *m_userData; writeSEI(const SPS &)88 void writeSEI(const SPS&) 89 { 90 for (uint32_t i = 0; i < ISO_IEC_11578_LEN; i++) 91 WRITE_CODE(m_uuid_iso_iec_11578[i], 8, "sei.uuid_iso_iec_11578[i]"); 92 for (uint32_t i = 0; i < m_payloadSize; i++) 93 WRITE_CODE(m_userData[i], 8, "user_data"); 94 } 95 }; 96 97 class SEIMasteringDisplayColorVolume : public SEI 98 { 99 public: SEIMasteringDisplayColorVolume()100 SEIMasteringDisplayColorVolume() 101 { 102 m_payloadType = MASTERING_DISPLAY_INFO; 103 m_payloadSize = (8 * 2 + 2 * 4); 104 } 105 uint16_t displayPrimaryX[3]; 106 uint16_t displayPrimaryY[3]; 107 uint16_t whitePointX, whitePointY; 108 uint32_t maxDisplayMasteringLuminance; 109 uint32_t minDisplayMasteringLuminance; parse(const char * value)110 bool parse(const char* value) 111 { 112 return sscanf(value, "G(%hu,%hu)B(%hu,%hu)R(%hu,%hu)WP(%hu,%hu)L(%u,%u)", 113 &displayPrimaryX[0], &displayPrimaryY[0], 114 &displayPrimaryX[1], &displayPrimaryY[1], 115 &displayPrimaryX[2], &displayPrimaryY[2], 116 &whitePointX, &whitePointY, 117 &maxDisplayMasteringLuminance, &minDisplayMasteringLuminance) == 10; 118 } writeSEI(const SPS &)119 void writeSEI(const SPS&) 120 { 121 for (uint32_t i = 0; i < 3; i++) 122 { 123 WRITE_CODE(displayPrimaryX[i], 16, "display_primaries_x[ c ]"); 124 WRITE_CODE(displayPrimaryY[i], 16, "display_primaries_y[ c ]"); 125 } 126 WRITE_CODE(whitePointX, 16, "white_point_x"); 127 WRITE_CODE(whitePointY, 16, "white_point_y"); 128 WRITE_CODE(maxDisplayMasteringLuminance, 32, "max_display_mastering_luminance"); 129 WRITE_CODE(minDisplayMasteringLuminance, 32, "min_display_mastering_luminance"); 130 } 131 }; 132 133 class SEIContentLightLevel : public SEI 134 { 135 public: SEIContentLightLevel()136 SEIContentLightLevel() 137 { 138 m_payloadType = CONTENT_LIGHT_LEVEL_INFO; 139 m_payloadSize = 4; 140 } 141 uint16_t max_content_light_level; 142 uint16_t max_pic_average_light_level; writeSEI(const SPS &)143 void writeSEI(const SPS&) 144 { 145 WRITE_CODE(max_content_light_level, 16, "max_content_light_level"); 146 WRITE_CODE(max_pic_average_light_level, 16, "max_pic_average_light_level"); 147 } 148 }; 149 150 class SEIDecodedPictureHash : public SEI 151 { 152 public: SEIDecodedPictureHash()153 SEIDecodedPictureHash() 154 { 155 m_payloadType = DECODED_PICTURE_HASH; 156 m_payloadSize = 0; 157 } 158 enum Method 159 { 160 MD5, 161 CRC, 162 CHECKSUM, 163 } m_method; 164 165 MD5Context m_state[3]; 166 uint32_t m_crc[3]; 167 uint32_t m_checksum[3]; 168 uint8_t m_digest[3][16]; 169 writeSEI(const SPS & sps)170 void writeSEI(const SPS& sps) 171 { 172 int planes = (sps.chromaFormatIdc != X265_CSP_I400) ? 3 : 1; 173 WRITE_CODE(m_method, 8, "hash_type"); 174 for (int yuvIdx = 0; yuvIdx < planes; yuvIdx++) 175 { 176 if (m_method == MD5) 177 { 178 for (uint32_t i = 0; i < 16; i++) 179 WRITE_CODE(m_digest[yuvIdx][i], 8, "picture_md5"); 180 } 181 else if (m_method == CRC) 182 { 183 uint32_t val = (m_digest[yuvIdx][0] << 8) + m_digest[yuvIdx][1]; 184 WRITE_CODE(val, 16, "picture_crc"); 185 } 186 else if (m_method == CHECKSUM) 187 { 188 uint32_t val = (m_digest[yuvIdx][0] << 24) + (m_digest[yuvIdx][1] << 16) + (m_digest[yuvIdx][2] << 8) + m_digest[yuvIdx][3]; 189 WRITE_CODE(val, 32, "picture_checksum"); 190 } 191 } 192 } 193 }; 194 195 class SEIActiveParameterSets : public SEI 196 { 197 public: SEIActiveParameterSets()198 SEIActiveParameterSets() 199 { 200 m_payloadType = ACTIVE_PARAMETER_SETS; 201 m_payloadSize = 0; 202 } 203 bool m_selfContainedCvsFlag; 204 bool m_noParamSetUpdateFlag; 205 writeSEI(const SPS &)206 void writeSEI(const SPS&) 207 { 208 WRITE_CODE(0, 4, "active_vps_id"); 209 WRITE_FLAG(m_selfContainedCvsFlag, "self_contained_cvs_flag"); 210 WRITE_FLAG(m_noParamSetUpdateFlag, "no_param_set_update_flag"); 211 WRITE_UVLC(0, "num_sps_ids_minus1"); 212 WRITE_UVLC(0, "active_seq_param_set_id"); 213 writeByteAlign(); 214 } 215 }; 216 217 class SEIBufferingPeriod : public SEI 218 { 219 public: SEIBufferingPeriod()220 SEIBufferingPeriod() 221 : m_cpbDelayOffset(0) 222 , m_dpbDelayOffset(0) 223 , m_concatenationFlag(0) 224 , m_auCpbRemovalDelayDelta(1) 225 { 226 m_payloadType = BUFFERING_PERIOD; 227 m_payloadSize = 0; 228 } 229 bool m_cpbDelayOffset; 230 bool m_dpbDelayOffset; 231 bool m_concatenationFlag; 232 uint32_t m_initialCpbRemovalDelay; 233 uint32_t m_initialCpbRemovalDelayOffset; 234 uint32_t m_auCpbRemovalDelayDelta; 235 writeSEI(const SPS & sps)236 void writeSEI(const SPS& sps) 237 { 238 const HRDInfo& hrd = sps.vuiParameters.hrdParameters; 239 240 WRITE_UVLC(0, "bp_seq_parameter_set_id"); 241 WRITE_FLAG(0, "rap_cpb_params_present_flag"); 242 WRITE_FLAG(m_concatenationFlag, "concatenation_flag"); 243 WRITE_CODE(m_auCpbRemovalDelayDelta - 1, hrd.cpbRemovalDelayLength, "au_cpb_removal_delay_delta_minus1"); 244 WRITE_CODE(m_initialCpbRemovalDelay, hrd.initialCpbRemovalDelayLength, "initial_cpb_removal_delay"); 245 WRITE_CODE(m_initialCpbRemovalDelayOffset, hrd.initialCpbRemovalDelayLength, "initial_cpb_removal_delay_offset"); 246 247 writeByteAlign(); 248 } 249 }; 250 251 class SEIPictureTiming : public SEI 252 { 253 public: SEIPictureTiming()254 SEIPictureTiming() 255 { 256 m_payloadType = PICTURE_TIMING; 257 m_payloadSize = 0; 258 } 259 uint32_t m_picStruct; 260 uint32_t m_sourceScanType; 261 bool m_duplicateFlag; 262 263 uint32_t m_auCpbRemovalDelay; 264 uint32_t m_picDpbOutputDelay; 265 writeSEI(const SPS & sps)266 void writeSEI(const SPS& sps) 267 { 268 const VUI *vui = &sps.vuiParameters; 269 const HRDInfo *hrd = &vui->hrdParameters; 270 271 if (vui->frameFieldInfoPresentFlag) 272 { 273 WRITE_CODE(m_picStruct, 4, "pic_struct"); 274 WRITE_CODE(m_sourceScanType, 2, "source_scan_type"); 275 WRITE_FLAG(m_duplicateFlag, "duplicate_flag"); 276 } 277 278 if (vui->hrdParametersPresentFlag) 279 { 280 WRITE_CODE(m_auCpbRemovalDelay - 1, hrd->cpbRemovalDelayLength, "au_cpb_removal_delay_minus1"); 281 WRITE_CODE(m_picDpbOutputDelay, hrd->dpbOutputDelayLength, "pic_dpb_output_delay"); 282 /* Removed sub-pic signaling June 2014 */ 283 } 284 writeByteAlign(); 285 } 286 }; 287 288 class SEIRecoveryPoint : public SEI 289 { 290 public: SEIRecoveryPoint()291 SEIRecoveryPoint() 292 { 293 m_payloadType = RECOVERY_POINT; 294 m_payloadSize = 0; 295 } 296 int m_recoveryPocCnt; 297 bool m_exactMatchingFlag; 298 bool m_brokenLinkFlag; 299 writeSEI(const SPS &)300 void writeSEI(const SPS&) 301 { 302 WRITE_SVLC(m_recoveryPocCnt, "recovery_poc_cnt"); 303 WRITE_FLAG(m_exactMatchingFlag, "exact_matching_flag"); 304 WRITE_FLAG(m_brokenLinkFlag, "broken_link_flag"); 305 writeByteAlign(); 306 } 307 }; 308 309 class SEIAlternativeTC : public SEI 310 { 311 public: 312 int m_preferredTransferCharacteristics; SEIAlternativeTC()313 SEIAlternativeTC() 314 { 315 m_payloadType = ALTERNATIVE_TRANSFER_CHARACTERISTICS; 316 m_payloadSize = 0; 317 m_preferredTransferCharacteristics = -1; 318 } 319 writeSEI(const SPS &)320 void writeSEI(const SPS&) 321 { 322 WRITE_CODE(m_preferredTransferCharacteristics, 8, "Preferred transfer characteristics"); 323 } 324 }; 325 326 } 327 #endif // ifndef X265_SEI_H 328