/** * parse bitstream bs and unpack a user_data_unregistered SEI message * of payloasSize bytes into sei. */ Void SEIReader::xParseSEIuserDataUnregistered(SEIuserDataUnregistered &sei, UInt payloadSize) { assert(payloadSize >= 16); UInt val; for (UInt i = 0; i < 16; i++) { READ_CODE (8, val, "uuid_iso_iec_11578"); sei.uuid_iso_iec_11578[i] = val; } sei.userDataLength = payloadSize - 16; if (!sei.userDataLength) { sei.userData = 0; return; } sei.userData = new UChar[sei.userDataLength]; for (UInt i = 0; i < sei.userDataLength; i++) { READ_CODE (8, val, "user_data" ); sei.userData[i] = val; } }
Void SEIReader::xReadSEImessage(SEImessages& seis) { #if ENC_DEC_TRACE xTraceSEIHeader(); #endif Int payloadType = 0; UInt val = 0; do { READ_CODE (8, val, "payload_type"); payloadType += val; } while (val==0xFF); UInt payloadSize = 0; do { READ_CODE (8, val, "payload_size"); payloadSize += val; } while (val==0xFF); #if ENC_DEC_TRACE xTraceSEIMessageType((SEI::PayloadType)payloadType); #endif switch (payloadType) { case SEI::USER_DATA_UNREGISTERED: seis.user_data_unregistered = new SEIuserDataUnregistered; xParseSEIuserDataUnregistered(*seis.user_data_unregistered, payloadSize); break; case SEI::ACTIVE_PARAMETER_SETS: seis.active_parameter_sets = new SEIActiveParameterSets; xParseSEIActiveParameterSets(*seis.active_parameter_sets, payloadSize); break; case SEI::DECODED_PICTURE_HASH: seis.picture_digest = new SEIDecodedPictureHash; xParseSEIDecodedPictureHash(*seis.picture_digest, payloadSize); break; case SEI::BUFFERING_PERIOD: seis.buffering_period = new SEIBufferingPeriod; seis.buffering_period->m_sps = seis.m_pSPS; xParseSEIBufferingPeriod(*seis.buffering_period, payloadSize); break; case SEI::PICTURE_TIMING: seis.picture_timing = new SEIPictureTiming; seis.picture_timing->m_sps = seis.m_pSPS; xParseSEIPictureTiming(*seis.picture_timing, payloadSize); break; case SEI::RECOVERY_POINT: seis.recovery_point = new SEIRecoveryPoint; xParseSEIRecoveryPoint(*seis.recovery_point, payloadSize); break; default: assert(!"Unhandled SEI message"); } }
/** * parse bitstream bs and unpack a decoded picture hash SEI message * of payloadSize bytes into sei. */ Void SEIReader::xParseSEIDecodedPictureHash(SEIDecodedPictureHash& sei, UInt /*payloadSize*/) { UInt val; READ_CODE (8, val, "hash_type"); sei.method = static_cast<SEIDecodedPictureHash::Method>(val); for(Int yuvIdx = 0; yuvIdx < 3; yuvIdx++) { if(SEIDecodedPictureHash::MD5 == sei.method) { for (UInt i = 0; i < 16; i++) { READ_CODE(8, val, "picture_md5"); sei.digest[yuvIdx][i] = val; } } else if(SEIDecodedPictureHash::CRC == sei.method) { READ_CODE(16, val, "picture_crc"); sei.digest[yuvIdx][0] = val >> 8 & 0xFF; sei.digest[yuvIdx][1] = val & 0xFF; } else if(SEIDecodedPictureHash::CHECKSUM == sei.method)
/** * unmarshal a single SEI message from bitstream bs */ void SEIReader::parseSEImessage(TComInputBitstream* bs, SEIMessages& seis, const NalUnitType nalUnitType, TComSPS *sps) { setBitstream(bs); assert(!m_pcBitstream->getNumBitsUntilByteAligned()); do { xReadSEImessage(seis, nalUnitType, sps); /* SEI messages are an integer number of bytes, something has failed * in the parsing if bitstream not byte-aligned */ assert(!m_pcBitstream->getNumBitsUntilByteAligned()); } while (m_pcBitstream->getNumBitsLeft() > 8); UInt rbspTrailingBits; READ_CODE(8, rbspTrailingBits, "rbsp_trailing_bits"); assert(rbspTrailingBits == 0x80); }
/*static*/ int DreamGrafix::UnpackLZW(const uint8_t* srcBuf, long srcLen, uint8_t* dstBuf, long dstLen) { uint16_t finChar, oldCode, inCode, freeCode, maxCode, k; uint16_t nBitMod1, nBitMask; int bitOffset; uint16_t hashNext[4096]; uint16_t hashChar[4096]; uint8_t* pOrigDst = dstBuf; int iCode; uint16_t stack[32768]; int stackIdx = 0; /* initialize table and code reader */ INIT_TABLE(); bitOffset = 0; while (true) { if (dstBuf - pOrigDst > dstLen) { LOGI("LZW overrun"); return -1; } int A; int Y; READ_CODE(); if (iCode == kEofCode) { break; } if (iCode == kClearCode) { // Got Clear INIT_TABLE(); READ_CODE(); oldCode = iCode; k = iCode; finChar = iCode; *dstBuf++ = (uint8_t) iCode; continue; } A = inCode = iCode; if (iCode < freeCode) { goto inTable; } stack[stackIdx] = finChar; stackIdx++; A = oldCode; inTable: if (A < 256) { goto gotChar; } while (A >= 256) { Y = A; A = hashChar[Y]; stack[stackIdx] = A; stackIdx++; A = hashNext[Y]; } gotChar: A &= 0xFF; finChar = A; k = A; Y = 0; dstBuf[Y++] = A; while (stackIdx) { stackIdx--; A = stack[stackIdx]; dstBuf[Y++] = A; } dstBuf += Y; ADD_CODE(); oldCode = inCode; if (freeCode < maxCode) { continue; // goto nextCode; } if (12 == nBitMod1) { continue; // goto nextCode; } nBitMod1++; nBitMask = bitMasks[nBitMod1]; //printf("nBitMod1 = %d, nBitMask = %04x\n", // nBitMod1, nBitMask); maxCode <<= 1; } return dstBuf - pOrigDst; }
Void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType, TComSPS *sps) { #if ENC_DEC_TRACE xTraceSEIHeader(); #endif Int payloadType = 0; UInt val = 0; do { READ_CODE (8, val, "payload_type"); payloadType += val; } while (val==0xFF); UInt payloadSize = 0; do { READ_CODE (8, val, "payload_size"); payloadSize += val; } while (val==0xFF); #if ENC_DEC_TRACE xTraceSEIMessageType((SEI::PayloadType)payloadType); #endif /* extract the payload for this single SEI message. * This allows greater safety in erroneous parsing of an SEI message * from affecting subsequent messages. * After parsing the payload, bs needs to be restored as the primary * bitstream. */ TComInputBitstream *bs = getBitstream(); setBitstream(bs->extractSubstream(payloadSize * 8)); SEI *sei = NULL; if(nalUnitType == NAL_UNIT_SEI) { switch (payloadType) { case SEI::USER_DATA_UNREGISTERED: sei = new SEIuserDataUnregistered; xParseSEIuserDataUnregistered((SEIuserDataUnregistered&) *sei, payloadSize); break; case SEI::ACTIVE_PARAMETER_SETS: sei = new SEIActiveParameterSets; xParseSEIActiveParameterSets((SEIActiveParameterSets&) *sei, payloadSize); break; case SEI::DECODING_UNIT_INFO: if (!sps) { printf ("Warning: Found Decoding unit SEI message, but no active SPS is available. Ignoring."); } else { sei = new SEIDecodingUnitInfo; xParseSEIDecodingUnitInfo((SEIDecodingUnitInfo&) *sei, payloadSize, sps); } break; case SEI::BUFFERING_PERIOD: if (!sps) { printf ("Warning: Found Buffering period SEI message, but no active SPS is available. Ignoring."); } else { sei = new SEIBufferingPeriod; xParseSEIBufferingPeriod((SEIBufferingPeriod&) *sei, payloadSize, sps); } break; case SEI::PICTURE_TIMING: if (!sps) { printf ("Warning: Found Picture timing SEI message, but no active SPS is available. Ignoring."); } else { sei = new SEIPictureTiming; xParseSEIPictureTiming((SEIPictureTiming&)*sei, payloadSize, sps); } break; case SEI::RECOVERY_POINT: sei = new SEIRecoveryPoint; xParseSEIRecoveryPoint((SEIRecoveryPoint&) *sei, payloadSize); break; case SEI::FRAME_PACKING: sei = new SEIFramePacking; xParseSEIFramePacking((SEIFramePacking&) *sei, payloadSize); break; case SEI::DISPLAY_ORIENTATION: sei = new SEIDisplayOrientation; xParseSEIDisplayOrientation((SEIDisplayOrientation&) *sei, payloadSize); break; case SEI::TEMPORAL_LEVEL0_INDEX: sei = new SEITemporalLevel0Index; xParseSEITemporalLevel0Index((SEITemporalLevel0Index&) *sei, payloadSize); break; case SEI::REGION_REFRESH_INFO: sei = new SEIGradualDecodingRefreshInfo; xParseSEIGradualDecodingRefreshInfo((SEIGradualDecodingRefreshInfo&) *sei, payloadSize); break; default: for (UInt i = 0; i < payloadSize; i++) { UInt seiByte; READ_CODE (8, seiByte, "unknown prefix SEI payload byte"); } printf ("Unknown prefix SEI message (payloadType = %d) was found!\n", payloadType); } } else { switch (payloadType) { #if L0363_SEI_ALLOW_SUFFIX case SEI::USER_DATA_UNREGISTERED: sei = new SEIuserDataUnregistered; xParseSEIuserDataUnregistered((SEIuserDataUnregistered&) *sei, payloadSize); break; #endif case SEI::DECODED_PICTURE_HASH: sei = new SEIDecodedPictureHash; xParseSEIDecodedPictureHash((SEIDecodedPictureHash&) *sei, payloadSize); break; default: for (UInt i = 0; i < payloadSize; i++) { UInt seiByte; READ_CODE (8, seiByte, "unknown suffix SEI payload byte"); } printf ("Unknown suffix SEI message (payloadType = %d) was found!\n", payloadType); } } if (sei != NULL) { seis.push_back(sei); } /* By definition the underlying bitstream terminates in a byte-aligned manner. * 1. Extract all bar the last MIN(bitsremaining,nine) bits as reserved_payload_extension_data * 2. Examine the final 8 bits to determine the payload_bit_equal_to_one marker * 3. Extract the remainingreserved_payload_extension_data bits. * * If there are fewer than 9 bits available, extract them. */ Int payloadBitsRemaining = getBitstream()->getNumBitsLeft(); if (payloadBitsRemaining) /* more_data_in_payload() */ { for (; payloadBitsRemaining > 9; payloadBitsRemaining--) { UInt reservedPayloadExtensionData; READ_CODE (1, reservedPayloadExtensionData, "reserved_payload_extension_data"); } /* 2 */ Int finalBits = getBitstream()->peekBits(payloadBitsRemaining); Int finalPayloadBits = 0; for (Int mask = 0xff; finalBits & (mask >> finalPayloadBits); finalPayloadBits++) { continue; } /* 3 */ for (; payloadBitsRemaining > 9 - finalPayloadBits; payloadBitsRemaining--) { UInt reservedPayloadExtensionData; READ_CODE (1, reservedPayloadExtensionData, "reserved_payload_extension_data"); } UInt dummy; READ_CODE (1, dummy, "payload_bit_equal_to_one"); READ_CODE (payloadBitsRemaining-1, dummy, "payload_bit_equal_to_zero"); } /* restore primary bitstream for sei_message */ delete getBitstream(); setBitstream(bs); }