| 278 | |
| 279 | /** Serializes an AvcDecoderConfigurationRecord into the format specified in Section 5.3.3.1 of ISO 14496-15. */ |
| 280 | export const serializeAvcDecoderConfigurationRecord = (record: AvcDecoderConfigurationRecord) => { |
| 281 | const bytes: number[] = []; |
| 282 | |
| 283 | // Write header |
| 284 | bytes.push(record.configurationVersion); |
| 285 | bytes.push(record.avcProfileIndication); |
| 286 | bytes.push(record.profileCompatibility); |
| 287 | bytes.push(record.avcLevelIndication); |
| 288 | bytes.push(0xFC | (record.lengthSizeMinusOne & 0x03)); // Reserved bits (6) + lengthSizeMinusOne (2) |
| 289 | |
| 290 | // Reserved bits (3) + numOfSequenceParameterSets (5) |
| 291 | bytes.push(0xE0 | (record.sequenceParameterSets.length & 0x1F)); |
| 292 | |
| 293 | // Write SPS |
| 294 | for (const sps of record.sequenceParameterSets) { |
| 295 | const length = sps.byteLength; |
| 296 | bytes.push(length >> 8); // High byte |
| 297 | bytes.push(length & 0xFF); // Low byte |
| 298 | |
| 299 | for (let i = 0; i < length; i++) { |
| 300 | bytes.push(sps[i]); |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | bytes.push(record.pictureParameterSets.length); |
| 305 | |
| 306 | // Write PPS |
| 307 | for (const pps of record.pictureParameterSets) { |
| 308 | const length = pps.byteLength; |
| 309 | bytes.push(length >> 8); // High byte |
| 310 | bytes.push(length & 0xFF); // Low byte |
| 311 | |
| 312 | for (let i = 0; i < length; i++) { |
| 313 | bytes.push(pps[i]); |
| 314 | } |
| 315 | } |
| 316 | |
| 317 | if ( |
| 318 | record.avcProfileIndication === 100 |
| 319 | || record.avcProfileIndication === 110 |
| 320 | || record.avcProfileIndication === 122 |
| 321 | || record.avcProfileIndication === 144 |
| 322 | ) { |
| 323 | assert(record.chromaFormat !== null); |
| 324 | assert(record.bitDepthLumaMinus8 !== null); |
| 325 | assert(record.bitDepthChromaMinus8 !== null); |
| 326 | assert(record.sequenceParameterSetExt !== null); |
| 327 | |
| 328 | bytes.push(0xFC | (record.chromaFormat & 0x03)); // Reserved bits + chroma_format |
| 329 | bytes.push(0xF8 | (record.bitDepthLumaMinus8 & 0x07)); // Reserved bits + bit_depth_luma_minus8 |
| 330 | bytes.push(0xF8 | (record.bitDepthChromaMinus8 & 0x07)); // Reserved bits + bit_depth_chroma_minus8 |
| 331 | |
| 332 | bytes.push(record.sequenceParameterSetExt.length); |
| 333 | |
| 334 | // Write SPS Ext |
| 335 | for (const spsExt of record.sequenceParameterSetExt) { |
| 336 | const length = spsExt.byteLength; |
| 337 | bytes.push(length >> 8); // High byte |