diff --git a/src/parser/hevc_parser.cpp b/src/parser/hevc_parser.cpp index 264da52cd6..72e221eb32 100644 --- a/src/parser/hevc_parser.cpp +++ b/src/parser/hevc_parser.cpp @@ -22,549 +22,263 @@ THE SOFTWARE. #include "hevc_parser.h" -//size_id = 0 -extern int scaling_list_default_0[1][6][16]; -//size_id = 1, 2 -extern int scaling_list_default_1_2[2][6][64]; -//size_id = 3 -extern int scaling_list_default_3[1][2][64]; - -/** - * @brief Constructs a new HEVCVideoParser object - * - */ -HEVCVideoParser::HEVCVideoParser() : - m_use_start_codes_(false), - m_current_frame_timestamp_(0), - m_packet_count_(0), - m_eof_(false), - m_fps_(0), - m_max_frames_number_(0) { - m_pmemory_ = new uint8_t [DATA_STREAM_SIZE]; - m_allocated_size_ = DATA_STREAM_SIZE; - m_memory_size_ = sizeof(m_pmemory_); - m_pos_ = 0; +HEVCVideoParser::HEVCVideoParser() { + b_new_picture_ = false; + m_vps_ = NULL; + m_sps_ = NULL; + m_pps_ = NULL; + m_sh_ = NULL; + m_sh_copy_ = NULL; + m_slice_ = NULL; } -/** - * @brief Function to initialize any hevc parser related members - * - * @return rocDecStatus - */ -rocDecStatus HEVCVideoParser::Initialize(RocdecParserParams *pParams) { - //todo:: - RocVideoParser::Initialize(pParams); - return ROCDEC_NOT_IMPLEMENTED; +rocDecStatus HEVCVideoParser::Initialize(RocdecParserParams *p_params) { + ParserResult status = Init(); + if (status) + return ROCDEC_RUNTIME_ERROR; + RocVideoParser::Initialize(p_params); + return ROCDEC_SUCCESS; } -/** - * @brief Function to Parse video data: Typically called from application when a demuxed picture is ready to be parsed - * - * @param pData: IN: pointer to demuxed data packet - * @return rocDecStatus - */ -rocDecStatus HEVCVideoParser::ParseVideoData(RocdecSourceDataPacket *pData) { - if (!CheckDataStreamEof(pData->payload_size)) { - Write(pData->payload, pData->payload_size, NULL); - Seek(PARSER_SEEK_BEGIN, 0, NULL); - FindSPSandPPS(); - - ParserBuffer* outputBuffer; - outputBuffer = NULL; - QueryOutput(&outputBuffer); +rocDecStatus HEVCVideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) { + bool status = ParseFrameData(p_data->payload, p_data->payload_size); + if (!status) { + ERR(STR("Parser failed!\n")); + return ROCDEC_RUNTIME_ERROR; } return ROCDEC_SUCCESS; } -void HEVCVideoParser::FindFirstFrameSPSandPPS() { - Seek(PARSER_SEEK_BEGIN, 0, NULL); - FindSPSandPPS(); -} - HEVCVideoParser::~HEVCVideoParser() { - std::cout << "parsed frames: " << m_packet_count_ << std::endl; - Close(); + if (m_vps_) { + delete [] m_vps_; + } + if (m_sps_) { + delete [] m_sps_; + } + if (m_pps_) { + delete [] m_pps_; + } + if (m_sh_) { + delete m_sh_; + } + if (m_sh_copy_) { + delete m_sh_copy_; + } + if (m_slice_) { + delete m_slice_; + } } -ParserResult HEVCVideoParser::ReInit() { - m_current_frame_timestamp_ = 0; - Seek(PARSER_SEEK_BEGIN, 0, NULL); - m_packet_count_ = 0; - m_eof_ = false; +HEVCVideoParser::VpsData* HEVCVideoParser::AllocVps() { + VpsData *p = nullptr; + try { + p = new VpsData [MAX_VPS_COUNT]; + } + catch(const std::exception& e) { + ERR(STR("Failed to alloc VPS Data, ") + STR(e.what())) + } + memset(p, 0, sizeof(VpsData) * MAX_VPS_COUNT); + return p; +} + +HEVCVideoParser::SpsData* HEVCVideoParser::AllocSps() { + SpsData *p = nullptr; + try { + p = new SpsData [MAX_SPS_COUNT]; + } + catch(const std::exception& e) { + ERR(STR("Failed to alloc SPS Data, ") + STR(e.what())) + } + memset(p, 0, sizeof(SpsData) * MAX_SPS_COUNT); + return p; +} + +HEVCVideoParser::PpsData* HEVCVideoParser::AllocPps() { + PpsData *p = nullptr; + try { + p = new PpsData [MAX_PPS_COUNT]; + } + catch(const std::exception& e) { + ERR(STR("Failed to alloc PPS Data, ") + STR(e.what())) + } + memset(p, 0, sizeof(PpsData) * MAX_PPS_COUNT); + return p; +} + +HEVCVideoParser::SliceData* HEVCVideoParser::AllocSlice() { + SliceData *p = nullptr; + try { + p = new SliceData; + } + catch(const std::exception& e) { + ERR(STR("Failed to alloc Slice Data, ") + STR(e.what())) + } + memset(p, 0, sizeof(SliceData)); + return p; +} + +HEVCVideoParser::SliceHeaderData* HEVCVideoParser::AllocSliceHeader() { + SliceHeaderData *p = nullptr; + try { + p = new SliceHeaderData; + } + catch(const std::exception& e) { + ERR(STR("Failed to alloc Slice Header Data, ") + STR(e.what())) + } + memset(p, 0, sizeof(SliceHeaderData)); + return p; +} + +ParserResult HEVCVideoParser::Init() { + m_active_vps_ = 0; + m_active_sps_ = 0; + m_active_pps_ = 0; + b_new_picture_ = false; + m_vps_ = AllocVps(); + m_sps_ = AllocSps(); + m_pps_ = AllocPps(); + m_slice_ = AllocSlice(); + m_sh_ = AllocSliceHeader(); + m_sh_copy_ = AllocSliceHeader(); return PARSER_OK; } -static const int s_win_unit_x[]={1,2,2,1}; -static const int s_win_unit_y[]={1,2,1,1}; +bool HEVCVideoParser::ParseFrameData(const uint8_t* p_stream, uint32_t frame_data_size) { + int ret = PARSER_OK; + NalUnitHeader nal_unit_header; -static int GetWinUnitX (int chromaFormatIdc) { return s_win_unit_x[chromaFormatIdc]; } -// static int GetWinUnitX (int chromaFormatIdc) { return s_win_unit_y[chromaFormatIdc]; } + frame_data_buffer_ptr_ = (uint8_t*)p_stream; + frame_data_size_ = frame_data_size; + curr_byte_offset_ = 0; + start_code_num_ = 0; + curr_start_code_offset_ = 0; + next_start_code_offset_ = 0; -void HEVCVideoParser::SetFrameRate(double fps) { - m_fps_ = fps; + slice_num_ = 0; + + do { + ret = GetNalUnit(); + + if (ret == PARSER_NOT_FOUND) { + ERR(STR("Error: no start code found in the frame data.\n")); + return false; + } + + // Parse the NAL unit + if (nal_unit_size_) { + // start code + NAL unit header = 5 bytes + int ebsp_size = nal_unit_size_ - 5 > RBSP_BUF_SIZE ? RBSP_BUF_SIZE : nal_unit_size_ - 5; // only copy enough bytes for header parsing + + nal_unit_header = ParseNalUnitHeader(&frame_data_buffer_ptr_[curr_start_code_offset_ + 3]); + switch (nal_unit_header.nal_unit_type) { + case NAL_UNIT_VPS: { + memcpy(m_rbsp_buf_, (frame_data_buffer_ptr_ + curr_start_code_offset_ + 5), ebsp_size); + m_rbsp_size_ = EBSPtoRBSP(m_rbsp_buf_, 0, ebsp_size); + ParseVps(m_rbsp_buf_, m_rbsp_size_); + break; + } + + case NAL_UNIT_SPS: { + memcpy(m_rbsp_buf_, (frame_data_buffer_ptr_ + curr_start_code_offset_ + 5), ebsp_size); + m_rbsp_size_ = EBSPtoRBSP(m_rbsp_buf_, 0, ebsp_size); + ParseSps(m_rbsp_buf_, m_rbsp_size_); + break; + } + + case NAL_UNIT_PPS: { + memcpy(m_rbsp_buf_, (frame_data_buffer_ptr_ + curr_start_code_offset_ + 5), ebsp_size); + m_rbsp_size_ = EBSPtoRBSP(m_rbsp_buf_, 0, ebsp_size); + ParsePps(m_rbsp_buf_, m_rbsp_size_); + break; + } + + case NAL_UNIT_CODED_SLICE_TRAIL_R: + case NAL_UNIT_CODED_SLICE_TRAIL_N: + case NAL_UNIT_CODED_SLICE_TLA_R: + case NAL_UNIT_CODED_SLICE_TSA_N: + case NAL_UNIT_CODED_SLICE_STSA_R: + case NAL_UNIT_CODED_SLICE_STSA_N: + case NAL_UNIT_CODED_SLICE_BLA_W_LP: + case NAL_UNIT_CODED_SLICE_BLA_W_RADL: + case NAL_UNIT_CODED_SLICE_BLA_N_LP: + case NAL_UNIT_CODED_SLICE_IDR_W_RADL: + case NAL_UNIT_CODED_SLICE_IDR_N_LP: + case NAL_UNIT_CODED_SLICE_CRA: + case NAL_UNIT_CODED_SLICE_RADL_N: + case NAL_UNIT_CODED_SLICE_RADL_R: + case NAL_UNIT_CODED_SLICE_RASL_N: + case NAL_UNIT_CODED_SLICE_RASL_R: { + memcpy(m_rbsp_buf_, (frame_data_buffer_ptr_ + curr_start_code_offset_ + 5), ebsp_size); + m_rbsp_size_ = EBSPtoRBSP(m_rbsp_buf_, 0, ebsp_size); + ParseSliceHeader(nal_unit_header.nal_unit_type, m_rbsp_buf_, m_rbsp_size_); + slice_num_++; + break; + } + + default: + // Do nothing for now. + break; + } + } + + // Break if this is the last NAL unit + if (ret == PARSER_EOF) { + break; + } + } while (1); + + return true; } -double HEVCVideoParser::GetFrameRate() const { - if(m_fps_ != 0) { - return m_fps_; - } - if(m_sps_map_.size() > 0) { - const SpsData &sps = m_sps_map_.cbegin()->second; - if(sps.vui_parameters_present_flag && sps.vui_parameters.vui_timing_info_present_flag && sps.vui_parameters.vui_num_units_in_tick) { - // according to the latest h264 standard nuit_field_based_flag is always = 1 and therefore this must be divided by two - // some old clips may get wrong FPS. This is just a sample. Use container information - return (double)sps.vui_parameters.vui_time_scale / sps.vui_parameters.vui_num_units_in_tick / 2; - } - } - return 25.0; -} +int HEVCVideoParser::GetNalUnit() { + bool start_code_found = false; -HEVCVideoParser::NalUnitHeader HEVCVideoParser::ReadNextNaluUnit(size_t *offset, size_t *nalu, size_t *size) { - *size = 0; - size_t start_offset = *offset; + nal_unit_size_ = 0; + curr_start_code_offset_ = next_start_code_offset_; // save the current start code offset - bool new_nal_found = false; - size_t zeros_count = 0; + // Search for the next start code + while (curr_byte_offset_ < frame_data_size_ - 2) { + if (frame_data_buffer_ptr_[curr_byte_offset_] == 0 && frame_data_buffer_ptr_[curr_byte_offset_ + 1] == 0 && frame_data_buffer_ptr_[curr_byte_offset_ + 2] == 0x01) { + curr_start_code_offset_ = next_start_code_offset_; // save the current start code offset - while (!new_nal_found) { - // read next portion if needed - size_t ready = m_read_data_.GetSize() - *offset; - printf("ReadNextNaluUnit: remaining data size for read: %zu\n", ready); - if (ready == 0) { - if (m_eof_ == false) { - m_read_data_.SetSize(m_read_data_.GetSize() + m_read_size_); - ready = 0; - Read(m_read_data_.GetData() + *offset, m_read_size_, &ready); - } - if (ready != m_read_size_ && ready != 0) { - m_read_data_.SetSize(m_read_data_.GetSize() - (m_read_size_ - ready)); - } - if (ready == 0 ) { - if (m_eof_ == false) - m_read_data_.SetSize(m_read_data_.GetSize() - m_read_size_); + start_code_found = true; + start_code_num_++; + next_start_code_offset_ = curr_byte_offset_; + // Move the pointer 3 bytes forward + curr_byte_offset_ += 3; - //m_eof_ = true; - new_nal_found = start_offset != *offset; - *offset = m_read_data_.GetSize(); - break; // EOF - } - } - - uint8_t* data = m_read_data_.GetData(); - if (data == nullptr) { // check data before adding the offset - NalUnitHeader header_nalu; - header_nalu.nal_unit_type = NAL_UNIT_INVALID; - return header_nalu; // no data read - } - data += *offset; // don't forget the offset! - - for (size_t i = 0; i < ready; i++) { - uint8_t ch = *data++; - if (0 == ch) { - zeros_count++; + // For the very first NAL unit, search for the next start code (or reach the end of frame) + if (start_code_num_ == 1) { + start_code_found = false; + curr_start_code_offset_ = next_start_code_offset_; + continue; } else { - if (1 == ch && zeros_count >=2) { // We found a start code in Annex B stream - if (*offset + (i - zeros_count) > start_offset) { - ready = i - zeros_count; - new_nal_found = true; // new NAL - break; - } - else { - *nalu = *offset + zeros_count + 1; - } - } - zeros_count = 0; + break; } } - // if zeros found but not a new NAL - continue with zeros_count on the next iteration - *offset += ready; + curr_byte_offset_++; + } + if (start_code_num_ == 0) { + // No NAL unit in the frame data + return PARSER_NOT_FOUND; } - if (!new_nal_found) { - NalUnitHeader header_nalu; - header_nalu.nal_unit_type = NAL_UNIT_INVALID; - return header_nalu; // EOF + if (start_code_found) { + nal_unit_size_ = next_start_code_offset_ - curr_start_code_offset_; + return PARSER_OK; } - *size = *offset - *nalu; - // get NAL type - return GetNaluUnitType(m_read_data_.GetData() + *nalu); -} - -ParserResult HEVCVideoParser::QueryOutput(ParserBuffer** pp_data) { - if ((m_eof_ && m_read_data_.GetSize() == 0) || m_max_frames_number_ && m_packet_count_ >= m_max_frames_number_) { + else { + nal_unit_size_ = frame_data_size_ - curr_start_code_offset_; return PARSER_EOF; - } - bool new_picture_detected = false; - size_t packet_size = 0; - size_t read_size = 0; - std::vector nalu_starts; - std::vector nalu_sizes; - size_t data_offset = 0; - bool b_slice_found = false; - uint32_t prev_slice_nal_unit_type = 0; - - do { - size_t nalu_size = 0; - size_t nalu_offset = 0; - size_t nalu_annex_boffset = data_offset; - NalUnitHeader nalu_header = ReadNextNaluUnit(&data_offset, &nalu_offset, &nalu_size); - if (b_slice_found == true) { - if (prev_slice_nal_unit_type != nalu_header.nal_unit_type) { - new_picture_detected = true; - } - } - - if (NAL_UNIT_ACCESS_UNIT_DELIMITER == nalu_header.nal_unit_type) { - if (packet_size > 0) { - new_picture_detected = true; - } - } - else if (NAL_UNIT_PREFIX_SEI == nalu_header.nal_unit_type) { - if (b_slice_found) { - new_picture_detected = true; - } - } - else if ( - NAL_UNIT_CODED_SLICE_TRAIL_R == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_TRAIL_N == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_TLA_R == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_TSA_N == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_STSA_R == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_STSA_N == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_BLA_W_LP == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_BLA_W_RADL == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_BLA_N_LP == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_IDR_W_RADL == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_IDR_N_LP == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_CRA == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_RADL_N == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_RADL_R == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_RASL_N == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_RASL_R == nalu_header.nal_unit_type - ) { - if (b_slice_found == true) { - if (prev_slice_nal_unit_type != nalu_header.nal_unit_type) { - new_picture_detected = true; - } - else { - AccessUnitSigns nalu_access_units_signs; - nalu_access_units_signs.Parse(m_read_data_.GetData() + nalu_offset, nalu_size, m_sps_map_, m_pps_map_); - new_picture_detected = nalu_access_units_signs.IsNewPicture() && b_slice_found; - } - b_slice_found = true; - prev_slice_nal_unit_type = nalu_header.nal_unit_type; - } - else { - AccessUnitSigns nalu_access_units_signs; - nalu_access_units_signs.Parse(m_read_data_.GetData() + nalu_offset, nalu_size, m_sps_map_, m_pps_map_); - new_picture_detected = nalu_access_units_signs.IsNewPicture() && b_slice_found; - b_slice_found = true; - prev_slice_nal_unit_type = nalu_header.nal_unit_type; - } - } - - if (nalu_size > 0 && !new_picture_detected ) { - packet_size += nalu_size; - if (!m_use_start_codes_) { - packet_size += nal_unit_length_size_; - nalu_starts.push_back(nalu_offset); - nalu_sizes.push_back(nalu_size); - } - else { - size_t startCodeSize = nalu_offset - nalu_annex_boffset; - packet_size += startCodeSize; - } - } - if (!new_picture_detected) { - read_size = data_offset; - } - if (nalu_header.nal_unit_type == NAL_UNIT_INVALID) { - break; - } - } while (!new_picture_detected); - - ParserResult ar = ParserBuffer::AllocBuffer(PARSER_MEMORY_HOST, packet_size, pp_data); - if (ar != PARSER_OK) { - return ar; - } - - uint8_t *data = (uint8_t*)(*pp_data)->GetNative(); - if (m_use_start_codes_) { - memcpy(data, m_read_data_.GetData(), packet_size); - } - else { - for (size_t i=0; i < nalu_starts.size(); i++) { - // copy size - uint32_t nalu_size= (uint32_t)nalu_sizes[i]; - *data++ = (nalu_size >> 24); - *data++ = static_cast(((nalu_size & 0x00FF0000) >> 16)); - *data++ = ((nalu_size & 0x0000FF00) >> 8); - *data++ = ((nalu_size & 0x000000FF)); - memcpy(data, m_read_data_.GetData() + nalu_starts[i], nalu_size); - data += nalu_size; - } - } - (*pp_data)->SetPts(m_current_frame_timestamp_); - int64_t frame_duration = int64_t(PARSER_SECOND / GetFrameRate()); // In 100 NanoSeconds - (*pp_data)->SetDuration(frame_duration); - m_current_frame_timestamp_ += frame_duration; - - // shift remaining data in m_ReadData - size_t remaining_data = m_read_data_.GetSize() - read_size; - memmove(m_read_data_.GetData(), m_read_data_.GetData()+read_size, remaining_data); - m_read_data_.SetSize(remaining_data); - - m_packet_count_++; - - return PARSER_OK; + } } -void HEVCVideoParser::FindSPSandPPS() { - ExtraDataBuilder extra_data_builder; - - size_t data_offset = 0; - do { - - size_t nalu_size = 0; - size_t nalu_offset = 0; - NalUnitHeader nalu_header = ReadNextNaluUnit(&data_offset, &nalu_offset, &nalu_size); - - if (nalu_header.nal_unit_type == NAL_UNIT_INVALID ) { - break; // EOF - } - - if (nalu_header.nal_unit_type == NAL_UNIT_SPS) { - m_EBSP_to_RBSP_data_.SetSize(nalu_size); - memcpy(m_EBSP_to_RBSP_data_.GetData(), m_read_data_.GetData() + nalu_offset, nalu_size); - size_t newNaluSize = EBSPtoRBSP(m_EBSP_to_RBSP_data_.GetData(),0, nalu_size); - - SpsData sps; - sps.Parse(m_EBSP_to_RBSP_data_.GetData(), newNaluSize); - m_sps_map_[sps.sps_video_parameter_set_id] = sps; - extra_data_builder.AddSPS(m_read_data_.GetData()+nalu_offset, nalu_size); - } - else if (nalu_header.nal_unit_type == NAL_UNIT_PPS) { - m_EBSP_to_RBSP_data_.SetSize(nalu_size); - memcpy(m_EBSP_to_RBSP_data_.GetData(), m_read_data_.GetData() + nalu_offset, nalu_size); - size_t newNaluSize = EBSPtoRBSP(m_EBSP_to_RBSP_data_.GetData(),0, nalu_size); - - PpsData pps; - pps.Parse(m_EBSP_to_RBSP_data_.GetData(), newNaluSize); - m_pps_map_[pps.pps_pic_parameter_set_id] = pps; - extra_data_builder.AddPPS(m_read_data_.GetData()+nalu_offset, nalu_size); - } - else if ( - NAL_UNIT_CODED_SLICE_TRAIL_R == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_TRAIL_N == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_TLA_R == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_TSA_N == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_STSA_R == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_STSA_N == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_BLA_W_LP == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_BLA_W_RADL == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_BLA_N_LP == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_IDR_W_RADL == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_IDR_N_LP == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_CRA == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_RADL_N == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_RADL_R == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_RASL_N == nalu_header.nal_unit_type - || NAL_UNIT_CODED_SLICE_RASL_R == nalu_header.nal_unit_type - ) { - break; // frame data - } - } while (true); - - Seek(PARSER_SEEK_BEGIN, 0, NULL); - m_read_data_.SetSize(0); - // It will fail if SPS or PPS are absent - extra_data_builder.GetExtradata(m_extra_data_); -} - -bool HEVCVideoParser::SpsData::Parse(uint8_t *nalu, size_t size) { - size_t offset = 16; // 2 bytes NALU header + - uint32_t active_vps = Parser::ReadBits(nalu, offset,4); - uint32_t max_sub_layer_minus1 = Parser::ReadBits(nalu, offset,3); - sps_temporal_id_nesting_flag = Parser::GetBit(nalu, offset); - H265ProfileTierLevel ptl; - memset (&ptl,0,sizeof(ptl)); - ParsePTL(&ptl, true, max_sub_layer_minus1, nalu, size, offset); - uint32_t sps_id = Parser::ExpGolomb::ReadUe(nalu, offset); - - sps_video_parameter_set_id = active_vps; - sps_max_sub_layers_minus1 = max_sub_layer_minus1; - memcpy (&profile_tier_level,&ptl,sizeof(ptl)); - sps_seq_parameter_set_id = sps_id; - - chroma_format_idc = Parser::ExpGolomb::ReadUe(nalu, offset); - if (chroma_format_idc == 3) { - separate_colour_plane_flag = Parser::GetBit(nalu, offset); - } - pic_width_in_luma_samples = Parser::ExpGolomb::ReadUe(nalu, offset); - pic_height_in_luma_samples = Parser::ExpGolomb::ReadUe(nalu, offset); - conformance_window_flag = Parser::GetBit(nalu, offset); - if (conformance_window_flag) { - conf_win_left_offset = Parser::ExpGolomb::ReadUe(nalu, offset); - conf_win_right_offset = Parser::ExpGolomb::ReadUe(nalu, offset); - conf_win_top_offset = Parser::ExpGolomb::ReadUe(nalu, offset); - conf_win_bottom_offset = Parser::ExpGolomb::ReadUe(nalu, offset); - } - bit_depth_luma_minus8 = Parser::ExpGolomb::ReadUe(nalu, offset); - bit_depth_chroma_minus8 = Parser::ExpGolomb::ReadUe(nalu, offset); - log2_max_pic_order_cnt_lsb_minus4 = Parser::ExpGolomb::ReadUe(nalu, offset); - sps_sub_layer_ordering_info_present_flag = Parser::GetBit(nalu, offset); - for (uint32_t i = (sps_sub_layer_ordering_info_present_flag?0:sps_max_sub_layers_minus1); i <= sps_max_sub_layers_minus1; i++) { - sps_max_dec_pic_buffering_minus1[i] = Parser::ExpGolomb::ReadUe(nalu, offset); - sps_max_num_reorder_pics[i] = Parser::ExpGolomb::ReadUe(nalu, offset); - sps_max_latency_increase_plus1[i] = Parser::ExpGolomb::ReadUe(nalu, offset); - } - log2_min_luma_coding_block_size_minus3 = Parser::ExpGolomb::ReadUe(nalu, offset); - - int log2_min_cu_size = log2_min_luma_coding_block_size_minus3 +3; - - log2_diff_max_min_luma_coding_block_size = Parser::ExpGolomb::ReadUe(nalu, offset); - - int max_cu_depth_delta = log2_diff_max_min_luma_coding_block_size; - max_cu_width = ( 1<<(log2_min_cu_size + max_cu_depth_delta) ); - max_cu_height = ( 1<<(log2_min_cu_size + max_cu_depth_delta) ); - - log2_min_transform_block_size_minus2 = Parser::ExpGolomb::ReadUe(nalu, offset); - - uint32_t quadtree_tu_log2_min_size = log2_min_transform_block_size_minus2 + 2; - int add_cu_depth = std::max (0, log2_min_cu_size - (int)quadtree_tu_log2_min_size ); - max_cu_depth = (max_cu_depth_delta + add_cu_depth); - - log2_diff_max_min_transform_block_size = Parser::ExpGolomb::ReadUe(nalu, offset); - max_transform_hierarchy_depth_inter = Parser::ExpGolomb::ReadUe(nalu, offset); - max_transform_hierarchy_depth_intra = Parser::ExpGolomb::ReadUe(nalu, offset); - scaling_list_enabled_flag = Parser::GetBit(nalu, offset); - if (scaling_list_enabled_flag) { - sps_scaling_list_data_present_flag = Parser::GetBit(nalu, offset); - if (sps_scaling_list_data_present_flag) { - ParseScalingList(&scaling_list_data, nalu, size, offset); - } - } - amp_enabled_flag = Parser::GetBit(nalu, offset); - sample_adaptive_offset_enabled_flag = Parser::GetBit(nalu, offset); - pcm_enabled_flag = Parser::GetBit(nalu, offset); - if (pcm_enabled_flag) { - pcm_sample_bit_depth_luma_minus1 = Parser::ReadBits(nalu, offset,4); - pcm_sample_bit_depth_chroma_minus1 = Parser::ReadBits(nalu, offset,4); - log2_min_pcm_luma_coding_block_size_minus3 = Parser::ExpGolomb::ReadUe(nalu, offset); - log2_diff_max_min_pcm_luma_coding_block_size = Parser::ExpGolomb::ReadUe(nalu, offset); - pcm_loop_filter_disabled_flag = Parser::GetBit(nalu, offset); - } - num_short_term_ref_pic_sets = Parser::ExpGolomb::ReadUe(nalu, offset); - for (uint32_t i=0; igeneral_profile_space = Parser::ReadBits(nalu, offset,2); + ptl->general_profile_space = Parser::ReadBits(nalu, offset, 2); ptl->general_tier_flag = Parser::GetBit(nalu, offset); - ptl->general_profile_idc = Parser::ReadBits(nalu, offset,5); + ptl->general_profile_idc = Parser::ReadBits(nalu, offset, 5); for (int i = 0; i < 32; i++) { ptl->general_profile_compatibility_flag[i] = Parser::GetBit(nalu, offset); } @@ -573,42 +287,35 @@ void HEVCVideoParser::SpsData::ParsePTL(H265ProfileTierLevel *ptl, bool profile_ ptl->general_non_packed_constraint_flag = Parser::GetBit(nalu, offset); ptl->general_frame_only_constraint_flag = Parser::GetBit(nalu, offset); //ReadBits is limited to 32 - //ptl->general_reserved_zero_44bits = Parser::ReadBits(nalu, offset,44); offset += 44; } - - ptl->general_level_idc = Parser::ReadBits(nalu, offset,8); + ptl->general_level_idc = Parser::ReadBits(nalu, offset, 8); for(uint32_t i = 0; i < max_num_sub_layers_minus1; i++) { ptl->sub_layer_profile_present_flag[i] = Parser::GetBit(nalu, offset); ptl->sub_layer_level_present_flag[i] = Parser::GetBit(nalu, offset); } if (max_num_sub_layers_minus1 > 0) { - for(uint32_t i=max_num_sub_layers_minus1; i<8; i++) { - ptl->reserved_zero_2bits[i] = Parser::ReadBits(nalu, offset,2); + for(uint32_t i = max_num_sub_layers_minus1; i < 8; i++) { + ptl->reserved_zero_2bits[i] = Parser::ReadBits(nalu, offset, 2); } } for (uint32_t i = 0; i < max_num_sub_layers_minus1; i++) { if (ptl->sub_layer_profile_present_flag[i]) { - ptl->sub_layer_profile_space[i] = Parser::ReadBits(nalu, offset,2); + ptl->sub_layer_profile_space[i] = Parser::ReadBits(nalu, offset, 2); ptl->sub_layer_tier_flag[i] = Parser::GetBit(nalu, offset); - ptl->sub_layer_profile_idc[i] = Parser::ReadBits(nalu, offset,5); - for (int j = 0; j < 32; j++) { - ptl->sub_layer_profile_compatibility_flag[i][j] = Parser::GetBit(nalu, offset); - } - ptl->sub_layer_progressive_source_flag[i] = Parser::GetBit(nalu, offset); - ptl->sub_layer_interlaced_source_flag[i] = Parser::GetBit(nalu, offset); + ptl->sub_layer_profile_idc[i] = Parser::ReadBits(nalu, offset, 5); ptl->sub_layer_non_packed_constraint_flag[i] = Parser::GetBit(nalu, offset); ptl->sub_layer_frame_only_constraint_flag[i] = Parser::GetBit(nalu, offset); - ptl->sub_layer_reserved_zero_44bits[i] = Parser::ReadBits(nalu, offset,44); + ptl->sub_layer_reserved_zero_44bits[i] = Parser::ReadBits(nalu, offset, 44); } if (ptl->sub_layer_level_present_flag[i]) { - ptl->sub_layer_level_idc[i] = Parser::ReadBits(nalu, offset,8); + ptl->sub_layer_level_idc[i] = Parser::ReadBits(nalu, offset, 8); } } } -void HEVCVideoParser::SpsData::ParseSubLayerHrdParameters(H265SubLayerHrdParameters *sub_hrd, uint32_t CpbCnt, bool sub_pic_hrd_params_present_flag, uint8_t *nalu, size_t /*size*/, size_t& offset) { - for (uint32_t i = 0; i <= CpbCnt; i++) { +void HEVCVideoParser::ParseSubLayerHrdParameters(H265SubLayerHrdParameters *sub_hrd, uint32_t cpb_cnt, bool sub_pic_hrd_params_present_flag, uint8_t *nalu, size_t /*size*/, size_t& offset) { + for (uint32_t i = 0; i <= cpb_cnt; i++) { sub_hrd->bit_rate_value_minus1[i] = Parser::ExpGolomb::ReadUe(nalu, offset); sub_hrd->cpb_size_value_minus1[i] = Parser::ExpGolomb::ReadUe(nalu, offset); if(sub_pic_hrd_params_present_flag) { @@ -619,26 +326,26 @@ void HEVCVideoParser::SpsData::ParseSubLayerHrdParameters(H265SubLayerHrdParamet } } -void HEVCVideoParser::SpsData::ParseHrdParameters(H265HrdParameters *hrd, bool common_inf_present_flag, uint32_t max_num_sub_layers_minus1, uint8_t *nalu, size_t size,size_t &offset) { +void HEVCVideoParser::ParseHrdParameters(H265HrdParameters *hrd, bool common_inf_present_flag, uint32_t max_num_sub_layers_minus1, uint8_t *nalu, size_t size,size_t &offset) { if (common_inf_present_flag) { hrd->nal_hrd_parameters_present_flag = Parser::GetBit(nalu, offset); hrd->vcl_hrd_parameters_present_flag = Parser::GetBit(nalu, offset); if (hrd->nal_hrd_parameters_present_flag || hrd->vcl_hrd_parameters_present_flag) { hrd->sub_pic_hrd_params_present_flag = Parser::GetBit(nalu, offset); if (hrd->sub_pic_hrd_params_present_flag) { - hrd->tick_divisor_minus2 = Parser::ReadBits(nalu, offset,8); - hrd->du_cpb_removal_delay_increment_length_minus1 = Parser::ReadBits(nalu, offset,5); + hrd->tick_divisor_minus2 = Parser::ReadBits(nalu, offset, 8); + hrd->du_cpb_removal_delay_increment_length_minus1 = Parser::ReadBits(nalu, offset, 5); hrd->sub_pic_cpb_params_in_pic_timing_sei_flag = Parser::GetBit(nalu, offset); - hrd->dpb_output_delay_du_length_minus1 = Parser::ReadBits(nalu, offset,5); + hrd->dpb_output_delay_du_length_minus1 = Parser::ReadBits(nalu, offset, 5); } - hrd->bit_rate_scale = Parser::ReadBits(nalu, offset,4); - hrd->cpb_size_scale = Parser::ReadBits(nalu, offset,4); + hrd->bit_rate_scale = Parser::ReadBits(nalu, offset, 4); + hrd->cpb_size_scale = Parser::ReadBits(nalu, offset, 4); if (hrd->sub_pic_hrd_params_present_flag) { - hrd->cpb_size_du_scale = Parser::ReadBits(nalu, offset,4); + hrd->cpb_size_du_scale = Parser::ReadBits(nalu, offset, 4); } - hrd->initial_cpb_removal_delay_length_minus1 = Parser::ReadBits(nalu, offset,5); - hrd->au_cpb_removal_delay_length_minus1 = Parser::ReadBits(nalu, offset,5); - hrd->dpb_output_delay_length_minus1 = Parser::ReadBits(nalu, offset,5); + hrd->initial_cpb_removal_delay_length_minus1 = Parser::ReadBits(nalu, offset, 5); + hrd->au_cpb_removal_delay_length_minus1 = Parser::ReadBits(nalu, offset, 5); + hrd->dpb_output_delay_length_minus1 = Parser::ReadBits(nalu, offset, 5); } } for (uint32_t i = 0; i <= max_num_sub_layers_minus1; i++) { @@ -670,17 +377,15 @@ void HEVCVideoParser::SpsData::ParseHrdParameters(H265HrdParameters *hrd, bool c } } -void HEVCVideoParser::SpsData::ParseScalingList(H265ScalingListData * s_data, uint8_t *nalu, size_t /*size*/, size_t& offset) { +void HEVCVideoParser::ParseScalingList(H265ScalingListData * s_data, uint8_t *nalu, size_t /*size*/, size_t& offset) { for (int size_id = 0; size_id < 4; size_id++) { - for (int matrix_id = 0; matrix_id < ((size_id == 3) ? 2:6); matrix_id++) { + for (int matrix_id = 0; matrix_id < ((size_id == 3) ? 2 : 6); matrix_id++) { s_data->scaling_list_pred_mode_flag[size_id][matrix_id] = Parser::GetBit(nalu, offset); if(!s_data->scaling_list_pred_mode_flag[size_id][matrix_id]) { s_data->scaling_list_pred_matrix_id_delta[size_id][matrix_id] = Parser::ExpGolomb::ReadUe(nalu, offset); int ref_matrix_id = matrix_id - s_data->scaling_list_pred_matrix_id_delta[size_id][matrix_id]; - int coef_num = std::min(64, (1<< (4 + (size_id<<1)))); - - //fill in scaling_list_dc_coef_minus8 + int coef_num = std::min(64, (1 << (4 + (size_id << 1)))); if (!s_data->scaling_list_pred_matrix_id_delta[size_id][matrix_id]) { if (size_id > 1) { s_data->scaling_list_dc_coef_minus8[size_id-2][matrix_id] = 8; @@ -713,12 +418,12 @@ void HEVCVideoParser::SpsData::ParseScalingList(H265ScalingListData * s_data, ui int next_coef = 8; int coef_num = std::min(64, (1 << (4 + (size_id << 1)))); if (size_id > 1) { - s_data->scaling_list_dc_coef_minus8[size_id-2][matrix_id] = Parser::ExpGolomb::ReadSe(nalu, offset); - next_coef = s_data->scaling_list_dc_coef_minus8[size_id-2][matrix_id] + 8; + s_data->scaling_list_dc_coef_minus8[size_id - 2][matrix_id] = Parser::ExpGolomb::ReadSe(nalu, offset); + next_coef = s_data->scaling_list_dc_coef_minus8[size_id - 2][matrix_id] + 8; } for (int i = 0; i < coef_num; i++) { s_data->scaling_list_delta_coef = Parser::ExpGolomb::ReadSe(nalu, offset); - next_coef = (next_coef + s_data->scaling_list_delta_coef +256)%256; + next_coef = (next_coef + s_data->scaling_list_delta_coef +256) % 256; s_data->scaling_list[size_id][matrix_id][i] = next_coef; } } @@ -726,7 +431,7 @@ void HEVCVideoParser::SpsData::ParseScalingList(H265ScalingListData * s_data, ui } } -void HEVCVideoParser::SpsData::ParseShortTermRefPicSet(H265ShortTermRPS *rps, int32_t st_rps_idx, uint32_t number_short_term_ref_pic_sets, H265ShortTermRPS rps_ref[], uint8_t *nalu, size_t /*size*/, size_t& offset) { +void HEVCVideoParser::ParseShortTermRefPicSet(H265ShortTermRPS *rps, int32_t st_rps_idx, uint32_t number_short_term_ref_pic_sets, H265ShortTermRPS rps_ref[], uint8_t *nalu, size_t /*size*/, size_t& offset) { uint32_t inter_rps_pred = 0; uint32_t delta_idx_minus1 = 0; int32_t i = 0; @@ -775,7 +480,6 @@ void HEVCVideoParser::SpsData::ParseShortTermRefPicSet(H265ShortTermRPS *rps, in } rps->num_negative_pics = i; - for (int j = rps_ref[ref_idx].num_negative_pics - 1; j >= 0; j--) { int32_t delta_poc = delta_rps + rps_ref[ref_idx].delta_poc[j]; //positive delta_poc from ref_rps if (delta_poc > 0 && use_delta_flag[j]) { @@ -790,7 +494,7 @@ void HEVCVideoParser::SpsData::ParseShortTermRefPicSet(H265ShortTermRPS *rps, in for (int j = 0; j < rps_ref[ref_idx].num_positive_pics; j++) { int32_t delta_poc = delta_rps + rps_ref[ref_idx].delta_poc[rps_ref[ref_idx].num_negative_pics+j]; if (delta_poc > 0 && use_delta_flag[rps_ref[ref_idx].num_negative_pics+j]) { - rps->delta_poc[i]=delta_poc; + rps->delta_poc[i] = delta_poc; rps->used_by_curr_pic[i++] = used_by_curr_pic_flag[rps_ref[ref_idx].num_negative_pics+j]; } } @@ -824,13 +528,13 @@ void HEVCVideoParser::SpsData::ParseShortTermRefPicSet(H265ShortTermRPS *rps, in } } -void HEVCVideoParser::SpsData::ParseVUI(H265VuiParameters *vui, uint32_t max_num_sub_layers_minus1, uint8_t *nalu, size_t size, size_t &offset) { +void HEVCVideoParser::ParseVui(H265VuiParameters *vui, uint32_t max_num_sub_layers_minus1, uint8_t *nalu, size_t size, size_t &offset) { vui->aspect_ratio_info_present_flag = Parser::GetBit(nalu, offset); if (vui->aspect_ratio_info_present_flag) { - vui->aspect_ratio_idc = Parser::ReadBits(nalu, offset,8); + vui->aspect_ratio_idc = Parser::ReadBits(nalu, offset, 8); if (vui->aspect_ratio_idc == 255) { - vui->sar_width = Parser::ReadBits(nalu, offset,16); - vui->sar_height = Parser::ReadBits(nalu, offset,16); + vui->sar_width = Parser::ReadBits(nalu, offset, 16); + vui->sar_height = Parser::ReadBits(nalu, offset, 16); } } vui->overscan_info_present_flag = Parser::GetBit(nalu, offset); @@ -839,13 +543,13 @@ void HEVCVideoParser::SpsData::ParseVUI(H265VuiParameters *vui, uint32_t max_num } vui->video_signal_type_present_flag = Parser::GetBit(nalu, offset); if (vui->video_signal_type_present_flag) { - vui->video_format = Parser::ReadBits(nalu, offset,3); + vui->video_format = Parser::ReadBits(nalu, offset, 3); vui->video_full_range_flag = Parser::GetBit(nalu, offset); vui->colour_description_present_flag = Parser::GetBit(nalu, offset); if (vui->colour_description_present_flag) { - vui->colour_primaries = Parser::ReadBits(nalu, offset,8); - vui->transfer_characteristics = Parser::ReadBits(nalu, offset,8); - vui->matrix_coeffs = Parser::ReadBits(nalu, offset,8); + vui->colour_primaries = Parser::ReadBits(nalu, offset, 8); + vui->transfer_characteristics = Parser::ReadBits(nalu, offset, 8); + vui->matrix_coeffs = Parser::ReadBits(nalu, offset, 8); } } vui->chroma_loc_info_present_flag = Parser::GetBit(nalu, offset); @@ -865,8 +569,8 @@ void HEVCVideoParser::SpsData::ParseVUI(H265VuiParameters *vui, uint32_t max_num } vui->vui_timing_info_present_flag = Parser::GetBit(nalu, offset); if (vui->vui_timing_info_present_flag) { - vui->vui_num_units_in_tick = Parser::ReadBits(nalu, offset,32); - vui->vui_time_scale = Parser::ReadBits(nalu, offset,32); + vui->vui_num_units_in_tick = Parser::ReadBits(nalu, offset, 32); + vui->vui_time_scale = Parser::ReadBits(nalu, offset, 32); vui->vui_poc_proportional_to_timing_flag = Parser::GetBit(nalu, offset); if (vui->vui_poc_proportional_to_timing_flag) { vui->vui_num_ticks_poc_diff_one_minus1 = Parser::ExpGolomb::ReadUe(nalu, offset); @@ -889,93 +593,373 @@ void HEVCVideoParser::SpsData::ParseVUI(H265VuiParameters *vui, uint32_t max_num } } -bool HEVCVideoParser::AccessUnitSigns::Parse(uint8_t *nalu, size_t /*size*/, std::map&/*sps_map*/, std::map& /*pps_map*/) { - size_t offset = 16; // 2 bytes NALU header - b_new_picture = Parser::GetBit(nalu, offset); - return true; -} +void HEVCVideoParser::ParseVps(uint8_t *nalu, size_t size) { + size_t offset = 0; // current bit offset + uint32_t vps_id = Parser::ReadBits(nalu, offset, 4); + memset(&m_vps_[vps_id], 0, sizeof(m_vps_[vps_id])); -bool HEVCVideoParser::AccessUnitSigns::IsNewPicture() { - return b_new_picture; -} + m_vps_[vps_id].vps_video_parameter_set_id = vps_id; + m_vps_[vps_id].vps_reserved_three_2bits = Parser::ReadBits(nalu, offset, 2); + m_vps_[vps_id].vps_max_layers_minus1 = Parser::ReadBits(nalu, offset, 6); + m_vps_[vps_id].vps_max_sub_layers_minus1 = Parser::ReadBits(nalu, offset, 3); + m_vps_[vps_id].vps_temporal_id_nesting_flag = Parser::GetBit(nalu, offset); + m_vps_[vps_id].vps_reserved_0xffff_16bits = Parser::ReadBits(nalu, offset, 16); + ParsePtl(&m_vps_[vps_id].profile_tier_level, true, m_vps_[vps_id].vps_max_sub_layers_minus1, nalu, size, offset); + m_vps_[vps_id].vps_sub_layer_ordering_info_present_flag = Parser::GetBit(nalu, offset); -void HEVCVideoParser::ExtraDataBuilder::AddSPS(uint8_t *sps, size_t size) { - m_sps_count_++; - size_t pos = m_sps_.GetSize(); - uint16_t spsSize = size & max_sps_size_; - m_sps_.SetSize(pos + spsSize +2); - uint8_t *data = m_sps_.GetData() + pos; - *data++ = Parser::GetLowByte(spsSize); - *data++ = Parser::GetHiByte(spsSize); - memcpy(data , sps, (size_t)spsSize); -} - -void HEVCVideoParser::ExtraDataBuilder::AddPPS(uint8_t *pps, size_t size) { - m_pps_count_++; - size_t pos = m_pps_.GetSize(); - uint16_t ppsSize = size & max_pps_size_; - m_pps_.SetSize(pos + ppsSize + 2); - uint8_t *data = m_pps_.GetData() + pos; - *data++ = Parser::GetLowByte(ppsSize); - *data++ = Parser::GetHiByte(ppsSize); - memcpy(data , pps, (size_t)ppsSize); -} - -bool HEVCVideoParser::ExtraDataBuilder::GetExtradata(ByteArray &extradata) { - if(m_sps_.GetSize() == 0 || m_pps_ .GetSize() == 0) { - return false; + for (int i = 0; i <= m_vps_[vps_id].vps_max_sub_layers_minus1; i++) { + if (m_vps_[vps_id].vps_sub_layer_ordering_info_present_flag || (i == 0)) { + m_vps_[vps_id].vps_max_dec_pic_buffering_minus1[i] = Parser::ExpGolomb::ReadUe(nalu, offset); + m_vps_[vps_id].vps_max_num_reorder_pics[i] = Parser::ExpGolomb::ReadUe(nalu, offset); + m_vps_[vps_id].vps_max_latency_increase_plus1[i] = Parser::ExpGolomb::ReadUe(nalu, offset); + } + else { + m_vps_[vps_id].vps_max_dec_pic_buffering_minus1[i] = m_vps_[vps_id].vps_max_dec_pic_buffering_minus1[0]; + m_vps_[vps_id].vps_max_num_reorder_pics[i] = m_vps_[vps_id].vps_max_num_reorder_pics[0]; + m_vps_[vps_id].vps_max_latency_increase_plus1[i] = m_vps_[vps_id].vps_max_latency_increase_plus1[0]; + } } - if (m_sps_count_ > 0x1F) { - return false; + m_vps_[vps_id].vps_max_layer_id = Parser::ReadBits(nalu, offset, 6); + m_vps_[vps_id].vps_num_layer_sets_minus1 = Parser::ExpGolomb::ReadUe(nalu, offset); + for (int i = 1; i <= m_vps_[vps_id].vps_num_layer_sets_minus1; i++) { + for (int j = 0; j <= m_vps_[vps_id].vps_max_layer_id; j++) { + m_vps_[vps_id].layer_id_included_flag[i][j] = Parser::GetBit(nalu, offset); + } } - if (m_sps_.GetSize() < min_sps_size_) { - return false; + m_vps_[vps_id].vps_timing_info_present_flag = Parser::GetBit(nalu, offset); + if(m_vps_[vps_id].vps_timing_info_present_flag) { + m_vps_[vps_id].vps_num_units_in_tick = Parser::ReadBits(nalu, offset, 32); + m_vps_[vps_id].vps_time_scale = Parser::ReadBits(nalu, offset, 32); + m_vps_[vps_id].vps_poc_proportional_to_timing_flag = Parser::GetBit(nalu, offset); + if(m_vps_[vps_id].vps_poc_proportional_to_timing_flag) { + m_vps_[vps_id].vps_num_ticks_poc_diff_one_minus1 = Parser::ExpGolomb::ReadUe(nalu, offset); + } + m_vps_[vps_id].vps_num_hrd_parameters = Parser::ExpGolomb::ReadUe(nalu, offset); + for (int i = 0; i 0) { + m_vps_[vps_id].cprms_present_flag[i] = Parser::GetBit(nalu, offset); + } + //parse HRD parameters + ParseHrdParameters(&m_vps_[vps_id].hrd_parameters[i], m_vps_[vps_id].cprms_present_flag[i], m_vps_[vps_id].vps_max_sub_layers_minus1, nalu, size, offset); + } } - extradata.SetSize( - 21 + // reserved - 1 + // length size - 1 + // array size - 3 + // SPS type + SPS count (2) - m_sps_.GetSize() + - 3 + // PPS type + PPS count (2) - m_pps_.GetSize() - ); + m_vps_[vps_id].vps_extension_flag = Parser::GetBit(nalu, offset); +} - uint8_t *data = extradata.GetData(); +void HEVCVideoParser::ParseSps(uint8_t *nalu, size_t size) { + size_t offset = 0; + m_active_vps_ = Parser::ReadBits(nalu, offset, 4); + uint32_t max_sub_layer_minus1 = Parser::ReadBits(nalu, offset, 3); + uint32_t sps_temporal_id_nesting_flag = Parser::GetBit(nalu, offset); + H265ProfileTierLevel ptl; + memset (&ptl, 0, sizeof(ptl)); + ParsePtl(&ptl, true, max_sub_layer_minus1, nalu, size, offset); + uint32_t sps_id = Parser::ExpGolomb::ReadUe(nalu, offset); + memset(&m_sps_[sps_id], 0, sizeof(m_sps_[sps_id])); + m_sps_[sps_id].sps_video_parameter_set_id = m_active_vps_; + m_sps_[sps_id].sps_max_sub_layers_minus1 = max_sub_layer_minus1; + m_sps_[sps_id].sps_temporal_id_nesting_flag = sps_temporal_id_nesting_flag; + memcpy (&m_sps_[sps_id].profile_tier_level, &ptl, sizeof(ptl)); + m_sps_[sps_id].sps_seq_parameter_set_id = sps_id; + m_sps_[sps_id].chroma_format_idc = Parser::ExpGolomb::ReadUe(nalu, offset); + if (m_sps_[sps_id].chroma_format_idc == 3) { + m_sps_[sps_id].separate_colour_plane_flag = Parser::GetBit(nalu, offset); + m_sps_[sps_id].pic_width_in_luma_samples = Parser::ExpGolomb::ReadUe(nalu, offset); + m_sps_[sps_id].conf_win_right_offset = Parser::ExpGolomb::ReadUe(nalu, offset); + m_sps_[sps_id].conf_win_top_offset = Parser::ExpGolomb::ReadUe(nalu, offset); + m_sps_[sps_id].conf_win_bottom_offset = Parser::ExpGolomb::ReadUe(nalu, offset); + } + m_sps_[sps_id].bit_depth_luma_minus8 = Parser::ExpGolomb::ReadUe(nalu, offset); + m_sps_[sps_id].bit_depth_chroma_minus8 = Parser::ExpGolomb::ReadUe(nalu, offset); + m_sps_[sps_id].log2_max_pic_order_cnt_lsb_minus4 = Parser::ExpGolomb::ReadUe(nalu, offset); + m_sps_[sps_id].sps_sub_layer_ordering_info_present_flag = Parser::GetBit(nalu, offset); + for (int i = 0; i <= m_sps_[sps_id].sps_max_sub_layers_minus1; i++) { + if (m_sps_[sps_id].sps_sub_layer_ordering_info_present_flag || (i == 0)) { + m_sps_[sps_id].sps_max_dec_pic_buffering_minus1[i] = Parser::ExpGolomb::ReadUe(nalu, offset); + m_sps_[sps_id].sps_max_num_reorder_pics[i] = Parser::ExpGolomb::ReadUe(nalu, offset); + m_sps_[sps_id].sps_max_latency_increase_plus1[i] = Parser::ExpGolomb::ReadUe(nalu, offset); + } + else { + m_sps_[sps_id].sps_max_dec_pic_buffering_minus1[i] = m_sps_[sps_id].sps_max_dec_pic_buffering_minus1[0]; + m_sps_[sps_id].sps_max_num_reorder_pics[i] = m_sps_[sps_id].sps_max_num_reorder_pics[0]; + m_sps_[sps_id].sps_max_latency_increase_plus1[i] = m_sps_[sps_id].sps_max_latency_increase_plus1[0]; + } + } + m_sps_[sps_id].log2_min_luma_coding_block_size_minus3 = Parser::ExpGolomb::ReadUe(nalu, offset); + + int log2_min_cu_size = m_sps_[sps_id].log2_min_luma_coding_block_size_minus3 + 3; + + m_sps_[sps_id].log2_diff_max_min_luma_coding_block_size = Parser::ExpGolomb::ReadUe(nalu, offset); + + int max_cu_depth_delta = m_sps_[sps_id].log2_diff_max_min_luma_coding_block_size; + m_sps_[sps_id].max_cu_width = ( 1<<(log2_min_cu_size + max_cu_depth_delta)); + m_sps_[sps_id].max_cu_height = ( 1<<(log2_min_cu_size + max_cu_depth_delta)); + + m_sps_[sps_id].log2_min_transform_block_size_minus2 = Parser::ExpGolomb::ReadUe(nalu, offset); + + uint32_t quadtree_tu_log2_min_size = m_sps_[sps_id].log2_min_transform_block_size_minus2 + 2; + int add_cu_depth = max (0, log2_min_cu_size - (int)quadtree_tu_log2_min_size); + m_sps_[sps_id].max_cu_depth = (max_cu_depth_delta + add_cu_depth); + + m_sps_[sps_id].log2_diff_max_min_transform_block_size = Parser::ExpGolomb::ReadUe(nalu, offset); + m_sps_[sps_id].max_transform_hierarchy_depth_inter = Parser::ExpGolomb::ReadUe(nalu, offset); + m_sps_[sps_id].max_transform_hierarchy_depth_intra = Parser::ExpGolomb::ReadUe(nalu, offset); + m_sps_[sps_id].scaling_list_enabled_flag = Parser::GetBit(nalu, offset); + if (m_sps_[sps_id].scaling_list_enabled_flag) { + m_sps_[sps_id].sps_scaling_list_data_present_flag = Parser::GetBit(nalu, offset); + if (m_sps_[sps_id].sps_scaling_list_data_present_flag) { + ParseScalingList(&m_sps_[sps_id].scaling_list_data, nalu, size, offset); + } + } + m_sps_[sps_id].amp_enabled_flag = Parser::GetBit(nalu, offset); + m_sps_[sps_id].sample_adaptive_offset_enabled_flag = Parser::GetBit(nalu, offset); + m_sps_[sps_id].pcm_enabled_flag = Parser::GetBit(nalu, offset); + if (m_sps_[sps_id].pcm_enabled_flag) { + m_sps_[sps_id].pcm_sample_bit_depth_luma_minus1 = Parser::ReadBits(nalu, offset, 4); + m_sps_[sps_id].pcm_sample_bit_depth_chroma_minus1 = Parser::ReadBits(nalu, offset, 4); + m_sps_[sps_id].log2_min_pcm_luma_coding_block_size_minus3 = Parser::ExpGolomb::ReadUe(nalu, offset); + m_sps_[sps_id].log2_diff_max_min_pcm_luma_coding_block_size = Parser::ExpGolomb::ReadUe(nalu, offset); + m_sps_[sps_id].pcm_loop_filter_disabled_flag = Parser::GetBit(nalu, offset); + } + m_sps_[sps_id].num_short_term_ref_pic_sets = Parser::ExpGolomb::ReadUe(nalu, offset); + for (int i = 0; i(2); // reserved(11100000) + numOfSequenceParameterSets - - *data++ = NAL_UNIT_SPS; - *data++ = Parser::GetLowByte(static_cast(m_sps_count_)); - *data++ = Parser::GetHiByte(static_cast(m_sps_count_)); - - memcpy(data, m_sps_.GetData(), m_sps_.GetSize()); - data += m_sps_.GetSize(); - - *data++ = NAL_UNIT_PPS; - *data++ = Parser::GetLowByte(static_cast(m_pps_count_)); - *data++ = Parser::GetHiByte(static_cast(m_pps_count_)); - memcpy(data, m_pps_.GetData(), m_pps_.GetSize()); - data += m_pps_.GetSize(); - return true; } -bool HEVCVideoParser::CheckDataStreamEof(int n_video_bytes) { - if (n_video_bytes <= 0) { - m_eof_ = true; - return true; +bool HEVCVideoParser::ParseSliceHeader(uint32_t nal_unit_type, uint8_t *nalu, size_t size) { + size_t offset = 0; + SliceHeaderData temp_sh; + memset(&temp_sh, 0, sizeof(temp_sh)); + + temp_sh.first_slice_segment_in_pic_flag = m_sh_->first_slice_segment_in_pic_flag = Parser::GetBit(nalu, offset); + if (nal_unit_type == NAL_UNIT_CODED_SLICE_IDR_W_RADL + || nal_unit_type == NAL_UNIT_CODED_SLICE_IDR_N_LP + || nal_unit_type == NAL_UNIT_CODED_SLICE_BLA_N_LP + || nal_unit_type == NAL_UNIT_CODED_SLICE_BLA_W_RADL + || nal_unit_type == NAL_UNIT_CODED_SLICE_BLA_W_LP + || nal_unit_type == NAL_UNIT_CODED_SLICE_CRA + ) { + temp_sh.no_output_of_prior_pics_flag = m_sh_->no_output_of_prior_pics_flag = Parser::GetBit(nalu, offset); + } + + m_active_pps_ = Parser::ExpGolomb::ReadUe(nalu, offset); + temp_sh.slice_pic_parameter_set_id = m_sh_->slice_pic_parameter_set_id = m_active_pps_; + if (!m_sh_->first_slice_segment_in_pic_flag) { + if (m_pps_[m_active_pps_].dependent_slice_segments_enabled_flag) { + temp_sh.dependent_slice_segment_flag = m_sh_->dependent_slice_segment_flag = Parser::GetBit(nalu, offset); + } + int num_ctus = 0; + int max_parts = (1 << (m_sps_[m_active_sps_].max_cu_depth << 1)); + int bits_slice_segment_address = 0; + while(num_ctus > (1 << bits_slice_segment_address)) { + bits_slice_segment_address++; + } + temp_sh.slice_segment_address = m_sh_->slice_segment_address = Parser::ReadBits(nalu, offset, bits_slice_segment_address); + } + if (!m_sh_->dependent_slice_segment_flag) { + for (int i = 0; i < m_pps_[m_active_pps_].num_extra_slice_header_bits; i++) { + m_sh_->slice_reserved_flag[i] = Parser::GetBit(nalu, offset); + } + m_sh_->slice_type = Parser::ExpGolomb::ReadUe(nalu, offset); + if (m_pps_[m_active_pps_].output_flag_present_flag) { + m_sh_->pic_output_flag = Parser::GetBit(nalu, offset); + } + if (m_sps_[m_active_sps_].separate_colour_plane_flag) { + m_sh_->colour_plane_id = Parser::ReadBits(nalu, offset, 2); + } + if (nal_unit_type == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nal_unit_type == NAL_UNIT_CODED_SLICE_IDR_N_LP) { + m_slice_->curr_poc = 0; + m_slice_->prev_poc = m_slice_->curr_poc; + m_slice_->curr_poc_lsb = 0; + m_slice_->curr_poc_msb = 0; + m_slice_->prev_poc_lsb = m_slice_->curr_poc_lsb; + m_slice_->prev_poc_msb = m_slice_->curr_poc_msb; + } + else { + //length of slice_pic_order_cnt_lsb is log2_max_pic_order_cnt_lsb_minus4 + 4 bits. + m_sh_->slice_pic_order_cnt_lsb = Parser::ReadBits(nalu, offset, (m_sps_[m_active_sps_].log2_max_pic_order_cnt_lsb_minus4 + 4)); + + //get POC + m_slice_->curr_poc_lsb = m_sh_->slice_pic_order_cnt_lsb; + m_slice_->max_poc_lsb = 1 << (m_sps_[m_active_sps_].log2_max_pic_order_cnt_lsb_minus4 + 4); + + if (nal_unit_type >= NAL_UNIT_CODED_SLICE_BLA_W_LP && nal_unit_type < NAL_UNIT_CODED_SLICE_CRA) { + m_slice_->curr_poc_msb = 0; + } + else { + if ((m_slice_->curr_poc_lsb < m_slice_->prev_poc_lsb) && ((m_slice_->prev_poc_lsb - m_slice_->curr_poc_lsb) >= (m_slice_->max_poc_lsb / 2))) + m_slice_->curr_poc_msb = m_slice_->prev_poc_msb + m_slice_->max_poc_lsb; + else if ((m_slice_->curr_poc_lsb > m_slice_->prev_poc_lsb) && ((m_slice_->curr_poc_lsb - m_slice_->prev_poc_lsb) > (m_slice_->max_poc_lsb / 2))) + m_slice_->curr_poc_msb = m_slice_->prev_poc_msb - m_slice_->max_poc_lsb; + else + m_slice_->curr_poc_msb = m_slice_->prev_poc_msb; + } + + m_slice_->curr_poc = m_slice_->curr_poc_lsb + m_slice_->curr_poc_msb; + m_slice_->prev_poc = m_slice_->curr_poc; + m_slice_->prev_poc_lsb = m_slice_->curr_poc_lsb; + m_slice_->prev_poc_msb = m_slice_->curr_poc_msb; + + m_sh_->short_term_ref_pic_set_sps_flag = Parser::GetBit(nalu, offset); + int32_t pos = offset; + if (!m_sh_->short_term_ref_pic_set_sps_flag) { + ParseShortTermRefPicSet(&m_sh_->st_rps, m_sps_[m_active_sps_].num_short_term_ref_pic_sets, m_sps_[m_active_sps_].num_short_term_ref_pic_sets, m_sps_[m_active_sps_].st_rps, nalu, size, offset); + } + else if (m_sps_[m_active_sps_].num_short_term_ref_pic_sets > 1) { + int num_bits = 0; + while ((1 << num_bits) < m_sps_[m_active_sps_].num_short_term_ref_pic_sets) { + num_bits++; + } + if (num_bits > 0) { + m_sh_->short_term_ref_pic_set_idx = Parser::ReadBits(nalu, offset, num_bits); + } + } + m_sh_->short_term_ref_pic_set_size = offset - pos; + + if (m_sps_[m_active_sps_].long_term_ref_pics_present_flag) { + if (m_sps_[m_active_sps_].num_long_term_ref_pics_sps > 0) { + m_sh_->num_long_term_sps = Parser::ExpGolomb::ReadUe(nalu, offset); + } + m_sh_->num_long_term_pics = Parser::ExpGolomb::ReadUe(nalu, offset); + + int bits_for_ltrp_in_sps = 0; + while (m_sps_[m_active_sps_].num_long_term_ref_pics_sps > (1 << bits_for_ltrp_in_sps)) { + bits_for_ltrp_in_sps++; + } + m_sh_->lt_rps.num_of_pics = m_sh_->num_long_term_sps + m_sh_->num_long_term_pics; + for (int i = 0; i < (m_sh_->num_long_term_sps + m_sh_->num_long_term_pics); i++) { + if (i < m_sh_->num_long_term_sps) { + if (m_sps_[m_active_sps_].num_long_term_ref_pics_sps > 1) { + if( bits_for_ltrp_in_sps > 0) { + m_sh_->lt_idx_sps[i] = Parser::ReadBits(nalu, offset, bits_for_ltrp_in_sps); + m_sh_->lt_rps.pocs[i] = m_sps_[m_active_sps_].lt_rps.pocs[m_sh_->lt_idx_sps[i]]; + m_sh_->lt_rps.used_by_curr_pic[i] = m_sps_[m_active_sps_].lt_rps.used_by_curr_pic[m_sh_->lt_idx_sps[i]]; + } + } + } + else { + m_sh_->poc_lsb_lt[i] = Parser::ReadBits(nalu, offset, (m_sps_[m_active_sps_].log2_max_pic_order_cnt_lsb_minus4 + 4)); + m_sh_->used_by_curr_pic_lt_flag[i] = Parser::GetBit(nalu, offset); + m_sh_->lt_rps.pocs[i] = m_sh_->poc_lsb_lt[i]; + m_sh_->lt_rps.used_by_curr_pic[i] = m_sh_->used_by_curr_pic_lt_flag[i]; + } + m_sh_->delta_poc_msb_present_flag[i] = Parser::GetBit(nalu, offset); + if (m_sh_->delta_poc_msb_present_flag[i]) { + m_sh_->delta_poc_msb_cycle_lt[i] = Parser::ExpGolomb::ReadUe(nalu, offset); + } + } + } + if (m_sps_[m_active_sps_].sps_temporal_mvp_enabled_flag) { + m_sh_->slice_temporal_mvp_enabled_flag = Parser::GetBit(nalu, offset); + } + } + memcpy(m_sh_copy_, m_sh_, sizeof(*m_sh_)); + } + else { + //dependant slice + memcpy(m_sh_, m_sh_copy_, sizeof(*m_sh_copy_)); + m_sh_->first_slice_segment_in_pic_flag = temp_sh.first_slice_segment_in_pic_flag; + m_sh_->no_output_of_prior_pics_flag = temp_sh.no_output_of_prior_pics_flag; + m_sh_->slice_pic_parameter_set_id = temp_sh.slice_pic_parameter_set_id; + m_sh_->dependent_slice_segment_flag = temp_sh.dependent_slice_segment_flag; + m_sh_->slice_segment_address = temp_sh.slice_segment_address; } return false; } -#define ZEROBYTES_SHORTSTARTCODE 2 //indicates the number of zero bytes in the short start-code prefix - size_t HEVCVideoParser::EBSPtoRBSP(uint8_t *streamBuffer,size_t begin_bytepos, size_t end_bytepos) { int count = 0; if (end_bytepos < begin_bytepos) { @@ -1018,97 +1002,6 @@ size_t HEVCVideoParser::EBSPtoRBSP(uint8_t *streamBuffer,size_t begin_bytepos, s return end_bytepos - begin_bytepos + reduce_count; } -//data stream functions -ParserResult HEVCVideoParser::Close() { - m_pmemory_ = NULL, - m_memory_size_ = 0, - m_allocated_size_ = 0, - m_pos_ = 0; - return PARSER_OK; -} - -ParserResult HEVCVideoParser::Realloc(size_t size) { - if (size > m_memory_size_) { - uint8_t* p_new_memory = new uint8_t [size]; - if (p_new_memory == NULL) { - return PARSER_OUT_OF_MEMORY; - } - m_allocated_size_ = size; - if (m_pmemory_ != NULL) { - delete m_pmemory_; - } - m_pmemory_ = p_new_memory; - } - m_memory_size_ = size; - return PARSER_OK; -} - -ParserResult HEVCVideoParser::Read(void* p_data, size_t size, size_t* p_read) { - if (p_data == NULL) { - return PARSER_INVALID_POINTER; - } - if (m_pmemory_ == NULL) { - return PARSER_NOT_INITIALIZED; - } - size_t to_read = std::min(size, m_memory_size_ - m_pos_); - memcpy(p_data, m_pmemory_ + m_pos_, to_read); - m_pos_ += to_read; - if(p_read != NULL) { - *p_read = to_read; - } - return PARSER_OK; -} - -ParserResult HEVCVideoParser::Write(const void* p_data, size_t size, size_t* p_written) { - if (p_data == NULL) { - return PARSER_INVALID_POINTER; - } - m_pos_ = 0; - if (Realloc(size)) { - return PARSER_STREAM_NOT_ALLOCATED; - } - - size_t to_write = std::min(size, m_memory_size_); - memcpy(m_pmemory_, p_data, to_write); - - if(p_written != NULL) { - *p_written = to_write; - } - return PARSER_OK; -} - -ParserResult HEVCVideoParser::Seek(ParserSeekOrigin e_origin, int64_t i_position, int64_t* p_new_position) { - switch(e_origin) { - case PARSER_SEEK_BEGIN: - m_pos_ = (size_t)i_position; - break; - - case PARSER_SEEK_CURRENT: - m_pos_ += (size_t)i_position; - break; - - case PARSER_SEEK_END: - m_pos_ = m_memory_size_ - (size_t)i_position; - break; - } - - if(m_pos_ > m_memory_size_) { - m_pos_ = m_memory_size_; - } - if(p_new_position != NULL) { - *p_new_position = m_pos_; - } - return PARSER_OK; -} - -ParserResult HEVCVideoParser::GetSize(int64_t* p_size) { - if (p_size != NULL) { - return PARSER_INVALID_POINTER; - } - *p_size = m_memory_size_; - return PARSER_OK; -} - //size_id = 0 int scaling_list_default_0 [1][6][16] = {{{16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}, {16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}, diff --git a/src/parser/hevc_parser.h b/src/parser/hevc_parser.h index 773bb04a65..b14364fa82 100644 --- a/src/parser/hevc_parser.h +++ b/src/parser/hevc_parser.h @@ -22,160 +22,49 @@ THE SOFTWARE. #pragma once #include "roc_video_parser.h" -#include "parser_buffer.h" #include #include #include -#define PARSER_SECOND 10000000L // 1 second in 100 nanoseconds -#define DATA_STREAM_SIZE 10*1024 // allocating buffer to hold video stream -#define INIT_ARRAY_SIZE 1024 -#define ARRAY_MAX_SIZE (1LL << 60LL) // extremely large maximum size +#define ZEROBYTES_SHORTSTARTCODE 2 //indicates the number of zero bytes in the short start-code prefix -class ByteArray { -protected: - uint8_t *m_pdata_; - size_t m_size_; - size_t m_max_size_; -public: - ByteArray() : m_pdata_(0), m_size_(0), m_max_size_(0) {} - ByteArray(const ByteArray &other) : m_pdata_(0), m_size_(0), m_max_size_(0) { - *this = other; - } - ByteArray(size_t num) : m_pdata_(0), m_size_(0), m_max_size_(0) { - SetSize(num); - } - virtual ~ByteArray() { - if (m_pdata_ != 0) { - delete[] m_pdata_; - } - } - void SetSize(size_t num) { - if (num == m_size_) { - return; - } - if (num < m_size_) { - memset(m_pdata_ + num, 0, m_max_size_ - num); - } - else if (num > m_max_size_) { - // This is done to prevent the following error from surfacing - // for the p_new_data allocation on some compilers: - // -Werror=alloc-size-larger-than= - size_t new_size = (num / INIT_ARRAY_SIZE) * INIT_ARRAY_SIZE + INIT_ARRAY_SIZE; - if (new_size > ARRAY_MAX_SIZE) { - return; - } - m_max_size_ = new_size; +//size_id = 0 +extern int scaling_list_default_0[1][6][16]; +//size_id = 1, 2 +extern int scaling_list_default_1_2[2][6][64]; +//size_id = 3 +extern int scaling_list_default_3[1][2][64]; - uint8_t *p_new_data = new uint8_t[m_max_size_]; - memset(p_new_data, 0, m_max_size_); - if (m_pdata_ != NULL) { - memcpy(p_new_data, m_pdata_, m_size_); - delete[] m_pdata_; - } - m_pdata_ = p_new_data; - } - m_size_ = num; - } - void Copy(const ByteArray &old) { - if (m_max_size_ < old.m_size_) { - m_max_size_ = old.m_max_size_; - if (m_pdata_ != NULL) { - delete[] m_pdata_; - } - m_pdata_ = new uint8_t[m_max_size_]; - memset(m_pdata_, 0, m_max_size_); - } - memcpy(m_pdata_, old.m_pdata_, old.m_size_); - m_size_ = old.m_size_; - } - uint8_t operator[] (size_t iPos) const { - return m_pdata_[iPos]; - } - uint8_t& operator[] (size_t iPos) { - return m_pdata_[iPos]; - } - ByteArray& operator=(const ByteArray &other) { - SetSize(other.GetSize()); - if (GetSize() > 0) { - memcpy(GetData(), other.GetData(), GetSize()); - } - return *this; - } - uint8_t *GetData() const { return m_pdata_; } - size_t GetSize() const { return m_size_; } -}; +#define MAX_VPS_COUNT 16 // 7.3.2.1 +#define MAX_SPS_COUNT 16 // 7.3.2.2.1 +#define MAX_PPS_COUNT 64 // 7.4.3.3.1 +#define RBSP_BUF_SIZE 1024 // enough to parse any parameter sets or slice headers class HEVCVideoParser : public RocVideoParser { public: - /** - * @brief Construct a new HEVCParser object - * + /*! \brief Construct a new HEVCParser object */ HEVCVideoParser(); - /** - * @brief Function to Initialize the parser - * - * @return rocDecStatus + /*! \brief Function to Initialize the parser + * \param [in] p_params Input of RocdecParserParams with codec type to initialize parser. + * \return rocDecStatus Returns success on completion, else error code for failure */ - virtual rocDecStatus Initialize(RocdecParserParams *pParams); - /** - * @brief Function to Parse video data: Typically called from application when a demuxed picture is ready to be parsed - * - * @param pData: Pointer to picture data - * @return rocDecStatus: returns success on completion, else error_code for failure + virtual rocDecStatus Initialize(RocdecParserParams *p_params); + /*! \brief Function to Parse video data: Typically called from application when a demuxed picture is ready to be parsed + * \param [in] p_data Pointer to picture data of type RocdecSourceDataPacket + * @return rocDecStatus Returns success on completion, else error_code for failure */ - virtual rocDecStatus ParseVideoData(RocdecSourceDataPacket *pData); // pure virtual: implemented by derived class + virtual rocDecStatus ParseVideoData(RocdecSourceDataPacket *p_data); - /** - * @brief HEVCParser object destructor - * + /*! \brief HEVCParser object destructor */ virtual ~HEVCVideoParser(); - /** - * @brief Function to set the frames per second - * - * @param fps: Value of fps to set in double - * @return void: returns on completion - */ - void SetFrameRate(double fps); - /** - * @brief Function to get the frames per second - * - * @return double: returns fps in double on completion. - */ - double GetFrameRate() const; - /** - * @brief Function to reinitialize the HEVC parser. Resets the timestamp, packet count and pointer to beginning of stream. - * - * @return ParserResult: returns PARSER_OK on successful completion. - */ - ParserResult ReInit(); - /** - * @brief Function to get the output buffer in type ParserBuffer after parsing the HEVC stream. - * - * @param pp_data: Pointer to pointer to the ParserBuffer data which is also the returned. - * @return ParserResult: returns PARSER_OK on successful completion. - */ - ParserResult QueryOutput(ParserBuffer** pp_data); - /** - * @brief Function to set the parser to beginning of frame and call the SPS and PPS funtions. - * - * @return void: returns on completion - */ - void FindFirstFrameSPSandPPS(); - /** - * @brief Function to check if it's the last frame after dumuxing. - * - * @return bool: returns true if last frame, else false. - */ - bool CheckDataStreamEof(int n_video_bytes); - protected: - // ISO-IEC 14496-15-2004.pdf, page 14, table 1 " NAL unit types in elementary streams. + /*! \brief Enumerator for the NAL Unit types - ISO-IEC 14496-15-2004.pdf, page 14, table 1 " NAL unit types in elementary streams. + */ enum NalUnitType { NAL_UNIT_CODED_SLICE_TRAIL_N = 0, // 0 NAL_UNIT_CODED_SLICE_TRAIL_R, // 1 @@ -252,6 +141,8 @@ protected: NAL_UNIT_INVALID, }; + /*! \brief Structure to hold the NAL Unit Header + */ struct NalUnitHeader { uint32_t forbidden_zero_bit; uint32_t nal_unit_type; @@ -260,6 +151,8 @@ protected: uint32_t num_emu_byte_removed; }; + /*! \brief Enumerator for the scaling list sizes + */ enum H265ScalingListSize { H265_SCALING_LIST_4x4 = 0, H265_SCALING_LIST_8x8, @@ -268,6 +161,8 @@ protected: H265_SCALING_LIST_SIZE_NUM }; + /*! \brief Structure for Profile Tier Levels + */ typedef struct { uint32_t general_profile_space; //u(2) bool general_tier_flag; //u(1) @@ -300,6 +195,8 @@ protected: #define H265_SCALING_LIST_NUM 6 ///< list number for quantization matrix #define H265_SCALING_LIST_MAX_I 64 + /*! \brief Structure for Scaling List Data + */ typedef struct { bool scaling_list_pred_mode_flag[4][6]; //u(1) uint32_t scaling_list_pred_matrix_id_delta[4][6]; //ue(v) @@ -308,6 +205,8 @@ protected: int32_t scaling_list[H265_SCALING_LIST_SIZE_NUM][H265_SCALING_LIST_NUM][H265_SCALING_LIST_MAX_I]; } H265ScalingListData; + /*! \brief Structure for Short Term Reference Picture Set + */ typedef struct { int32_t num_negative_pics; int32_t num_positive_pics; @@ -317,12 +216,16 @@ protected: bool used_by_curr_pic[16]; } H265ShortTermRPS; + /*! \brief Structure for Long Term Reference Picture Set + */ typedef struct { int32_t num_of_pics; - int32_t POCs[32]; + int32_t pocs[32]; bool used_by_curr_pic[32]; } H265LongTermRPS; + /*! \brief Structure for Sub Layer Hypothetical Reference Decoder Parameters + */ typedef struct { //CpbCnt = cpb_cnt_minus1 uint32_t bit_rate_value_minus1[32]; //ue(v) @@ -332,6 +235,8 @@ protected: bool cbr_flag[32]; //u(1) } H265SubLayerHrdParameters; + /*! \brief Structure for Hypothetical Reference Decoder Parameters + */ typedef struct { bool nal_hrd_parameters_present_flag; //u(1) bool vcl_hrd_parameters_present_flag; //u(1) @@ -357,6 +262,8 @@ protected: H265SubLayerHrdParameters sub_layer_hrd_parameters_1[7]; } H265HrdParameters; + /*! \brief Structure for Video Usability Information Parameters + */ typedef struct { bool aspect_ratio_info_present_flag; //u(1) uint32_t aspect_ratio_idc; //u(8) @@ -401,12 +308,54 @@ protected: uint32_t log2_max_mv_length_vertical; //ue(v) } H265VuiParameters; + /*! \brief Structure for Raw Byte Sequence Payload Trialing Bits + */ typedef struct { uint32_t rbsp_stop_one_bit; /* equal to 1 */ uint32_t rbsp_alignment_zero_bit; /* equal to 0 */ } H265RbspTrailingBits; - struct SpsData { + /*! \brief Structure for Video Parameter Set + */ + typedef struct{ + uint32_t vps_video_parameter_set_id; //u(4) + uint32_t vps_reserved_three_2bits; //u(2) + uint32_t vps_max_layers_minus1; //u(6) + uint32_t vps_max_sub_layers_minus1; //u(3) + bool vps_temporal_id_nesting_flag; //u(1) + uint32_t vps_reserved_0xffff_16bits; //u(16) + //profile_tier_level( vps_max_sub_layers_minus1 ) + H265ProfileTierLevel profile_tier_level; + bool vps_sub_layer_ordering_info_present_flag; //u(1) + //vps_max_sub_layers_minus1 max is 6, need to +1 + uint32_t vps_max_dec_pic_buffering_minus1[7]; //ue(v) + uint32_t vps_max_num_reorder_pics[7]; //ue(v) + uint32_t vps_max_latency_increase_plus1[7]; //ue(v) + uint32_t vps_max_layer_id; //u(6) + uint32_t vps_num_layer_sets_minus1; //ue(v) + //vps_num_layer_sets_minus1 max is 1023 (dont +1 since starts from 1) + //vps_max_layer_id max is 62 (+1 since starts from 0 and <= condition) + bool layer_id_included_flag[1023][63]; //u(1) + bool vps_timing_info_present_flag; //u(1) + uint32_t vps_num_units_in_tick; //u(32) + uint32_t vps_time_scale; //u(32) + bool vps_poc_proportional_to_timing_flag; //u(1) + uint32_t vps_num_ticks_poc_diff_one_minus1; //ue(v) + uint32_t vps_num_hrd_parameters; //ue(v) + //vps_num_hrd_parameters max is 1024 + uint32_t hrd_layer_set_idx[1024]; //ue(v) + bool cprms_present_flag[1024]; //u(1) + //hrd_parameters() + H265HrdParameters hrd_parameters[1024]; + bool vps_extension_flag; //u(1) + bool vps_extension_data_flag; //u(1) + //rbsp_trailing_bits() + H265RbspTrailingBits rbsp_trailing_bits; + } VpsData; + + /*! \brief Structure for Sequence Parameter Set + */ + typedef struct { uint32_t sps_video_parameter_set_id; //u(4) uint32_t sps_max_sub_layers_minus1; //u(3) bool sps_temporal_id_nesting_flag; //u(1) @@ -452,8 +401,8 @@ protected: bool pcm_loop_filter_disabled_flag; //u(1) uint32_t num_short_term_ref_pic_sets; //ue(v) //short_term_ref_pic_set(i) max is 64 - H265ShortTermRPS stRPS[64]; - H265LongTermRPS ltRPS; + H265ShortTermRPS st_rps[64]; + H265LongTermRPS lt_rps; //H265_short_term_ref_pic_set_t short_term_ref_pic_set[64]; bool long_term_ref_pics_present_flag; //u(1) uint32_t num_long_term_ref_pics_sps; //ue(v) @@ -469,21 +418,11 @@ protected: bool sps_extension_data_flag; //u(1) //rbsp_trailing_bits( ) H265RbspTrailingBits rbsp_trailing_bits; + } SpsData; - SpsData(void) { - memset(this, 0, sizeof(*this)); - } - - bool Parse(uint8_t *data, size_t size); - void ParsePTL(H265ProfileTierLevel *ptl, bool profile_present_flag, uint32_t max_num_sub_layers_minus1, uint8_t *nalu, size_t size, size_t &offset); - void ParseSubLayerHrdParameters(H265SubLayerHrdParameters *sub_hrd, uint32_t CpbCnt, bool sub_pic_hrd_params_present_flag, uint8_t *nalu, size_t size, size_t &offset); - void ParseHrdParameters(H265HrdParameters *hrd, bool common_inf_present_flag, uint32_t max_num_sub_layers_minus1, uint8_t *nalu, size_t size, size_t &offset); - static void ParseScalingList(H265ScalingListData * s_data, uint8_t *data, size_t size,size_t &offset); - void ParseVUI(H265VuiParameters *vui, uint32_t max_num_sub_layers_minus1, uint8_t *data, size_t size,size_t &offset); - void ParseShortTermRefPicSet(H265ShortTermRPS *rps, int32_t st_rps_idx, uint32_t num_short_term_ref_pic_sets, H265ShortTermRPS rps_ref[], uint8_t *data, size_t size,size_t &offset); - }; - - struct PpsData { + /*! \brief Structure for Picture Parameter Set + */ + typedef struct { uint32_t pps_pic_parameter_set_id; //ue(v) uint32_t pps_seq_parameter_set_id; //ue(v) bool dependent_slice_segments_enabled_flag; //u(1) @@ -532,85 +471,262 @@ protected: bool pps_extension_data_flag; //u(1) //rbsp_trailing_bits( ) H265RbspTrailingBits rbsp_trailing_bits; - PpsData(void) { - memset(this, 0, sizeof(*this)); - } - bool Parse(uint8_t *data, size_t size); - }; + } PpsData; - // See ITU-T Rec. H.264 (04/2013) Advanced video coding for generic audiovisual services, page 28, 91. - struct AccessUnitSigns { - bool b_new_picture; - AccessUnitSigns() : b_new_picture(false) {} - bool Parse(uint8_t *data, size_t size, std::map &sps_map, std::map &pps_map); - bool IsNewPicture(); - }; + /*! \brief Structure for Slice Data + */ + typedef struct { + uint32_t prev_poc; + uint32_t curr_poc; + uint32_t prev_poc_lsb; + uint32_t prev_poc_msb; + uint32_t curr_poc_lsb; + uint32_t curr_poc_msb; + uint32_t max_poc_lsb; + } SliceData; - class ExtraDataBuilder { - public: - ExtraDataBuilder() : m_sps_count_(0), m_pps_count_(0) {} + /*! \brief Structure for Slice Header Data + */ + typedef struct { + bool first_slice_segment_in_pic_flag; //u(1) + bool no_output_of_prior_pics_flag; //u(1) + uint32_t slice_pic_parameter_set_id; //ue(v) + bool dependent_slice_segment_flag; //u(1) + uint32_t slice_segment_address; //u(v) + //num_extra_slice_header_bits is u(3), so max is 7 + bool slice_reserved_flag[7]; //u(1) + uint32_t slice_type; //ue(v) + bool pic_output_flag; //u(1) + uint32_t colour_plane_id; //u(2) + uint32_t slice_pic_order_cnt_lsb; //u(v) + bool short_term_ref_pic_set_sps_flag; //u(1) + //short_term_ref_pic_set( num_short_term_ref_pic_sets ) + uint32_t short_term_ref_pic_set_size; //MM + H265ShortTermRPS st_rps; + uint32_t short_term_ref_pic_set_idx; //u(v) + uint32_t num_long_term_sps; //ue(v) + uint32_t num_long_term_pics; //ue(v) + //num_long_term_sps + num_long_term_pics max is 32 + H265LongTermRPS lt_rps; + uint32_t lt_idx_sps[32]; //u(v) + uint32_t poc_lsb_lt[32]; //u(v) + bool used_by_curr_pic_lt_flag[32]; //u(1) + bool delta_poc_msb_present_flag[32]; //u(1) + uint32_t delta_poc_msb_cycle_lt[32]; //ue(v) + bool slice_temporal_mvp_enabled_flag; //u(1) + bool slice_sao_luma_flag; //u(1) + bool slice_sao_chroma_flag; //u(1) + bool num_ref_idx_active_override_flag; //u(1) + uint32_t num_ref_idx_l0_active_minus1; //ue(v) + uint32_t num_ref_idx_l1_active_minus1; //ue(v) + bool mvd_l1_zero_flag; //u(1) + bool cabac_init_flag; //u(1) + bool collocated_from_l0_flag; //u(1) + uint32_t collocated_ref_idx; //ue(v) + uint32_t five_minus_max_num_merge_cand; //ue(v) + int32_t slice_qp_delta; //se(v) + int32_t slice_cb_qp_offset; //se(v) + int32_t slice_cr_qp_offset; //se(v) + bool deblocking_filter_override_flag; //u(1) + bool slice_deblocking_filter_disabled_flag; //u(1) + int32_t slice_beta_offset_div2; //se(v) + int32_t slice_tc_offset_div2; //se(v) + bool slice_loop_filter_across_slices_enabled_flag; //u(1) + uint32_t num_entry_point_offsets; //ue(v) + uint32_t offset_len_minus1; //ue(v) + //num_entry_point_offsets max is 440 + uint32_t entry_point_offset_minus1[440]; //u(v) + uint32_t slice_segment_header_extension_length; //ue(v) + //slice_segment_header_extension_length max is 256 + uint8_t slice_segment_header_extension_data_byte[256]; //u(8) + } SliceHeaderData; - void AddSPS(uint8_t *sps, size_t size); - void AddPPS(uint8_t *pps, size_t size); - bool GetExtradata(ByteArray &extradata); - - private: - ByteArray m_sps_; - ByteArray m_pps_; - int32_t m_sps_count_; - int32_t m_pps_count_; - }; - - friend struct AccessUnitSigns; - - static const uint8_t nal_unit_length_size_ = 4U; - - static const size_t m_read_size_ = 1024*4; - - static const uint16_t max_sps_size_ = 0xFFFF; - static const uint16_t min_sps_size_ = 5; - static const uint16_t max_pps_size_ = 0xFFFF; - - NalUnitHeader ReadNextNaluUnit(size_t *offset, size_t *nalu, size_t *size); - void FindSPSandPPS(); - static inline NalUnitHeader GetNaluUnitType(uint8_t *nal_unit) { + /*! \brief Inline function to Parse the NAL Unit Header + * + * \param [in] nal_unit A pointer of uint8_t containing the Demuxed output stream + * \return Returns an object of NALUnitHeader + */ + static inline NalUnitHeader ParseNalUnitHeader(uint8_t *nal_unit) { NalUnitHeader nalu_header; nalu_header.num_emu_byte_removed = 0; //read nalu header - nalu_header.forbidden_zero_bit = (uint32_t) ((nal_unit[0] >> 7)&1); - nalu_header.nal_unit_type = (uint32_t) ((nal_unit[0] >> 1)&63); - nalu_header.nuh_layer_id = (uint32_t) (((nal_unit[0]&1) << 6) | ((nal_unit[1] & 248) >> 3)); + nalu_header.forbidden_zero_bit = (uint32_t) ((nal_unit[0] >> 7) & 1); + nalu_header.nal_unit_type = (uint32_t) ((nal_unit[0] >> 1) & 63); + nalu_header.nuh_layer_id = (uint32_t) (((nal_unit[0] & 1) << 6) | ((nal_unit[1] & 248) >> 3)); nalu_header.nuh_temporal_id_plus1 = (uint32_t) (nal_unit[1] & 7); return nalu_header; } - size_t EBSPtoRBSP(uint8_t *streamBuffer,size_t begin_bytepos, size_t end_bytepos); - ByteArray m_read_data_; - ByteArray m_extra_data_; + /*! \brief Function to convert from Encapsulated Byte Sequence Packets to Raw Byte Sequence Payload + * + * \param [inout] stream_buffer A pointer of uint8_t for the converted RBSP buffer. + * \param [in] begin_bytepos Start position in the EBSP buffer to convert + * \param [in] end_bytepos End position in the EBSP buffer to convert, generally it's size. + * \return Returns the size of the converted buffer in size_t + */ + size_t EBSPtoRBSP(uint8_t *stream_buffer, size_t begin_bytepos, size_t end_bytepos); + + // Data members of HEVC class + uint32_t m_active_vps_; + uint32_t m_active_sps_; + uint32_t m_active_pps_; + VpsData* m_vps_; + SpsData* m_sps_; + PpsData* m_pps_; + SliceHeaderData* m_sh_; + SliceHeaderData* m_sh_copy_; + SliceData* m_slice_; + bool b_new_picture_; + int m_packet_count_; + int slice_num_; + int m_rbsp_size_; + uint8_t m_rbsp_buf_[RBSP_BUF_SIZE]; // to store parameter set or slice header RBSP + + // Frame bit stream info + uint8_t *frame_data_buffer_ptr_; // bit stream buffer pointer of the current frame from the demuxer + int frame_data_size_; // bit stream size of the current frame + int curr_byte_offset_; // current parsing byte offset + + // NAL unit info + int start_code_num_; // number of start codes found so far + int curr_start_code_offset_; + int next_start_code_offset_; + int nal_unit_size_; + + /*! \brief Function to parse Video Parameter Set + * \param [in] nalu A pointer of uint8_t for the input stream to be parsed + * \param [in] size Size of the input stream + * \return No return value + */ + void ParseVps(uint8_t *nalu, size_t size); + + /*! \brief Function to parse Sequence Parameter Set + * \param [in] nalu A pointer of uint8_t for the input stream to be parsed + * \param [in] size Size of the input stream + * \return No return value + */ + void ParseSps(uint8_t *nalu, size_t size); + + /*! \brief Function to parse Picture Parameter Set + * \param [in] nalu A pointer of uint8_t for the input stream to be parsed + * \param [in] size Size of the input stream + * \return No return value + */ + void ParsePps(uint8_t *nalu, size_t size); + + /*! \brief Function to parse Profiles, Tiers and Levels + * \param [out] ptl A pointer of H265ProfileTierLevel for the output from teh parsed stream + * \param [in] profile_present_flag Input of bool - 1 specifies profile information is present, else 0 + * \param [in] max_num_sub_layers_minus1 Input of uint32_t - plus 1 specifies the maximum number of temporal sub-layers that may be present + * \param [in] nalu A pointer of uint8_t for the input stream to be parsed + * \param [in] size Size of the input stream + * \param [in] offset Reference to the offset in the input buffer + * \return No return value + */ + void ParsePtl(H265ProfileTierLevel *ptl, bool profile_present_flag, uint32_t max_num_sub_layers_minus1, uint8_t *nalu, size_t size, size_t &offset); - ByteArray m_EBSP_to_RBSP_data_; + /*! \brief Function to parse Sub Layer Hypothetical Reference Decoder Parameters + * \param [out] sub_hrd A pointer of H265SubLayerHrdParameters for the output from teh parsed stream + * \param [in] cpb_cnt Input of uint32_t - specifies the coded picture buffer count in a HRD buffer + * \param [in] sub_pic_hrd_params_present_flag Input of bool - 1 specifies sub layer HRD information is present, else 0 + * \param [in] nalu A pointer of uint8_t for the input stream to be parsed + * \param [in] size Size of the input stream + * \param [in] offset Reference to the offset in the input buffer + * \return No return value + */ + void ParseSubLayerHrdParameters(H265SubLayerHrdParameters *sub_hrd, uint32_t cpb_cnt, bool sub_pic_hrd_params_present_flag, uint8_t *nalu, size_t size, size_t &offset); + + /*! \brief Function to parse Hypothetical Reference Decoder Parameters + * \param [out] hrd A pointer of H265HrdParameters for the output from the parsed stream + * \param [in] common_inf_present_flag Input of bool - 1 specifies HRD information is present, else 0 + * \param [in] max_num_sub_layers_minus1 Input of uint32_t - plus 1 specifies the maximum number of temporal sub-layers that may be present + * \param [in] nalu A pointer of uint8_t for the input stream to be parsed + * \param [in] size Size of the input stream + * \param [in] offset Reference to the offset in the input buffer + * \return No return value + */ + void ParseHrdParameters(H265HrdParameters *hrd, bool common_inf_present_flag, uint32_t max_num_sub_layers_minus1, uint8_t *nalu, size_t size, size_t &offset); + + /*! \brief Function to parse Scaling List + * \param [out] s_data A pointer of H265ScalingListData for the output from the parsed stream + * \param [in] data A pointer of uint8_t for the input stream to be parsed + * \param [in] size Size of the input stream + * \param [in] offset Reference to the offset in the input buffer + * \return No return value + */ + void ParseScalingList(H265ScalingListData * s_data, uint8_t *data, size_t size, size_t &offset); + + /*! \brief Function to parse Video Usability Information + * \param [out] vui A pointer of H265VuiParameters for the output from the parsed stream + * \param [in] max_num_sub_layers_minus1 Input of uint32_t - plus 1 specifies the maximum number of temporal sub-layers that may be present + * \param [in] data A pointer of uint8_t for the input stream to be parsed + * \param [in] size Size of the input stream + * \param [in] offset Reference to the offset in the input buffer + * \return No return value + */ + void ParseVui(H265VuiParameters *vui, uint32_t max_num_sub_layers_minus1, uint8_t *data, size_t size, size_t &offset); + + /*! \brief Function to parse Short Term Reference Picture Set + * \param [out] rps A pointer of H265ShortTermRPS for the output from the parsed stream + * \param [in] st_rps_idx Input of int32_t - specifies the index in the RPS buffer + * \param [in] num_short_term_ref_pic_sets Specifies the count of Short Term RPS in uint32_t + * \param [in] rps_ref A reference of H265ShortTermRPS to the RPS buffer + * \param [in] data A pointer of uint8_t for the input stream to be parsed + * \param [in] size Size of the input stream + * \param [in] offset Reference to the offset in the input buffer + * \return No return value + */ + void ParseShortTermRefPicSet(H265ShortTermRPS *rps, int32_t st_rps_idx, uint32_t num_short_term_ref_pic_sets, H265ShortTermRPS rps_ref[], uint8_t *data, size_t size,size_t &offset); + + /*! \brief Function to parse Slice Header + * \param [in] nal_unit_type Input of uint32_t containing the enumerator value to the NAL Unit Type + * \param [in] nalu A pointer of uint8_t for the input stream to be parsed + * \param [in] size Size of the input stream + * \return True is successful, else false + */ + bool ParseSliceHeader(uint32_t nal_unit_type, uint8_t *nalu, size_t size); - bool m_use_start_codes_; - int64_t m_current_frame_timestamp_; - std::map m_sps_map_; - std::map m_pps_map_; - size_t m_packet_count_; - bool m_eof_; - double m_fps_; - size_t m_max_frames_number_; + /*! \brief Function to parse the data received from the demuxer. + * \param [in] p_stream A pointer of uint8_t for the input stream to be parsed + * \param [in] frame_data_size Size of the input stream + * \return True is successful, else false + */ + bool ParseFrameData(const uint8_t* p_stream, uint32_t frame_data_size); - // data stream info - uint8_t* m_pmemory_; - size_t m_memory_size_; - size_t m_allocated_size_; - size_t m_pos_; + /*! \brief Function to get the NAL Unit data + * \return Returns OK if successful, else error code + */ + int GetNalUnit(); - ParserResult Close(); - ParserResult Read(void* p_data, size_t size, size_t* p_read); - ParserResult Write(const void* p_data, size_t size, size_t* p_written); - ParserResult Seek(ParserSeekOrigin e_origin, int64_t i_position, int64_t* p_new_position); - ParserResult GetSize(int64_t* p_size); - ParserResult Realloc(size_t size); +private: + /*! \brief Function to initialize the HEVC parser members + * \return Returns OK in ParserResult if successful, else error code + */ + ParserResult Init(); + /*! \brief Function to allocate memory for VPS Structure + * \return Returns pointer to the allocated memory for VpsData + */ + VpsData* AllocVps(); + + /*! \brief Function to allocate memory for SPS Structure + * \return Returns pointer to the allocated memory for SpsData + */ + SpsData* AllocSps(); + + /*! \brief Function to allocate memory for PPS Structure + * \return Returns pointer to the allocated memory for PpsData + */ + PpsData* AllocPps(); + + /*! \brief Function to allocate memory for Slice Structure + * \return Returns pointer to the allocated memory for SliceData + */ + SliceData* AllocSlice(); + + /*! \brief Function to allocate memory for Slice Header Structure + * \return Returns pointer to the allocated memory for SliceHeaderData + */ + SliceHeaderData* AllocSliceHeader(); }; \ No newline at end of file diff --git a/src/parser/parser_buffer.cpp b/src/parser/parser_buffer.cpp deleted file mode 100644 index a69a7affe4..0000000000 --- a/src/parser/parser_buffer.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* -Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include "parser_buffer.h" - -ParserBuffer::ParserBuffer() : - m_buffer_(NULL), - m_packet_size_(0), - m_duration_(0), - m_current_timestamp_(0) {} - -ParserBuffer::~ParserBuffer () { - if (m_buffer_) { - delete[] m_buffer_; - } - m_buffer_ = NULL; - m_packet_size_ = 0; - m_duration_ = 0; - m_current_timestamp_ = 0; -} - -int64_t ParserBuffer::GetPts() const { - return m_current_timestamp_; -} - -void ParserBuffer::SetPts(int64_t pts) { - if (pts == m_current_timestamp_) { - return; - } - m_current_timestamp_ = pts; -} - -int64_t ParserBuffer::GetDuration() const { - return m_duration_; -} - -void ParserBuffer::SetDuration(int64_t duration) { - m_duration_ = duration; -} - -bool ParserBuffer::IsReusable() { return PARSER_NOT_IMPLEMENTED; } - -ParserResult ParserBuffer::SetSize(size_t new_size) { - m_packet_size_ = new_size; - return PARSER_OK; -} - -size_t ParserBuffer::GetSize() { - return m_packet_size_; -} - -void* ParserBuffer::GetNative() { - return m_buffer_; -} - -void ParserBuffer::SetNative(size_t size) { - m_buffer_ = new uint8_t[size]; -} - -ParserResult ParserBuffer::AllocBuffer(ParserMemoryType type, size_t size, ParserBuffer** pp_buffer) { - ParserResult res = PARSER_OK; - switch(type) { - case PARSER_MEMORY_HOST: { - ParserBuffer* p_new_buffer = new ParserBuffer; - if (p_new_buffer != NULL) { - p_new_buffer->SetNative(size); - res = p_new_buffer->SetSize(size); - if (res != PARSER_OK) { - return res; - } - *pp_buffer = p_new_buffer; - } - } - break; - case PARSER_MEMORY_HIP: { - res = PARSER_NOT_IMPLEMENTED; - } - break; - case PARSER_MEMORY_UNKNOWN:{ - res = PARSER_NOT_IMPLEMENTED; - } - break; - default: { - res = PARSER_INVALID_ARG; - } - break; - } - return res; -} \ No newline at end of file diff --git a/src/parser/parser_buffer.h b/src/parser/parser_buffer.h deleted file mode 100644 index 085f3ae00d..0000000000 --- a/src/parser/parser_buffer.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef PARSERBUFFER_H -#define PARSERBUFFER_H -#pragma once - -#include -#include -#include -#include -#include -#include "roc_video_parser.h" - -typedef enum ParserMemoryType { - PARSER_MEMORY_UNKNOWN = 0, - PARSER_MEMORY_HOST = 1, - PARSER_MEMORY_HIP = 2, -} ParserMemoryType; - -class ParserBuffer { -public: - ParserBuffer(); - virtual ~ParserBuffer(); - - virtual ParserResult SetSize(size_t new_size); - virtual size_t GetSize(); - virtual void* GetNative(); - virtual void SetNative(size_t size); - - //parser data functions - virtual bool IsReusable(); - virtual void SetPts(int64_t pts); - virtual int64_t GetPts() const; - virtual void SetDuration(int64_t duration); - virtual int64_t GetDuration() const; - - static ParserResult AllocBuffer(ParserMemoryType type, size_t size, ParserBuffer** pp_buffer); - -private: - int64_t m_current_timestamp_; - int64_t m_duration_; - size_t m_packet_size_; - uint8_t* m_buffer_; -}; - -// smart pointer -typedef std::shared_ptr ParserBufferPtr; - -#endif // PARSERBUFFER_H \ No newline at end of file