From 309c9e3e6eef9e23a9804b998391a80d09d85a4d Mon Sep 17 00:00:00 2001 From: liangyiping Date: Thu, 31 Jul 2025 15:15:18 +0800 Subject: [PATCH] feat: Add H.264 parsing support and related features Newly added H.264 video stream parsing capabilities include: 1. Implement the core functionality of the H.264 parser 2. Add parsing of H.264 parameter sets (SPS/PPS) 3. Support parsing of H.264 slice headers 4. Introduce a new unified video parsing interface 5. Extend GUI to support H.264 analysis 6. Add command-line tool support for H.264 7. Update documentation to document the new features --- CMakeLists.txt | 4 +- README.md | 35 +- h264parser/CMakeLists.txt | 35 + h264parser/include/H264.h | 268 + h264parser/include/H264Parser.h | 44 + h264parser/include/H264Utils.h | 19 + h264parser/src/BitstreamReader.cpp | 161 + h264parser/src/BitstreamReader.h | 29 + h264parser/src/H264.cpp | 324 + h264parser/src/H264Parser.cpp | 19 + h264parser/src/H264ParserImpl.cpp | 444 ++ h264parser/src/H264ParserImpl.h | 44 + h264parser/src/H264Utils.cpp | 152 + h264parser/tests/Params.cpp | 9 + h264parser/tests/Params.h | 8 + h264parser/tests/Parsing.cpp | 67 + h264parser/tests/main.cpp | 2 + utils/CMakeLists.txt | 10 + utils/hevc_es_browser_gui/CMakeLists.txt | 72 + utils/hevc_es_browser_gui/CentralWidget.cpp | 44 +- utils/hevc_es_browser_gui/CentralWidget.h | 5 + .../hevc_es_browser_gui/CommonInfoViewer.cpp | 1 + utils/hevc_es_browser_gui/CommonInfoViewer.h | 5 +- utils/hevc_es_browser_gui/MainWindow.cpp | 168 +- utils/hevc_es_browser_gui/MainWindow.h | 6 +- utils/hevc_es_browser_gui/SyntaxViewer.cpp | 5815 +++++++++-------- utils/hevc_es_browser_gui/SyntaxViewer.h | 20 + .../UnifiedCommonInfoViewer.cpp | 313 + .../UnifiedCommonInfoViewer.h | 69 + .../UnifiedWarningsViewer.cpp | 111 + .../UnifiedWarningsViewer.h | 30 + utils/hevc_es_browser_gui/VideoParser.cpp | 334 + utils/hevc_es_browser_gui/VideoParser.h | 112 + utils/hevc_es_browser_gui/WarningsViewer.cpp | 3 + .../hevc_es_browser_gui.pro | 10 +- .../hevc_es_browser_gui.pro.user | 226 + utils/hevc_es_browser_gui/test_include.cpp | Bin 0 -> 54 bytes utils/video_es_browser_console/CMakeLists.txt | 29 + .../src/H264InfoWriter.cpp | 220 + .../src/H264InfoWriter.h | 44 + .../src/VideoInfoWriter.cpp | 208 + .../src/VideoInfoWriter.h | 34 + utils/video_es_browser_console/src/main.cpp | 91 + 43 files changed, 6915 insertions(+), 2729 deletions(-) create mode 100644 h264parser/CMakeLists.txt create mode 100644 h264parser/include/H264.h create mode 100644 h264parser/include/H264Parser.h create mode 100644 h264parser/include/H264Utils.h create mode 100644 h264parser/src/BitstreamReader.cpp create mode 100644 h264parser/src/BitstreamReader.h create mode 100644 h264parser/src/H264.cpp create mode 100644 h264parser/src/H264Parser.cpp create mode 100644 h264parser/src/H264ParserImpl.cpp create mode 100644 h264parser/src/H264ParserImpl.h create mode 100644 h264parser/src/H264Utils.cpp create mode 100644 h264parser/tests/Params.cpp create mode 100644 h264parser/tests/Params.h create mode 100644 h264parser/tests/Parsing.cpp create mode 100644 h264parser/tests/main.cpp create mode 100644 utils/hevc_es_browser_gui/CMakeLists.txt create mode 100644 utils/hevc_es_browser_gui/UnifiedCommonInfoViewer.cpp create mode 100644 utils/hevc_es_browser_gui/UnifiedCommonInfoViewer.h create mode 100644 utils/hevc_es_browser_gui/UnifiedWarningsViewer.cpp create mode 100644 utils/hevc_es_browser_gui/UnifiedWarningsViewer.h create mode 100644 utils/hevc_es_browser_gui/VideoParser.cpp create mode 100644 utils/hevc_es_browser_gui/VideoParser.h create mode 100644 utils/hevc_es_browser_gui/hevc_es_browser_gui.pro.user create mode 100644 utils/hevc_es_browser_gui/test_include.cpp create mode 100644 utils/video_es_browser_console/CMakeLists.txt create mode 100644 utils/video_es_browser_console/src/H264InfoWriter.cpp create mode 100644 utils/video_es_browser_console/src/H264InfoWriter.h create mode 100644 utils/video_es_browser_console/src/VideoInfoWriter.cpp create mode 100644 utils/video_es_browser_console/src/VideoInfoWriter.h create mode 100644 utils/video_es_browser_console/src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 10c4e50..83f1506 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,5 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.5) +project(HEVCESBrowser) set (BUILD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/build @@ -22,5 +23,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") endif() add_subdirectory(hevcparser) +add_subdirectory(h264parser) add_subdirectory(utils) enable_testing() diff --git a/README.md b/README.md index ce411ea..4dba148 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,24 @@ HEVCESBrowser ========== -HEVCESBrowser is a tool for analyzing HEVC(h265) bitstreams. +HEVCESBrowser is a tool for analyzing HEVC(H.265) and H.264 bitstreams. -This application displays syntax elements of hevc elementary streams. Input file for HEVCESBrowser should be unmuxed elementary stream. If analysis of the video in any type of container (e.g. in .ts or .mp4 files) is needed, preliminary demuxing is required. For example, you can use ffmpeg for this: ffmpeg -i your_file -vcodec copy -an video.h265. There are gui and cli applications in this product. +This application displays syntax elements of HEVC and H.264 elementary streams. Input file for HEVCESBrowser should be unmuxed elementary stream. If analysis of the video in any type of container (e.g. in .ts or .mp4 files) is needed, preliminary demuxing is required. + +For HEVC streams, you can use ffmpeg for demuxing: `ffmpeg -i your_file -vcodec copy -an video.h265` + +For H.264 streams, you can use ffmpeg for demuxing: `ffmpeg -i your_file -vcodec copy -an video.h264` + +There are gui and cli applications in this product. + +## Features + +- **HEVC (H.265) Support**: Complete analysis of HEVC elementary streams including VPS, SPS, PPS, Slice headers, SEI messages, and more +- **H.264 Support**: Comprehensive analysis of H.264 elementary streams including SPS, PPS, Slice headers, AUD, SEI messages with detailed syntax information +- **Detailed Syntax Display**: Shows all syntax elements with meaningful descriptions and calculated values +- **Cross-Platform**: Available for Windows, macOS, and Linux +- **Multiple Interfaces**: Both GUI and command-line applications available Current building status: [![Build Status](https://travis-ci.org/virinext/hevcesbrowser.svg)](https://travis-ci.org/virinext/hevcesbrowser) @@ -36,6 +50,7 @@ Building requirements: Building: ----- +```bash cd hevcesbrowser git submodule init && git submodule update @@ -55,4 +70,20 @@ qmake hevc_es_browser_gui.pro make gitinfo make +``` + +## Project Structure + +The project includes the following main components: + +- **hevcparser/**: HEVC (H.265) bitstream parser library +- **h264parser/**: H.264 bitstream parser library +- **utils/hevc_es_browser_gui/**: Qt-based GUI application +- **utils/hevc_es_browser_console/**: Command-line application +- **utils/video_es_browser_console/**: Unified video stream browser + +## Supported Formats + +- **HEVC (H.265)**: All NAL unit types including VPS, SPS, PPS, Slice headers, SEI messages +- **H.264**: All NAL unit types including SPS, PPS, Slice headers, AUD, SEI messages with comprehensive syntax analysis diff --git a/h264parser/CMakeLists.txt b/h264parser/CMakeLists.txt new file mode 100644 index 0000000..6762584 --- /dev/null +++ b/h264parser/CMakeLists.txt @@ -0,0 +1,35 @@ +FIND_PACKAGE(Boost) + +include_directories( + include/ + ${Boost_INCLUDE_DIR} +) + +set(SOURCES + src/H264Parser.cpp + src/H264.cpp + src/H264ParserImpl.cpp + src/BitstreamReader.cpp + src/H264Utils.cpp +) + +add_library(h264parser ${SOURCES}) + +find_package(Boost COMPONENTS system unit_test_framework filesystem REQUIRED) + +set(TEST_SOURCES + tests/main.cpp + tests/Params.cpp + tests/Parsing.cpp +) + +if(UNIX) + ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK) +endif() + +add_executable(h264parser_test ${TEST_SOURCES}) +target_link_libraries(h264parser_test h264parser ${Boost_LIBRARIES}) +add_dependencies(h264parser_test h264parser) + +add_test(h264parser_test ${BUILD_DIR}/h264parser_test) +enable_testing() \ No newline at end of file diff --git a/h264parser/include/H264.h b/h264parser/include/H264.h new file mode 100644 index 0000000..70a83b7 --- /dev/null +++ b/h264parser/include/H264.h @@ -0,0 +1,268 @@ +#ifndef H264_H_ +#define H264_H_ + +#include +#include +#include +#include +#include + +namespace H264 +{ + + enum NALUnitType + { + NAL_UNSPECIFIED = 0, + NAL_SLICE = 1, + NAL_DPA = 2, + NAL_DPB = 3, + NAL_DPC = 4, + NAL_IDR_SLICE = 5, + NAL_SEI = 6, + NAL_SPS = 7, + NAL_PPS = 8, + NAL_AUD = 9, + NAL_END_SEQUENCE = 10, + NAL_END_STREAM = 11, + NAL_FILLER_DATA = 12, + NAL_SPS_EXT = 13, + NAL_PREFIX = 14, + NAL_SUB_SPS = 15, + NAL_AUXILIARY_SLICE = 19, + NAL_SLICE_EXT = 20, + }; + + class NALHeader + { + public: + uint8_t forbidden_zero_bit; + uint8_t nal_ref_idc; + NALUnitType nal_unit_type; + + bool operator == (const NALHeader &) const; + }; + + class VuiParameters + { + public: + uint8_t aspect_ratio_info_present_flag; + uint8_t aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + uint8_t overscan_info_present_flag; + uint8_t overscan_appropriate_flag; + uint8_t video_signal_type_present_flag; + uint8_t video_format; + uint8_t video_full_range_flag; + uint8_t colour_description_present_flag; + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; + uint8_t chroma_loc_info_present_flag; + uint32_t chroma_sample_loc_type_top_field; + uint32_t chroma_sample_loc_type_bottom_field; + uint8_t timing_info_present_flag; + uint32_t num_units_in_tick; + uint32_t time_scale; + uint8_t fixed_frame_rate_flag; + uint8_t nal_hrd_parameters_present_flag; + uint8_t vcl_hrd_parameters_present_flag; + uint8_t low_delay_hrd_flag; + uint8_t pic_struct_present_flag; + uint8_t bitstream_restriction_flag; + uint8_t motion_vectors_over_pic_boundaries_flag; + uint32_t max_bytes_per_pic_denom; + uint32_t max_bits_per_mb_denom; + uint32_t log2_max_mv_length_horizontal; + uint32_t log2_max_mv_length_vertical; + uint32_t num_reorder_frames; + uint32_t max_dec_frame_buffering; + + void toDefault(); + bool operator == (const VuiParameters &) const; + }; + + class HrdParameters + { + public: + uint32_t cpb_cnt_minus1; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + std::vector bit_rate_value_minus1; + std::vector cpb_size_value_minus1; + std::vector cbr_flag; + uint8_t initial_cpb_removal_delay_length_minus1; + uint8_t cpb_removal_delay_length_minus1; + uint8_t dpb_output_delay_length_minus1; + uint8_t time_offset_length; + + void toDefault(); + bool operator == (const HrdParameters &) const; + }; + + class NALUnit + { + public: + NALUnit(NALHeader header); + virtual ~NALUnit(); + virtual NALUnitType getType() const; + + std::shared_ptr copy() const; + + bool m_processFailed; + NALHeader m_nalHeader; + }; + + class SPS: public NALUnit + { + public: + SPS(); + uint8_t profile_idc; + uint8_t constraint_set0_flag; + uint8_t constraint_set1_flag; + uint8_t constraint_set2_flag; + uint8_t constraint_set3_flag; + uint8_t constraint_set4_flag; + uint8_t constraint_set5_flag; + uint8_t reserved_zero_2bits; + uint8_t level_idc; + uint32_t seq_parameter_set_id; + uint32_t chroma_format_idc; + uint8_t separate_colour_plane_flag; + uint32_t bit_depth_luma_minus8; + uint32_t bit_depth_chroma_minus8; + uint8_t qpprime_y_zero_transform_bypass_flag; + uint8_t seq_scaling_matrix_present_flag; + uint32_t log2_max_frame_num_minus4; + uint32_t pic_order_cnt_type; + uint32_t log2_max_pic_order_cnt_lsb_minus4; + uint8_t delta_pic_order_always_zero_flag; + int32_t offset_for_non_ref_pic; + int32_t offset_for_top_to_bottom_field; + uint32_t num_ref_frames_in_pic_order_cnt_cycle; + std::vector offset_for_ref_frame; + uint32_t max_num_ref_frames; + uint8_t gaps_in_frame_num_value_allowed_flag; + uint32_t pic_width_in_mbs_minus1; + uint32_t pic_height_in_map_units_minus1; + uint8_t frame_mbs_only_flag; + uint8_t mb_adaptive_frame_field_flag; + uint8_t direct_8x8_inference_flag; + uint8_t frame_cropping_flag; + uint32_t frame_crop_left_offset; + uint32_t frame_crop_right_offset; + uint32_t frame_crop_top_offset; + uint32_t frame_crop_bottom_offset; + uint8_t vui_parameters_present_flag; + VuiParameters vui_parameters; + + void toDefault(); + bool operator == (const SPS &) const; + }; + + class PPS: public NALUnit + { + public: + PPS(); + uint32_t pic_parameter_set_id; + uint32_t seq_parameter_set_id; + uint8_t entropy_coding_mode_flag; + uint8_t bottom_field_pic_order_in_frame_present_flag; + uint32_t num_slice_groups_minus1; + uint32_t slice_group_map_type; + std::vector run_length_minus1; + std::vector top_left; + std::vector bottom_right; + uint8_t slice_group_change_direction_flag; + uint32_t slice_group_change_rate_minus1; + uint32_t pic_size_in_map_units_minus1; + std::vector slice_group_id; + uint32_t num_ref_idx_l0_default_active_minus1; + uint32_t num_ref_idx_l1_default_active_minus1; + uint8_t weighted_pred_flag; + uint8_t weighted_bipred_idc; + int32_t pic_init_qp_minus26; + int32_t pic_init_qs_minus26; + int32_t chroma_qp_index_offset; + uint8_t deblocking_filter_control_present_flag; + uint8_t constrained_intra_pred_flag; + uint8_t redundant_pic_cnt_present_flag; + uint8_t transform_8x8_mode_flag; + uint8_t pic_scaling_matrix_present_flag; + int32_t second_chroma_qp_index_offset; + + void toDefault(); + bool operator == (const PPS &) const; + }; + + class Slice: public NALUnit + { + public: + enum SliceType + { + P_SLICE = 0, + B_SLICE = 1, + I_SLICE = 2, + SP_SLICE = 3, + SI_SLICE = 4, + P_SLICE_A = 5, + B_SLICE_A = 6, + I_SLICE_A = 7, + SP_SLICE_A = 8, + SI_SLICE_A = 9, + NONE_SLICE = 10 + }; + + Slice(NALHeader header); + uint32_t first_mb_in_slice; + uint32_t slice_type; + uint32_t pic_parameter_set_id; + uint8_t colour_plane_id; + uint32_t frame_num; + uint8_t field_pic_flag; + uint8_t bottom_field_flag; + uint32_t idr_pic_id; + uint32_t pic_order_cnt_lsb; + int32_t delta_pic_order_cnt_bottom; + std::vector delta_pic_order_cnt; + uint32_t redundant_pic_cnt; + uint8_t direct_spatial_mv_pred_flag; + uint8_t num_ref_idx_active_override_flag; + uint32_t num_ref_idx_l0_active_minus1; + uint32_t num_ref_idx_l1_active_minus1; + uint8_t ref_pic_list_modification_flag_l0; + uint8_t ref_pic_list_modification_flag_l1; + uint8_t no_output_of_prior_pics_flag; + uint8_t long_term_reference_flag; + uint8_t adaptive_ref_pic_marking_mode_flag; + uint32_t cabac_init_idc; + int32_t slice_qp_delta; + uint8_t sp_for_switch_flag; + int32_t slice_qs_delta; + uint32_t disable_deblocking_filter_idc; + int32_t slice_alpha_c0_offset_div2; + int32_t slice_beta_offset_div2; + uint32_t slice_group_change_cycle; + + void toDefault(); + }; + + class AUD: public NALUnit + { + public: + AUD(); + uint8_t primary_pic_type; + void toDefault(); + }; + + class SEI: public NALUnit + { + public: + SEI(NALHeader header); + std::vector sei_payload; + void toDefault(); + }; + +} + +#endif \ No newline at end of file diff --git a/h264parser/include/H264Parser.h b/h264parser/include/H264Parser.h new file mode 100644 index 0000000..3fbfb32 --- /dev/null +++ b/h264parser/include/H264Parser.h @@ -0,0 +1,44 @@ +#ifndef H264_PARSER_H_ +#define H264_PARSER_H_ + +#include "H264.h" + +#include + +namespace H264 +{ + class Parser + { + public: + struct Info + { + std::size_t m_position; + }; + + enum WarningType + { + NONE, + OUT_OF_RANGE, + REFERENCE_STRUCT_NOT_PRESENT, + PROFILE_CONFORMANCE + }; + + class Consumer + { + public: + virtual void onNALUnit(std::shared_ptr pNALUnit, const Info *pInfo) = 0; + virtual void onWarning(const std::string &warning, const Info *pInfo, WarningType type) = 0; + }; + + virtual ~Parser(); + + virtual std::size_t process(const uint8_t *pdata, std::size_t size, std::size_t offset = 0) = 0; + virtual void addConsumer(Consumer *pconsumer) = 0; + virtual void releaseConsumer(Consumer *pconsumer) = 0; + + static Parser *create(); + static void release(Parser *); + }; +} + +#endif \ No newline at end of file diff --git a/h264parser/include/H264Utils.h b/h264parser/include/H264Utils.h new file mode 100644 index 0000000..175612e --- /dev/null +++ b/h264parser/include/H264Utils.h @@ -0,0 +1,19 @@ +#ifndef H264_UTILS_H_ +#define H264_UTILS_H_ + +#include "H264.h" +#include + +namespace H264 +{ + class H264Utils + { + public: + static std::string NALUnitTypeToString(NALUnitType type); + static std::string SliceTypeToString(Slice::SliceType type); + static std::string ProfileToString(uint8_t profile_idc); + static std::string LevelToString(uint8_t level_idc); + }; +} + +#endif \ No newline at end of file diff --git a/h264parser/src/BitstreamReader.cpp b/h264parser/src/BitstreamReader.cpp new file mode 100644 index 0000000..df504f8 --- /dev/null +++ b/h264parser/src/BitstreamReader.cpp @@ -0,0 +1,161 @@ +#include "BitstreamReader.h" + +#include +#include +#include + +BitstreamReader::BitstreamReader(const uint8_t *ptr, std::size_t size): + m_ptr(ptr) + ,m_size(size) + ,m_posBase(0) + ,m_posInBase(CHAR_BIT - 1) +{ +} + +std::size_t BitstreamReader::available() +{ + return (m_size - m_posBase -1) * CHAR_BIT + m_posInBase + 1; +} + +std::size_t BitstreamReader::availableInNalU() +{ + std::size_t pos = m_posBase; + if(m_posInBase) + pos++; + for(; pos<(m_size - 3); pos++) + { + bool naluFound = m_ptr[pos] == 0 && m_ptr[pos+1] == 0 && m_ptr[pos+2] == 1; + + if(!naluFound) + { + if(m_size - pos >= 4 && m_ptr[pos] == 0 && m_ptr[pos+1] == 0 && m_ptr[pos+2] == 0 && m_ptr[pos+3] == 1) + naluFound = true; + } + + if(naluFound) + { + return (pos - m_posBase - 1) * CHAR_BIT + m_posInBase + 1; + } + + } + + return m_size; +} + + +bool BitstreamReader::getBit() +{ + if(m_posBase >= m_size) + throw std::runtime_error("BitstreamReader: not enought data"); + + bool res = m_ptr[m_posBase] & 1 << m_posInBase; + + m_posInBase--; + + if(m_posInBase > CHAR_BIT) + { + m_posInBase = CHAR_BIT-1; + m_posBase++; + + if(m_posBase >= 2) + { + if(m_ptr[m_posBase - 2] == 0 && m_ptr[m_posBase - 1] == 0 && m_ptr[m_posBase] == 3) + m_posBase++; + } + } + + return res; +} + + +uint32_t BitstreamReader::getBits(std::size_t num) +{ + assert(num <= 32); + + uint32_t result = 0; + for(std::size_t i=0; i= 2) + { + if(m_ptr[m_posBase - 2] == 0 && m_ptr[m_posBase - 1] == 0 && m_ptr[m_posBase] == 3) + m_posBase++; + } + + uint32_t scipBytes = num / 8; + + + while(scipBytes) + { + scipBytes--; + m_posBase++; + if(m_posBase >= 2) + { + if(m_ptr[m_posBase - 2] == 0 && m_ptr[m_posBase - 1] == 0 && m_ptr[m_posBase] == 3) + m_posBase++; + } + } + + if(m_posInBase >= num % 8) + m_posInBase -= num % 8; + else + { + m_posBase++; + m_posInBase = m_posInBase - num % 8 + 8; + } + +} + +uint32_t BitstreamReader::showBits(std::size_t num) +{ + assert(num <= 32); + + std::size_t posBasePrev = m_posBase; + std::size_t posInBasePrev = m_posInBase; + + uint32_t result = 0; + for(std::size_t i=0; i= 32) + return 0; +// throw std::range_error("Golomb: size of value more then 32 bits"); + + return (1 << numZeroBits) - 1 + getBits(numZeroBits); +} + + + +int32_t BitstreamReader::getGolombS() +{ + int32_t buf = getGolombU(); + + if (buf & 1) + buf = (buf + 1) >> 1; + else + buf = -(buf >> 1); + + return buf; +} \ No newline at end of file diff --git a/h264parser/src/BitstreamReader.h b/h264parser/src/BitstreamReader.h new file mode 100644 index 0000000..f52cf3c --- /dev/null +++ b/h264parser/src/BitstreamReader.h @@ -0,0 +1,29 @@ +#ifndef BITSTREAM_READER_H_ +#define BITSTREAM_READER_H_ + +#include +#include + +class BitstreamReader +{ +public: + BitstreamReader(const uint8_t *ptr, std::size_t size); + bool getBit(); + uint32_t getBits(std::size_t num); + void skipBits(std::size_t num); + uint32_t showBits(std::size_t num); + uint32_t getGolombU(); + int32_t getGolombS(); + + std::size_t available(); + std::size_t availableInNalU(); + +private: + const uint8_t *m_ptr; + std::size_t m_size; + std::size_t m_posBase; + std::size_t m_posInBase; +}; + + +#endif \ No newline at end of file diff --git a/h264parser/src/H264.cpp b/h264parser/src/H264.cpp new file mode 100644 index 0000000..9f6c358 --- /dev/null +++ b/h264parser/src/H264.cpp @@ -0,0 +1,324 @@ +#include "H264.h" + +#include + +using namespace H264; + +bool NALHeader::operator == (const NALHeader &other) const +{ + return forbidden_zero_bit == other.forbidden_zero_bit && + nal_ref_idc == other.nal_ref_idc && + nal_unit_type == other.nal_unit_type; +} + +void VuiParameters::toDefault() +{ + aspect_ratio_info_present_flag = 0; + aspect_ratio_idc = 0; + sar_width = 0; + sar_height = 0; + overscan_info_present_flag = 0; + overscan_appropriate_flag = 0; + video_signal_type_present_flag = 0; + video_format = 5; + video_full_range_flag = 0; + colour_description_present_flag = 0; + colour_primaries = 2; + transfer_characteristics = 2; + matrix_coefficients = 2; + chroma_loc_info_present_flag = 0; + chroma_sample_loc_type_top_field = 0; + chroma_sample_loc_type_bottom_field = 0; + timing_info_present_flag = 0; + num_units_in_tick = 0; + time_scale = 0; + fixed_frame_rate_flag = 0; + nal_hrd_parameters_present_flag = 0; + vcl_hrd_parameters_present_flag = 0; + low_delay_hrd_flag = 0; + pic_struct_present_flag = 0; + bitstream_restriction_flag = 0; + motion_vectors_over_pic_boundaries_flag = 1; + max_bytes_per_pic_denom = 2; + max_bits_per_mb_denom = 1; + log2_max_mv_length_horizontal = 15; + log2_max_mv_length_vertical = 15; + num_reorder_frames = 0; + max_dec_frame_buffering = 0; +} + +bool VuiParameters::operator == (const VuiParameters &other) const +{ + return aspect_ratio_info_present_flag == other.aspect_ratio_info_present_flag && + aspect_ratio_idc == other.aspect_ratio_idc && + sar_width == other.sar_width && + sar_height == other.sar_height && + overscan_info_present_flag == other.overscan_info_present_flag && + overscan_appropriate_flag == other.overscan_appropriate_flag && + video_signal_type_present_flag == other.video_signal_type_present_flag && + video_format == other.video_format && + video_full_range_flag == other.video_full_range_flag && + colour_description_present_flag == other.colour_description_present_flag && + colour_primaries == other.colour_primaries && + transfer_characteristics == other.transfer_characteristics && + matrix_coefficients == other.matrix_coefficients && + chroma_loc_info_present_flag == other.chroma_loc_info_present_flag && + chroma_sample_loc_type_top_field == other.chroma_sample_loc_type_top_field && + chroma_sample_loc_type_bottom_field == other.chroma_sample_loc_type_bottom_field && + timing_info_present_flag == other.timing_info_present_flag && + num_units_in_tick == other.num_units_in_tick && + time_scale == other.time_scale && + fixed_frame_rate_flag == other.fixed_frame_rate_flag && + nal_hrd_parameters_present_flag == other.nal_hrd_parameters_present_flag && + vcl_hrd_parameters_present_flag == other.vcl_hrd_parameters_present_flag && + low_delay_hrd_flag == other.low_delay_hrd_flag && + pic_struct_present_flag == other.pic_struct_present_flag && + bitstream_restriction_flag == other.bitstream_restriction_flag && + motion_vectors_over_pic_boundaries_flag == other.motion_vectors_over_pic_boundaries_flag && + max_bytes_per_pic_denom == other.max_bytes_per_pic_denom && + max_bits_per_mb_denom == other.max_bits_per_mb_denom && + log2_max_mv_length_horizontal == other.log2_max_mv_length_horizontal && + log2_max_mv_length_vertical == other.log2_max_mv_length_vertical && + num_reorder_frames == other.num_reorder_frames && + max_dec_frame_buffering == other.max_dec_frame_buffering; +} + +void HrdParameters::toDefault() +{ + cpb_cnt_minus1 = 0; + bit_rate_scale = 0; + cpb_size_scale = 0; + bit_rate_value_minus1.clear(); + cpb_size_value_minus1.clear(); + cbr_flag.clear(); + initial_cpb_removal_delay_length_minus1 = 23; + cpb_removal_delay_length_minus1 = 23; + dpb_output_delay_length_minus1 = 23; + time_offset_length = 24; +} + +bool HrdParameters::operator == (const HrdParameters &other) const +{ + return cpb_cnt_minus1 == other.cpb_cnt_minus1 && + bit_rate_scale == other.bit_rate_scale && + cpb_size_scale == other.cpb_size_scale && + bit_rate_value_minus1 == other.bit_rate_value_minus1 && + cpb_size_value_minus1 == other.cpb_size_value_minus1 && + cbr_flag == other.cbr_flag && + initial_cpb_removal_delay_length_minus1 == other.initial_cpb_removal_delay_length_minus1 && + cpb_removal_delay_length_minus1 == other.cpb_removal_delay_length_minus1 && + dpb_output_delay_length_minus1 == other.dpb_output_delay_length_minus1 && + time_offset_length == other.time_offset_length; +} + +NALUnit::NALUnit(NALHeader header): + m_processFailed(false), + m_nalHeader(header) +{ + +} + +NALUnit::~NALUnit() +{ + +} + +NALUnitType NALUnit::getType() const +{ + return m_nalHeader.nal_unit_type; +} + +std::shared_ptr NALUnit::copy() const +{ + return std::shared_ptr(new NALUnit(m_nalHeader)); +} + +SPS::SPS(): + NALUnit(NALHeader()) +{ + toDefault(); +} + +void SPS::toDefault() +{ + profile_idc = 0; + constraint_set0_flag = 0; + constraint_set1_flag = 0; + constraint_set2_flag = 0; + constraint_set3_flag = 0; + constraint_set4_flag = 0; + constraint_set5_flag = 0; + reserved_zero_2bits = 0; + level_idc = 0; + seq_parameter_set_id = 0; + chroma_format_idc = 1; + separate_colour_plane_flag = 0; + bit_depth_luma_minus8 = 0; + bit_depth_chroma_minus8 = 0; + qpprime_y_zero_transform_bypass_flag = 0; + seq_scaling_matrix_present_flag = 0; + log2_max_frame_num_minus4 = 0; + pic_order_cnt_type = 0; + log2_max_pic_order_cnt_lsb_minus4 = 0; + delta_pic_order_always_zero_flag = 0; + offset_for_non_ref_pic = 0; + offset_for_top_to_bottom_field = 0; + num_ref_frames_in_pic_order_cnt_cycle = 0; + offset_for_ref_frame.clear(); + max_num_ref_frames = 0; + gaps_in_frame_num_value_allowed_flag = 0; + pic_width_in_mbs_minus1 = 0; + pic_height_in_map_units_minus1 = 0; + frame_mbs_only_flag = 1; + mb_adaptive_frame_field_flag = 0; + direct_8x8_inference_flag = 0; + frame_cropping_flag = 0; + frame_crop_left_offset = 0; + frame_crop_right_offset = 0; + frame_crop_top_offset = 0; + frame_crop_bottom_offset = 0; + vui_parameters_present_flag = 0; + vui_parameters.toDefault(); +} + +bool SPS::operator == (const SPS &other) const +{ + return profile_idc == other.profile_idc && + constraint_set0_flag == other.constraint_set0_flag && + constraint_set1_flag == other.constraint_set1_flag && + constraint_set2_flag == other.constraint_set2_flag && + constraint_set3_flag == other.constraint_set3_flag && + constraint_set4_flag == other.constraint_set4_flag && + constraint_set5_flag == other.constraint_set5_flag && + level_idc == other.level_idc && + seq_parameter_set_id == other.seq_parameter_set_id && + chroma_format_idc == other.chroma_format_idc && + separate_colour_plane_flag == other.separate_colour_plane_flag && + bit_depth_luma_minus8 == other.bit_depth_luma_minus8 && + bit_depth_chroma_minus8 == other.bit_depth_chroma_minus8 && + log2_max_frame_num_minus4 == other.log2_max_frame_num_minus4 && + pic_order_cnt_type == other.pic_order_cnt_type && + log2_max_pic_order_cnt_lsb_minus4 == other.log2_max_pic_order_cnt_lsb_minus4 && + max_num_ref_frames == other.max_num_ref_frames && + pic_width_in_mbs_minus1 == other.pic_width_in_mbs_minus1 && + pic_height_in_map_units_minus1 == other.pic_height_in_map_units_minus1 && + frame_mbs_only_flag == other.frame_mbs_only_flag && + vui_parameters_present_flag == other.vui_parameters_present_flag && + (!vui_parameters_present_flag || vui_parameters == other.vui_parameters); +} + +PPS::PPS(): + NALUnit(NALHeader()) +{ + toDefault(); +} + +void PPS::toDefault() +{ + pic_parameter_set_id = 0; + seq_parameter_set_id = 0; + entropy_coding_mode_flag = 0; + bottom_field_pic_order_in_frame_present_flag = 0; + num_slice_groups_minus1 = 0; + slice_group_map_type = 0; + run_length_minus1.clear(); + top_left.clear(); + bottom_right.clear(); + slice_group_change_direction_flag = 0; + slice_group_change_rate_minus1 = 0; + pic_size_in_map_units_minus1 = 0; + slice_group_id.clear(); + num_ref_idx_l0_default_active_minus1 = 0; + num_ref_idx_l1_default_active_minus1 = 0; + weighted_pred_flag = 0; + weighted_bipred_idc = 0; + pic_init_qp_minus26 = 0; + pic_init_qs_minus26 = 0; + chroma_qp_index_offset = 0; + deblocking_filter_control_present_flag = 0; + constrained_intra_pred_flag = 0; + redundant_pic_cnt_present_flag = 0; + transform_8x8_mode_flag = 0; + pic_scaling_matrix_present_flag = 0; + second_chroma_qp_index_offset = 0; +} + +bool PPS::operator == (const PPS &other) const +{ + return pic_parameter_set_id == other.pic_parameter_set_id && + seq_parameter_set_id == other.seq_parameter_set_id && + entropy_coding_mode_flag == other.entropy_coding_mode_flag && + bottom_field_pic_order_in_frame_present_flag == other.bottom_field_pic_order_in_frame_present_flag && + num_slice_groups_minus1 == other.num_slice_groups_minus1 && + num_ref_idx_l0_default_active_minus1 == other.num_ref_idx_l0_default_active_minus1 && + num_ref_idx_l1_default_active_minus1 == other.num_ref_idx_l1_default_active_minus1 && + weighted_pred_flag == other.weighted_pred_flag && + weighted_bipred_idc == other.weighted_bipred_idc && + pic_init_qp_minus26 == other.pic_init_qp_minus26 && + pic_init_qs_minus26 == other.pic_init_qs_minus26 && + chroma_qp_index_offset == other.chroma_qp_index_offset && + deblocking_filter_control_present_flag == other.deblocking_filter_control_present_flag && + constrained_intra_pred_flag == other.constrained_intra_pred_flag && + redundant_pic_cnt_present_flag == other.redundant_pic_cnt_present_flag; +} + +Slice::Slice(NALHeader header): + NALUnit(header) +{ + toDefault(); +} + +void Slice::toDefault() +{ + first_mb_in_slice = 0; + slice_type = 0; + pic_parameter_set_id = 0; + colour_plane_id = 0; + frame_num = 0; + field_pic_flag = 0; + bottom_field_flag = 0; + idr_pic_id = 0; + pic_order_cnt_lsb = 0; + delta_pic_order_cnt_bottom = 0; + delta_pic_order_cnt.clear(); + redundant_pic_cnt = 0; + direct_spatial_mv_pred_flag = 0; + num_ref_idx_active_override_flag = 0; + num_ref_idx_l0_active_minus1 = 0; + num_ref_idx_l1_active_minus1 = 0; + ref_pic_list_modification_flag_l0 = 0; + ref_pic_list_modification_flag_l1 = 0; + no_output_of_prior_pics_flag = 0; + long_term_reference_flag = 0; + adaptive_ref_pic_marking_mode_flag = 0; + cabac_init_idc = 0; + slice_qp_delta = 0; + sp_for_switch_flag = 0; + slice_qs_delta = 0; + disable_deblocking_filter_idc = 0; + slice_alpha_c0_offset_div2 = 0; + slice_beta_offset_div2 = 0; + slice_group_change_cycle = 0; +} + +AUD::AUD(): + NALUnit(NALHeader()) +{ + toDefault(); +} + +void AUD::toDefault() +{ + primary_pic_type = 0; +} + +SEI::SEI(NALHeader header): + NALUnit(header) +{ + toDefault(); +} + +void SEI::toDefault() +{ + sei_payload.clear(); +} \ No newline at end of file diff --git a/h264parser/src/H264Parser.cpp b/h264parser/src/H264Parser.cpp new file mode 100644 index 0000000..392be1b --- /dev/null +++ b/h264parser/src/H264Parser.cpp @@ -0,0 +1,19 @@ +#include "H264Parser.h" +#include "H264ParserImpl.h" + +using namespace H264; + +Parser::~Parser() +{ + +} + +Parser *Parser::create() +{ + return new H264ParserImpl; +} + +void Parser::release(Parser *pparser) +{ + delete pparser; +} \ No newline at end of file diff --git a/h264parser/src/H264ParserImpl.cpp b/h264parser/src/H264ParserImpl.cpp new file mode 100644 index 0000000..bbfb6ac --- /dev/null +++ b/h264parser/src/H264ParserImpl.cpp @@ -0,0 +1,444 @@ +#include "H264ParserImpl.h" +#include "H264Utils.h" + +#include +#include +#include +#include +#include + +using namespace H264; + +#define SLICE_P 0 +#define SLICE_B 1 +#define SLICE_I 2 +#define SLICE_SP 3 +#define SLICE_SI 4 + +void H264ParserImpl::addConsumer(Consumer *pconsumer) +{ + m_consumers.push_back(pconsumer); +} + +void H264ParserImpl::releaseConsumer(Consumer *pconsumer) +{ + m_consumers.remove(pconsumer); +} + +void H264ParserImpl::onWarning(const std::string &warning, const Info *pInfo, WarningType type) +{ + std::list::const_iterator itr = m_consumers.begin(); + for(; itr != m_consumers.end(); itr++) + (*itr) -> onWarning(warning, pInfo, type); +} + +std::size_t H264ParserImpl::process(const uint8_t *pdata, std::size_t size, std::size_t offset) +{ + std::size_t parsed = 0; + bool parseFailed = false; + for(std::size_t pos = 0; pos + 3 < size;) + { + std::size_t startOffset = 3; + bool naluFinded = pdata[pos] == 0 && pdata[pos+1] == 0 && pdata[pos+2] == 1; + + if(!naluFinded) + { + if(size - pos >= 4 && pdata[pos] == 0 && pdata[pos+1] == 0 && pdata[pos+2] == 0 && pdata[pos+3] == 1) + { + naluFinded = true; + startOffset = 4; + } + } + if(naluFinded) + { + Parser::Info info; + info.m_position = offset + pos; + + try + { + processNALUnit(pdata + pos + startOffset, size - pos - startOffset, info); + } + catch (std::runtime_error &err) + { + std::cerr << pos << " " << err.what(); + parseFailed = true; + } + + std::size_t nextPos = pos + startOffset; + for(; nextPos + 2 < size; nextPos++) + { + if(pdata[nextPos] == 0 && pdata[nextPos+1] == 0 && pdata[nextPos+2] == 1) + break; + if(nextPos + 3 < size && pdata[nextPos] == 0 && pdata[nextPos+1] == 0 && pdata[nextPos+2] == 0 && pdata[nextPos+3] == 1) + break; + } + pos = nextPos; + parsed = pos; + } + else + { + pos++; + } + } + + if(parseFailed) + throw std::runtime_error("Parsing failed"); + + return parsed; +} + +void H264ParserImpl::processNALUnit(const uint8_t *pdata, std::size_t size, const Parser::Info &info) +{ + if(size < 1) + return; + + BitstreamReader bs(pdata, size); + NALHeader nalHeader; + processNALUnitHeader(bs, &nalHeader); + + std::shared_ptr pnalu; + + switch(nalHeader.nal_unit_type) + { + case NAL_SPS: + { + std::shared_ptr psps(new SPS); + psps->m_nalHeader = nalHeader; + processSPS(psps, bs, info); + pnalu = std::dynamic_pointer_cast(psps); + m_spsMap[psps->seq_parameter_set_id] = psps; + break; + } + + case NAL_PPS: + { + std::shared_ptr ppps(new PPS); + ppps->m_nalHeader = nalHeader; + processPPS(ppps, bs, info); + pnalu = std::dynamic_pointer_cast(ppps); + m_ppsMap[ppps->pic_parameter_set_id] = ppps; + break; + } + + case NAL_SLICE: + case NAL_IDR_SLICE: + { + std::shared_ptr pslice(new Slice(nalHeader)); + processSlice(pslice, bs, info); + pnalu = std::dynamic_pointer_cast(pslice); + m_lastSlice = pslice; + break; + } + + case NAL_AUD: + { + std::shared_ptr paud(new AUD); + paud->m_nalHeader = nalHeader; + processAUD(paud, bs, info); + pnalu = std::dynamic_pointer_cast(paud); + break; + } + + case NAL_SEI: + { + std::shared_ptr psei(new SEI(nalHeader)); + processSEI(psei, bs, info); + pnalu = std::dynamic_pointer_cast(psei); + break; + } + + default: + { + pnalu = std::shared_ptr(new NALUnit(nalHeader)); + break; + } + } + + std::list::const_iterator itr = m_consumers.begin(); + for(; itr != m_consumers.end(); itr++) + (*itr) -> onNALUnit(pnalu, &info); +} + +void H264ParserImpl::processNALUnitHeader(BitstreamReader &bs, NALHeader* header) +{ + header->forbidden_zero_bit = bs.getBits(1); + header->nal_ref_idc = bs.getBits(2); + header->nal_unit_type = (NALUnitType)bs.getBits(5); +} + +void H264ParserImpl::processSPS(std::shared_ptr psps, BitstreamReader &bs, const Parser::Info &info) +{ + psps->toDefault(); + + psps->profile_idc = bs.getBits(8); + psps->constraint_set0_flag = bs.getBits(1); + psps->constraint_set1_flag = bs.getBits(1); + psps->constraint_set2_flag = bs.getBits(1); + psps->constraint_set3_flag = bs.getBits(1); + psps->constraint_set4_flag = bs.getBits(1); + psps->constraint_set5_flag = bs.getBits(1); + psps->reserved_zero_2bits = bs.getBits(2); + psps->level_idc = bs.getBits(8); + psps->seq_parameter_set_id = bs.getGolombU(); + + if(psps->profile_idc == 100 || psps->profile_idc == 110 || + psps->profile_idc == 122 || psps->profile_idc == 244 || + psps->profile_idc == 44 || psps->profile_idc == 83 || + psps->profile_idc == 86 || psps->profile_idc == 118 || + psps->profile_idc == 128 || psps->profile_idc == 138) + { + psps->chroma_format_idc = bs.getGolombU(); + if(psps->chroma_format_idc == 3) + psps->separate_colour_plane_flag = bs.getBits(1); + psps->bit_depth_luma_minus8 = bs.getGolombU(); + psps->bit_depth_chroma_minus8 = bs.getGolombU(); + psps->qpprime_y_zero_transform_bypass_flag = bs.getBits(1); + psps->seq_scaling_matrix_present_flag = bs.getBits(1); + // Note: scaling matrix parsing would go here + } + + psps->log2_max_frame_num_minus4 = bs.getGolombU(); + psps->pic_order_cnt_type = bs.getGolombU(); + + if(psps->pic_order_cnt_type == 0) + { + psps->log2_max_pic_order_cnt_lsb_minus4 = bs.getGolombU(); + } + else if(psps->pic_order_cnt_type == 1) + { + psps->delta_pic_order_always_zero_flag = bs.getBits(1); + psps->offset_for_non_ref_pic = bs.getGolombS(); + psps->offset_for_top_to_bottom_field = bs.getGolombS(); + psps->num_ref_frames_in_pic_order_cnt_cycle = bs.getGolombU(); + psps->offset_for_ref_frame.resize(psps->num_ref_frames_in_pic_order_cnt_cycle); + for(uint32_t i = 0; i < psps->num_ref_frames_in_pic_order_cnt_cycle; i++) + psps->offset_for_ref_frame[i] = bs.getGolombS(); + } + + psps->max_num_ref_frames = bs.getGolombU(); + psps->gaps_in_frame_num_value_allowed_flag = bs.getBits(1); + psps->pic_width_in_mbs_minus1 = bs.getGolombU(); + psps->pic_height_in_map_units_minus1 = bs.getGolombU(); + psps->frame_mbs_only_flag = bs.getBits(1); + + if(!psps->frame_mbs_only_flag) + psps->mb_adaptive_frame_field_flag = bs.getBits(1); + + psps->direct_8x8_inference_flag = bs.getBits(1); + psps->frame_cropping_flag = bs.getBits(1); + + if(psps->frame_cropping_flag) + { + psps->frame_crop_left_offset = bs.getGolombU(); + psps->frame_crop_right_offset = bs.getGolombU(); + psps->frame_crop_top_offset = bs.getGolombU(); + psps->frame_crop_bottom_offset = bs.getGolombU(); + } + + psps->vui_parameters_present_flag = bs.getBits(1); + if(psps->vui_parameters_present_flag) + psps->vui_parameters = processVuiParameters(bs); +} + +void H264ParserImpl::processPPS(std::shared_ptr ppps, BitstreamReader &bs, const Parser::Info &info) +{ + ppps->toDefault(); + + ppps->pic_parameter_set_id = bs.getGolombU(); + ppps->seq_parameter_set_id = bs.getGolombU(); + ppps->entropy_coding_mode_flag = bs.getBits(1); + ppps->bottom_field_pic_order_in_frame_present_flag = bs.getBits(1); + ppps->num_slice_groups_minus1 = bs.getGolombU(); + + if(ppps->num_slice_groups_minus1 > 0) + { + ppps->slice_group_map_type = bs.getGolombU(); + // Note: slice group mapping would be parsed here based on map type + } + + ppps->num_ref_idx_l0_default_active_minus1 = bs.getGolombU(); + ppps->num_ref_idx_l1_default_active_minus1 = bs.getGolombU(); + ppps->weighted_pred_flag = bs.getBits(1); + ppps->weighted_bipred_idc = bs.getBits(2); + ppps->pic_init_qp_minus26 = bs.getGolombS(); + ppps->pic_init_qs_minus26 = bs.getGolombS(); + ppps->chroma_qp_index_offset = bs.getGolombS(); + ppps->deblocking_filter_control_present_flag = bs.getBits(1); + ppps->constrained_intra_pred_flag = bs.getBits(1); + ppps->redundant_pic_cnt_present_flag = bs.getBits(1); + + // More PPS fields would be parsed here if needed +} + +void H264ParserImpl::processSlice(std::shared_ptr pslice, BitstreamReader &bs, const Parser::Info &info) +{ + pslice->toDefault(); + processSliceHeader(pslice, bs, info); +} + +void H264ParserImpl::processSliceHeader(std::shared_ptr pslice, BitstreamReader &bs, const Parser::Info &info) +{ + pslice->first_mb_in_slice = bs.getGolombU(); + pslice->slice_type = bs.getGolombU(); + pslice->pic_parameter_set_id = bs.getGolombU(); + + if(m_ppsMap.find(pslice->pic_parameter_set_id) == m_ppsMap.end()) + { + onWarning("PPS not found", &info, REFERENCE_STRUCT_NOT_PRESENT); + return; + } + + std::shared_ptr ppps = m_ppsMap[pslice->pic_parameter_set_id]; + if(m_spsMap.find(ppps->seq_parameter_set_id) == m_spsMap.end()) + { + onWarning("SPS not found", &info, REFERENCE_STRUCT_NOT_PRESENT); + return; + } + + std::shared_ptr psps = m_spsMap[ppps->seq_parameter_set_id]; + + if(psps->separate_colour_plane_flag) + pslice->colour_plane_id = bs.getBits(2); + + pslice->frame_num = bs.getBits(psps->log2_max_frame_num_minus4 + 4); + + if(!psps->frame_mbs_only_flag) + { + pslice->field_pic_flag = bs.getBits(1); + if(pslice->field_pic_flag) + pslice->bottom_field_flag = bs.getBits(1); + } + + if(pslice->m_nalHeader.nal_unit_type == NAL_IDR_SLICE) + pslice->idr_pic_id = bs.getGolombU(); + + if(psps->pic_order_cnt_type == 0) + { + pslice->pic_order_cnt_lsb = bs.getBits(psps->log2_max_pic_order_cnt_lsb_minus4 + 4); + if(ppps->bottom_field_pic_order_in_frame_present_flag && !pslice->field_pic_flag) + pslice->delta_pic_order_cnt_bottom = bs.getGolombS(); + } + + // Additional slice header parsing would continue here... +} + +void H264ParserImpl::processAUD(std::shared_ptr paud, BitstreamReader &bs, const Parser::Info &info) +{ + paud->toDefault(); + paud->primary_pic_type = bs.getBits(3); +} + +void H264ParserImpl::processSEI(std::shared_ptr psei, BitstreamReader &bs, const Parser::Info &info) +{ + psei->toDefault(); + // SEI parsing would be implemented here +} + +VuiParameters H264ParserImpl::processVuiParameters(BitstreamReader &bs) +{ + VuiParameters vui; + vui.toDefault(); + + vui.aspect_ratio_info_present_flag = bs.getBits(1); + if(vui.aspect_ratio_info_present_flag) + { + vui.aspect_ratio_idc = bs.getBits(8); + if(vui.aspect_ratio_idc == 255) // Extended_SAR + { + vui.sar_width = bs.getBits(16); + vui.sar_height = bs.getBits(16); + } + } + + vui.overscan_info_present_flag = bs.getBits(1); + if(vui.overscan_info_present_flag) + vui.overscan_appropriate_flag = bs.getBits(1); + + vui.video_signal_type_present_flag = bs.getBits(1); + if(vui.video_signal_type_present_flag) + { + vui.video_format = bs.getBits(3); + vui.video_full_range_flag = bs.getBits(1); + vui.colour_description_present_flag = bs.getBits(1); + if(vui.colour_description_present_flag) + { + vui.colour_primaries = bs.getBits(8); + vui.transfer_characteristics = bs.getBits(8); + vui.matrix_coefficients = bs.getBits(8); + } + } + + vui.chroma_loc_info_present_flag = bs.getBits(1); + if(vui.chroma_loc_info_present_flag) + { + vui.chroma_sample_loc_type_top_field = bs.getGolombU(); + vui.chroma_sample_loc_type_bottom_field = bs.getGolombU(); + } + + vui.timing_info_present_flag = bs.getBits(1); + if(vui.timing_info_present_flag) + { + vui.num_units_in_tick = bs.getBits(32); + vui.time_scale = bs.getBits(32); + vui.fixed_frame_rate_flag = bs.getBits(1); + } + + vui.nal_hrd_parameters_present_flag = bs.getBits(1); + if(vui.nal_hrd_parameters_present_flag) + { + // HRD parameters parsing would go here + } + + vui.vcl_hrd_parameters_present_flag = bs.getBits(1); + if(vui.vcl_hrd_parameters_present_flag) + { + // HRD parameters parsing would go here + } + + if(vui.nal_hrd_parameters_present_flag || vui.vcl_hrd_parameters_present_flag) + vui.low_delay_hrd_flag = bs.getBits(1); + + vui.pic_struct_present_flag = bs.getBits(1); + vui.bitstream_restriction_flag = bs.getBits(1); + + if(vui.bitstream_restriction_flag) + { + vui.motion_vectors_over_pic_boundaries_flag = bs.getBits(1); + vui.max_bytes_per_pic_denom = bs.getGolombU(); + vui.max_bits_per_mb_denom = bs.getGolombU(); + vui.log2_max_mv_length_horizontal = bs.getGolombU(); + vui.log2_max_mv_length_vertical = bs.getGolombU(); + vui.num_reorder_frames = bs.getGolombU(); + vui.max_dec_frame_buffering = bs.getGolombU(); + } + + return vui; +} + +HrdParameters H264ParserImpl::processHrdParameters(BitstreamReader &bs) +{ + HrdParameters hrd; + hrd.toDefault(); + + hrd.cpb_cnt_minus1 = bs.getGolombU(); + hrd.bit_rate_scale = bs.getBits(4); + hrd.cpb_size_scale = bs.getBits(4); + + hrd.bit_rate_value_minus1.resize(hrd.cpb_cnt_minus1 + 1); + hrd.cpb_size_value_minus1.resize(hrd.cpb_cnt_minus1 + 1); + hrd.cbr_flag.resize(hrd.cpb_cnt_minus1 + 1); + + for(uint32_t i = 0; i <= hrd.cpb_cnt_minus1; i++) + { + hrd.bit_rate_value_minus1[i] = bs.getGolombU(); + hrd.cpb_size_value_minus1[i] = bs.getGolombU(); + hrd.cbr_flag[i] = bs.getBits(1); + } + + hrd.initial_cpb_removal_delay_length_minus1 = bs.getBits(5); + hrd.cpb_removal_delay_length_minus1 = bs.getBits(5); + hrd.dpb_output_delay_length_minus1 = bs.getBits(5); + hrd.time_offset_length = bs.getBits(5); + + return hrd; +} \ No newline at end of file diff --git a/h264parser/src/H264ParserImpl.h b/h264parser/src/H264ParserImpl.h new file mode 100644 index 0000000..b88d0fa --- /dev/null +++ b/h264parser/src/H264ParserImpl.h @@ -0,0 +1,44 @@ +#ifndef H264_PARSER_IMPL +#define H264_PARSER_IMPL + +#include "H264Parser.h" +#include "BitstreamReader.h" + +#include +#include +#include + +namespace H264 +{ + class H264ParserImpl: public Parser + { + public: + virtual std::size_t process(const uint8_t *pdata, std::size_t size, std::size_t offset = 0); + + virtual void addConsumer(Consumer *pconsumer); + virtual void releaseConsumer(Consumer *pconsumer); + + protected: + void processNALUnit(const uint8_t *pdata, std::size_t size, const Parser::Info &info); + void processNALUnitHeader(BitstreamReader &bs, NALHeader* header); + void processSPS(std::shared_ptr psps, BitstreamReader &bs, const Parser::Info &info); + void processPPS(std::shared_ptr ppps, BitstreamReader &bs, const Parser::Info &info); + void processSlice(std::shared_ptr pslice, BitstreamReader &bs, const Parser::Info &info); + void processAUD(std::shared_ptr paud, BitstreamReader &bs, const Parser::Info &info); + void processSEI(std::shared_ptr psei, BitstreamReader &bs, const Parser::Info &info); + void processSliceHeader(std::shared_ptr pslice, BitstreamReader &bs, const Parser::Info &info); + + VuiParameters processVuiParameters(BitstreamReader &bs); + HrdParameters processHrdParameters(BitstreamReader &bs); + + void onWarning(const std::string &warning, const Info *pInfo, WarningType type); + + std::map > m_spsMap; + std::map > m_ppsMap; + std::shared_ptr m_lastSlice; + + std::list m_consumers; + }; +} + +#endif \ No newline at end of file diff --git a/h264parser/src/H264Utils.cpp b/h264parser/src/H264Utils.cpp new file mode 100644 index 0000000..6e8b220 --- /dev/null +++ b/h264parser/src/H264Utils.cpp @@ -0,0 +1,152 @@ +#include "H264Utils.h" + +using namespace H264; + +std::string H264Utils::NALUnitTypeToString(NALUnitType type) +{ + switch(type) + { + case NAL_UNSPECIFIED: + return "Unspecified"; + case NAL_SLICE: + return "Coded slice of a non-IDR picture"; + case NAL_DPA: + return "Coded slice data partition A"; + case NAL_DPB: + return "Coded slice data partition B"; + case NAL_DPC: + return "Coded slice data partition C"; + case NAL_IDR_SLICE: + return "Coded slice of an IDR picture"; + case NAL_SEI: + return "Supplemental enhancement information (SEI)"; + case NAL_SPS: + return "Sequence parameter set"; + case NAL_PPS: + return "Picture parameter set"; + case NAL_AUD: + return "Access unit delimiter"; + case NAL_END_SEQUENCE: + return "End of sequence"; + case NAL_END_STREAM: + return "End of stream"; + case NAL_FILLER_DATA: + return "Filler data"; + case NAL_SPS_EXT: + return "Sequence parameter set extension"; + case NAL_PREFIX: + return "Prefix NAL unit"; + case NAL_SUB_SPS: + return "Subset sequence parameter set"; + case NAL_AUXILIARY_SLICE: + return "Coded slice of an auxiliary coded picture"; + case NAL_SLICE_EXT: + return "Coded slice extension"; + default: + return "Unknown"; + } +} + +std::string H264Utils::SliceTypeToString(Slice::SliceType type) +{ + switch(type) + { + case Slice::P_SLICE: + case Slice::P_SLICE_A: + return "P"; + case Slice::B_SLICE: + case Slice::B_SLICE_A: + return "B"; + case Slice::I_SLICE: + case Slice::I_SLICE_A: + return "I"; + case Slice::SP_SLICE: + case Slice::SP_SLICE_A: + return "SP"; + case Slice::SI_SLICE: + case Slice::SI_SLICE_A: + return "SI"; + default: + return "Unknown"; + } +} + +std::string H264Utils::ProfileToString(uint8_t profile_idc) +{ + switch(profile_idc) + { + case 66: + return "Baseline"; + case 77: + return "Main"; + case 88: + return "Extended"; + case 100: + return "High"; + case 110: + return "High 10"; + case 122: + return "High 4:2:2"; + case 244: + return "High 4:4:4 Predictive"; + case 44: + return "CAVLC 4:4:4"; + case 83: + return "Scalable Baseline"; + case 86: + return "Scalable High"; + case 118: + return "Multiview High"; + case 128: + return "Stereo High"; + default: + return "Unknown"; + } +} + +std::string H264Utils::LevelToString(uint8_t level_idc) +{ + switch(level_idc) + { + case 10: + return "1"; + case 11: + return "1.1"; + case 12: + return "1.2"; + case 13: + return "1.3"; + case 20: + return "2"; + case 21: + return "2.1"; + case 22: + return "2.2"; + case 30: + return "3"; + case 31: + return "3.1"; + case 32: + return "3.2"; + case 40: + return "4"; + case 41: + return "4.1"; + case 42: + return "4.2"; + case 50: + return "5"; + case 51: + return "5.1"; + case 52: + return "5.2"; + case 60: + return "6"; + case 61: + return "6.1"; + case 62: + return "6.2"; + default: + return "Unknown"; + } +} \ No newline at end of file diff --git a/h264parser/tests/Params.cpp b/h264parser/tests/Params.cpp new file mode 100644 index 0000000..d46d7ff --- /dev/null +++ b/h264parser/tests/Params.cpp @@ -0,0 +1,9 @@ +#include "Params.h" + +#include + +std::string getSourceDir() +{ + boost::filesystem::path full_path(boost::filesystem::current_path()); + return full_path.string() + "/h264parser/tests"; +} \ No newline at end of file diff --git a/h264parser/tests/Params.h b/h264parser/tests/Params.h new file mode 100644 index 0000000..e0ad1d1 --- /dev/null +++ b/h264parser/tests/Params.h @@ -0,0 +1,8 @@ +#ifndef PARAMS_H_ +#define PARAMS_H_ + +#include + +std::string getSourceDir(); + +#endif \ No newline at end of file diff --git a/h264parser/tests/Parsing.cpp b/h264parser/tests/Parsing.cpp new file mode 100644 index 0000000..e903fd8 --- /dev/null +++ b/h264parser/tests/Parsing.cpp @@ -0,0 +1,67 @@ +#include + +#include +#include + +#include "Params.h" + +#include +#include + +using namespace H264; + +class Consumer: public Parser::Consumer +{ +public: + struct NALUInfo + { + std::shared_ptr m_pnalu; + Parser::Info m_info; + }; + + virtual void onNALUnit(std::shared_ptr pNALUnit, const Parser::Info *pInfo) + { + NALUInfo naluInfo; + naluInfo.m_pnalu = pNALUnit; + naluInfo.m_info = *pInfo; + m_nalus.push_back(naluInfo); + } + + virtual void onWarning(const std::string &warning, const Parser::Info *pInfo, Parser::WarningType) + { + std::cout << "Warning: " << warning << std::endl; + } + + std::vector m_nalus; +}; + +BOOST_AUTO_TEST_CASE(BASIC_PARSING) +{ + Parser *pparser = Parser::create(); + + Consumer consumer; + + pparser -> addConsumer(&consumer); + + // Simple test data with SPS NAL unit + uint8_t testData[] = { + 0x00, 0x00, 0x00, 0x01, // Start code + 0x67, // NAL header (SPS) + 0x42, 0x00, 0x1E, // profile_idc, constraints, level_idc + 0xFF, 0xE1, 0x00, 0x18, // More SPS data (simplified) + 0x00, 0x00, 0x00, 0x01, // Next start code + 0x68, // NAL header (PPS) + 0xCE, 0x3C, 0x80 // PPS data (simplified) + }; + + pparser -> process(testData, sizeof(testData)); + + pparser -> releaseConsumer(&consumer); + Parser::release(pparser); + + BOOST_CHECK(consumer.m_nalus.size() >= 1); + if(consumer.m_nalus.size() >= 1) + { + BOOST_CHECK_EQUAL(consumer.m_nalus[0].m_pnalu -> getType(), NAL_SPS); + } +} \ No newline at end of file diff --git a/h264parser/tests/main.cpp b/h264parser/tests/main.cpp new file mode 100644 index 0000000..6094ff5 --- /dev/null +++ b/h264parser/tests/main.cpp @@ -0,0 +1,2 @@ +#define BOOST_TEST_MODULE H264ParserTest +#include \ No newline at end of file diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index a93e9df..c6f330a 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -1 +1,11 @@ add_subdirectory(hevc_es_browser_console) +add_subdirectory(video_es_browser_console) + +# Find Qt5 for GUI application +find_package(Qt5 COMPONENTS Core Widgets QUIET) +if(Qt5_FOUND) + message(STATUS "Qt5 found, building GUI application") + add_subdirectory(hevc_es_browser_gui) +else() + message(STATUS "Qt5 not found, skipping GUI application") +endif() \ No newline at end of file diff --git a/utils/hevc_es_browser_gui/CMakeLists.txt b/utils/hevc_es_browser_gui/CMakeLists.txt new file mode 100644 index 0000000..256f09f --- /dev/null +++ b/utils/hevc_es_browser_gui/CMakeLists.txt @@ -0,0 +1,72 @@ +project(hevcesbrowser) + +find_package(Qt5 REQUIRED COMPONENTS Core Widgets) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +set(SOURCES + main.cpp + MainWindow.cpp + CentralWidget.cpp + CommonInfoViewer.cpp + SyntaxViewer.cpp + WarningsViewer.cpp + StreamInfoViewer.cpp + HDRInfoViewer.cpp + ProfileConformanceAnalyzer.cpp + VideoParser.cpp + UnifiedCommonInfoViewer.cpp + UnifiedWarningsViewer.cpp + ../common/ConvToString.cpp + ../../external/QHexView/src/QHexView.cpp +) + +set(HEADERS + MainWindow.h + CentralWidget.h + CommonInfoViewer.h + SyntaxViewer.h + WarningsViewer.h + StreamInfoViewer.h + HDRInfoViewer.h + ProfileConformanceAnalyzer.h + VideoParser.h + UnifiedCommonInfoViewer.h + UnifiedWarningsViewer.h + types.h + ../common/ConvToString.h + ../../external/QHexView/include/QHexView.h +) + +# Generate version info +add_custom_command( + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/version_info.h + COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/verinfo/verinfo.sh ${CMAKE_CURRENT_SOURCE_DIR}/version ${CMAKE_CURRENT_SOURCE_DIR}/version_info.h + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Generating version info" +) + +add_custom_target(version_info_target DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/version_info.h) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../../hevcparser/include + ${CMAKE_CURRENT_SOURCE_DIR}/../../h264parser/include + ${CMAKE_CURRENT_SOURCE_DIR}/../common + ${CMAKE_CURRENT_SOURCE_DIR}/../../external/QHexView/include +) + +add_executable(hevcesbrowser WIN32 ${SOURCES} ${HEADERS}) +add_dependencies(hevcesbrowser version_info_target) + +target_link_libraries(hevcesbrowser + Qt5::Core + Qt5::Widgets + hevcparser + h264parser +) + +add_dependencies(hevcesbrowser hevcparser h264parser) \ No newline at end of file diff --git a/utils/hevc_es_browser_gui/CentralWidget.cpp b/utils/hevc_es_browser_gui/CentralWidget.cpp index 91b6820..1d2c6c6 100644 --- a/utils/hevc_es_browser_gui/CentralWidget.cpp +++ b/utils/hevc_es_browser_gui/CentralWidget.cpp @@ -15,11 +15,13 @@ CentralWidget::CentralWidget(QWidget *pwgt): QWidget(pwgt) ,m_pcomInfoViewer(new CommonInfoViewer) + ,m_punifiedComInfoViewer(new UnifiedCommonInfoViewer) ,m_psyntaxViewer(new SyntaxViewer) ,m_phexViewer(new QHexView) { m_psplitterH = new QSplitter; - m_psplitterH->addWidget(m_pcomInfoViewer.data()); + // Use the unified viewer by default + m_psplitterH->addWidget(m_punifiedComInfoViewer.data()); m_psplitterH->addWidget(m_phexViewer.data()); m_psplitterH->setOrientation(Qt::Vertical); @@ -36,6 +38,7 @@ CentralWidget::CentralWidget(QWidget *pwgt): m_psyntaxViewer -> header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); m_psyntaxViewer -> header()->setStretchLastSection(false); + // Connection of the existing HEVC viewer (to maintain compatibility) QObject::connect(m_pcomInfoViewer.data(), SIGNAL(naluSelected(std::shared_ptr, ParserInfo)), m_psyntaxViewer.data(), @@ -51,6 +54,29 @@ CentralWidget::CentralWidget(QWidget *pwgt): this, SLOT(setHexOffset(std::shared_ptr, ParserInfo))); + // Connection of the unified viewer + QObject::connect(m_punifiedComInfoViewer.data(), + SIGNAL(naluSelected(std::shared_ptr, VideoParserInfo)), + this, + SLOT(setUnifiedHexOffset(std::shared_ptr, VideoParserInfo))); + + QObject::connect(m_punifiedComInfoViewer.data(), + SIGNAL(hevcParameterSetsChanged(const VPSMap &, const SPSMap &, const PPSMap &)), + m_psyntaxViewer.data(), + SLOT(setParameretsSets(const VPSMap &, const SPSMap &, const PPSMap &))); + + // Connection of the unified viewer to SyntaxViewer (supports HEVC and H264 NAL units) + QObject::connect(m_punifiedComInfoViewer.data(), + SIGNAL(naluSelected(std::shared_ptr, VideoParserInfo)), + this, + SLOT(onUnifiedNaluSelected(std::shared_ptr, VideoParserInfo))); + + // Direct connection to the unified method of SyntaxViewer + QObject::connect(m_punifiedComInfoViewer.data(), + SIGNAL(naluSelected(std::shared_ptr, VideoParserInfo)), + m_psyntaxViewer.data(), + SLOT(onVideoNalUChanged(std::shared_ptr, VideoParserInfo))); + setLayout(phblay); @@ -72,6 +98,22 @@ void CentralWidget::setHexOffset(std::shared_ptr, ParserInfo info } +void CentralWidget::setUnifiedHexOffset(std::shared_ptr pNALUnit, VideoParserInfo info) +{ + m_phexViewer -> showFromOffset(info.m_position); + m_phexViewer->setFocus(); +} + + +void CentralWidget::onUnifiedNaluSelected(std::shared_ptr pNALUnit, VideoParserInfo info) +{ + // The SyntaxViewer now handles all NAL unit types through direct connection + // This method is reserved for other possible processing logic + (void)pNALUnit; + (void)info; +} + + void CentralWidget::saveCustomData() { QSettings settings("HEVCESBrowser", "HEVCESBrowser"); diff --git a/utils/hevc_es_browser_gui/CentralWidget.h b/utils/hevc_es_browser_gui/CentralWidget.h index 42c5961..693ad73 100644 --- a/utils/hevc_es_browser_gui/CentralWidget.h +++ b/utils/hevc_es_browser_gui/CentralWidget.h @@ -9,6 +9,8 @@ #include "CommonInfoViewer.h" #include "SyntaxViewer.h" +#include "UnifiedCommonInfoViewer.h" +#include "VideoParser.h" class CentralWidget: public QWidget { @@ -19,6 +21,7 @@ class CentralWidget: public QWidget ~CentralWidget(); QSharedPointer m_pcomInfoViewer; + QSharedPointer m_punifiedComInfoViewer; QSharedPointer m_psyntaxViewer; QSharedPointer m_phexViewer; @@ -29,6 +32,8 @@ class CentralWidget: public QWidget private slots: void setHexOffset(std::shared_ptr, ParserInfo); + void setUnifiedHexOffset(std::shared_ptr, VideoParserInfo); + void onUnifiedNaluSelected(std::shared_ptr, VideoParserInfo); private: QSplitter *m_psplitterV; diff --git a/utils/hevc_es_browser_gui/CommonInfoViewer.cpp b/utils/hevc_es_browser_gui/CommonInfoViewer.cpp index c0f339b..ab3eeb6 100644 --- a/utils/hevc_es_browser_gui/CommonInfoViewer.cpp +++ b/utils/hevc_es_browser_gui/CommonInfoViewer.cpp @@ -180,6 +180,7 @@ void CommonInfoViewer::onNALUnit(std::shared_ptr pNALUnit, const void CommonInfoViewer::onSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected) { + (void)deselected; QModelIndexList idxs = selected.indexes(); if(!idxs.empty()) diff --git a/utils/hevc_es_browser_gui/CommonInfoViewer.h b/utils/hevc_es_browser_gui/CommonInfoViewer.h index 1eed8cf..7e7987a 100644 --- a/utils/hevc_es_browser_gui/CommonInfoViewer.h +++ b/utils/hevc_es_browser_gui/CommonInfoViewer.h @@ -32,7 +32,10 @@ class CommonInfoViewer: void clear(); virtual void onNALUnit(std::shared_ptr pNALUnit, const HEVC::Parser::Info *pInfo); - virtual void onWarning(const std::string &warning, const HEVC::Parser::Info *pInfo, HEVC::Parser::WarningType) {}; + virtual void onWarning(const std::string &warning, const HEVC::Parser::Info *pInfo, HEVC::Parser::WarningType) { + (void)warning; + (void)pInfo; + }; private slots: void onSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected); diff --git a/utils/hevc_es_browser_gui/MainWindow.cpp b/utils/hevc_es_browser_gui/MainWindow.cpp index f6246b7..2c0bfff 100644 --- a/utils/hevc_es_browser_gui/MainWindow.cpp +++ b/utils/hevc_es_browser_gui/MainWindow.cpp @@ -24,10 +24,13 @@ #include "StreamInfoViewer.h" #include "HDRInfoViewer.h" #include "ProfileConformanceAnalyzer.h" +#include "UnifiedWarningsViewer.h" #include "version_info.h" #include +#include +#include "VideoParser.h" MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags): QMainWindow(parent, flags) @@ -87,68 +90,163 @@ void MainWindow::process(const QString &fileName) return; } - HEVC::Parser *pparser = HEVC::Parser::create(); + // Read the file header for codec detection + QByteArray headerData = file.read(1024); + file.seek(0); + + // Create a unified video parser + VideoParser videoParser; + VideoCodec codec = videoParser.detectCodec((const uint8_t*)headerData.data(), headerData.size()); + + if (codec == VideoCodec::UNKNOWN) + { + QMessageBox::warning(this, "Codec Detection", "Unable to detect video codec. Trying HEVC as default."); + codec = VideoCodec::HEVC; + } + + if (!videoParser.setCodec(codec)) + { + QMessageBox::critical(this, "Parser Error", "Failed to initialize parser for detected codec."); + return; + } + CentralWidget *pcntwgt = dynamic_cast(centralWidget()); - pparser -> addConsumer(pcntwgt -> m_pcomInfoViewer.data()); - pparser -> addConsumer(dynamic_cast (m_pwarnViewer)); - pparser -> addConsumer(dynamic_cast (m_pinfoViewer)); - pparser -> addConsumer(dynamic_cast (m_phdrInfoViewer)); + + // Check if the unified viewer is used + if (pcntwgt->m_punifiedComInfoViewer) + { + videoParser.addConsumer(pcntwgt->m_punifiedComInfoViewer.data()); + } + else + { + // Fallback to the original HEVC viewer (only for HEVC) + if (codec == VideoCodec::HEVC) + { + HEVC::Parser *pparser = HEVC::Parser::create(); + pparser->addConsumer(pcntwgt->m_pcomInfoViewer.data()); + pparser->addConsumer(dynamic_cast(m_pwarnViewer)); + pparser->addConsumer(dynamic_cast(m_pinfoViewer)); + pparser->addConsumer(dynamic_cast(m_phdrInfoViewer)); + + ProfileConformanceAnalyzer profConfAnalyzer; + profConfAnalyzer.m_pconsumer = dynamic_cast(m_pwarnViewer); + pparser->addConsumer(&profConfAnalyzer); + + // Process the file (original logic) + processWithHEVCParser(file, pparser); + HEVC::Parser::release(pparser); + return; + } + else + { + QMessageBox::critical(this, "Unsupported", "H.264 support requires unified viewer components."); + return; + } + } + + // Add the unified warnings viewer + UnifiedWarningsViewer* unifiedWarningsViewer = dynamic_cast(m_pwarnViewer); + if (unifiedWarningsViewer) + { + videoParser.addConsumer(unifiedWarningsViewer); + } - ProfileConformanceAnalyzer profConfAnalyzer; - profConfAnalyzer.m_pconsumer = dynamic_cast (m_pwarnViewer); - pparser -> addConsumer(&profConfAnalyzer); + // Process the file using the unified video parser + processWithVideoParser(file, videoParser); +} +void MainWindow::processWithHEVCParser(QFile& file, HEVC::Parser* pparser) +{ std::size_t position = 0; QProgressBar *pprogressBar = new QProgressBar(NULL); - pprogressBar -> setWindowTitle("Opening..."); - pprogressBar -> setMinimum(0); - pprogressBar -> setMaximum(100); - pprogressBar -> setValue(0); + pprogressBar->setWindowTitle("Opening HEVC file..."); + pprogressBar->setMinimum(0); + pprogressBar->setMaximum(100); + pprogressBar->setValue(0); std::size_t fileSize = file.size(); - Qt::WindowFlags flags = pprogressBar -> windowFlags(); + Qt::WindowFlags flags = pprogressBar->windowFlags(); - pprogressBar -> show(); + pprogressBar->show(); while(!file.atEnd()) { QByteArray arr = file.read(4 * (1 << 20)); - std::size_t parsed = pparser -> process((const uint8_t *)arr.data(), arr.size(), position); + std::size_t parsed = pparser->process((const uint8_t *)arr.data(), arr.size(), position); position += parsed; if(file.atEnd()) { - break; + pprogressBar->setValue(100); } - - file.seek(position); - pprogressBar -> setValue(position * 100 / fileSize); - QCoreApplication::processEvents(); - - if(!pprogressBar -> isVisible()) + else { - break; + pprogressBar->setValue((int)(100.0 * position / fileSize)); } + QCoreApplication::processEvents(); } - if(pcntwgt -> m_pcomInfoViewer -> rowCount() > 0) + pprogressBar->close(); + delete pprogressBar; +} + +void MainWindow::processWithVideoParser(QFile& file, VideoParser& videoParser) +{ + std::size_t position = 0; + + QProgressBar *pprogressBar = new QProgressBar(NULL); + pprogressBar->setWindowTitle("Opening video file..."); + pprogressBar->setMinimum(0); + pprogressBar->setMaximum(100); + pprogressBar->setValue(0); + + std::size_t fileSize = file.size(); + + Qt::WindowFlags flags = pprogressBar->windowFlags(); + + pprogressBar->show(); + + int updateCounter = 0; + const int updateInterval = 10; // Update the UI every 10 data blocks + + while(!file.atEnd()) { - QString lastOffset = pcntwgt -> m_pcomInfoViewer -> item(pcntwgt -> m_pcomInfoViewer -> rowCount() - 1, 0) -> text(); - std::size_t start = lastOffset.indexOf('('); - std::size_t end = lastOffset.lastIndexOf(')'); - lastOffset = lastOffset.mid(start + 1); - lastOffset.remove(")"); - std::size_t lastNalUOffset = lastOffset.toULongLong(NULL); - pcntwgt -> m_pcomInfoViewer -> item(pcntwgt -> m_pcomInfoViewer -> rowCount() - 1, 1) -> setText(QString::number(position - lastNalUOffset)); + // Increase the data block size to 8MB to improve performance + QByteArray arr = file.read(8 * (1 << 20)); + std::size_t parsed = videoParser.process((const uint8_t *)arr.data(), arr.size(), position); + position += parsed; + + updateCounter++; + + // Reduce the UI update frequency to improve performance + if (updateCounter >= updateInterval || file.atEnd()) + { + if(file.atEnd()) + { + pprogressBar->setValue(100); + } + else + { + pprogressBar->setValue((int)(100.0 * position / fileSize)); + } + QCoreApplication::processEvents(); + updateCounter = 0; + + if(!pprogressBar->isVisible()) + { + break; + } + } } - pcntwgt -> m_phexViewer -> setData((QHexView::DataStorage *)new QHexView::DataStorageFile(fileName)); - - pprogressBar -> close(); + pprogressBar->close(); delete pprogressBar; - HEVC::Parser::release(pparser); + CentralWidget *pcntwgt = dynamic_cast(centralWidget()); + if (pcntwgt && pcntwgt->m_phexViewer) { + pcntwgt->m_phexViewer->setData((QHexView::DataStorage *)new QHexView::DataStorageFile(file.fileName())); + } } diff --git a/utils/hevc_es_browser_gui/MainWindow.h b/utils/hevc_es_browser_gui/MainWindow.h index 3031057..dadd074 100644 --- a/utils/hevc_es_browser_gui/MainWindow.h +++ b/utils/hevc_es_browser_gui/MainWindow.h @@ -3,13 +3,15 @@ #include #include +#include +#include "VideoParser.h" class MainWindow: public QMainWindow { Q_OBJECT public: - MainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0); + MainWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = {}); void dragEnterEvent(QDragEnterEvent *); void dropEvent(QDropEvent *); void openFile(const QString &fileName); @@ -24,6 +26,8 @@ class MainWindow: public QMainWindow private: void process(const QString &fileName); + void processWithHEVCParser(QFile& file, HEVC::Parser* pparser); + void processWithVideoParser(QFile& file, VideoParser& videoParser); virtual void closeEvent(QCloseEvent *); void saveCustomData(); void readCustomData(); diff --git a/utils/hevc_es_browser_gui/SyntaxViewer.cpp b/utils/hevc_es_browser_gui/SyntaxViewer.cpp index 6058141..bf81623 100644 --- a/utils/hevc_es_browser_gui/SyntaxViewer.cpp +++ b/utils/hevc_es_browser_gui/SyntaxViewer.cpp @@ -1,2686 +1,3129 @@ -#include "SyntaxViewer.h" - -#include -#include -#include - -#include - -#include - -#define SLICE_B 0 -#define SLICE_P 1 -#define SLICE_I 2 - -SyntaxViewer::SyntaxViewer(QWidget* pwgt): - QTreeWidget(pwgt) -{ - header()->hide(); - QObject::connect(this, SIGNAL(itemCollapsed(QTreeWidgetItem *)), SLOT(onItemCollapsed(QTreeWidgetItem *))); - QObject::connect(this, SIGNAL(itemExpanded(QTreeWidgetItem *)), SLOT(onItemExpanded(QTreeWidgetItem *))); -} - - -void SyntaxViewer::setParameretsSets(const VPSMap &vpsMap, - const SPSMap &spsMap, - const PPSMap &ppsMap) -{ - m_vpsMap = vpsMap; - m_spsMap = spsMap; - m_ppsMap = ppsMap; -} - - -void SyntaxViewer::onNalUChanged(std::shared_ptr pNalU, ParserInfo info) -{ - clear(); - using namespace HEVC; - switch(pNalU -> m_nalHeader.type) - { - case NAL_VPS: - { - std::shared_ptr pVPS = std::dynamic_pointer_cast(pNalU); - createVPS(pVPS); - break; - } - - case NAL_SPS: - { - std::shared_ptr pSPS = std::dynamic_pointer_cast(pNalU); - createSPS(pSPS); - break; - } - - case NAL_PPS: - { - std::shared_ptr pPPS = std::dynamic_pointer_cast(pNalU); - createPPS(pPPS); - break; - } - - case NAL_TRAIL_R: - case NAL_TRAIL_N: - case NAL_TSA_N: - case NAL_TSA_R: - case NAL_STSA_N: - case NAL_STSA_R: - case NAL_BLA_W_LP: - case NAL_BLA_W_RADL: - case NAL_BLA_N_LP: - case NAL_IDR_W_RADL: - case NAL_IDR_N_LP: - case NAL_CRA_NUT: - case NAL_RADL_N: - case NAL_RADL_R: - case NAL_RASL_N: - case NAL_RASL_R: - { - createSlice(std::dynamic_pointer_cast(pNalU)); - break; - } - - case NAL_AUD: - { - createAUD(std::dynamic_pointer_cast(pNalU)); - break; - } - - case NAL_SEI_PREFIX: - case NAL_SEI_SUFFIX: - { - createSEI(std::dynamic_pointer_cast(pNalU)); - break; - } - - default: - break; - }; - - updateItemsState(); -} - - -void SyntaxViewer::createVPS(std::shared_ptr pVPS) -{ - QTreeWidgetItem *pvpsItem = new QTreeWidgetItem(QStringList("VPS")); - addTopLevelItem(pvpsItem); - - pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_video_parameter_set_id = " + QString::number(pVPS -> vps_video_parameter_set_id)))); - pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_max_layers_minus1 = " + QString::number(pVPS -> vps_max_layers_minus1)))); - pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_max_sub_layers_minus1 = " + QString::number(pVPS -> vps_max_sub_layers_minus1)))); - pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_temporal_id_nesting_flag = " + QString::number(pVPS -> vps_temporal_id_nesting_flag)))); - - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("profile_tier_level")); - pvpsItem -> addChild(pitem); - createProfileTierLevel(pVPS -> profile_tier_level, pitem); - - - pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_sub_layer_ordering_info_present_flag = " + QString::number(pVPS -> vps_sub_layer_ordering_info_present_flag)))); - - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = ( vps_sub_layer_ordering_info_present_flag ? 0 : vps_max_sub_layers_minus1 ); i <= vps_max_sub_layers_minus1; i++ )")); - - pvpsItem -> addChild(ploop); - - for(std::size_t i = (pVPS -> vps_sub_layer_ordering_info_present_flag ? 0 : pVPS -> vps_max_sub_layers_minus1); i <= pVPS -> vps_max_sub_layers_minus1; i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("vps_max_dec_pic_buffering_minus1[" + QString::number(i) + "] = " + QString::number(pVPS -> vps_max_dec_pic_buffering_minus1[i])))); - ploop -> addChild(new QTreeWidgetItem(QStringList("vps_max_num_reorder_pics[" + QString::number(i) + "] = " + QString::number(pVPS -> vps_max_num_reorder_pics[i])))); - ploop -> addChild(new QTreeWidgetItem(QStringList("vps_max_latency_increase_plus1[" + QString::number(i) + "] = " + QString::number(pVPS -> vps_max_latency_increase_plus1[i])))); - } - - pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_max_layer_id = " + QString::number(pVPS -> vps_max_layer_id)))); - pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_num_layer_sets_minus1 = " + QString::number(pVPS -> vps_num_layer_sets_minus1)))); - - - if(pVPS -> vps_num_layer_sets_minus1 == 0) - { - pvpsItem -> addChild(new QTreeWidgetItem(QStringList("layer_id_included_flag = { }"))); - } - else - { - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for(std::size_t i=0; i vps_num_layer_sets_minus1; i++) - { - QString str; - - if(pVPS -> vps_max_layer_id == 0) - str = "layer_id_included_flag[" + QString::number(i) + "] = { } "; - else - { - for(int j=0; j vps_max_layer_id - 1; j++) - { - str += QString::number(pVPS -> layer_id_included_flag[i][j]) + ", "; - if((j + 1) % 8) - str += "\n"; - } - str += QString::number(pVPS -> layer_id_included_flag[i][pVPS -> vps_max_layer_id - 1]) + " } "; - } - ploop -> addChild(new QTreeWidgetItem(QStringList(str))); - } - } - - pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_timing_info_present_flag = " + QString::number(pVPS -> vps_timing_info_present_flag)))); - - if(pVPS -> vps_timing_info_present_flag) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( vps_timing_info_present_flag )")); - pvpsItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("vps_num_units_in_tick = " + QString::number(pVPS -> vps_num_units_in_tick)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("vps_time_scale = " + QString::number(pVPS -> vps_time_scale)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("vps_poc_proportional_to_timing_flag = " + QString::number(pVPS -> vps_poc_proportional_to_timing_flag)))); - - if(pVPS -> vps_poc_proportional_to_timing_flag) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( vps_poc_proportional_to_timing_flag )")); - pitem -> addChild(pitemSecond); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("vps_num_ticks_poc_diff_one_minus1 = " + QString::number(pVPS -> vps_num_ticks_poc_diff_one_minus1)))); - } - - pitem -> addChild(new QTreeWidgetItem(QStringList("vps_num_hrd_parameters = " + QString::number(pVPS -> vps_num_hrd_parameters)))); - - if(pVPS -> vps_num_hrd_parameters) - { - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < vps_num_hrd_parameters; i++ )")); - pitem -> addChild(ploop); - - for(std::size_t i=0; i vps_num_hrd_parameters; i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("hrd_layer_set_idx[ " + QString::number(i) + "] = " + QString::number(pVPS -> hrd_layer_set_idx[i])))); - if(i > 0) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( i > 0 )")); - ploop -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("cprms_present_flag[ " + QString::number(i) + "] = " + QString::number(pVPS -> cprms_present_flag[i])))); - } - - - QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("hrd_parameters(" + QString::number(i) + ", " + QString::number(pVPS -> vps_max_sub_layers_minus1) + ")")); - ploop -> addChild(pitemThird); - - createHrdParameters(pVPS -> hrd_parameters[i], pVPS -> cprms_present_flag[i], pitemThird); - } - } - } - - pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_extension_flag = " + QString::number(pVPS -> vps_extension_flag)))); -} - - - -void SyntaxViewer::createSPS(std::shared_ptr pSPS) -{ - QTreeWidgetItem *pspsItem = new QTreeWidgetItem(QStringList("SPS")); - addTopLevelItem(pspsItem); - - QTreeWidgetItem *pitem; - pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_video_parameter_set_id = " + QString::number(pSPS -> sps_video_parameter_set_id)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_max_sub_layers_minus1 = " + QString::number(pSPS -> sps_max_sub_layers_minus1)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_temporal_id_nesting_flag = " + QString::number(pSPS -> sps_temporal_id_nesting_flag)))); - - pitem = new QTreeWidgetItem(QStringList("profile_tier_level")); - pspsItem -> addChild(pitem); - createProfileTierLevel(pSPS -> profile_tier_level, pitem); - - - - pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_seq_parameter_set_id = " + QString::number(pSPS -> sps_seq_parameter_set_id)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("chroma_format_idc = " + QString::number(pSPS -> chroma_format_idc)))); - - if(pSPS -> chroma_format_idc == 3) - { - pitem = new QTreeWidgetItem(QStringList("if( chroma_format_idc == 3 )")); - pspsItem -> addChild(pitem); - pitem -> addChild(new QTreeWidgetItem(QStringList("separate_colour_plane_flag = " + QString::number(pSPS -> separate_colour_plane_flag)))); - } - - - pspsItem -> addChild(new QTreeWidgetItem(QStringList("pic_width_in_luma_samples = " + QString::number(pSPS -> pic_width_in_luma_samples)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("pic_height_in_luma_samples = " + QString::number(pSPS -> pic_height_in_luma_samples)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("conformance_window_flag = " + QString::number(pSPS -> conformance_window_flag)))); - - if(pSPS -> conformance_window_flag) - { - pitem = new QTreeWidgetItem(QStringList("if( conformance_window_flag )")); - pspsItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("conf_win_left_offset = " + QString::number(pSPS -> conf_win_left_offset)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("conf_win_right_offset = " + QString::number(pSPS -> conf_win_right_offset)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("conf_win_top_offset = " + QString::number(pSPS -> conf_win_top_offset)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("conf_win_bottom_offset = " + QString::number(pSPS -> conf_win_bottom_offset)))); - } - - pspsItem -> addChild(new QTreeWidgetItem(QStringList("bit_depth_luma_minus8 = " + QString::number(pSPS -> bit_depth_luma_minus8)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("bit_depth_chroma_minus8 = " + QString::number(pSPS -> bit_depth_chroma_minus8)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("log2_max_pic_order_cnt_lsb_minus4 = " + QString::number(pSPS -> log2_max_pic_order_cnt_lsb_minus4)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_sub_layer_ordering_info_present_flag = " + QString::number(pSPS -> sps_sub_layer_ordering_info_present_flag)))); - - pitem = new QTreeWidgetItem(QStringList("for( i = ( sps_sub_layer_ordering_info_present_flag ? 0 : sps_max_sub_layers_minus1 );i <= sps_max_sub_layers_minus1; i++ )")); - pspsItem -> addChild(pitem); - - for(std::size_t i = (pSPS -> sps_sub_layer_ordering_info_present_flag ? 0 : pSPS -> sps_max_sub_layers_minus1); i <= pSPS -> sps_max_sub_layers_minus1; i++ ) - { - pitem -> addChild(new QTreeWidgetItem(QStringList("sps_max_dec_pic_buffering_minus1[" + QString::number(i) + "] = " + QString::number(pSPS -> sps_max_dec_pic_buffering_minus1[i])))); - pitem -> addChild(new QTreeWidgetItem(QStringList("sps_max_num_reorder_pics[" + QString::number(i) + "] = " + QString::number(pSPS -> sps_max_num_reorder_pics[i])))); - pitem -> addChild(new QTreeWidgetItem(QStringList("sps_max_latency_increase_plus1[" + QString::number(i) + "] = " + QString::number(pSPS -> sps_max_latency_increase_plus1[i])))); - } - - - pspsItem -> addChild(new QTreeWidgetItem(QStringList("log2_min_luma_coding_block_size_minus3 = " + QString::number(pSPS -> log2_min_luma_coding_block_size_minus3)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("log2_diff_max_min_luma_coding_block_size = " + QString::number(pSPS -> log2_diff_max_min_luma_coding_block_size)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("log2_min_transform_block_size_minus2 = " + QString::number(pSPS -> log2_min_transform_block_size_minus2)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("log2_diff_max_min_transform_block_size = " + QString::number(pSPS -> log2_diff_max_min_transform_block_size)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("max_transform_hierarchy_depth_inter = " + QString::number(pSPS -> max_transform_hierarchy_depth_inter)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("max_transform_hierarchy_depth_intra = " + QString::number(pSPS -> max_transform_hierarchy_depth_intra)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("scaling_list_enabled_flag = " + QString::number(pSPS -> scaling_list_enabled_flag)))); - - if(pSPS -> scaling_list_enabled_flag) - { - pitem = new QTreeWidgetItem(QStringList("if( scaling_list_enabled_flag )")); - pspsItem -> addChild(pitem); - pitem -> addChild(new QTreeWidgetItem(QStringList("sps_scaling_list_data_present_flag = " + QString::number(pSPS -> sps_scaling_list_data_present_flag)))); - - if(pSPS -> sps_scaling_list_data_present_flag) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("scaling_list_data( )")); - pitem -> addChild(pitemSecond); - createScalingListData(pSPS -> scaling_list_data, pitemSecond); - } - } - - pspsItem -> addChild(new QTreeWidgetItem(QStringList("amp_enabled_flag = " + QString::number(pSPS -> amp_enabled_flag)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("sample_adaptive_offset_enabled_flag = " + QString::number(pSPS -> sample_adaptive_offset_enabled_flag)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("pcm_enabled_flag = " + QString::number(pSPS -> pcm_enabled_flag)))); - if(pSPS -> pcm_enabled_flag) - { - pitem = new QTreeWidgetItem(QStringList("if( pcm_enabled_flag )")); - pspsItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("pcm_sample_bit_depth_luma_minus1 = " + QString::number(pSPS -> pcm_sample_bit_depth_luma_minus1)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("pcm_sample_bit_depth_chroma_minus1 = " + QString::number(pSPS -> pcm_sample_bit_depth_chroma_minus1)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("log2_min_pcm_luma_coding_block_size_minus3 = " + QString::number(pSPS -> log2_min_pcm_luma_coding_block_size_minus3)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("log2_diff_max_min_pcm_luma_coding_block_size = " + QString::number(pSPS -> log2_diff_max_min_pcm_luma_coding_block_size)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("pcm_loop_filter_disabled_flag = " + QString::number(pSPS -> pcm_loop_filter_disabled_flag)))); - } - - pspsItem -> addChild(new QTreeWidgetItem(QStringList("num_short_term_ref_pic_sets = " + QString::number(pSPS -> num_short_term_ref_pic_sets)))); - - if(pSPS -> num_short_term_ref_pic_sets) - { - pitem = new QTreeWidgetItem(QStringList("for( i = 0; i < num_short_term_ref_pic_sets; i++)")); - pspsItem -> addChild(pitem); - - for(std::size_t i=0; i num_short_term_ref_pic_sets; i++) - { - QTreeWidgetItem *pStrpc = new QTreeWidgetItem(QStringList("short_term_ref_pic_set(" + QString::number(i) + ")")); - pitem -> addChild(pStrpc); - - HEVC::ShortTermRefPicSet rpset = pSPS -> short_term_ref_pic_set[i]; - createShortTermRefPicSet(i, rpset, pSPS -> num_short_term_ref_pic_sets, pSPS -> short_term_ref_pic_set, pStrpc); - } - } - - - pspsItem -> addChild(new QTreeWidgetItem(QStringList("long_term_ref_pics_present_flag = " + QString::number(pSPS -> long_term_ref_pics_present_flag)))); - if(pSPS -> long_term_ref_pics_present_flag) - { - pitem = new QTreeWidgetItem(QStringList("if( long_term_ref_pics_present_flag )")); - pspsItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("num_long_term_ref_pics_sps = " + QString::number(pSPS -> num_long_term_ref_pics_sps)))); - - - if(pSPS -> num_long_term_ref_pics_sps > 0) - { - QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_long_term_ref_pics_sps; i++ )")); - pitem -> addChild(pitemLoop); - - for(std::size_t i=0; i num_long_term_ref_pics_sps; i++) - { - pspsItem -> addChild(new QTreeWidgetItem(QStringList("lt_ref_pic_poc_lsb_sps[ " + QString::number(i) + "] = " + QString::number(pSPS -> lt_ref_pic_poc_lsb_sps[i])))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("used_by_curr_pic_lt_sps_flag[ " + QString::number(i) + "] = " + QString::number(pSPS -> used_by_curr_pic_lt_sps_flag[i])))); - } - } - } - - pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_temporal_mvp_enabled_flag = " + QString::number(pSPS -> sps_temporal_mvp_enabled_flag)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("strong_intra_smoothing_enabled_flag = " + QString::number(pSPS -> strong_intra_smoothing_enabled_flag)))); - pspsItem -> addChild(new QTreeWidgetItem(QStringList("vui_parameters_present_flag = " + QString::number(pSPS -> vui_parameters_present_flag)))); - - if(pSPS -> vui_parameters_present_flag) - { - pitem = new QTreeWidgetItem(QStringList("if( vui_parameters_present_flag )")); - pspsItem -> addChild(pitem); - QTreeWidgetItem *pVuiItem = new QTreeWidgetItem(QStringList("vui_parameters")); - pitem -> addChild(pVuiItem); - - createVuiParameters(pSPS -> vui_parameters, pSPS -> sps_max_sub_layers_minus1, pVuiItem); - } - - pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_extension_flag = " + QString::number(pSPS -> sps_extension_flag)))); -} - -void SyntaxViewer::createPPS(std::shared_ptr pPPS) -{ - QTreeWidgetItem *pppsItem = new QTreeWidgetItem(QStringList("PPS")); - addTopLevelItem(pppsItem); - - QTreeWidgetItem *pitem; - pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_pic_parameter_set_id = " + QString::number(pPPS -> pps_pic_parameter_set_id)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_seq_parameter_set_id = " + QString::number(pPPS -> pps_seq_parameter_set_id)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("dependent_slice_segments_enabled_flag = " + QString::number(pPPS -> dependent_slice_segments_enabled_flag)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("output_flag_present_flag = " + QString::number(pPPS -> output_flag_present_flag)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("num_extra_slice_header_bits = " + QString::number(pPPS -> num_extra_slice_header_bits)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("sign_data_hiding_flag = " + QString::number(pPPS -> sign_data_hiding_flag)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("cabac_init_present_flag = " + QString::number(pPPS -> cabac_init_present_flag)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("num_ref_idx_l0_default_active_minus1 = " + QString::number(pPPS -> num_ref_idx_l0_default_active_minus1)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("num_ref_idx_l1_default_active_minus1 = " + QString::number(pPPS -> num_ref_idx_l1_default_active_minus1)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("init_qp_minus26 = " + QString::number(pPPS -> init_qp_minus26)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("constrained_intra_pred_flag = " + QString::number(pPPS -> constrained_intra_pred_flag)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("transform_skip_enabled_flag = " + QString::number(pPPS -> transform_skip_enabled_flag)))); - - pitem = new QTreeWidgetItem(QStringList("cu_qp_delta_enabled_flag = " + QString::number(pPPS -> cu_qp_delta_enabled_flag))); - pppsItem -> addChild(pitem); - - if(pPPS -> cu_qp_delta_enabled_flag) - { - pitem = new QTreeWidgetItem(QStringList("if(cu_qp_delta_enabled_flag)")); - pppsItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("diff_cu_qp_delta_depth = " + QString::number(pPPS -> diff_cu_qp_delta_depth)))); - } - - pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_cb_qp_offset = " + QString::number(pPPS -> pps_cb_qp_offset)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_cr_qp_offset = " + QString::number(pPPS -> pps_cr_qp_offset)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_slice_chroma_qp_offsets_present_flag = " + QString::number(pPPS -> pps_slice_chroma_qp_offsets_present_flag)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("weighted_pred_flag = " + QString::number(pPPS -> weighted_pred_flag)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("weighted_bipred_flag = " + QString::number(pPPS -> weighted_bipred_flag)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("transquant_bypass_enabled_flag = " + QString::number(pPPS -> transquant_bypass_enabled_flag)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("tiles_enabled_flag = " + QString::number(pPPS -> tiles_enabled_flag)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("entropy_coding_sync_enabled_flag = " + QString::number(pPPS -> entropy_coding_sync_enabled_flag)))); - - - if(pPPS -> tiles_enabled_flag) - { - pitem = new QTreeWidgetItem(QStringList("if(tiles_enabled_flag)")); - pppsItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("num_tile_columns_minus1 = " + QString::number(pPPS -> num_tile_columns_minus1)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("num_tile_rows_minus1 = " + QString::number(pPPS -> num_tile_rows_minus1)))); - - pitem -> addChild(new QTreeWidgetItem(QStringList("uniform_spacing_flag = " + QString::number(pPPS -> uniform_spacing_flag)))); - - if(!pPPS -> uniform_spacing_flag) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if(!uniform_spacing_flag)")); - pitem -> addChild(pitemSecond); - - QString str = "column_width_minus1 = {\n\t"; - for(int i=0; i<(int)pPPS -> num_tile_columns_minus1 - 1; i++) - { - str += QString::number(pPPS -> column_width_minus1[i]) + ", "; - if((i+1) % 8 == 0) - str += "\n\t"; - } - if(pPPS -> num_tile_columns_minus1 > 0) - str += QString::number(pPPS -> column_width_minus1[pPPS -> num_tile_columns_minus1 - 1]) + " \n}"; - else - str += "}"; - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList(str))); - - str = "row_height_minus1 = {\n\t"; - for(int i=0; i<(int)pPPS -> num_tile_rows_minus1 - 1; i++) - { - str += QString::number(pPPS -> row_height_minus1[i]) + ", "; - if((i+1) % 8 == 0) - str += "\n\t"; - } - if(pPPS -> num_tile_rows_minus1 > 0) - str += QString::number(pPPS -> row_height_minus1[pPPS -> num_tile_rows_minus1 - 1]) + " \n}"; - else - str += "}"; - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList(str))); - } - - pitem -> addChild(new QTreeWidgetItem(QStringList("loop_filter_across_tiles_enabled_flag = " + QString::number(pPPS -> loop_filter_across_tiles_enabled_flag)))); - } - - pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_loop_filter_across_slices_enabled_flag = " + QString::number(pPPS -> pps_loop_filter_across_slices_enabled_flag)))); - - pppsItem -> addChild(new QTreeWidgetItem(QStringList("deblocking_filter_control_present_flag = " + QString::number(pPPS -> deblocking_filter_control_present_flag)))); - - if(pPPS -> deblocking_filter_control_present_flag) - { - - pitem = new QTreeWidgetItem(QStringList("if(deblocking_filter_control_present_flag)")); - pppsItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("deblocking_filter_override_enabled_flag = " + QString::number(pPPS -> deblocking_filter_override_enabled_flag)))); - - pitem -> addChild(new QTreeWidgetItem(QStringList("pps_deblocking_filter_disabled_flag = " + QString::number(pPPS -> pps_deblocking_filter_disabled_flag)))); - - if(!pPPS -> pps_deblocking_filter_disabled_flag) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if(!pps_deblocking_filter_disabled_flag)")); - pitem -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("pps_beta_offset_div2 = " + QString::number(pPPS -> pps_beta_offset_div2)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("pps_tc_offset_div2 = " + QString::number(pPPS -> pps_tc_offset_div2)))); - } - } - - - pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_scaling_list_data_present_flag = " + QString::number(pPPS -> pps_scaling_list_data_present_flag)))); - - if(pPPS -> pps_scaling_list_data_present_flag) - { - pitem = new QTreeWidgetItem(QStringList("if(pps_scaling_list_data_present_flag)")); - pppsItem -> addChild(pitem); - - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("scaling_list_data")); - pitem -> addChild(pitemSecond); - createScalingListData(pPPS -> scaling_list_data, pitemSecond); - - } - - pppsItem -> addChild(new QTreeWidgetItem(QStringList("lists_modification_present_flag = " + QString::number(pPPS -> lists_modification_present_flag)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("log2_parallel_merge_level_minus2 = " + QString::number(pPPS -> log2_parallel_merge_level_minus2)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("slice_segment_header_extension_present_flag = " + QString::number(pPPS -> slice_segment_header_extension_present_flag)))); - pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_extension_flag = " + QString::number(pPPS -> pps_extension_flag)))); -} - -void SyntaxViewer::createSlice(std::shared_ptr pSlice) -{ - if(pSlice -> m_processFailed) - return; - - std::shared_ptr pPPS = m_ppsMap[pSlice -> slice_pic_parameter_set_id]; - if(!pPPS) - return; - - int32_t spsId = pPPS -> pps_seq_parameter_set_id; - QTreeWidgetItem *pitemDepend, *pitemThird; - QTreeWidgetItem *psliceItem = new QTreeWidgetItem(QStringList("Slice")); - addTopLevelItem(psliceItem); - - QTreeWidgetItem *pitem; - psliceItem -> addChild(new QTreeWidgetItem(QStringList("first_slice_segment_in_pic_flag = " + QString::number(pSlice -> first_slice_segment_in_pic_flag)))); - - if(pSlice -> m_nalHeader.type >= HEVC::NAL_BLA_W_LP && pSlice -> m_nalHeader.type <= HEVC::NAL_IRAP_VCL23) - { - pitem = new QTreeWidgetItem(QStringList("if ( nal_unit_type >= BLA_W_LP && nal_unit_type <= RSV_IRAP_VCL23)")); - psliceItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("no_output_of_prior_pics_flag = " + QString::number(pSlice -> no_output_of_prior_pics_flag)))); - } - - psliceItem -> addChild(new QTreeWidgetItem(QStringList("slice_pic_parameter_set_id = " + QString::number(pSlice -> slice_pic_parameter_set_id)))); - - if(!pSlice -> first_slice_segment_in_pic_flag) - { - pitem = new QTreeWidgetItem(QStringList("if (!first_slice_segment_in_pic_flag)")); - psliceItem -> addChild(pitem); - - if(pPPS -> dependent_slice_segments_enabled_flag) - { - pitemDepend = new QTreeWidgetItem(QStringList("pps -> dependent_slice_segments_enabled_flag = " + QString::number(pPPS -> dependent_slice_segments_enabled_flag))); - pitem -> addChild(pitemDepend); - - pitemDepend -> addChild(new QTreeWidgetItem(QStringList("dependent_slice_segment_flag = " + QString::number(pSlice -> dependent_slice_segment_flag)))); - } - pitem -> addChild(new QTreeWidgetItem(QStringList("slice_segment_address = " + QString::number(pSlice -> slice_segment_address)))); - } - - if(!pSlice -> dependent_slice_segment_flag) - { - pitem = new QTreeWidgetItem(QStringList("if (!dependent_slice_segment_flag)")); - psliceItem -> addChild(pitem); - - long num_extra_slice_header_bits = pPPS -> num_extra_slice_header_bits; - - QString str; - if(num_extra_slice_header_bits > 0) - { - str = "slice_reserved_undetermined_flag = {\n\t"; - - if(num_extra_slice_header_bits > pSlice -> slice_reserved_undetermined_flag.size()) - return; - - for(long i=0; i slice_reserved_undetermined_flag[i]) + ", "; - - str += QString::number(pSlice -> slice_reserved_undetermined_flag[num_extra_slice_header_bits - 1]) + ", "; - } - else - str = "slice_reserved_undetermined_flag = { }"; - - pitem -> addChild(new QTreeWidgetItem(QStringList(str))); - pitem -> addChild(new QTreeWidgetItem(QStringList("slice_type = " + QString::number(pSlice -> slice_type)))); - - if(pPPS -> output_flag_present_flag) - { - pitemDepend = new QTreeWidgetItem(QStringList("if (output_flag_present_flag)")); - pitem -> addChild(pitemDepend); - pitemDepend -> addChild(new QTreeWidgetItem(QStringList("pic_output_flag = " + QString::number(pSlice -> pic_output_flag)))); - } - - - if(!m_spsMap[spsId]) - return; - - if(m_spsMap[spsId] -> separate_colour_plane_flag) - { - pitemDepend = new QTreeWidgetItem(QStringList("if (sps -> separate_colour_plane_flag)")); - pitem -> addChild(pitemDepend); - pitemDepend -> addChild(new QTreeWidgetItem(QStringList("colour_plane_id = " + QString::number(pSlice -> colour_plane_id)))); - } - bool IdrPicFlag = pSlice -> m_nalHeader.type == HEVC::NAL_IDR_W_RADL || pSlice -> m_nalHeader.type == HEVC::NAL_IDR_N_LP; - - if(!IdrPicFlag) - { - pitemDepend = new QTreeWidgetItem(QStringList("if (nal_unit_type != IDR_W_RADL && nal_unit_type != IDR_N_LP)")); - pitem -> addChild(pitemDepend); - - pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_pic_order_cnt_lsb = " + QString::number(pSlice -> slice_pic_order_cnt_lsb)))); - - QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("short_term_ref_pic_set_sps_flag = " + QString::number(pSlice -> short_term_ref_pic_set_sps_flag))); - pitemDepend -> addChild(pitemThird); - if(!pSlice -> short_term_ref_pic_set_sps_flag) - { - pitemThird = new QTreeWidgetItem(QStringList("if (!short_term_ref_pic_set_sps_flag)")); - pitemDepend -> addChild(pitemThird); - QTreeWidgetItem *pStrpc = new QTreeWidgetItem(QStringList("short_term_ref_pic_set(" + QString::number(m_spsMap[spsId] -> num_short_term_ref_pic_sets) + ")")); - pitemThird -> addChild(pStrpc); - createShortTermRefPicSet(m_spsMap[spsId] -> num_short_term_ref_pic_sets, pSlice -> short_term_ref_pic_set, m_spsMap[spsId] -> num_short_term_ref_pic_sets, m_spsMap[spsId] -> short_term_ref_pic_set, pStrpc); - } - else if(m_spsMap[spsId] -> num_short_term_ref_pic_sets > 1) - { - pitemThird = new QTreeWidgetItem(QStringList("if (short_term_ref_pic_set_sps_flag && num_long_term_ref_pics_sps > 0)")); - pitemDepend -> addChild(pitemThird); - - pitemThird -> addChild(new QTreeWidgetItem(QStringList("short_term_ref_pic_set_idx = " + QString::number(pSlice -> short_term_ref_pic_set_idx)))); - } - - if(m_spsMap[spsId] -> long_term_ref_pics_present_flag) - { - pitemThird = new QTreeWidgetItem(QStringList("if (long_term_ref_pics_present_flag)")); - pitemDepend -> addChild(pitemThird); - - if(m_spsMap[spsId] -> num_long_term_ref_pics_sps > 0) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if (num_long_term_ref_pics_sps)")); - pitemThird -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("num_long_term_sps = " + QString::number(pSlice -> num_long_term_sps)))); - } - - pitemThird -> addChild(new QTreeWidgetItem(QStringList("num_long_term_pics = " + QString::number(pSlice -> num_long_term_pics)))); - - std::size_t num_long_term = pSlice -> num_long_term_sps + pSlice -> num_long_term_pics; - QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_long_term_sps + num_long_term_pics; i++ )")); - pitemThird -> addChild(pitemLoop); - - for(std::size_t i=0; i < num_long_term; i++) - { - if(i < pSlice -> num_long_term_sps) - { - QTreeWidgetItem *pitem1 = new QTreeWidgetItem(QStringList("if (i < num_long_term_sps)")); - pitemLoop -> addChild(pitem1); - - if(m_spsMap[spsId] -> num_long_term_ref_pics_sps > 1) - { - QTreeWidgetItem *pitem2 = new QTreeWidgetItem(QStringList("if (num_long_term_ref_pics_sps > 1)")); - pitem1 -> addChild(pitem2); - pitem2 -> addChild(new QTreeWidgetItem(QStringList("lt_idx_sps[" + QString::number(i) + "] = " + QString::number(pSlice -> lt_idx_sps[i])))); - } - } - else - { - QTreeWidgetItem *pitem1 = new QTreeWidgetItem(QStringList("if (i >= num_long_term_sps)")); - pitemLoop -> addChild(pitem1); - pitem1 -> addChild(new QTreeWidgetItem(QStringList("poc_lsb_lt[" + QString::number(i) + "] = " + QString::number(pSlice -> poc_lsb_lt[i])))); - pitem1 -> addChild(new QTreeWidgetItem(QStringList("used_by_curr_pic_lt_flag[" + QString::number(i) + "] = " + QString::number(pSlice -> used_by_curr_pic_lt_flag[i])))); - } - - pitemLoop -> addChild(new QTreeWidgetItem(QStringList("delta_poc_msb_present_flag[" + QString::number(i) + "] = " + QString::number(pSlice -> delta_poc_msb_present_flag[i])))); - if(pSlice -> delta_poc_msb_present_flag[i]) - { - QTreeWidgetItem *pitem1 = new QTreeWidgetItem(QStringList("if (delta_poc_msb_present_flag[" + QString::number(i) + "])")); - pitemLoop -> addChild(pitem1); - pitem1 -> addChild(new QTreeWidgetItem(QStringList("delta_poc_msb_cycle_lt[" + QString::number(i) + "] = " + QString::number(pSlice -> delta_poc_msb_cycle_lt[i])))); - } - } - } - - if(m_spsMap[spsId] -> sps_temporal_mvp_enabled_flag) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if (sps_temporal_mvp_enabled_flag)")); - pitemDepend -> addChild(pitemSecond); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("slice_temporal_mvp_enabled_flag = " + QString::number(pSlice -> slice_temporal_mvp_enabled_flag)))); - } - } - - if(m_spsMap[spsId] -> sample_adaptive_offset_enabled_flag) - { - pitemDepend = new QTreeWidgetItem(QStringList("if (sample_adaptive_offset_enabled_flag)")); - pitem -> addChild(pitemDepend); - - pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_sao_luma_flag = " + QString::number(pSlice -> slice_sao_luma_flag)))); - pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_sao_chroma_flag = " + QString::number(pSlice -> slice_sao_chroma_flag)))); - } - - if(pSlice -> slice_type == SLICE_B || pSlice -> slice_type == SLICE_P) - { - pitemDepend = new QTreeWidgetItem(QStringList("if (slice_type == P || slice_type == B)")); - pitem -> addChild(pitemDepend); - - pitemDepend -> addChild(new QTreeWidgetItem(QStringList("num_ref_idx_active_override_flag = " + QString::number(pSlice -> num_ref_idx_active_override_flag)))); - - if(pSlice -> num_ref_idx_active_override_flag) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if (num_ref_idx_active_override_flag)")); - pitemDepend -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("num_ref_idx_l0_active_minus1 = " + QString::number(pSlice -> num_ref_idx_l0_active_minus1)))); - - if(pSlice -> slice_type == SLICE_B) - { - QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("if (slice_type == B)")); - pitemSecond -> addChild(pitemThird); - - pitemThird -> addChild(new QTreeWidgetItem(QStringList("num_ref_idx_l1_active_minus1 = " + QString::number(pSlice -> num_ref_idx_l1_active_minus1)))); - } - } - - if(pPPS -> lists_modification_present_flag) - { - std::size_t NumPocTotalCurr = calcNumPocTotalCurr(pSlice, m_spsMap[spsId]); - - if(NumPocTotalCurr > 1) - { - pitemThird = new QTreeWidgetItem(QStringList("if (lists_modification_present_flag && NumPocTotalCurr > 1 )")); - pitemDepend -> addChild(pitemThird); - QTreeWidgetItem *pitemRplMod = new QTreeWidgetItem(QStringList("short_term_ref_pic_set(" + QString::number(m_spsMap[spsId] -> num_short_term_ref_pic_sets) + ")")); - pitemThird -> addChild(pitemRplMod); - - - createRefPicListModification(pSlice -> ref_pic_lists_modification, pitemRplMod); - } - } - - if(pSlice -> slice_type == SLICE_B) - { - pitemThird = new QTreeWidgetItem(QStringList("if (slice_type == B)")); - pitemDepend -> addChild(pitemThird); - pitemThird -> addChild(new QTreeWidgetItem(QStringList("mvd_l1_zero_flag = " + QString::number(pSlice -> mvd_l1_zero_flag)))); - } - - if(pPPS -> cabac_init_present_flag) - { - pitemThird = new QTreeWidgetItem(QStringList("if (cabac_init_present_flag)")); - pitemDepend -> addChild(pitemThird); - pitemThird-> addChild(new QTreeWidgetItem(QStringList("cabac_init_flag = " + QString::number(pSlice -> cabac_init_flag)))); - } - - if(pSlice -> slice_temporal_mvp_enabled_flag) - { - pitemThird = new QTreeWidgetItem(QStringList("if (slice_temporal_mvp_enabled_flag)")); - pitemDepend -> addChild(pitemThird); - - if(pSlice -> slice_type == SLICE_B) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if (slice_type == B)")); - pitemThird -> addChild(pitemSecond); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("collocated_from_l0_flag = " + QString::number(pSlice -> collocated_from_l0_flag)))); - } - - if((pSlice -> collocated_from_l0_flag && pSlice -> num_ref_idx_l0_active_minus1) || - (!pSlice -> collocated_from_l0_flag && pSlice -> num_ref_idx_l1_active_minus1)) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if ((collocated_from_l0_flag && num_ref_idx_l0_active_minus1 > 0 ) || (!collocated_from_l0_flag && num_ref_idx_l1_active_minus1 > 0))")); - pitemThird -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("collocated_ref_idx = " + QString::number(pSlice -> collocated_ref_idx)))); - } - } - - if((pPPS -> weighted_pred_flag && pSlice -> slice_type == SLICE_P) || - (pPPS -> weighted_bipred_flag && pSlice -> slice_type == SLICE_B)) - { - pitemThird = new QTreeWidgetItem(QStringList("if ((weighted_pred_flag && slice_type == P) || (weighted_bipred_flag && slice_type == B))")); - pitemDepend -> addChild(pitemThird); - - QTreeWidgetItem *pitempwt = new QTreeWidgetItem(QStringList("pred_weight_table")); - pitemThird -> addChild(pitempwt); - - createPredWeightTable(pSlice -> pred_weight_table, pSlice, pitempwt); - } - - pitemDepend -> addChild(new QTreeWidgetItem(QStringList("five_minus_max_num_merge_cand = " + QString::number(pSlice -> five_minus_max_num_merge_cand)))); - } - - pitem -> addChild(new QTreeWidgetItem(QStringList("slice_qp_delta = " + QString::number(pSlice -> slice_qp_delta)))); - - - if(pPPS -> pps_slice_chroma_qp_offsets_present_flag) - { - pitemDepend = new QTreeWidgetItem(QStringList("if (pps_slice_chroma_qp_offsets_present_flag)")); - pitem -> addChild(pitemDepend); - - pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_cb_qp_offset = " + QString::number(pSlice -> slice_cb_qp_offset)))); - pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_cr_qp_offset = " + QString::number(pSlice -> slice_cr_qp_offset)))); - } - - if(pPPS -> deblocking_filter_override_enabled_flag) - { - pitemDepend = new QTreeWidgetItem(QStringList("if (deblocking_filter_override_enabled_flag)")); - pitem -> addChild(pitemDepend); - pitemDepend -> addChild(new QTreeWidgetItem(QStringList("deblocking_filter_override_flag = " + QString::number(pSlice -> deblocking_filter_override_flag)))); - } - - if(pSlice -> deblocking_filter_override_flag) - { - pitemDepend = new QTreeWidgetItem(QStringList("if (deblocking_filter_override_flag)")); - pitem -> addChild(pitemDepend); - - pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_deblocking_filter_disabled_flag = " + QString::number(pSlice -> slice_deblocking_filter_disabled_flag)))); - - if(!pSlice -> slice_deblocking_filter_disabled_flag) - { - pitemThird = new QTreeWidgetItem(QStringList("if (!slice_deblocking_filter_disabled_flag)")); - pitemDepend -> addChild(pitemThird); - - pitemThird -> addChild(new QTreeWidgetItem(QStringList("slice_beta_offset_div2 = " + QString::number(pSlice -> slice_beta_offset_div2)))); - pitemThird -> addChild(new QTreeWidgetItem(QStringList("slice_tc_offset_div2 = " + QString::number(pSlice -> slice_tc_offset_div2)))); - } - } - - if(pPPS -> pps_loop_filter_across_slices_enabled_flag && - (pSlice -> slice_sao_luma_flag || pSlice -> slice_sao_chroma_flag || !pSlice -> slice_deblocking_filter_disabled_flag)) - { - pitemDepend = new QTreeWidgetItem(QStringList("if (pps_loop_filter_across_slices_enabled_flag && (slice_sao_luma_flag || slice_sao_chroma_flag || !slice_deblocking_filter_disabled_flag ))")); - pitem -> addChild(pitemDepend); - - pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_loop_filter_across_slices_enabled_flag = " + QString::number(pSlice -> slice_loop_filter_across_slices_enabled_flag)))); - } - } - - if(pPPS -> tiles_enabled_flag || pPPS -> entropy_coding_sync_enabled_flag) - { - pitem = new QTreeWidgetItem(QStringList("if (tiles_enabled_flag || entropy_coding_sync_enabled_flag)")); - psliceItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("num_entry_point_offsets = " + QString::number(pSlice -> num_entry_point_offsets)))); - - if(pSlice -> num_entry_point_offsets > 0) - { - pitemThird = new QTreeWidgetItem(QStringList("if (num_entry_point_offsets > 0)")); - pitem -> addChild(pitemThird); - - pitemThird -> addChild(new QTreeWidgetItem(QStringList("offset_len_minus1 = " + QString::number(pSlice -> offset_len_minus1)))); - - QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_entry_point_offsets; i++ )")); - pitemThird -> addChild(pitemLoop); - - for(std::size_t i=0; i num_entry_point_offsets; i++) - pitemLoop -> addChild(new QTreeWidgetItem(QStringList("entry_point_offset_minus1[" + QString::number(i) + "] = " + QString::number(pSlice -> entry_point_offset_minus1[i])))); - } - } - - if(pPPS -> slice_segment_header_extension_present_flag) - { - pitem = new QTreeWidgetItem(QStringList("if (slice_segment_header_extension_present_flag)")); - psliceItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("slice_segment_header_extension_length = " + QString::number(pSlice -> slice_segment_header_extension_length)))); - - QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < slice_segment_header_extension_length; i++ )")); - pitem -> addChild(pitemLoop); - - for(std::size_t i=0; i slice_segment_header_extension_length; i++) - { - pitemLoop -> addChild(new QTreeWidgetItem(QStringList("slice_segment_header_extension_data_byte[" + QString::number(i) + "] = " + QString::number(pSlice -> slice_segment_header_extension_data_byte[i])))); - } - } -} - -void SyntaxViewer::createAUD(std::shared_ptr pAUD) -{ - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("AUD")); - addTopLevelItem(pitem); - pitem -> addChild(new QTreeWidgetItem(QStringList("pic_type = " + QString::number(pAUD -> pic_type)))); -} - - -void SyntaxViewer::createSEI(std::shared_ptr pSEI) -{ - QTreeWidgetItem *pitemSEI = new QTreeWidgetItem(QStringList("SEI")); - addTopLevelItem(pitemSEI); - - - - for(std::size_t i=0; i< pSEI -> sei_message.size(); i++) - { - std::size_t payloadType = 0; - std::size_t payloadSize = 0; - - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("sei_message(" + QString::number(i) + ")")); - pitemSEI -> addChild(pitem); - - if(pSEI -> sei_message[i].num_payload_type_ff_bytes) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("while( next_bits( 8 ) == 0xFF )")); - pitem -> addChild(pitemSecond); - for(std::size_t i=0; i sei_message[i].num_payload_type_ff_bytes; i++) - { - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("0xFF"))); - payloadType += 255; - } - } - - pitem -> addChild(new QTreeWidgetItem(QStringList("last_payload_type_byte = " + QString::number(pSEI -> sei_message[i].last_payload_type_byte)))); - payloadType += pSEI -> sei_message[i].last_payload_type_byte; - - - if(pSEI -> sei_message[i].num_payload_size_ff_bytes) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("while( next_bits( 8 ) == 0xFF )")); - pitem -> addChild(pitemSecond); - for(std::size_t j=0; j sei_message[i].num_payload_size_ff_bytes; j++) - { - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("0xFF"))); - payloadSize += 255; - } - } - - pitem -> addChild(new QTreeWidgetItem(QStringList("last_payload_size_byte = " + QString::number(pSEI -> sei_message[i].last_payload_size_byte)))); - - payloadSize += pSEI -> sei_message[i].last_payload_size_byte; - switch(payloadType) - { - case HEVC::SeiMessage::DECODED_PICTURE_HASH: - { - std::shared_ptr pdecPictHash = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemDecPictHash = new QTreeWidgetItem(QStringList("decoded_picture_hash(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemDecPictHash); - createDecodedPictureHash(pdecPictHash, pitemDecPictHash); - break; - } - - case HEVC::SeiMessage::USER_DATA_UNREGISTERED: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("user_data_unregistered(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createUserDataUnregistered(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::SCENE_INFO: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("scene_info(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createSceneInfo(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::FULL_FRAME_SNAPSHOT: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("picture_snapshot(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createFullFrameSnapshot(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::PROGRESSIVE_REFINEMENT_SEGMENT_START: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("progressive_refinement_segment_start(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createProgressiveRefinementSegmentStart(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::PROGRESSIVE_REFINEMENT_SEGMENT_END: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("progressive_refinement_segment_end(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createProgressiveRefinementSegmentEnd(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::BUFFERING_PERIOD: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("buffering_period(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createBufferingPeriod(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::FILLER_PAYLOAD: - { - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("filler_payload(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - break; - } - - case HEVC::SeiMessage::PICTURE_TIMING: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("pic_timing(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createPicTiming(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::RECOVERY_POINT: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("recovery_point(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createRecoveryPoint(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::TONE_MAPPING_INFO: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("tone_mapping_info(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createToneMapping(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::FRAME_PACKING: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("frame_packing_arrangement(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createFramePacking(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::DISPLAY_ORIENTATION: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("display_orientation(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createDisplayOrientation(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::SOP_DESCRIPTION: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("structure_of_pictures_info(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createSOPDescription(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::ACTIVE_PARAMETER_SETS: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("active_parameter_sets(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createActiveParameterSets(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::TEMPORAL_LEVEL0_INDEX: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("temporal_sub_layer_zero_index(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createTemporalLevel0Index(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::REGION_REFRESH_INFO: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("region_refresh_info(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createRegionRefreshInfo(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::TIME_CODE: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("time_code(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createTimeCode(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::MASTERING_DISPLAY_INFO: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("mastering_display_info(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createMasteringDisplayInfo(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::SEGM_RECT_FRAME_PACKING: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("segm_rect_frame_packing(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createSegmRectFramePacking(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::KNEE_FUNCTION_INFO: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("knee_function_info(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createKneeFunctionInfo(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::CHROMA_RESAMPLING_FILTER_HINT: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("chroma_resampling_filter_hint(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createChromaResamplingFilterHint(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::COLOUR_REMAPPING_INFO: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("colour_remapping_info(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createColourRemappingInfo(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::CONTENT_LIGHT_LEVEL_INFO: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("content_light_level_info(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createContentLightLevelInfo(pSeiMessage, pitemSei); - break; - } - - case HEVC::SeiMessage::ALTERNATIVE_TRANSFER_CHARACTERISTICS: - { - std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); - - QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("alternative_transfer_characteristics(" + QString::number(payloadSize) + ")")); - pitem -> addChild(pitemSei); - createAlternativeTransferCharacteristics(pSeiMessage, pitemSei); - break; - } - - default: - pitem -> addChild(new QTreeWidgetItem(QStringList("sei_payload(" + QString::number(payloadType) + ", " + QString::number(payloadSize) + ")"))); - } - } -} - - -void SyntaxViewer::createProfileTierLevel(const HEVC::ProfileTierLevel &ptl, QTreeWidgetItem *pPtlItem) -{ - - pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_profile_space = " + QString::number(ptl.general_profile_space)))); - pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_tier_flag = " + QString::number(ptl.general_tier_flag)))); - pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_profile_idc = " + QString::number(ptl.general_profile_idc)))); - - QString str = "general_profile_compatibility_flag[i] = { \n\t"; - for(std::size_t i=0; i<31; i++) - { - str += QString::number(ptl.general_profile_compatibility_flag[i]) + ", "; - if((i+1) % 8 == 0) - str += "\n\t"; - } - str += QString::number(ptl.general_profile_compatibility_flag[31]) + "\n}"; - pPtlItem -> addChild(new QTreeWidgetItem(QStringList(str))); - - pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_progressive_source_flag = " + QString::number(ptl.general_progressive_source_flag)))); - pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_interlaced_source_flag = " + QString::number(ptl.general_interlaced_source_flag)))); - pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_non_packed_constraint_flag = " + QString::number(ptl.general_non_packed_constraint_flag)))); - pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_frame_only_constraint_flag = " + QString::number(ptl.general_frame_only_constraint_flag)))); - pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_level_idc = " + QString::number(ptl.general_level_idc)))); - - if(ptl.sub_layer_profile_present_flag.size() == 0) - { - pPtlItem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_profile_present_flag = {}"))); - pPtlItem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_level_present_flag = {}"))); - } - else - { - str = "sub_layer_profile_present_flag = {\n\t"; - for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList(str))); - - str = "sub_layer_level_present_flag = {\n\t"; - for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList(str))); - } - - std::size_t maxNumSubLayersMinus1 = ptl.sub_layer_profile_present_flag.size(); - bool needLoop = false; - - for(std::size_t i=0; i addChild(pitemLoop); - - for(std::size_t i=0; i addChild(pitem); - - - pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_profile_space[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_profile_space[i])))); - pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_tier_flag[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_tier_flag[i])))); - pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_profile_idc[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_profile_idc[i])))); - - QString str = "sub_layer_profile_compatibility_flag = { \n\t"; - for(std::size_t j=0; j<31; j++) - { - str += QString::number(ptl.sub_layer_profile_compatibility_flag[i][j]) + ", "; - if((j+1) % 8 == 0) - str += "\n\t"; - } - str += QString::number(ptl.sub_layer_profile_compatibility_flag[i][31]) + " \n}"; - pitem -> addChild(new QTreeWidgetItem(QStringList(str))); - - - pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_progressive_source_flag[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_progressive_source_flag[i])))); - pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_interlaced_source_flag[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_interlaced_source_flag[i])))); - pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_non_packed_constraint_flag[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_non_packed_constraint_flag[i])))); - pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_frame_only_constraint_flag[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_frame_only_constraint_flag[i])))); - } - - if(ptl.sub_layer_level_present_flag[i]) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( sub_layer_level_present_flag[" + QString::number(i) + "] )")); - pitemLoop -> addChild(pitem); - pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_level_idc[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_level_idc[i])))); - } - } - } -} - - -void SyntaxViewer::createVuiParameters(const HEVC::VuiParameters &vui, std::size_t maxNumSubLayersMinus1, QTreeWidgetItem *pVuiItem) -{ - pVuiItem -> addChild(new QTreeWidgetItem(QStringList("aspect_ratio_info_present_flag = " + QString::number(vui.aspect_ratio_info_present_flag)))); - - if(vui.aspect_ratio_info_present_flag) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( aspect_ratio_info_present_flag )")); - pVuiItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("aspect_ratio_idc = " + QString::number(vui.aspect_ratio_idc)))); - - if(vui.aspect_ratio_idc == 255) //EXTENDED_SAR - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( aspect_ratio_idc == EXTENDED_SAR )")); - pitem -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("sar_width = " + QString::number(vui.sar_width)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("sar_height = " + QString::number(vui.sar_height)))); - } - } - - pVuiItem -> addChild(new QTreeWidgetItem(QStringList("overscan_info_present_flag = " + QString::number(vui.overscan_info_present_flag)))); - - if(vui.overscan_info_present_flag) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( overscan_info_present_flag )")); - pVuiItem -> addChild(pitem); - pitem -> addChild(new QTreeWidgetItem(QStringList("overscan_appropriate_flag = " + QString::number(vui.overscan_appropriate_flag)))); - } - - pVuiItem -> addChild(new QTreeWidgetItem(QStringList("video_signal_type_present_flag = " + QString::number(vui.video_signal_type_present_flag)))); - - if(vui.video_signal_type_present_flag) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( video_signal_type_present_flag )")); - pVuiItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("video_format = " + QString::number(vui.video_format)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("video_full_range_flag = " + QString::number(vui.video_full_range_flag)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("colour_description_present_flag = " + QString::number(vui.colour_description_present_flag)))); - - if(vui.colour_description_present_flag) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( colour_description_present_flag )")); - pitem -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("colour_primaries = " + QString::number(vui.colour_primaries)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("transfer_characteristics = " + QString::number(vui.transfer_characteristics)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("matrix_coeffs = " + QString::number(vui.matrix_coeffs)))); - } - } - - pVuiItem -> addChild(new QTreeWidgetItem(QStringList("chroma_loc_info_present_flag = " + QString::number(vui.chroma_loc_info_present_flag)))); - - if(vui.chroma_loc_info_present_flag) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( chroma_loc_info_present_flag )")); - pVuiItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("chroma_sample_loc_type_top_field = " + QString::number(vui.chroma_sample_loc_type_top_field)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("chroma_sample_loc_type_bottom_field = " + QString::number(vui.chroma_sample_loc_type_bottom_field)))); - } - - pVuiItem -> addChild(new QTreeWidgetItem(QStringList("neutral_chroma_indication_flag = " + QString::number(vui.neutral_chroma_indication_flag)))); - pVuiItem -> addChild(new QTreeWidgetItem(QStringList("field_seq_flag = " + QString::number(vui.field_seq_flag)))); - pVuiItem -> addChild(new QTreeWidgetItem(QStringList("frame_field_info_present_flag = " + QString::number(vui.frame_field_info_present_flag)))); - pVuiItem -> addChild(new QTreeWidgetItem(QStringList("default_display_window_flag = " + QString::number(vui.default_display_window_flag)))); - - - if(vui.default_display_window_flag) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( default_display_window_flag )")); - pVuiItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("def_disp_win_left_offset = " + QString::number(vui.def_disp_win_left_offset)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("def_disp_win_right_offset = " + QString::number(vui.def_disp_win_right_offset)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("def_disp_win_top_offset = " + QString::number(vui.def_disp_win_top_offset)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("def_disp_win_bottom_offset = " + QString::number(vui.def_disp_win_bottom_offset)))); - } - - pVuiItem -> addChild(new QTreeWidgetItem(QStringList("vui_timing_info_present_flag = " + QString::number(vui.vui_timing_info_present_flag)))); - - if(vui.vui_timing_info_present_flag) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( vui_timing_info_present_flag )")); - pVuiItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("vui_num_units_in_tick = " + QString::number(vui.vui_num_units_in_tick)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("vui_time_scale = " + QString::number(vui.vui_time_scale)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("vui_poc_proportional_to_timing_flag = " + QString::number(vui.vui_poc_proportional_to_timing_flag)))); - - if(vui.vui_poc_proportional_to_timing_flag) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( vui_poc_proportional_to_timing_flag )")); - pitem -> addChild(pitemSecond); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("vui_num_ticks_poc_diff_one_minus1 = " + QString::number(vui.vui_num_ticks_poc_diff_one_minus1)))); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("vui_hrd_parameters_present_flag = " + QString::number(vui.vui_hrd_parameters_present_flag)))); - } - - pitem -> addChild(new QTreeWidgetItem(QStringList("vui_hrd_parameters_present_flag = " + QString::number(vui.vui_hrd_parameters_present_flag)))); - - if(vui.vui_hrd_parameters_present_flag) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( vui_hrd_parameters_present_flag )")); - pitem -> addChild(pitemSecond); - - QTreeWidgetItem *pitemHrd = new QTreeWidgetItem(QStringList("hrd_parameters(1, " + QString::number(maxNumSubLayersMinus1) + ")")); - pitemSecond -> addChild(pitemHrd); - - createHrdParameters(vui.hrd_parameters, 1, pitemHrd); - } - } - - pVuiItem -> addChild(new QTreeWidgetItem(QStringList("bitstream_restriction_flag = " + QString::number(vui.bitstream_restriction_flag)))); - - if(vui.bitstream_restriction_flag) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( bitstream_restriction_flag )")); - pVuiItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("tiles_fixed_structure_flag = " + QString::number(vui.tiles_fixed_structure_flag)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("motion_vectors_over_pic_boundaries_flag = " + QString::number(vui.motion_vectors_over_pic_boundaries_flag)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("restricted_ref_pic_lists_flag = " + QString::number(vui.restricted_ref_pic_lists_flag)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("min_spatial_segmentation_idc = " + QString::number(vui.min_spatial_segmentation_idc)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("max_bytes_per_pic_denom = " + QString::number(vui.max_bytes_per_pic_denom)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("max_bits_per_min_cu_denom = " + QString::number(vui.max_bits_per_min_cu_denom)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("log2_max_mv_length_horizontal = " + QString::number(vui.log2_max_mv_length_horizontal)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("log2_max_mv_length_vertical = " + QString::number(vui.log2_max_mv_length_vertical)))); - } -} - - -void SyntaxViewer::createHrdParameters(const HEVC::HrdParameters &hrd, uint8_t commonInfPresentFlag, QTreeWidgetItem *pHrdItem) -{ - if(commonInfPresentFlag) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( commonInfPresentFlag )")); - pHrdItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("nal_hrd_parameters_present_flag = " + QString::number(hrd.nal_hrd_parameters_present_flag)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("vcl_hrd_parameters_present_flag = " + QString::number(hrd.vcl_hrd_parameters_present_flag)))); - - if(hrd.nal_hrd_parameters_present_flag || hrd.vcl_hrd_parameters_present_flag) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag )")); - pitem -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("sub_pic_hrd_params_present_flag = " + QString::number(hrd.sub_pic_hrd_params_present_flag)))); - if(hrd.sub_pic_hrd_params_present_flag) - { - QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("if (sub_pic_hrd_params_present_flag )")); - pitemSecond -> addChild(pitemThird); - - pitemThird -> addChild(new QTreeWidgetItem(QStringList("tick_divisor_minus2 = " + QString::number(hrd.tick_divisor_minus2)))); - pitemThird -> addChild(new QTreeWidgetItem(QStringList("du_cpb_removal_delay_increment_length_minus1 = " + QString::number(hrd.du_cpb_removal_delay_increment_length_minus1)))); - pitemThird -> addChild(new QTreeWidgetItem(QStringList("sub_pic_cpb_params_in_pic_timing_sei_flag = " + QString::number(hrd.sub_pic_cpb_params_in_pic_timing_sei_flag)))); - pitemThird -> addChild(new QTreeWidgetItem(QStringList("dpb_output_delay_du_length_minus1 = " + QString::number(hrd.dpb_output_delay_du_length_minus1)))); - } - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("bit_rate_scale = " + QString::number(hrd.bit_rate_scale)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("cpb_size_scale = " + QString::number(hrd.cpb_size_scale)))); - - if(hrd.sub_pic_hrd_params_present_flag) - { - QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("if (sub_pic_hrd_params_present_flag )")); - pitemSecond -> addChild(pitemThird); - - pitemThird -> addChild(new QTreeWidgetItem(QStringList("cpb_size_du_scale = " + QString::number(hrd.cpb_size_du_scale)))); - } - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("initial_cpb_removal_delay_length_minus1 = " + QString::number(hrd.initial_cpb_removal_delay_length_minus1)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("au_cpb_removal_delay_length_minus1 = " + QString::number(hrd.au_cpb_removal_delay_length_minus1)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("dpb_output_delay_length_minus1 = " + QString::number(hrd.dpb_output_delay_length_minus1)))); - } - } - - if(hrd.fixed_pic_rate_general_flag.size() > 0) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("for( i = 0; i <= maxNumSubLayersMinus1; i++ )")); - pHrdItem -> addChild(pitem); - - for(std::size_t i = 0; i < hrd.fixed_pic_rate_general_flag.size(); i++ ) - { - pitem -> addChild(new QTreeWidgetItem(QStringList("fixed_pic_rate_general_flag[" + QString::number(i) + "] = " + QString::number(hrd.fixed_pic_rate_general_flag[i])))); - - if(!hrd.fixed_pic_rate_general_flag[i]) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( !fixed_pic_rate_general_flag [" + QString::number(i) + "] )")); - pitem -> addChild(pitemSecond); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("fixed_pic_rate_within_cvs_flag[" + QString::number(i) + "] = " + QString::number(hrd.fixed_pic_rate_within_cvs_flag[i])))); - } - - if(hrd.fixed_pic_rate_within_cvs_flag[i]) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( fixed_pic_rate_within_cvs_flag[" + QString::number(i) + "] )")); - pitem -> addChild(pitemSecond); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("elemental_duration_in_tc_minus1[" + QString::number(i) + "] = " + QString::number(hrd.elemental_duration_in_tc_minus1[i])))); - } - else - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( !fixed_pic_rate_within_cvs_flag[" + QString::number(i) + "] )")); - pitem -> addChild(pitemSecond); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("low_delay_hrd_flag[" + QString::number(i) + "] = " + QString::number(hrd.low_delay_hrd_flag[i])))); - } - - if(!hrd.low_delay_hrd_flag[i]) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( !low_delay_hrd_flag[" + QString::number(i) + "] )")); - pitem -> addChild(pitemSecond); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("cpb_cnt_minus1[" + QString::number(i) + "] = " + QString::number(hrd.cpb_cnt_minus1[i])))); - } - - if(hrd.nal_hrd_parameters_present_flag) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( nal_hrd_parameters_present_flag )")); - pitem -> addChild(pitemSecond); - - QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("sub_layer_hrd_parameters(" + QString::number(i) + ")")); - pitemSecond -> addChild(pitemThird); - - createSubLayerHrdParameters(hrd.nal_sub_layer_hrd_parameters[i], hrd.sub_pic_hrd_params_present_flag, pitemThird); - } - if(hrd.vcl_hrd_parameters_present_flag) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( vcl_hrd_parameters_present_flag )")); - pitem -> addChild(pitemSecond); - - QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("sub_layer_hrd_parameters(" + QString::number(i) + ")")); - pitemSecond -> addChild(pitemThird); - - createSubLayerHrdParameters(hrd.vcl_sub_layer_hrd_parameters[i], hrd.sub_pic_hrd_params_present_flag, pitemThird); - } - } - } -} - - - -void SyntaxViewer::createSubLayerHrdParameters(const HEVC::SubLayerHrdParameters &slhrd, uint8_t sub_pic_hrd_params_present_flag, QTreeWidgetItem *pSlhrdItem) -{ - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("for( i = 0; i <= CpbCnt; i++ )")); - pSlhrdItem -> addChild(pitem); - - for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList("bit_rate_value_minus1[" + QString::number(i) + "] = " + QString::number(slhrd.bit_rate_value_minus1[i])))); - pitem -> addChild(new QTreeWidgetItem(QStringList("cpb_size_value_minus1[" + QString::number(i) + "] = " + QString::number(slhrd.cpb_size_value_minus1[i])))); - - if(sub_pic_hrd_params_present_flag) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( sub_pic_hrd_params_present_flag )")); - pitem -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("cpb_size_du_value_minus1[" + QString::number(i) + "] = " + QString::number(slhrd.cpb_size_du_value_minus1[i])))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("bit_rate_du_value_minus1[" + QString::number(i) + "] = " + QString::number(slhrd.bit_rate_du_value_minus1[i])))); - } - - pitem -> addChild(new QTreeWidgetItem(QStringList("cbr_flag[" + QString::number(i) + "] = " + QString::number(slhrd.cbr_flag[i])))); - } -} - - -void SyntaxViewer::createShortTermRefPicSet(std::size_t stRpsIdx, const HEVC::ShortTermRefPicSet &rpset, std::size_t num_short_term_ref_pic_sets, const std::vector &refPicSets, QTreeWidgetItem *pStrpsItem) -{ -// HEVC::ShortTermRefPicSet rpset = refPicSets[stRpsIdx]; - - if(stRpsIdx) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( stRpsIdx )")); - pStrpsItem -> addChild(pitem); - pitem -> addChild(new QTreeWidgetItem(QStringList("inter_ref_pic_set_prediction_flag = " + QString::number(rpset.inter_ref_pic_set_prediction_flag)))); - } - - if(rpset.inter_ref_pic_set_prediction_flag) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( inter_ref_pic_set_prediction_flag )")); - pStrpsItem -> addChild(pitem); - - if(stRpsIdx == num_short_term_ref_pic_sets) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( stRpsIdx == num_short_term_ref_pic_sets )")); - pitem -> addChild(pitemSecond); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("delta_idx_minus1 = " + QString::number(rpset.delta_idx_minus1)))); - } - - pitem -> addChild(new QTreeWidgetItem(QStringList("delta_rps_sign = " + QString::number(rpset.delta_rps_sign)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("abs_delta_rps_minus1 = " + QString::number(rpset.abs_delta_rps_minus1)))); - - std::size_t RefRpsIdx = stRpsIdx - (rpset.delta_idx_minus1 + 1); - - std::size_t NumDeltaPocs = 0; - - if(refPicSets[RefRpsIdx].inter_ref_pic_set_prediction_flag) - { - for(std::size_t i=0; i addChild(pitemLoop); - - for(std::size_t i=0; i<=NumDeltaPocs; i++ ) - { - pitemLoop -> addChild(new QTreeWidgetItem(QStringList("used_by_curr_pic_flag[" + QString::number(i) + "] = " + QString::number(rpset.used_by_curr_pic_flag[i])))); - - if(!rpset.used_by_curr_pic_flag[i]) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( !used_by_curr_pic_flag[j] )")); - pitemLoop -> addChild(pitem); - pitem -> addChild(new QTreeWidgetItem(QStringList("use_delta_flag[" + QString::number(i) + "] = " + QString::number(rpset.use_delta_flag[i])))); - - } - } - } - else - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( !inter_ref_pic_set_prediction_flag )")); - pStrpsItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("num_negative_pics = " + QString::number(rpset.num_negative_pics)))); - pitem -> addChild(new QTreeWidgetItem(QStringList("num_positive_pics = " + QString::number(rpset.num_positive_pics)))); - - QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_negative_pics; i++ )")); - pitem -> addChild(pitemLoop); - - for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList("delta_poc_s0_minus1[" + QString::number(i) + "] = " + QString::number(rpset.delta_poc_s0_minus1[i])))); - pitemLoop -> addChild(new QTreeWidgetItem(QStringList("used_by_curr_pic_s0_flag[" + QString::number(i) + "] = " + QString::number(rpset.used_by_curr_pic_s0_flag[i])))); - } - - pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_positive_pics; i++ )")); - pitem -> addChild(pitemLoop); - - for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList("delta_poc_s1_minus1[" + QString::number(i) + "] = " + QString::number(rpset.delta_poc_s1_minus1[i])))); - pitemLoop -> addChild(new QTreeWidgetItem(QStringList("used_by_curr_pic_s1_flag[" + QString::number(i) + "] = " + QString::number(rpset.used_by_curr_pic_s1_flag[i])))); - } - } -} - - -void SyntaxViewer::createScalingListData(const HEVC::ScalingListData &scdata, QTreeWidgetItem *pScItem) -{ - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("for( sizeId = 0; sizeId < 4; sizeId++ )")); - pScItem -> addChild(pitem); - - - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("for( matrixId = 0; matrixId < ( ( sizeId == 3 ) ? 2 : 6 ); matrixId++ )")); - pitem -> addChild(pitemSecond); - - - for(std::size_t sizeId = 0; sizeId < 4; sizeId++) - { - for(std::size_t matrixId = 0; matrixId<((sizeId == 3)?2:6); matrixId++) - { - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("scaling_list_pred_mode_flag[" + QString::number(sizeId) + "][" + QString::number(matrixId) + "] = " + QString::number(scdata.scaling_list_pred_mode_flag[sizeId][matrixId])))); - - if(!scdata.scaling_list_pred_mode_flag[sizeId][matrixId]) - { - pitem = new QTreeWidgetItem(QStringList("if( !scaling_list_pred_mode_flag[ sizeId ][ matrixId ] )")); - pitemSecond -> addChild(pitem); - pitem -> addChild(new QTreeWidgetItem(QStringList("scaling_list_pred_matrix_id_delta[" + QString::number(sizeId) + "][" + QString::number(matrixId) + "] = " + QString::number(scdata.scaling_list_pred_matrix_id_delta[sizeId][matrixId])))); - } - else - { - std::size_t coefNum = std::min(64, (1 << (4 + (sizeId << 1)))); - if(sizeId > 1) - { - pitem = new QTreeWidgetItem(QStringList("if( sizeId > 1 )")); - pitemSecond -> addChild(pitem); - pitem -> addChild(new QTreeWidgetItem(QStringList("scaling_list_dc_coef_minus8[" + QString::number(sizeId) + "][" + QString::number(matrixId) + "] = " + QString::number(scdata.scaling_list_dc_coef_minus8[sizeId-2][matrixId])))); - } - - pitem = new QTreeWidgetItem(QStringList("for( i = 0; i < coefNum; i++ )")); - pitemSecond -> addChild(pitem); - - for(std::size_t i = 0; i < coefNum; i++) - { - pitem -> addChild(new QTreeWidgetItem(QStringList("scaling_list_delta_coef[" + QString::number(sizeId) + "][" + QString::number(matrixId) + "][" + QString::number(i) + "] = " + QString::number(scdata.scaling_list_delta_coef[sizeId][matrixId][i])))); - } - } - } - } -} - - -void SyntaxViewer::createRefPicListModification(const HEVC::RefPicListModification &rplModif, QTreeWidgetItem *pRplmItem) -{ - pRplmItem -> addChild(new QTreeWidgetItem(QStringList("ref_pic_list_modification_flag_l0 = " + QString::number(rplModif.ref_pic_list_modification_flag_l0)))); - - if(rplModif.ref_pic_list_modification_flag_l0) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("for( i = 0; i <= num_ref_idx_l0_active_minus1; i++ )")); - pRplmItem -> addChild(pitem); - - for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList("list_entry_l0[" + QString::number(i) + "] = " + QString::number(rplModif.list_entry_l0[i])))); - } - - pRplmItem -> addChild(new QTreeWidgetItem(QStringList("ref_pic_list_modification_flag_l1 = " + QString::number(rplModif.ref_pic_list_modification_flag_l1)))); - - if(rplModif.ref_pic_list_modification_flag_l1) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("for( i = 0; i <= num_ref_idx_l1_active_minus1; i++ )")); - pRplmItem -> addChild(pitem); - - for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList("list_entry_l1[" + QString::number(i) + "] = " + QString::number(rplModif.list_entry_l1[i])))); - } -} - - -void SyntaxViewer::createPredWeightTable(const HEVC::PredWeightTable &pwt, std::shared_ptr pSlice, QTreeWidgetItem *ppwtItem) -{ - std::shared_ptr ppps = m_ppsMap[pSlice -> slice_pic_parameter_set_id]; - if(!ppps) - return ; - - std::shared_ptr psps = m_spsMap[ppps -> pps_seq_parameter_set_id]; - - if(!psps) - return ; - - ppwtItem -> addChild(new QTreeWidgetItem(QStringList("luma_log2_weight_denom = " + QString::number(pwt.luma_log2_weight_denom)))); - - if(psps -> chroma_format_idc != 0) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (psps -> chroma_format_idc)")); - ppwtItem -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("delta_chroma_log2_weight_denom = " + QString::number(pwt.delta_chroma_log2_weight_denom)))); - } - - QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for(i=0; i<=num_ref_idx_l0_active_minus1; i++)")); - ppwtItem -> addChild(pitemLoop); - - for(std::size_t i=0; i<=pSlice -> num_ref_idx_l0_active_minus1; i++) - pitemLoop -> addChild(new QTreeWidgetItem(QStringList("luma_weight_l0_flag[" + QString::number(i) + "] = " + QString::number(pwt.luma_weight_l0_flag[i])))); - - if(psps -> chroma_format_idc != 0) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (psps -> chroma_format_idc)")); - ppwtItem -> addChild(pitem); - - pitemLoop = new QTreeWidgetItem(QStringList("for(i=0; i<=num_ref_idx_l0_active_minus1; i++)")); - pitem -> addChild(pitemLoop); - - for(std::size_t i=0; i<=pSlice -> num_ref_idx_l0_active_minus1; i++) - pitemLoop -> addChild(new QTreeWidgetItem(QStringList("chroma_weight_l0_flag[" + QString::number(i) + "] = " + QString::number(pwt.chroma_weight_l0_flag[i])))); - } - - - for(std::size_t i=0; i<=pSlice -> num_ref_idx_l0_active_minus1; i++) - { - pitemLoop = new QTreeWidgetItem(QStringList("for(i=0; i<=num_ref_idx_l0_active_minus1; i++)")); - ppwtItem -> addChild(pitemLoop); - - if(pwt.luma_weight_l0_flag[i]) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (luma_weight_l0_flag[" + QString::number(i) +"])")); - pitemLoop -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("delta_luma_weight_l0[" + QString::number(i) + "] = " + QString::number(pwt.delta_luma_weight_l0[i])))); - pitem -> addChild(new QTreeWidgetItem(QStringList("luma_offset_l0[" + QString::number(i) + "] = " + QString::number(pwt.luma_offset_l0[i])))); - } - if(pwt.chroma_weight_l0_flag[i]) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (chroma_weight_l0_flag[" + QString::number(i) +"])")); - pitemLoop -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("delta_chroma_weight_l0[" + QString::number(i) + "] = { " + QString::number(pwt.delta_chroma_weight_l0[i][0]) + ", " + QString::number(pwt.delta_chroma_weight_l0[i][1]) + " } "))); - pitem -> addChild(new QTreeWidgetItem(QStringList("delta_chroma_offset_l0[" + QString::number(i) + "] = { " + QString::number(pwt.delta_chroma_offset_l0[i][0]) + ", " + QString::number(pwt.delta_chroma_offset_l0[i][1]) + " } "))); - } - } - - if(pSlice -> slice_type == SLICE_B) - { - QTreeWidgetItem *pitemBSlice = new QTreeWidgetItem(QStringList("slice_type == B")); - ppwtItem -> addChild(pitemBSlice); - - QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for(i=0; i<=num_ref_idx_l1_active_minus1; i++)")); - pitemBSlice -> addChild(pitemLoop); - - for(std::size_t i=0; i<=pSlice -> num_ref_idx_l1_active_minus1; i++) - pitemLoop -> addChild(new QTreeWidgetItem(QStringList("luma_weight_l1_flag[" + QString::number(i) + "] = " + QString::number(pwt.luma_weight_l1_flag[i])))); - - if(psps -> chroma_format_idc != 0) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (psps -> chroma_format_idc)")); - pitemBSlice -> addChild(pitem); - - pitemLoop = new QTreeWidgetItem(QStringList("for(i=0; i<=num_ref_idx_l1_active_minus1; i++)")); - pitem -> addChild(pitemLoop); - - for(std::size_t i=0; i<=pSlice -> num_ref_idx_l1_active_minus1; i++) - pitemLoop -> addChild(new QTreeWidgetItem(QStringList("chroma_weight_l1_flag[" + QString::number(i) + "] = " + QString::number(pwt.chroma_weight_l1_flag[i])))); - } - - - for(std::size_t i=0; i<=pSlice -> num_ref_idx_l1_active_minus1; i++) - { - pitemLoop = new QTreeWidgetItem(QStringList("for(i=0; i<=num_ref_idx_l1_active_minus1; i++)")); - pitemBSlice -> addChild(pitemLoop); - - if(pwt.luma_weight_l1_flag[i]) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (luma_weight_l1_flag[" + QString::number(i) +"])")); - pitemLoop -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("delta_luma_weight_l1[" + QString::number(i) + "] = " + QString::number(pwt.delta_luma_weight_l1[i])))); - pitem -> addChild(new QTreeWidgetItem(QStringList("luma_offset_l1[" + QString::number(i) + "] = " + QString::number(pwt.luma_offset_l1[i])))); - } - if(pwt.chroma_weight_l1_flag[i]) - { - QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (chroma_weight_l1_flag[" + QString::number(i) +"])")); - pitemLoop -> addChild(pitem); - - pitem -> addChild(new QTreeWidgetItem(QStringList("delta_chroma_weight_l1[" + QString::number(i) + "] = { " + QString::number(pwt.delta_chroma_weight_l1[i][0]) + ", " + QString::number(pwt.delta_chroma_weight_l1[i][1]) + " } "))); - pitem -> addChild(new QTreeWidgetItem(QStringList("delta_chroma_offset_l1[" + QString::number(i) + "] = { " + QString::number(pwt.delta_chroma_offset_l1[i][0]) + ", " + QString::number(pwt.delta_chroma_offset_l1[i][1]) + " } "))); - } - } - } - -} - -void SyntaxViewer::createDecodedPictureHash(std::shared_ptr pDecPictHash, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("hash_type = " + QString::number(pDecPictHash->hash_type)))); - - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( cIdx = 0; cIdx < ( chroma_format_idc = = 0 ? 1 : 3 ); cIdx++ )")); - pItem -> addChild(ploop); - - QTreeWidgetItem *pif = new QTreeWidgetItem(QStringList("if(hash_type = " + QString::number(pDecPictHash->hash_type) + ") ")); - ploop -> addChild(pif); - - - if(pDecPictHash->hash_type == 0) - { - for(std::size_t i=0; ipicture_md5.size(); i++) - { - QString str; - for(std::size_t j=0; j<16; j++) - str += QString("%1").arg(pDecPictHash->picture_md5[i][j], 2, 16, QChar('0')).toUpper(); - pif -> addChild(new QTreeWidgetItem(QStringList("picture_md5[" + QString::number(i) + "] = " + str))); - } - } - if(pDecPictHash->hash_type == 1) - { - for(std::size_t i=0; ipicture_crc.size(); i++) - { - pif -> addChild(new QTreeWidgetItem(QStringList("picture_crc[" + QString::number(i) + "] = " + QString::number(pDecPictHash -> picture_crc[i])))); - } - } - else - { - for(std::size_t i=0; ipicture_crc.size(); i++) - { - pif -> addChild(new QTreeWidgetItem(QStringList("picture_checksum[" + QString::number(i) + "] = " + QString::number(pDecPictHash -> picture_checksum[i])))); - } - } -} - - -void SyntaxViewer::createMasteringDisplayInfo(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < 3 ; i++ )")); - pItem -> addChild(pitemLoop); - - - for (uint32_t i = 0; i < 3; i++) - { - pitemLoop -> addChild(new QTreeWidgetItem(QStringList("display_primary_x[" + QString::number(i) + "] = " + QString::number(pSei -> display_primary_x[i])))); - pitemLoop -> addChild(new QTreeWidgetItem(QStringList("display_primary_y[" + QString::number(i) + "] = " + QString::number(pSei -> display_primary_y[i])))); - } - - pItem -> addChild(new QTreeWidgetItem(QStringList("white_point_x = " + QString::number(pSei -> white_point_x)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("white_point_y = " + QString::number(pSei -> white_point_y)))); - - pItem -> addChild(new QTreeWidgetItem(QStringList("max_display_mastering_luminance = " + QString::number(pSei -> max_display_mastering_luminance)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("min_display_mastering_luminance = " + QString::number(pSei -> min_display_mastering_luminance)))); -} - - -void SyntaxViewer::createActiveParameterSets(std::shared_ptr pSeiPayload, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("active_video_parameter_set_id = " + QString::number(pSeiPayload -> active_video_parameter_set_id)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("self_contained_cvs_flag = " + QString::number(pSeiPayload -> self_contained_cvs_flag)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("no_parameter_set_update_flag = " + QString::number(pSeiPayload -> no_parameter_set_update_flag)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("num_sps_ids_minus1 = " + QString::number(pSeiPayload -> num_sps_ids_minus1)))); - - QString str = "active_seq_parameter_set_id = {\n\t"; - for (uint32_t i = 0; i < pSeiPayload -> num_sps_ids_minus1; i++) - { - str += QString::number(pSeiPayload -> active_seq_parameter_set_id[i]) + ", "; - if((i + 1) % 8) - str += "\n\t"; - } - - str += QString::number(pSeiPayload -> active_seq_parameter_set_id[pSeiPayload -> num_sps_ids_minus1]) + "\n}"; - pItem -> addChild(new QTreeWidgetItem(QStringList(str))); -} - - -void SyntaxViewer::createUserDataUnregistered(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - QString str = - QString("%1").arg(pSei -> uuid_iso_iec_11578[0], 2, 16, QChar('0')).toLower() + - QString("%1").arg(pSei -> uuid_iso_iec_11578[1], 2, 16, QChar('0')).toLower() + - QString("%1").arg(pSei -> uuid_iso_iec_11578[2], 2, 16, QChar('0')).toLower() + - QString("%1").arg(pSei -> uuid_iso_iec_11578[3], 2, 16, QChar('0')).toLower() + - "-" + - QString("%1").arg(pSei -> uuid_iso_iec_11578[4], 2, 16, QChar('0')).toLower() + - QString("%1").arg(pSei -> uuid_iso_iec_11578[5], 2, 16, QChar('0')).toLower() + - "-" + - QString("%1").arg(pSei -> uuid_iso_iec_11578[6], 2, 16, QChar('0')).toLower() + - QString("%1").arg(pSei -> uuid_iso_iec_11578[7], 2, 16, QChar('0')).toLower() + - "-" + - QString("%1").arg(pSei -> uuid_iso_iec_11578[8], 2, 16, QChar('0')).toLower() + - QString("%1").arg(pSei -> uuid_iso_iec_11578[9], 2, 16, QChar('0')).toLower() + - "-" + - QString("%1").arg(pSei -> uuid_iso_iec_11578[10], 2, 16, QChar('0')).toLower() + - QString("%1").arg(pSei -> uuid_iso_iec_11578[11], 2, 16, QChar('0')).toLower() + - QString("%1").arg(pSei -> uuid_iso_iec_11578[12], 2, 16, QChar('0')).toLower() + - QString("%1").arg(pSei -> uuid_iso_iec_11578[13], 2, 16, QChar('0')).toLower() + - QString("%1").arg(pSei -> uuid_iso_iec_11578[14], 2, 16, QChar('0')).toLower() + - QString("%1").arg(pSei -> uuid_iso_iec_11578[15], 2, 16, QChar('0')).toLower(); - - pItem -> addChild(new QTreeWidgetItem(QStringList("uuid_iso_iec_11578 = " + str))); - - - if(pSei -> user_data_payload_byte.empty()) - { - str = "user_data_payload_byte = { }"; - } - else - { - str = "user_data_payload_byte = {\n\t"; - for (int i = 0; i < pSei -> user_data_payload_byte.size() - 1; i++) - { - str += QString("%1").arg(pSei -> user_data_payload_byte[i], 2, 16, QChar('0')).toLower(); - if((i + 1) % 16 == 0) - str += "\n\t"; - } - str += QString::number(pSei -> user_data_payload_byte[pSei -> user_data_payload_byte.size() - 1], 16) + "\n}"; - } - - pItem -> addChild(new QTreeWidgetItem(QStringList(str))); -} - - -void SyntaxViewer::createBufferingPeriod(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("bp_seq_parameter_set_id = " + QString::number(pSei->bp_seq_parameter_set_id)))); - - std::shared_ptr psps = m_spsMap[pSei -> bp_seq_parameter_set_id]; - if(!psps) - return; - - if(!psps->vui_parameters.hrd_parameters.sub_pic_hrd_params_present_flag) - { - QTreeWidgetItem *pitemIrap = new QTreeWidgetItem(QStringList("if( !sub_pic_hrd_params_present_flag )")); - pItem -> addChild(pitemIrap); - pitemIrap -> addChild(new QTreeWidgetItem(QStringList("irap_cpb_params_present_flag = " + QString::number(pSei->irap_cpb_params_present_flag)))); - } - - if(pSei -> irap_cpb_params_present_flag) - { - QTreeWidgetItem *pitemIrap = new QTreeWidgetItem(QStringList("if( irap_cpb_params_present_flag )")); - pItem -> addChild(pitemIrap); - pitemIrap -> addChild(new QTreeWidgetItem(QStringList("cpb_delay_offset = " + QString::number(pSei->cpb_delay_offset)))); - pitemIrap -> addChild(new QTreeWidgetItem(QStringList("dpb_delay_offset = " + QString::number(pSei->dpb_delay_offset)))); - } - - pItem -> addChild(new QTreeWidgetItem(QStringList("concatenation_flag = " + QString::number(pSei->concatenation_flag)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("au_cpb_removal_delay_delta_minus1 = " + QString::number(pSei->au_cpb_removal_delay_delta_minus1)))); - - bool NalHrdBpPresentFlag = psps->vui_parameters.hrd_parameters.nal_hrd_parameters_present_flag; - if(NalHrdBpPresentFlag) - { - QTreeWidgetItem *pitemBpPresentFlag= new QTreeWidgetItem(QStringList("if( NalHrdBpPresentFlag )")); - pItem -> addChild(pitemBpPresentFlag); - - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i <= CpbCnt; i++ )")); - pitemBpPresentFlag -> addChild(ploop); - - for(std::size_t i=0; inal_initial_cpb_removal_delay.size(); i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("nal_initial_cpb_removal_delay[" + QString::number(i) + "] = " + QString::number(pSei -> nal_initial_cpb_removal_delay[i])))); - ploop -> addChild(new QTreeWidgetItem(QStringList("nal_initial_cpb_removal_offset[" + QString::number(i) + "] = " + QString::number(pSei -> nal_initial_cpb_removal_offset[i])))); - - if(psps->vui_parameters.hrd_parameters.sub_pic_hrd_params_present_flag || pSei->irap_cpb_params_present_flag) - { - QTreeWidgetItem *pitemAlt = new QTreeWidgetItem(QStringList("if( sub_pic_hrd_params_present_flag | | irap_cpb_params_present_flag )")); - ploop -> addChild(pitemAlt); - - pitemAlt -> addChild(new QTreeWidgetItem(QStringList("nal_initial_alt_cpb_removal_delay[" + QString::number(i) + "] = " + QString::number(pSei -> nal_initial_alt_cpb_removal_delay[i])))); - pitemAlt -> addChild(new QTreeWidgetItem(QStringList("nal_initial_alt_cpb_removal_offset[" + QString::number(i) + "] = " + QString::number(pSei -> nal_initial_alt_cpb_removal_offset[i])))); - } - - } - } - - bool VclHrdBpPresentFlag = psps->vui_parameters.hrd_parameters.vcl_hrd_parameters_present_flag; - if(VclHrdBpPresentFlag) - { - QTreeWidgetItem *pitemBpPresentFlag= new QTreeWidgetItem(QStringList("if( VclHrdBpPresentFlag )")); - pItem -> addChild(pitemBpPresentFlag); - - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i <= CpbCnt; i++ )")); - pitemBpPresentFlag -> addChild(ploop); - - for(std::size_t i=0; ivcl_initial_cpb_removal_delay.size(); i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("vcl_initial_cpb_removal_delay[" + QString::number(i) + "] = " + QString::number(pSei -> vcl_initial_cpb_removal_delay[i])))); - ploop -> addChild(new QTreeWidgetItem(QStringList("vcl_initial_cpb_removal_offset[" + QString::number(i) + "] = " + QString::number(pSei -> vcl_initial_cpb_removal_offset[i])))); - - if(psps->vui_parameters.hrd_parameters.sub_pic_hrd_params_present_flag || pSei->irap_cpb_params_present_flag) - { - QTreeWidgetItem *pitemAlt = new QTreeWidgetItem(QStringList("if( sub_pic_hrd_params_present_flag | | irap_cpb_params_present_flag )")); - ploop -> addChild(pitemAlt); - - pitemAlt -> addChild(new QTreeWidgetItem(QStringList("vcl_initial_alt_cpb_removal_delay[" + QString::number(i) + "] = " + QString::number(pSei -> vcl_initial_alt_cpb_removal_delay[i])))); - pitemAlt -> addChild(new QTreeWidgetItem(QStringList("vcl_initial_alt_cpb_removal_offset[" + QString::number(i) + "] = " + QString::number(pSei -> vcl_initial_alt_cpb_removal_offset[i])))); - } - } - } -} - - -void SyntaxViewer::createPicTiming(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - std::shared_ptr psps; - - if(m_spsMap.size()) - psps = m_spsMap.begin() -> second; - - if(!psps) - return; - - - if(psps->vui_parameters.frame_field_info_present_flag) - { - QTreeWidgetItem *pitemField = new QTreeWidgetItem(QStringList("if( frame_field_info_present_flag )")); - pItem -> addChild(pitemField); - - pitemField -> addChild(new QTreeWidgetItem(QStringList("pic_struct = " + QString::number(pSei->pic_struct)))); - pitemField -> addChild(new QTreeWidgetItem(QStringList("source_scan_type = " + QString::number(pSei->source_scan_type)))); - pitemField -> addChild(new QTreeWidgetItem(QStringList("duplicate_flag = " + QString::number(pSei->duplicate_flag)))); - } - - bool CpbDpbDelaysPresentFlag = psps->vui_parameters.hrd_parameters.nal_hrd_parameters_present_flag || - psps->vui_parameters.hrd_parameters.vcl_hrd_parameters_present_flag; - - if(CpbDpbDelaysPresentFlag) - { - QTreeWidgetItem *pitemDpbDelays = new QTreeWidgetItem(QStringList("if( CpbDpbDelaysPresentFlag )")); - pItem -> addChild(pitemDpbDelays); - - pitemDpbDelays -> addChild(new QTreeWidgetItem(QStringList("au_cpb_removal_delay_minus1 = " + QString::number(pSei->au_cpb_removal_delay_minus1)))); - pitemDpbDelays -> addChild(new QTreeWidgetItem(QStringList("pic_dpb_output_delay = " + QString::number(pSei->pic_dpb_output_delay)))); - - if(psps->vui_parameters.hrd_parameters.sub_pic_hrd_params_present_flag) - { - QTreeWidgetItem *pitemDuDelay = new QTreeWidgetItem(QStringList("if( CpbDpbDelaysPresentFlag )")); - pitemDpbDelays -> addChild(pitemDuDelay); - - pitemDuDelay -> addChild(new QTreeWidgetItem(QStringList("pic_dpb_output_du_delay = " + QString::number(pSei->pic_dpb_output_du_delay)))); - } - - if(psps->vui_parameters.hrd_parameters.sub_pic_hrd_params_present_flag && - psps->vui_parameters.hrd_parameters.sub_pic_cpb_params_in_pic_timing_sei_flag) - { - QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( CpbDpbDelaysPresentFlag )")); - pitemDpbDelays -> addChild(pitemIf); - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("num_decoding_units_minus1 = " + QString::number(pSei->num_decoding_units_minus1)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("du_common_cpb_removal_delay_flag = " + QString::number(pSei->du_common_cpb_removal_delay_flag)))); - - if(pSei -> du_common_cpb_removal_delay_flag) - { - QTreeWidgetItem *pitemDuCommCpb = new QTreeWidgetItem(QStringList("if( CpbDpbDelaysPresentFlag )")); - pitemIf -> addChild(pitemDuCommCpb); - - pitemDuCommCpb -> addChild(new QTreeWidgetItem(QStringList("du_common_cpb_removal_delay_increment_minus1 = " + QString::number(pSei->num_decoding_units_minus1)))); - } - - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i <= num_decoding_units_minus1; i++ )")); - pitemIf -> addChild(ploop); - - for(std::size_t i=0; i<=pSei -> num_decoding_units_minus1; i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("num_nalus_in_du_minus1[" + QString::number(i) + "] = " + QString::number(pSei -> num_nalus_in_du_minus1[i])))); - - if(!pSei -> du_common_cpb_removal_delay_flag && i num_decoding_units_minus1) - { - QTreeWidgetItem *pitemDuCommCpb = new QTreeWidgetItem(QStringList("if( !du_common_cpb_removal_delay_flag && i < num_decoding_units_minus1 )")); - ploop -> addChild(pitemDuCommCpb); - - pitemDuCommCpb -> addChild(new QTreeWidgetItem(QStringList("du_cpb_removal_delay_increment_minus1[" + QString::number(i) + "] = " + QString::number(pSei -> du_cpb_removal_delay_increment_minus1[i])))); - } - } - } - } -} - - -void SyntaxViewer::createRecoveryPoint(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("recovery_poc_cnt = " + QString::number(pSei->recovery_poc_cnt)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("exact_match_flag = " + QString::number(pSei->exact_match_flag)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("broken_link_flag = " + QString::number(pSei->broken_link_flag)))); -} - - -void SyntaxViewer::createContentLightLevelInfo(std::shared_ptr pSeiPayload, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("max_content_light_level = " + QString::number(pSeiPayload->max_content_light_level)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("max_pic_average_light_level = " + QString::number(pSeiPayload->max_pic_average_light_level)))); -} - -void SyntaxViewer::createAlternativeTransferCharacteristics(std::shared_ptr pSeiPayload, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("alternative_transfer_characteristics = " + QString::number(pSeiPayload->alternative_transfer_characteristics)))); -} - - -void SyntaxViewer::createFramePacking(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("frame_packing_arrangement_id = " + QString::number(pSei->frame_packing_arrangement_id)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("frame_packing_arrangement_cancel_flag = " + QString::number(pSei->frame_packing_arrangement_cancel_flag)))); - - if(!pSei -> frame_packing_arrangement_cancel_flag) - { - QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( !frame_packing_arrangement_cancel_flag )")); - pItem -> addChild(pitemIf); - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("frame_packing_arrangement_type = " + QString::number(pSei->frame_packing_arrangement_type)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("quincunx_sampling_flag = " + QString::number(pSei->quincunx_sampling_flag)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("content_interpretation_type = " + QString::number(pSei->content_interpretation_type)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("spatial_flipping_flag = " + QString::number(pSei->spatial_flipping_flag)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("frame0_flipped_flag = " + QString::number(pSei->frame0_flipped_flag)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("field_views_flag = " + QString::number(pSei->field_views_flag)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("current_frame_is_frame0_flag = " + QString::number(pSei->current_frame_is_frame0_flag)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("frame0_self_contained_flag = " + QString::number(pSei->frame0_self_contained_flag)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("frame1_self_contained_flag = " + QString::number(pSei->frame1_self_contained_flag)))); - - if(!pSei -> quincunx_sampling_flag && pSei -> frame_packing_arrangement_type != 5) - { - QTreeWidgetItem *pitemGridPos = new QTreeWidgetItem(QStringList("if( !quincunx_sampling_flag && frame_packing_arrangement_type != 5 )")); - pitemIf -> addChild(pitemGridPos); - - pitemGridPos -> addChild(new QTreeWidgetItem(QStringList("frame0_grid_position_x = " + QString::number(pSei->frame0_grid_position_x)))); - pitemGridPos -> addChild(new QTreeWidgetItem(QStringList("frame0_grid_position_y = " + QString::number(pSei->frame0_grid_position_y)))); - pitemGridPos -> addChild(new QTreeWidgetItem(QStringList("frame1_grid_position_x = " + QString::number(pSei->frame1_grid_position_x)))); - pitemGridPos -> addChild(new QTreeWidgetItem(QStringList("frame1_grid_position_y = " + QString::number(pSei->frame1_grid_position_y)))); - } - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("frame_packing_arrangement_reserved_byte = " + QString::number(pSei->frame_packing_arrangement_reserved_byte)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("frame_packing_arrangement_persistence_flag = " + QString::number(pSei->frame_packing_arrangement_persistence_flag)))); - - } - - pItem -> addChild(new QTreeWidgetItem(QStringList("upsampled_aspect_ratio_flag = " + QString::number(pSei->upsampled_aspect_ratio_flag)))); -} - - -void SyntaxViewer::createDisplayOrientation(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("display_orientation_cancel_flag = " + QString::number(pSei->display_orientation_cancel_flag)))); - if(!pSei -> display_orientation_cancel_flag) - { - QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( !display_orientation_cancel_flag )")); - pItem -> addChild(pitemIf); - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("hor_flip = " + QString::number(pSei->hor_flip)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("ver_flip = " + QString::number(pSei->ver_flip)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("anticlockwise_rotation = " + QString::number(pSei->anticlockwise_rotation)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("display_orientation_persistence_flag = " + QString::number(pSei->display_orientation_persistence_flag)))); - } -} - - -void SyntaxViewer::createToneMapping(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("tone_map_id = " + QString::number(pSei->tone_map_id)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("tone_map_cancel_flag = " + QString::number(pSei->tone_map_cancel_flag)))); - - if(!pSei -> tone_map_cancel_flag) - { - QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( !tone_map_cancel_flag )")); - pItem -> addChild(pitemIf); - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("tone_map_persistence_flag = " + QString::number(pSei->tone_map_persistence_flag)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("coded_data_bit_depth = " + QString::number(pSei->coded_data_bit_depth)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("target_bit_depth = " + QString::number(pSei->target_bit_depth)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("tone_map_model_id = " + QString::number(pSei->tone_map_model_id)))); - - if(pSei -> tone_map_model_id == 0) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( tone_map_model_id = = 0 )")); - pItem -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("min_value = " + QString::number(pSei->min_value)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("max_value = " + QString::number(pSei->max_value)))); - } - else if(pSei -> tone_map_model_id == 1) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( tone_map_model_id = = 1 )")); - pItem -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("sigmoid_midpoint = " + QString::number(pSei->sigmoid_midpoint)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("sigmoid_width = " + QString::number(pSei->sigmoid_width)))); - } - else if(pSei -> tone_map_model_id == 2) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( tone_map_model_id = = 2 )")); - pItem -> addChild(pitemSecond); - - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < ( 1 << target_bit_depth ); i++ )")); - pitemSecond -> addChild(ploop); - - for(std::size_t i = 0; i<(1 << pSei->target_bit_depth); i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("start_of_coded_interval[" + QString::number(i) + "] = " + QString::number(pSei -> start_of_coded_interval[i])))); - } - - } - else if(pSei -> tone_map_model_id == 3) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( tone_map_model_id = = 3 )")); - pItem -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("num_pivots = " + QString::number(pSei->num_pivots)))); - - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_pivots; i++ )")); - pitemSecond -> addChild(ploop); - - for(std::size_t i=0; i num_pivots; i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("coded_pivot_value[" + QString::number(i) + "] = " + QString::number(pSei -> coded_pivot_value[i])))); - ploop -> addChild(new QTreeWidgetItem(QStringList("target_pivot_value[" + QString::number(i) + "] = " + QString::number(pSei -> target_pivot_value[i])))); - } - } - else if(pSei -> tone_map_model_id == 4) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( tone_map_model_id = = 4 )")); - pItem -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("camera_iso_speed_idc = " + QString::number(pSei->camera_iso_speed_idc)))); - if(pSei -> camera_iso_speed_idc == 255) - { - QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("if( camera_iso_speed_idc = = EXTENDED_ISO )")); - pitemSecond -> addChild(pitemThird); - - pitemThird -> addChild(new QTreeWidgetItem(QStringList("camera_iso_speed_value = " + QString::number(pSei->camera_iso_speed_value)))); - } - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("exposure_index_idc = " + QString::number(pSei->exposure_index_idc)))); - if(pSei -> exposure_index_idc == 255) - { - QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("if( exposure_index_idc = = EXTENDED_ISO )")); - pitemSecond -> addChild(pitemThird); - - pitemThird -> addChild(new QTreeWidgetItem(QStringList("exposure_index_value = " + QString::number(pSei->exposure_index_value)))); - } - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("exposure_compensation_value_sign_flag = " + QString::number(pSei->exposure_compensation_value_sign_flag)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("exposure_compensation_value_numerator = " + QString::number(pSei->exposure_compensation_value_numerator)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("exposure_compensation_value_denom_idc = " + QString::number(pSei->exposure_compensation_value_denom_idc)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("ref_screen_luminance_white = " + QString::number(pSei->ref_screen_luminance_white)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("extended_range_white_level = " + QString::number(pSei->extended_range_white_level)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("nominal_black_level_code_value = " + QString::number(pSei->nominal_black_level_code_value)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("nominal_white_level_code_value = " + QString::number(pSei->nominal_white_level_code_value)))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("extended_white_level_code_value = " + QString::number(pSei->extended_white_level_code_value)))); - } - } -} - - -void SyntaxViewer::createSOPDescription(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("sop_seq_parameter_set_id = " + QString::number(pSei->sop_seq_parameter_set_id)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("num_entries_in_sop_minus1 = " + QString::number(pSei->num_entries_in_sop_minus1)))); - - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i <= num_entries_in_sop_minus1; i++ )")); - pItem -> addChild(ploop); - - for(std::size_t i=0; i<=pSei -> num_entries_in_sop_minus1; i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("sop_vcl_nut[" + QString::number(i) + "] = " + QString::number(pSei -> sop_vcl_nut[i])))); - ploop -> addChild(new QTreeWidgetItem(QStringList("sop_temporal_id[" + QString::number(i) + "] = " + QString::number(pSei -> sop_temporal_id[i])))); - - if(pSei -> sop_vcl_nut[i] != 19 && pSei -> sop_vcl_nut[i] != 20) - { - QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( sop_vcl_nut[ i ] != IDR_W_RADL && sop_vcl_nut[ i ] != IDR_N_LP )")); - ploop -> addChild(pitemIf); - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("sop_short_term_rps_idx[" + QString::number(i) + "] = " + QString::number(pSei -> sop_short_term_rps_idx[i])))); - } - - if(i > 0) - { - QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( i > 0 )")); - ploop -> addChild(pitemIf); - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("sop_poc_delta[" + QString::number(i) + "] = " + QString::number(pSei -> sop_poc_delta[i])))); - } - } -} - - -void SyntaxViewer::createTemporalLevel0Index(std::shared_ptr pSeiPayload, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("temporal_sub_layer_zero_idx = " + QString::number(pSeiPayload->temporal_sub_layer_zero_idx)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("irap_pic_id = " + QString::number(pSeiPayload->irap_pic_id)))); -} - -void SyntaxViewer::createSegmRectFramePacking(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("segmented_rect_frame_packing_arrangement_cancel_flag = " + QString::number(pSei->segmented_rect_frame_packing_arrangement_cancel_flag)))); - - if(!pSei -> segmented_rect_frame_packing_arrangement_cancel_flag) - { - QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( !segmented_rect_frame_packing_arrangement_cancel_flag )")); - pItem -> addChild(pitemIf); - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("segmented_rect_content_interpretation_type = " + QString::number(pSei->segmented_rect_content_interpretation_type)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("segmented_rect_frame_packing_arrangement_persistence = " + QString::number(pSei->segmented_rect_frame_packing_arrangement_persistence)))); - } -} - - -void SyntaxViewer::createTimeCode(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("num_clock_ts = " + QString::number(pSei->num_clock_ts)))); - - if(pSei -> num_clock_ts > 0) - { - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_clock_ts; i++ )")); - pItem -> addChild(ploop); - - for(std::size_t i=0; i num_clock_ts; i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("clock_time_stamp_flag[" + QString::number(i) + "] = " + QString::number(pSei -> clock_time_stamp_flag[i])))); - - if(pSei -> clock_time_stamp_flag[i]) - { - QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( clock_time_stamp_flag[" + QString::number(i) + "] )")); - ploop -> addChild(pitemIf); - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("nuit_field_based_flag[" + QString::number(i) + "] = " + QString::number(pSei -> nuit_field_based_flag[i])))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("counting_type[" + QString::number(i) + "] = " + QString::number(pSei -> counting_type[i])))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("full_timestamp_flag[" + QString::number(i) + "] = " + QString::number(pSei -> full_timestamp_flag[i])))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("discontinuity_flag[" + QString::number(i) + "] = " + QString::number(pSei -> discontinuity_flag[i])))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("cnt_dropped_flag[" + QString::number(i) + "] = " + QString::number(pSei -> cnt_dropped_flag[i])))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("n_frames[" + QString::number(i) + "] = " + QString::number(pSei -> n_frames[i])))); - - - if(pSei -> full_timestamp_flag[i]) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( full_timestamp_flag[" + QString::number(i) + "] )")); - pitemIf -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("seconds_value[" + QString::number(i) + "] = " + QString::number(pSei -> seconds_value[i])))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("minutes_value[" + QString::number(i) + "] = " + QString::number(pSei -> minutes_value[i])))); - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("hours_value[" + QString::number(i) + "] = " + QString::number(pSei -> hours_value[i])))); - } - else - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( !full_timestamp_flag[" + QString::number(i) + "] )")); - pitemIf -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("seconds_flag[" + QString::number(i) + "] = " + QString::number(pSei -> seconds_flag[i])))); - - if(pSei -> seconds_flag[i]) - { - QTreeWidgetItem *pitemSeconds = new QTreeWidgetItem(QStringList("if( seconds_flag[" + QString::number(i) + "] )")); - pitemSecond -> addChild(pitemSeconds); - - pitemSeconds -> addChild(new QTreeWidgetItem(QStringList("seconds_value[" + QString::number(i) + "] = " + QString::number(pSei -> seconds_value[i])))); - pitemSeconds -> addChild(new QTreeWidgetItem(QStringList("minutes_flag[" + QString::number(i) + "] = " + QString::number(pSei -> minutes_flag[i])))); - - if(pSei -> minutes_flag[i]) - { - QTreeWidgetItem *pitemMinuts = new QTreeWidgetItem(QStringList("if( minutes_flag[" + QString::number(i) + "] )")); - pitemSeconds -> addChild(pitemMinuts); - - pitemMinuts -> addChild(new QTreeWidgetItem(QStringList("minutes_value[" + QString::number(i) + "] = " + QString::number(pSei -> minutes_value[i])))); - pitemMinuts -> addChild(new QTreeWidgetItem(QStringList("hours_flag[" + QString::number(i) + "] = " + QString::number(pSei -> hours_flag[i])))); - - if(pSei -> hours_flag[i]) - { - QTreeWidgetItem *pitemHours = new QTreeWidgetItem(QStringList("if( hours_flag[" + QString::number(i) + "] )")); - pitemMinuts -> addChild(pitemHours); - - pitemHours -> addChild(new QTreeWidgetItem(QStringList("hours_value[" + QString::number(i) + "] = " + QString::number(pSei -> hours_value[i])))); - } - } - } - } - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("time_offset_length[" + QString::number(i) + "] = " + QString::number(pSei -> time_offset_length[i])))); - if(pSei -> time_offset_length[i]) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( time_offset_length[" + QString::number(i) + "] )")); - pitemIf -> addChild(pitemSecond); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("time_offset_value[" + QString::number(i) + "] = " + QString::number(pSei -> time_offset_value[i])))); - } - } - } - } -} - - -void SyntaxViewer::createKneeFunctionInfo(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("knee_function_id = " + QString::number(pSei->knee_function_id)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("knee_function_cancel_flag = " + QString::number(pSei->knee_function_cancel_flag)))); - - if(!pSei -> knee_function_cancel_flag) - { - QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( !knee_function_cancel_flag )")); - pItem -> addChild(pitemIf); - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("knee_function_persistence_flag = " + QString::number(pSei -> knee_function_persistence_flag)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("input_d_range = " + QString::number(pSei -> input_d_range)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("input_disp_luminance = " + QString::number(pSei -> input_disp_luminance)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("output_d_range = " + QString::number(pSei -> output_d_range)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("output_disp_luminance = " + QString::number(pSei -> output_disp_luminance)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("num_knee_points_minus1 = " + QString::number(pSei -> num_knee_points_minus1)))); - - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i <= num_knee_points_minus1; i++ )")); - pitemIf -> addChild(ploop); - - for(std::size_t i=0; i<=pSei -> num_knee_points_minus1; i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("input_knee_point[" + QString::number(i) + "] = " + QString::number(pSei -> input_knee_point[i])))); - ploop -> addChild(new QTreeWidgetItem(QStringList("output_knee_point[" + QString::number(i) + "] = " + QString::number(pSei -> output_knee_point[i])))); - } - } -} - - -void SyntaxViewer::createChromaResamplingFilterHint(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("ver_chroma_filter_idc = " + QString::number(pSei->ver_chroma_filter_idc)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("hor_chroma_filter_idc = " + QString::number(pSei->hor_chroma_filter_idc)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("ver_filtering_field_processing_flag = " + QString::number(pSei->ver_filtering_field_processing_flag)))); - - if(pSei -> ver_chroma_filter_idc == 1 || pSei -> hor_chroma_filter_idc == 1) - { - QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( ver_chroma_filter_idc == 1 || hor_chroma_filter_idc == 1 )")); - pItem -> addChild(pitemIf); - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("target_format_idc = " + QString::number(pSei -> target_format_idc)))); - - if(pSei -> ver_chroma_filter_idc == 1) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( ver_chroma_filter_idc == 1 )")); - pitemIf -> addChild(pitemIf); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("num_vertical_filters = " + QString::number(pSei -> num_vertical_filters)))); - - if(pSei -> num_vertical_filters) - { - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_vertical_filters; i++ )")); - pitemSecond -> addChild(ploop); - - for(std::size_t i=0; i num_vertical_filters; i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("ver_tap_length_minus_1[" + QString::number(i) + "] = " + QString::number(pSei -> ver_tap_length_minus_1[i])))); - - QString str = "ver_filter_coeff[" + QString::number(i) + "] = {\n\t"; - for(std::size_t j=0; j ver_tap_length_minus_1[i]; j++) - { - str += QString::number(pSei -> ver_filter_coeff[i][j]) + ", "; - if((i+1) % 8 == 0) - str += "\n\t"; - } - str += QString::number(pSei -> ver_filter_coeff[i][pSei -> ver_tap_length_minus_1[i]]) + " \n}"; - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList(str))); - } - } - } - - if(pSei -> hor_chroma_filter_idc == 1) - { - QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( hor_chroma_filter_idc == 1 )")); - pitemIf -> addChild(pitemIf); - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList("num_horizontal_filters = " + QString::number(pSei -> num_horizontal_filters)))); - - if(pSei -> num_horizontal_filters) - { - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_horizontal_filters; i++ )")); - pitemSecond -> addChild(ploop); - - for(std::size_t i=0; i num_horizontal_filters; i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("hor_tap_length_minus_1[" + QString::number(i) + "] = " + QString::number(pSei -> hor_tap_length_minus_1[i])))); - - QString str = "hor_filter_coeff[" + QString::number(i) + "] = {\n\t"; - for(std::size_t j=0; j hor_tap_length_minus_1[i]; j++) - { - str += QString::number(pSei -> hor_filter_coeff[i][j]) + ", "; - if((i+1) % 8 == 0) - str += "\n\t"; - } - str += QString::number(pSei -> hor_filter_coeff[i][pSei -> hor_tap_length_minus_1[i]]) + " \n}"; - - pitemSecond -> addChild(new QTreeWidgetItem(QStringList(str))); - } - } - } - } -} - - -void SyntaxViewer::createColourRemappingInfo(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("colour_remap_id = " + QString::number(pSei->colour_remap_id)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("colour_remap_cancel_flag = " + QString::number(pSei->colour_remap_cancel_flag)))); - - if(!pSei -> colour_remap_cancel_flag) - { - QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( !colour_remap_cancel_flag )")); - pItem -> addChild(pitemIf); - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("colour_remap_persistence_flag = " + QString::number(pSei -> colour_remap_persistence_flag)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("colour_remap_video_signal_info_present_flag = " + QString::number(pSei -> colour_remap_video_signal_info_present_flag)))); - - if(pSei -> colour_remap_video_signal_info_present_flag) - { - QTreeWidgetItem *pitemIfSecond = new QTreeWidgetItem(QStringList("if( colour_remap_video_signal_info_present_flag )")); - pitemIf -> addChild(pitemIfSecond); - - pitemIfSecond -> addChild(new QTreeWidgetItem(QStringList("colour_remap_full_range_flag = " + QString::number(pSei -> colour_remap_full_range_flag)))); - pitemIfSecond -> addChild(new QTreeWidgetItem(QStringList("colour_remap_primaries = " + QString::number(pSei -> colour_remap_primaries)))); - pitemIfSecond -> addChild(new QTreeWidgetItem(QStringList("colour_remap_transfer_function = " + QString::number(pSei -> colour_remap_transfer_function)))); - pitemIfSecond -> addChild(new QTreeWidgetItem(QStringList("colour_remap_matrix_coefficients = " + QString::number(pSei -> colour_remap_matrix_coefficients)))); - } - pitemIf -> addChild(new QTreeWidgetItem(QStringList("colour_remap_input_bit_depth = " + QString::number(pSei -> colour_remap_input_bit_depth)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("colour_remap_bit_depth = " + QString::number(pSei -> colour_remap_bit_depth)))); - - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < 3; i++ )")); - pitemIf -> addChild(ploop); - - for(std::size_t i=0 ; i<3 ; i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("pre_lut_num_val_minus1[" + QString::number(i) + "] = " + QString::number(pSei -> pre_lut_num_val_minus1[i])))); - - if(pSei -> pre_lut_num_val_minus1[i] > 0) - { - QTreeWidgetItem *pitemIfSecond = new QTreeWidgetItem(QStringList("if( pre_lut_num_val_minus1[" + QString::number(i) + "] > 0 )")); - ploop -> addChild(pitemIfSecond); - - QTreeWidgetItem *ploopSecond = new QTreeWidgetItem(QStringList("for( j = 0; j <= pre_lut_num_val_minus1[" + QString::number(i) + "]; j++ )")); - pitemIfSecond -> addChild(ploopSecond); - - for (std::size_t j=0 ; j<=pSei -> pre_lut_num_val_minus1[i]; j++) - { - ploopSecond -> addChild(new QTreeWidgetItem(QStringList("pre_lut_coded_value[" + QString::number(i) + "][" + QString::number(j) + "] = " + QString::number(pSei -> pre_lut_coded_value[i][j])))); - ploopSecond -> addChild(new QTreeWidgetItem(QStringList("pre_lut_target_value[" + QString::number(i) + "][" + QString::number(j) + "] = " + QString::number(pSei -> pre_lut_target_value[i][j])))); - } - } - } - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("colour_remap_matrix_present_flag = " + QString::number(pSei -> colour_remap_matrix_present_flag)))); - - if(pSei -> colour_remap_matrix_present_flag) - { - QTreeWidgetItem *pitemIfSecond = new QTreeWidgetItem(QStringList("if( colour_remap_matrix_present_flag )")); - pitemIf -> addChild(pitemIfSecond); - - pitemIfSecond -> addChild(new QTreeWidgetItem(QStringList("log2_matrix_denom = " + QString::number(pSei -> log2_matrix_denom)))); - - QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < 3; i++ )")); - pitemIfSecond -> addChild(ploop); - - for (std::size_t i=0 ; i<3 ; i++) - { - QString str = "colour_remap_coeffs[" + QString::number(i) + "] = { "; - for (std::size_t j=0 ; j<2 ; j++) - { - str += QString::number(pSei -> colour_remap_coeffs[i][j]) + ", "; - } - str += QString::number(pSei -> colour_remap_coeffs[i][2]) + " }"; - - ploop -> addChild(new QTreeWidgetItem(QStringList(str))); - } - } - - ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < 3; i++ )")); - pitemIf -> addChild(ploop); - - for(std::size_t i=0 ; i<3 ; i++) - { - ploop -> addChild(new QTreeWidgetItem(QStringList("post_lut_num_val_minus1[" + QString::number(i) + "] = " + QString::number(pSei -> post_lut_num_val_minus1[i])))); - - if(pSei -> post_lut_num_val_minus1[i] > 0) - { - QTreeWidgetItem *pitemIfSecond = new QTreeWidgetItem(QStringList("if( post_lut_num_val_minus1[" + QString::number(i) + "] > 0 )")); - ploop -> addChild(pitemIfSecond); - - QTreeWidgetItem *ploopSecond = new QTreeWidgetItem(QStringList("for( j = 0; j <= post_lut_num_val_minus1[" + QString::number(i) + "]; j++ )")); - pitemIfSecond -> addChild(ploopSecond); - - for (std::size_t j=0 ; j<=pSei -> post_lut_num_val_minus1[i]; j++) - { - ploopSecond -> addChild(new QTreeWidgetItem(QStringList("post_lut_coded_value[" + QString::number(i) + "][" + QString::number(j) + "] = " + QString::number(pSei -> post_lut_coded_value[i][j])))); - ploopSecond -> addChild(new QTreeWidgetItem(QStringList("post_lut_target_value[" + QString::number(i) + "][" + QString::number(j) + "] = " + QString::number(pSei -> post_lut_target_value[i][j])))); - } - } - } - } -} - - -void SyntaxViewer::createSceneInfo(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("scene_info_present_flag = " + QString::number(pSei->scene_info_present_flag)))); - - if(pSei -> scene_info_present_flag) - { - QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( scene_info_present_flag )")); - pItem -> addChild(pitemIf); - - pitemIf -> addChild(new QTreeWidgetItem(QStringList("prev_scene_id_valid_flag = " + QString::number(pSei -> prev_scene_id_valid_flag)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("scene_id = " + QString::number(pSei -> scene_id)))); - pitemIf -> addChild(new QTreeWidgetItem(QStringList("scene_transition_type = " + QString::number(pSei -> scene_transition_type)))); - - if(pSei -> scene_transition_type > 3) - { - QTreeWidgetItem *pitemIfSecond = new QTreeWidgetItem(QStringList("if( scene_transition_type > 3 )")); - pitemIf -> addChild(pitemIfSecond); - - pitemIfSecond -> addChild(new QTreeWidgetItem(QStringList("second_scene_id = " + QString::number(pSei -> second_scene_id)))); - } - } -} - -void SyntaxViewer::createProgressiveRefinementSegmentStart(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("progressive_refinement_id = " + QString::number(pSei->progressive_refinement_id)))); - pItem -> addChild(new QTreeWidgetItem(QStringList("pic_order_cnt_delta = " + QString::number(pSei->pic_order_cnt_delta)))); -} - - -void SyntaxViewer::createProgressiveRefinementSegmentEnd(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("progressive_refinement_id = " + QString::number(pSei->progressive_refinement_id)))); -} - - -void SyntaxViewer::createFullFrameSnapshot(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("snapshot_id = " + QString::number(pSei->snapshot_id)))); -} - - -void SyntaxViewer::createRegionRefreshInfo(std::shared_ptr pSei, QTreeWidgetItem *pItem) -{ - pItem -> addChild(new QTreeWidgetItem(QStringList("refreshed_region_flag = " + QString::number(pSei->refreshed_region_flag)))); -} - - -void SyntaxViewer::onItemCollapsed(QTreeWidgetItem * item) -{ - m_state.setActive(item, false); -} - - -void SyntaxViewer::onItemExpanded(QTreeWidgetItem * item) -{ - m_state.setActive(item, true); -} - - -void SyntaxViewer::updateItemsState() -{ - QTreeWidgetItemIterator itr(this); - - for(;*itr; itr++) - (*itr)-> setExpanded(m_state.isActive((*itr))); -} - - -bool SyntaxViewer::SyntaxViewerState::isActive(const QTreeWidgetItem *pitem) const -{ - std::map::const_iterator itr = m_state.find(name(pitem)); - if(itr != m_state.end()) - return itr -> second; - - return true; -} - - -void SyntaxViewer::SyntaxViewerState::setActive(const QTreeWidgetItem *pitem, bool isActive) -{ - m_state[name(pitem)] = isActive; -} - - -QString SyntaxViewer::SyntaxViewerState::name(const QTreeWidgetItem *pitem) const -{ - QString name; - while(pitem) - { - if(name.isEmpty()) - name = pitem -> text(0); - else - name = pitem -> text(0) + "::" + name; - - pitem = pitem -> parent(); - } - - return name; -} +#include "SyntaxViewer.h" + +#include +#include +#include + +#include + +#include +#include + +#define SLICE_B 0 +#define SLICE_P 1 +#define SLICE_I 2 + +SyntaxViewer::SyntaxViewer(QWidget* pwgt): + QTreeWidget(pwgt) +{ + header()->hide(); + QObject::connect(this, SIGNAL(itemCollapsed(QTreeWidgetItem *)), SLOT(onItemCollapsed(QTreeWidgetItem *))); + QObject::connect(this, SIGNAL(itemExpanded(QTreeWidgetItem *)), SLOT(onItemExpanded(QTreeWidgetItem *))); +} + + +void SyntaxViewer::setParameretsSets(const VPSMap &vpsMap, + const SPSMap &spsMap, + const PPSMap &ppsMap) +{ + m_vpsMap = vpsMap; + m_spsMap = spsMap; + m_ppsMap = ppsMap; +} + + +void SyntaxViewer::onNalUChanged(std::shared_ptr pNalU, ParserInfo info) +{ + (void)info; + clear(); + using namespace HEVC; + switch(pNalU -> m_nalHeader.type) + { + case NAL_VPS: + { + std::shared_ptr pVPS = std::dynamic_pointer_cast(pNalU); + createVPS(pVPS); + break; + } + + case NAL_SPS: + { + std::shared_ptr pSPS = std::dynamic_pointer_cast(pNalU); + createSPS(pSPS); + break; + } + + case NAL_PPS: + { + std::shared_ptr pPPS = std::dynamic_pointer_cast(pNalU); + createPPS(pPPS); + break; + } + + case NAL_TRAIL_R: + case NAL_TRAIL_N: + case NAL_TSA_N: + case NAL_TSA_R: + case NAL_STSA_N: + case NAL_STSA_R: + case NAL_BLA_W_LP: + case NAL_BLA_W_RADL: + case NAL_BLA_N_LP: + case NAL_IDR_W_RADL: + case NAL_IDR_N_LP: + case NAL_CRA_NUT: + case NAL_RADL_N: + case NAL_RADL_R: + case NAL_RASL_N: + case NAL_RASL_R: + { + createSlice(std::dynamic_pointer_cast(pNalU)); + break; + } + + case NAL_AUD: + { + createAUD(std::dynamic_pointer_cast(pNalU)); + break; + } + + case NAL_SEI_PREFIX: + case NAL_SEI_SUFFIX: + { + createSEI(std::dynamic_pointer_cast(pNalU)); + break; + } + + default: + break; + }; + + updateItemsState(); +} + +void SyntaxViewer::onH264NalUChanged(std::shared_ptr pNalU, H264::Parser::Info info) +{ + (void)info; + clear(); + using namespace H264; + switch(pNalU->m_nalHeader.nal_unit_type) + { + case NAL_SPS: + { + std::shared_ptr pSPS = std::dynamic_pointer_cast(pNalU); + createH264SPS(pSPS); + break; + } + + case NAL_PPS: + { + std::shared_ptr pPPS = std::dynamic_pointer_cast(pNalU); + createH264PPS(pPPS); + break; + } + + case NAL_SLICE: + case NAL_IDR_SLICE: + { + createH264Slice(std::dynamic_pointer_cast(pNalU)); + break; + } + + case NAL_AUD: + { + createH264AUD(std::dynamic_pointer_cast(pNalU)); + break; + } + + case NAL_SEI: + { + createH264SEI(std::dynamic_pointer_cast(pNalU)); + break; + } + + default: + break; + }; + + updateItemsState(); +} + +void SyntaxViewer::onVideoNalUChanged(std::shared_ptr pNalU, VideoParserInfo info) +{ + if (pNalU->getCodec() == VideoCodec::HEVC) + { + auto hevcWrapper = std::dynamic_pointer_cast(pNalU); + if (hevcWrapper) + { + auto hevcNALUnit = hevcWrapper->getHEVCNALUnit(); + ParserInfo hevcInfo; + hevcInfo.m_position = info.m_position; + onNalUChanged(hevcNALUnit, hevcInfo); + } + } + else if (pNalU->getCodec() == VideoCodec::H264) + { + auto h264Wrapper = std::dynamic_pointer_cast(pNalU); + if (h264Wrapper) + { + auto h264NALUnit = h264Wrapper->getH264NALUnit(); + H264::Parser::Info h264Info; + h264Info.m_position = info.m_position; + onH264NalUChanged(h264NALUnit, h264Info); + } + } +} + +void SyntaxViewer::setH264ParameterSets(const std::map> &spsMap, + const std::map> &ppsMap) +{ + m_h264SpsMap = spsMap; + m_h264PpsMap = ppsMap; +} + + +void SyntaxViewer::createVPS(std::shared_ptr pVPS) +{ + QTreeWidgetItem *pvpsItem = new QTreeWidgetItem(QStringList("VPS")); + addTopLevelItem(pvpsItem); + + pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_video_parameter_set_id = " + QString::number(pVPS -> vps_video_parameter_set_id)))); + pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_max_layers_minus1 = " + QString::number(pVPS -> vps_max_layers_minus1)))); + pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_max_sub_layers_minus1 = " + QString::number(pVPS -> vps_max_sub_layers_minus1)))); + pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_temporal_id_nesting_flag = " + QString::number(pVPS -> vps_temporal_id_nesting_flag)))); + + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("profile_tier_level")); + pvpsItem -> addChild(pitem); + createProfileTierLevel(pVPS -> profile_tier_level, pitem); + + + pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_sub_layer_ordering_info_present_flag = " + QString::number(pVPS -> vps_sub_layer_ordering_info_present_flag)))); + + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = ( vps_sub_layer_ordering_info_present_flag ? 0 : vps_max_sub_layers_minus1 ); i <= vps_max_sub_layers_minus1; i++ )")); + + pvpsItem -> addChild(ploop); + + for(std::size_t i = (pVPS -> vps_sub_layer_ordering_info_present_flag ? 0 : pVPS -> vps_max_sub_layers_minus1); i <= pVPS -> vps_max_sub_layers_minus1; i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("vps_max_dec_pic_buffering_minus1[" + QString::number(i) + "] = " + QString::number(pVPS -> vps_max_dec_pic_buffering_minus1[i])))); + ploop -> addChild(new QTreeWidgetItem(QStringList("vps_max_num_reorder_pics[" + QString::number(i) + "] = " + QString::number(pVPS -> vps_max_num_reorder_pics[i])))); + ploop -> addChild(new QTreeWidgetItem(QStringList("vps_max_latency_increase_plus1[" + QString::number(i) + "] = " + QString::number(pVPS -> vps_max_latency_increase_plus1[i])))); + } + + pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_max_layer_id = " + QString::number(pVPS -> vps_max_layer_id)))); + pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_num_layer_sets_minus1 = " + QString::number(pVPS -> vps_num_layer_sets_minus1)))); + + + if(pVPS -> vps_num_layer_sets_minus1 == 0) + { + pvpsItem -> addChild(new QTreeWidgetItem(QStringList("layer_id_included_flag = { }"))); + } + else + { + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for(std::size_t i=0; i vps_num_layer_sets_minus1; i++) + { + QString str; + + if(pVPS -> vps_max_layer_id == 0) + str = "layer_id_included_flag[" + QString::number(i) + "] = { } "; + else + { + for(int j=0; j vps_max_layer_id - 1; j++) + { + str += QString::number(pVPS -> layer_id_included_flag[i][j]) + ", "; + if((j + 1) % 8) + str += "\n"; + } + str += QString::number(pVPS -> layer_id_included_flag[i][pVPS -> vps_max_layer_id - 1]) + " } "; + } + ploop -> addChild(new QTreeWidgetItem(QStringList(str))); + } + } + + pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_timing_info_present_flag = " + QString::number(pVPS -> vps_timing_info_present_flag)))); + + if(pVPS -> vps_timing_info_present_flag) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( vps_timing_info_present_flag )")); + pvpsItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("vps_num_units_in_tick = " + QString::number(pVPS -> vps_num_units_in_tick)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("vps_time_scale = " + QString::number(pVPS -> vps_time_scale)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("vps_poc_proportional_to_timing_flag = " + QString::number(pVPS -> vps_poc_proportional_to_timing_flag)))); + + if(pVPS -> vps_poc_proportional_to_timing_flag) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( vps_poc_proportional_to_timing_flag )")); + pitem -> addChild(pitemSecond); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("vps_num_ticks_poc_diff_one_minus1 = " + QString::number(pVPS -> vps_num_ticks_poc_diff_one_minus1)))); + } + + pitem -> addChild(new QTreeWidgetItem(QStringList("vps_num_hrd_parameters = " + QString::number(pVPS -> vps_num_hrd_parameters)))); + + if(pVPS -> vps_num_hrd_parameters) + { + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < vps_num_hrd_parameters; i++ )")); + pitem -> addChild(ploop); + + for(std::size_t i=0; i vps_num_hrd_parameters; i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("hrd_layer_set_idx[ " + QString::number(i) + "] = " + QString::number(pVPS -> hrd_layer_set_idx[i])))); + if(i > 0) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( i > 0 )")); + ploop -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("cprms_present_flag[ " + QString::number(i) + "] = " + QString::number(pVPS -> cprms_present_flag[i])))); + } + + + QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("hrd_parameters(" + QString::number(i) + ", " + QString::number(pVPS -> vps_max_sub_layers_minus1) + ")")); + ploop -> addChild(pitemThird); + + createHrdParameters(pVPS -> hrd_parameters[i], pVPS -> cprms_present_flag[i], pitemThird); + } + } + } + + pvpsItem -> addChild(new QTreeWidgetItem(QStringList("vps_extension_flag = " + QString::number(pVPS -> vps_extension_flag)))); +} + + + +void SyntaxViewer::createSPS(std::shared_ptr pSPS) +{ + QTreeWidgetItem *pspsItem = new QTreeWidgetItem(QStringList("SPS")); + addTopLevelItem(pspsItem); + + QTreeWidgetItem *pitem; + pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_video_parameter_set_id = " + QString::number(pSPS -> sps_video_parameter_set_id)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_max_sub_layers_minus1 = " + QString::number(pSPS -> sps_max_sub_layers_minus1)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_temporal_id_nesting_flag = " + QString::number(pSPS -> sps_temporal_id_nesting_flag)))); + + pitem = new QTreeWidgetItem(QStringList("profile_tier_level")); + pspsItem -> addChild(pitem); + createProfileTierLevel(pSPS -> profile_tier_level, pitem); + + + + pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_seq_parameter_set_id = " + QString::number(pSPS -> sps_seq_parameter_set_id)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("chroma_format_idc = " + QString::number(pSPS -> chroma_format_idc)))); + + if(pSPS -> chroma_format_idc == 3) + { + pitem = new QTreeWidgetItem(QStringList("if( chroma_format_idc == 3 )")); + pspsItem -> addChild(pitem); + pitem -> addChild(new QTreeWidgetItem(QStringList("separate_colour_plane_flag = " + QString::number(pSPS -> separate_colour_plane_flag)))); + } + + + pspsItem -> addChild(new QTreeWidgetItem(QStringList("pic_width_in_luma_samples = " + QString::number(pSPS -> pic_width_in_luma_samples)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("pic_height_in_luma_samples = " + QString::number(pSPS -> pic_height_in_luma_samples)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("conformance_window_flag = " + QString::number(pSPS -> conformance_window_flag)))); + + if(pSPS -> conformance_window_flag) + { + pitem = new QTreeWidgetItem(QStringList("if( conformance_window_flag )")); + pspsItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("conf_win_left_offset = " + QString::number(pSPS -> conf_win_left_offset)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("conf_win_right_offset = " + QString::number(pSPS -> conf_win_right_offset)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("conf_win_top_offset = " + QString::number(pSPS -> conf_win_top_offset)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("conf_win_bottom_offset = " + QString::number(pSPS -> conf_win_bottom_offset)))); + } + + pspsItem -> addChild(new QTreeWidgetItem(QStringList("bit_depth_luma_minus8 = " + QString::number(pSPS -> bit_depth_luma_minus8)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("bit_depth_chroma_minus8 = " + QString::number(pSPS -> bit_depth_chroma_minus8)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("log2_max_pic_order_cnt_lsb_minus4 = " + QString::number(pSPS -> log2_max_pic_order_cnt_lsb_minus4)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_sub_layer_ordering_info_present_flag = " + QString::number(pSPS -> sps_sub_layer_ordering_info_present_flag)))); + + pitem = new QTreeWidgetItem(QStringList("for( i = ( sps_sub_layer_ordering_info_present_flag ? 0 : sps_max_sub_layers_minus1 );i <= sps_max_sub_layers_minus1; i++ )")); + pspsItem -> addChild(pitem); + + for(std::size_t i = (pSPS -> sps_sub_layer_ordering_info_present_flag ? 0 : pSPS -> sps_max_sub_layers_minus1); i <= pSPS -> sps_max_sub_layers_minus1; i++ ) + { + pitem -> addChild(new QTreeWidgetItem(QStringList("sps_max_dec_pic_buffering_minus1[" + QString::number(i) + "] = " + QString::number(pSPS -> sps_max_dec_pic_buffering_minus1[i])))); + pitem -> addChild(new QTreeWidgetItem(QStringList("sps_max_num_reorder_pics[" + QString::number(i) + "] = " + QString::number(pSPS -> sps_max_num_reorder_pics[i])))); + pitem -> addChild(new QTreeWidgetItem(QStringList("sps_max_latency_increase_plus1[" + QString::number(i) + "] = " + QString::number(pSPS -> sps_max_latency_increase_plus1[i])))); + } + + + pspsItem -> addChild(new QTreeWidgetItem(QStringList("log2_min_luma_coding_block_size_minus3 = " + QString::number(pSPS -> log2_min_luma_coding_block_size_minus3)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("log2_diff_max_min_luma_coding_block_size = " + QString::number(pSPS -> log2_diff_max_min_luma_coding_block_size)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("log2_min_transform_block_size_minus2 = " + QString::number(pSPS -> log2_min_transform_block_size_minus2)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("log2_diff_max_min_transform_block_size = " + QString::number(pSPS -> log2_diff_max_min_transform_block_size)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("max_transform_hierarchy_depth_inter = " + QString::number(pSPS -> max_transform_hierarchy_depth_inter)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("max_transform_hierarchy_depth_intra = " + QString::number(pSPS -> max_transform_hierarchy_depth_intra)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("scaling_list_enabled_flag = " + QString::number(pSPS -> scaling_list_enabled_flag)))); + + if(pSPS -> scaling_list_enabled_flag) + { + pitem = new QTreeWidgetItem(QStringList("if( scaling_list_enabled_flag )")); + pspsItem -> addChild(pitem); + pitem -> addChild(new QTreeWidgetItem(QStringList("sps_scaling_list_data_present_flag = " + QString::number(pSPS -> sps_scaling_list_data_present_flag)))); + + if(pSPS -> sps_scaling_list_data_present_flag) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("scaling_list_data( )")); + pitem -> addChild(pitemSecond); + createScalingListData(pSPS -> scaling_list_data, pitemSecond); + } + } + + pspsItem -> addChild(new QTreeWidgetItem(QStringList("amp_enabled_flag = " + QString::number(pSPS -> amp_enabled_flag)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("sample_adaptive_offset_enabled_flag = " + QString::number(pSPS -> sample_adaptive_offset_enabled_flag)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("pcm_enabled_flag = " + QString::number(pSPS -> pcm_enabled_flag)))); + if(pSPS -> pcm_enabled_flag) + { + pitem = new QTreeWidgetItem(QStringList("if( pcm_enabled_flag )")); + pspsItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("pcm_sample_bit_depth_luma_minus1 = " + QString::number(pSPS -> pcm_sample_bit_depth_luma_minus1)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("pcm_sample_bit_depth_chroma_minus1 = " + QString::number(pSPS -> pcm_sample_bit_depth_chroma_minus1)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("log2_min_pcm_luma_coding_block_size_minus3 = " + QString::number(pSPS -> log2_min_pcm_luma_coding_block_size_minus3)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("log2_diff_max_min_pcm_luma_coding_block_size = " + QString::number(pSPS -> log2_diff_max_min_pcm_luma_coding_block_size)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("pcm_loop_filter_disabled_flag = " + QString::number(pSPS -> pcm_loop_filter_disabled_flag)))); + } + + pspsItem -> addChild(new QTreeWidgetItem(QStringList("num_short_term_ref_pic_sets = " + QString::number(pSPS -> num_short_term_ref_pic_sets)))); + + if(pSPS -> num_short_term_ref_pic_sets) + { + pitem = new QTreeWidgetItem(QStringList("for( i = 0; i < num_short_term_ref_pic_sets; i++)")); + pspsItem -> addChild(pitem); + + for(std::size_t i=0; i num_short_term_ref_pic_sets; i++) + { + QTreeWidgetItem *pStrpc = new QTreeWidgetItem(QStringList("short_term_ref_pic_set(" + QString::number(i) + ")")); + pitem -> addChild(pStrpc); + + HEVC::ShortTermRefPicSet rpset = pSPS -> short_term_ref_pic_set[i]; + createShortTermRefPicSet(i, rpset, pSPS -> num_short_term_ref_pic_sets, pSPS -> short_term_ref_pic_set, pStrpc); + } + } + + + pspsItem -> addChild(new QTreeWidgetItem(QStringList("long_term_ref_pics_present_flag = " + QString::number(pSPS -> long_term_ref_pics_present_flag)))); + if(pSPS -> long_term_ref_pics_present_flag) + { + pitem = new QTreeWidgetItem(QStringList("if( long_term_ref_pics_present_flag )")); + pspsItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("num_long_term_ref_pics_sps = " + QString::number(pSPS -> num_long_term_ref_pics_sps)))); + + + if(pSPS -> num_long_term_ref_pics_sps > 0) + { + QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_long_term_ref_pics_sps; i++ )")); + pitem -> addChild(pitemLoop); + + for(std::size_t i=0; i num_long_term_ref_pics_sps; i++) + { + pspsItem -> addChild(new QTreeWidgetItem(QStringList("lt_ref_pic_poc_lsb_sps[ " + QString::number(i) + "] = " + QString::number(pSPS -> lt_ref_pic_poc_lsb_sps[i])))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("used_by_curr_pic_lt_sps_flag[ " + QString::number(i) + "] = " + QString::number(pSPS -> used_by_curr_pic_lt_sps_flag[i])))); + } + } + } + + pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_temporal_mvp_enabled_flag = " + QString::number(pSPS -> sps_temporal_mvp_enabled_flag)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("strong_intra_smoothing_enabled_flag = " + QString::number(pSPS -> strong_intra_smoothing_enabled_flag)))); + pspsItem -> addChild(new QTreeWidgetItem(QStringList("vui_parameters_present_flag = " + QString::number(pSPS -> vui_parameters_present_flag)))); + + if(pSPS -> vui_parameters_present_flag) + { + pitem = new QTreeWidgetItem(QStringList("if( vui_parameters_present_flag )")); + pspsItem -> addChild(pitem); + QTreeWidgetItem *pVuiItem = new QTreeWidgetItem(QStringList("vui_parameters")); + pitem -> addChild(pVuiItem); + + createVuiParameters(pSPS -> vui_parameters, pSPS -> sps_max_sub_layers_minus1, pVuiItem); + } + + pspsItem -> addChild(new QTreeWidgetItem(QStringList("sps_extension_flag = " + QString::number(pSPS -> sps_extension_flag)))); +} + +void SyntaxViewer::createPPS(std::shared_ptr pPPS) +{ + QTreeWidgetItem *pppsItem = new QTreeWidgetItem(QStringList("PPS")); + addTopLevelItem(pppsItem); + + QTreeWidgetItem *pitem; + pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_pic_parameter_set_id = " + QString::number(pPPS -> pps_pic_parameter_set_id)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_seq_parameter_set_id = " + QString::number(pPPS -> pps_seq_parameter_set_id)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("dependent_slice_segments_enabled_flag = " + QString::number(pPPS -> dependent_slice_segments_enabled_flag)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("output_flag_present_flag = " + QString::number(pPPS -> output_flag_present_flag)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("num_extra_slice_header_bits = " + QString::number(pPPS -> num_extra_slice_header_bits)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("sign_data_hiding_flag = " + QString::number(pPPS -> sign_data_hiding_flag)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("cabac_init_present_flag = " + QString::number(pPPS -> cabac_init_present_flag)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("num_ref_idx_l0_default_active_minus1 = " + QString::number(pPPS -> num_ref_idx_l0_default_active_minus1)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("num_ref_idx_l1_default_active_minus1 = " + QString::number(pPPS -> num_ref_idx_l1_default_active_minus1)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("init_qp_minus26 = " + QString::number(pPPS -> init_qp_minus26)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("constrained_intra_pred_flag = " + QString::number(pPPS -> constrained_intra_pred_flag)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("transform_skip_enabled_flag = " + QString::number(pPPS -> transform_skip_enabled_flag)))); + + pitem = new QTreeWidgetItem(QStringList("cu_qp_delta_enabled_flag = " + QString::number(pPPS -> cu_qp_delta_enabled_flag))); + pppsItem -> addChild(pitem); + + if(pPPS -> cu_qp_delta_enabled_flag) + { + pitem = new QTreeWidgetItem(QStringList("if(cu_qp_delta_enabled_flag)")); + pppsItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("diff_cu_qp_delta_depth = " + QString::number(pPPS -> diff_cu_qp_delta_depth)))); + } + + pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_cb_qp_offset = " + QString::number(pPPS -> pps_cb_qp_offset)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_cr_qp_offset = " + QString::number(pPPS -> pps_cr_qp_offset)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_slice_chroma_qp_offsets_present_flag = " + QString::number(pPPS -> pps_slice_chroma_qp_offsets_present_flag)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("weighted_pred_flag = " + QString::number(pPPS -> weighted_pred_flag)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("weighted_bipred_flag = " + QString::number(pPPS -> weighted_bipred_flag)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("transquant_bypass_enabled_flag = " + QString::number(pPPS -> transquant_bypass_enabled_flag)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("tiles_enabled_flag = " + QString::number(pPPS -> tiles_enabled_flag)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("entropy_coding_sync_enabled_flag = " + QString::number(pPPS -> entropy_coding_sync_enabled_flag)))); + + + if(pPPS -> tiles_enabled_flag) + { + pitem = new QTreeWidgetItem(QStringList("if(tiles_enabled_flag)")); + pppsItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("num_tile_columns_minus1 = " + QString::number(pPPS -> num_tile_columns_minus1)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("num_tile_rows_minus1 = " + QString::number(pPPS -> num_tile_rows_minus1)))); + + pitem -> addChild(new QTreeWidgetItem(QStringList("uniform_spacing_flag = " + QString::number(pPPS -> uniform_spacing_flag)))); + + if(!pPPS -> uniform_spacing_flag) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if(!uniform_spacing_flag)")); + pitem -> addChild(pitemSecond); + + QString str = "column_width_minus1 = {\n\t"; + for(int i=0; i<(int)pPPS -> num_tile_columns_minus1 - 1; i++) + { + str += QString::number(pPPS -> column_width_minus1[i]) + ", "; + if((i+1) % 8 == 0) + str += "\n\t"; + } + if(pPPS -> num_tile_columns_minus1 > 0) + str += QString::number(pPPS -> column_width_minus1[pPPS -> num_tile_columns_minus1 - 1]) + " \n}"; + else + str += "}"; + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList(str))); + + str = "row_height_minus1 = {\n\t"; + for(int i=0; i<(int)pPPS -> num_tile_rows_minus1 - 1; i++) + { + str += QString::number(pPPS -> row_height_minus1[i]) + ", "; + if((i+1) % 8 == 0) + str += "\n\t"; + } + if(pPPS -> num_tile_rows_minus1 > 0) + str += QString::number(pPPS -> row_height_minus1[pPPS -> num_tile_rows_minus1 - 1]) + " \n}"; + else + str += "}"; + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList(str))); + } + + pitem -> addChild(new QTreeWidgetItem(QStringList("loop_filter_across_tiles_enabled_flag = " + QString::number(pPPS -> loop_filter_across_tiles_enabled_flag)))); + } + + pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_loop_filter_across_slices_enabled_flag = " + QString::number(pPPS -> pps_loop_filter_across_slices_enabled_flag)))); + + pppsItem -> addChild(new QTreeWidgetItem(QStringList("deblocking_filter_control_present_flag = " + QString::number(pPPS -> deblocking_filter_control_present_flag)))); + + if(pPPS -> deblocking_filter_control_present_flag) + { + + pitem = new QTreeWidgetItem(QStringList("if(deblocking_filter_control_present_flag)")); + pppsItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("deblocking_filter_override_enabled_flag = " + QString::number(pPPS -> deblocking_filter_override_enabled_flag)))); + + pitem -> addChild(new QTreeWidgetItem(QStringList("pps_deblocking_filter_disabled_flag = " + QString::number(pPPS -> pps_deblocking_filter_disabled_flag)))); + + if(!pPPS -> pps_deblocking_filter_disabled_flag) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if(!pps_deblocking_filter_disabled_flag)")); + pitem -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("pps_beta_offset_div2 = " + QString::number(pPPS -> pps_beta_offset_div2)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("pps_tc_offset_div2 = " + QString::number(pPPS -> pps_tc_offset_div2)))); + } + } + + + pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_scaling_list_data_present_flag = " + QString::number(pPPS -> pps_scaling_list_data_present_flag)))); + + if(pPPS -> pps_scaling_list_data_present_flag) + { + pitem = new QTreeWidgetItem(QStringList("if(pps_scaling_list_data_present_flag)")); + pppsItem -> addChild(pitem); + + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("scaling_list_data")); + pitem -> addChild(pitemSecond); + createScalingListData(pPPS -> scaling_list_data, pitemSecond); + + } + + pppsItem -> addChild(new QTreeWidgetItem(QStringList("lists_modification_present_flag = " + QString::number(pPPS -> lists_modification_present_flag)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("log2_parallel_merge_level_minus2 = " + QString::number(pPPS -> log2_parallel_merge_level_minus2)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("slice_segment_header_extension_present_flag = " + QString::number(pPPS -> slice_segment_header_extension_present_flag)))); + pppsItem -> addChild(new QTreeWidgetItem(QStringList("pps_extension_flag = " + QString::number(pPPS -> pps_extension_flag)))); +} + +void SyntaxViewer::createSlice(std::shared_ptr pSlice) +{ + if(pSlice -> m_processFailed) + return; + + std::shared_ptr pPPS = m_ppsMap[pSlice -> slice_pic_parameter_set_id]; + if(!pPPS) + return; + + int32_t spsId = pPPS -> pps_seq_parameter_set_id; + QTreeWidgetItem *pitemDepend, *pitemThird; + QTreeWidgetItem *psliceItem = new QTreeWidgetItem(QStringList("Slice")); + addTopLevelItem(psliceItem); + + QTreeWidgetItem *pitem; + psliceItem -> addChild(new QTreeWidgetItem(QStringList("first_slice_segment_in_pic_flag = " + QString::number(pSlice -> first_slice_segment_in_pic_flag)))); + + if(pSlice -> m_nalHeader.type >= HEVC::NAL_BLA_W_LP && pSlice -> m_nalHeader.type <= HEVC::NAL_IRAP_VCL23) + { + pitem = new QTreeWidgetItem(QStringList("if ( nal_unit_type >= BLA_W_LP && nal_unit_type <= RSV_IRAP_VCL23)")); + psliceItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("no_output_of_prior_pics_flag = " + QString::number(pSlice -> no_output_of_prior_pics_flag)))); + } + + psliceItem -> addChild(new QTreeWidgetItem(QStringList("slice_pic_parameter_set_id = " + QString::number(pSlice -> slice_pic_parameter_set_id)))); + + if(!pSlice -> first_slice_segment_in_pic_flag) + { + pitem = new QTreeWidgetItem(QStringList("if (!first_slice_segment_in_pic_flag)")); + psliceItem -> addChild(pitem); + + if(pPPS -> dependent_slice_segments_enabled_flag) + { + pitemDepend = new QTreeWidgetItem(QStringList("pps -> dependent_slice_segments_enabled_flag = " + QString::number(pPPS -> dependent_slice_segments_enabled_flag))); + pitem -> addChild(pitemDepend); + + pitemDepend -> addChild(new QTreeWidgetItem(QStringList("dependent_slice_segment_flag = " + QString::number(pSlice -> dependent_slice_segment_flag)))); + } + pitem -> addChild(new QTreeWidgetItem(QStringList("slice_segment_address = " + QString::number(pSlice -> slice_segment_address)))); + } + + if(!pSlice -> dependent_slice_segment_flag) + { + pitem = new QTreeWidgetItem(QStringList("if (!dependent_slice_segment_flag)")); + psliceItem -> addChild(pitem); + + long num_extra_slice_header_bits = pPPS -> num_extra_slice_header_bits; + + QString str; + if(num_extra_slice_header_bits > 0) + { + str = "slice_reserved_undetermined_flag = {\n\t"; + + if(num_extra_slice_header_bits > pSlice -> slice_reserved_undetermined_flag.size()) + return; + + for(long i=0; i slice_reserved_undetermined_flag[i]) + ", "; + + str += QString::number(pSlice -> slice_reserved_undetermined_flag[num_extra_slice_header_bits - 1]) + ", "; + } + else + str = "slice_reserved_undetermined_flag = { }"; + + pitem -> addChild(new QTreeWidgetItem(QStringList(str))); + pitem -> addChild(new QTreeWidgetItem(QStringList("slice_type = " + QString::number(pSlice -> slice_type)))); + + if(pPPS -> output_flag_present_flag) + { + pitemDepend = new QTreeWidgetItem(QStringList("if (output_flag_present_flag)")); + pitem -> addChild(pitemDepend); + pitemDepend -> addChild(new QTreeWidgetItem(QStringList("pic_output_flag = " + QString::number(pSlice -> pic_output_flag)))); + } + + + if(!m_spsMap[spsId]) + return; + + if(m_spsMap[spsId] -> separate_colour_plane_flag) + { + pitemDepend = new QTreeWidgetItem(QStringList("if (sps -> separate_colour_plane_flag)")); + pitem -> addChild(pitemDepend); + pitemDepend -> addChild(new QTreeWidgetItem(QStringList("colour_plane_id = " + QString::number(pSlice -> colour_plane_id)))); + } + bool IdrPicFlag = pSlice -> m_nalHeader.type == HEVC::NAL_IDR_W_RADL || pSlice -> m_nalHeader.type == HEVC::NAL_IDR_N_LP; + + if(!IdrPicFlag) + { + pitemDepend = new QTreeWidgetItem(QStringList("if (nal_unit_type != IDR_W_RADL && nal_unit_type != IDR_N_LP)")); + pitem -> addChild(pitemDepend); + + pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_pic_order_cnt_lsb = " + QString::number(pSlice -> slice_pic_order_cnt_lsb)))); + + QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("short_term_ref_pic_set_sps_flag = " + QString::number(pSlice -> short_term_ref_pic_set_sps_flag))); + pitemDepend -> addChild(pitemThird); + if(!pSlice -> short_term_ref_pic_set_sps_flag) + { + pitemThird = new QTreeWidgetItem(QStringList("if (!short_term_ref_pic_set_sps_flag)")); + pitemDepend -> addChild(pitemThird); + QTreeWidgetItem *pStrpc = new QTreeWidgetItem(QStringList("short_term_ref_pic_set(" + QString::number(m_spsMap[spsId] -> num_short_term_ref_pic_sets) + ")")); + pitemThird -> addChild(pStrpc); + createShortTermRefPicSet(m_spsMap[spsId] -> num_short_term_ref_pic_sets, pSlice -> short_term_ref_pic_set, m_spsMap[spsId] -> num_short_term_ref_pic_sets, m_spsMap[spsId] -> short_term_ref_pic_set, pStrpc); + } + else if(m_spsMap[spsId] -> num_short_term_ref_pic_sets > 1) + { + pitemThird = new QTreeWidgetItem(QStringList("if (short_term_ref_pic_set_sps_flag && num_long_term_ref_pics_sps > 0)")); + pitemDepend -> addChild(pitemThird); + + pitemThird -> addChild(new QTreeWidgetItem(QStringList("short_term_ref_pic_set_idx = " + QString::number(pSlice -> short_term_ref_pic_set_idx)))); + } + + if(m_spsMap[spsId] -> long_term_ref_pics_present_flag) + { + pitemThird = new QTreeWidgetItem(QStringList("if (long_term_ref_pics_present_flag)")); + pitemDepend -> addChild(pitemThird); + + if(m_spsMap[spsId] -> num_long_term_ref_pics_sps > 0) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if (num_long_term_ref_pics_sps)")); + pitemThird -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("num_long_term_sps = " + QString::number(pSlice -> num_long_term_sps)))); + } + + pitemThird -> addChild(new QTreeWidgetItem(QStringList("num_long_term_pics = " + QString::number(pSlice -> num_long_term_pics)))); + + std::size_t num_long_term = pSlice -> num_long_term_sps + pSlice -> num_long_term_pics; + QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_long_term_sps + num_long_term_pics; i++ )")); + pitemThird -> addChild(pitemLoop); + + for(std::size_t i=0; i < num_long_term; i++) + { + if(i < pSlice -> num_long_term_sps) + { + QTreeWidgetItem *pitem1 = new QTreeWidgetItem(QStringList("if (i < num_long_term_sps)")); + pitemLoop -> addChild(pitem1); + + if(m_spsMap[spsId] -> num_long_term_ref_pics_sps > 1) + { + QTreeWidgetItem *pitem2 = new QTreeWidgetItem(QStringList("if (num_long_term_ref_pics_sps > 1)")); + pitem1 -> addChild(pitem2); + pitem2 -> addChild(new QTreeWidgetItem(QStringList("lt_idx_sps[" + QString::number(i) + "] = " + QString::number(pSlice -> lt_idx_sps[i])))); + } + } + else + { + QTreeWidgetItem *pitem1 = new QTreeWidgetItem(QStringList("if (i >= num_long_term_sps)")); + pitemLoop -> addChild(pitem1); + pitem1 -> addChild(new QTreeWidgetItem(QStringList("poc_lsb_lt[" + QString::number(i) + "] = " + QString::number(pSlice -> poc_lsb_lt[i])))); + pitem1 -> addChild(new QTreeWidgetItem(QStringList("used_by_curr_pic_lt_flag[" + QString::number(i) + "] = " + QString::number(pSlice -> used_by_curr_pic_lt_flag[i])))); + } + + pitemLoop -> addChild(new QTreeWidgetItem(QStringList("delta_poc_msb_present_flag[" + QString::number(i) + "] = " + QString::number(pSlice -> delta_poc_msb_present_flag[i])))); + if(pSlice -> delta_poc_msb_present_flag[i]) + { + QTreeWidgetItem *pitem1 = new QTreeWidgetItem(QStringList("if (delta_poc_msb_present_flag[" + QString::number(i) + "])")); + pitemLoop -> addChild(pitem1); + pitem1 -> addChild(new QTreeWidgetItem(QStringList("delta_poc_msb_cycle_lt[" + QString::number(i) + "] = " + QString::number(pSlice -> delta_poc_msb_cycle_lt[i])))); + } + } + } + + if(m_spsMap[spsId] -> sps_temporal_mvp_enabled_flag) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if (sps_temporal_mvp_enabled_flag)")); + pitemDepend -> addChild(pitemSecond); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("slice_temporal_mvp_enabled_flag = " + QString::number(pSlice -> slice_temporal_mvp_enabled_flag)))); + } + } + + if(m_spsMap[spsId] -> sample_adaptive_offset_enabled_flag) + { + pitemDepend = new QTreeWidgetItem(QStringList("if (sample_adaptive_offset_enabled_flag)")); + pitem -> addChild(pitemDepend); + + pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_sao_luma_flag = " + QString::number(pSlice -> slice_sao_luma_flag)))); + pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_sao_chroma_flag = " + QString::number(pSlice -> slice_sao_chroma_flag)))); + } + + if(pSlice -> slice_type == SLICE_B || pSlice -> slice_type == SLICE_P) + { + pitemDepend = new QTreeWidgetItem(QStringList("if (slice_type == P || slice_type == B)")); + pitem -> addChild(pitemDepend); + + pitemDepend -> addChild(new QTreeWidgetItem(QStringList("num_ref_idx_active_override_flag = " + QString::number(pSlice -> num_ref_idx_active_override_flag)))); + + if(pSlice -> num_ref_idx_active_override_flag) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if (num_ref_idx_active_override_flag)")); + pitemDepend -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("num_ref_idx_l0_active_minus1 = " + QString::number(pSlice -> num_ref_idx_l0_active_minus1)))); + + if(pSlice -> slice_type == SLICE_B) + { + QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("if (slice_type == B)")); + pitemSecond -> addChild(pitemThird); + + pitemThird -> addChild(new QTreeWidgetItem(QStringList("num_ref_idx_l1_active_minus1 = " + QString::number(pSlice -> num_ref_idx_l1_active_minus1)))); + } + } + + if(pPPS -> lists_modification_present_flag) + { + std::size_t NumPocTotalCurr = calcNumPocTotalCurr(pSlice, m_spsMap[spsId]); + + if(NumPocTotalCurr > 1) + { + pitemThird = new QTreeWidgetItem(QStringList("if (lists_modification_present_flag && NumPocTotalCurr > 1 )")); + pitemDepend -> addChild(pitemThird); + QTreeWidgetItem *pitemRplMod = new QTreeWidgetItem(QStringList("short_term_ref_pic_set(" + QString::number(m_spsMap[spsId] -> num_short_term_ref_pic_sets) + ")")); + pitemThird -> addChild(pitemRplMod); + + + createRefPicListModification(pSlice -> ref_pic_lists_modification, pitemRplMod); + } + } + + if(pSlice -> slice_type == SLICE_B) + { + pitemThird = new QTreeWidgetItem(QStringList("if (slice_type == B)")); + pitemDepend -> addChild(pitemThird); + pitemThird -> addChild(new QTreeWidgetItem(QStringList("mvd_l1_zero_flag = " + QString::number(pSlice -> mvd_l1_zero_flag)))); + } + + if(pPPS -> cabac_init_present_flag) + { + pitemThird = new QTreeWidgetItem(QStringList("if (cabac_init_present_flag)")); + pitemDepend -> addChild(pitemThird); + pitemThird-> addChild(new QTreeWidgetItem(QStringList("cabac_init_flag = " + QString::number(pSlice -> cabac_init_flag)))); + } + + if(pSlice -> slice_temporal_mvp_enabled_flag) + { + pitemThird = new QTreeWidgetItem(QStringList("if (slice_temporal_mvp_enabled_flag)")); + pitemDepend -> addChild(pitemThird); + + if(pSlice -> slice_type == SLICE_B) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if (slice_type == B)")); + pitemThird -> addChild(pitemSecond); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("collocated_from_l0_flag = " + QString::number(pSlice -> collocated_from_l0_flag)))); + } + + if((pSlice -> collocated_from_l0_flag && pSlice -> num_ref_idx_l0_active_minus1) || + (!pSlice -> collocated_from_l0_flag && pSlice -> num_ref_idx_l1_active_minus1)) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if ((collocated_from_l0_flag && num_ref_idx_l0_active_minus1 > 0 ) || (!collocated_from_l0_flag && num_ref_idx_l1_active_minus1 > 0))")); + pitemThird -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("collocated_ref_idx = " + QString::number(pSlice -> collocated_ref_idx)))); + } + } + + if((pPPS -> weighted_pred_flag && pSlice -> slice_type == SLICE_P) || + (pPPS -> weighted_bipred_flag && pSlice -> slice_type == SLICE_B)) + { + pitemThird = new QTreeWidgetItem(QStringList("if ((weighted_pred_flag && slice_type == P) || (weighted_bipred_flag && slice_type == B))")); + pitemDepend -> addChild(pitemThird); + + QTreeWidgetItem *pitempwt = new QTreeWidgetItem(QStringList("pred_weight_table")); + pitemThird -> addChild(pitempwt); + + createPredWeightTable(pSlice -> pred_weight_table, pSlice, pitempwt); + } + + pitemDepend -> addChild(new QTreeWidgetItem(QStringList("five_minus_max_num_merge_cand = " + QString::number(pSlice -> five_minus_max_num_merge_cand)))); + } + + pitem -> addChild(new QTreeWidgetItem(QStringList("slice_qp_delta = " + QString::number(pSlice -> slice_qp_delta)))); + + + if(pPPS -> pps_slice_chroma_qp_offsets_present_flag) + { + pitemDepend = new QTreeWidgetItem(QStringList("if (pps_slice_chroma_qp_offsets_present_flag)")); + pitem -> addChild(pitemDepend); + + pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_cb_qp_offset = " + QString::number(pSlice -> slice_cb_qp_offset)))); + pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_cr_qp_offset = " + QString::number(pSlice -> slice_cr_qp_offset)))); + } + + if(pPPS -> deblocking_filter_override_enabled_flag) + { + pitemDepend = new QTreeWidgetItem(QStringList("if (deblocking_filter_override_enabled_flag)")); + pitem -> addChild(pitemDepend); + pitemDepend -> addChild(new QTreeWidgetItem(QStringList("deblocking_filter_override_flag = " + QString::number(pSlice -> deblocking_filter_override_flag)))); + } + + if(pSlice -> deblocking_filter_override_flag) + { + pitemDepend = new QTreeWidgetItem(QStringList("if (deblocking_filter_override_flag)")); + pitem -> addChild(pitemDepend); + + pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_deblocking_filter_disabled_flag = " + QString::number(pSlice -> slice_deblocking_filter_disabled_flag)))); + + if(!pSlice -> slice_deblocking_filter_disabled_flag) + { + pitemThird = new QTreeWidgetItem(QStringList("if (!slice_deblocking_filter_disabled_flag)")); + pitemDepend -> addChild(pitemThird); + + pitemThird -> addChild(new QTreeWidgetItem(QStringList("slice_beta_offset_div2 = " + QString::number(pSlice -> slice_beta_offset_div2)))); + pitemThird -> addChild(new QTreeWidgetItem(QStringList("slice_tc_offset_div2 = " + QString::number(pSlice -> slice_tc_offset_div2)))); + } + } + + if(pPPS -> pps_loop_filter_across_slices_enabled_flag && + (pSlice -> slice_sao_luma_flag || pSlice -> slice_sao_chroma_flag || !pSlice -> slice_deblocking_filter_disabled_flag)) + { + pitemDepend = new QTreeWidgetItem(QStringList("if (pps_loop_filter_across_slices_enabled_flag && (slice_sao_luma_flag || slice_sao_chroma_flag || !slice_deblocking_filter_disabled_flag ))")); + pitem -> addChild(pitemDepend); + + pitemDepend -> addChild(new QTreeWidgetItem(QStringList("slice_loop_filter_across_slices_enabled_flag = " + QString::number(pSlice -> slice_loop_filter_across_slices_enabled_flag)))); + } + } + + if(pPPS -> tiles_enabled_flag || pPPS -> entropy_coding_sync_enabled_flag) + { + pitem = new QTreeWidgetItem(QStringList("if (tiles_enabled_flag || entropy_coding_sync_enabled_flag)")); + psliceItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("num_entry_point_offsets = " + QString::number(pSlice -> num_entry_point_offsets)))); + + if(pSlice -> num_entry_point_offsets > 0) + { + pitemThird = new QTreeWidgetItem(QStringList("if (num_entry_point_offsets > 0)")); + pitem -> addChild(pitemThird); + + pitemThird -> addChild(new QTreeWidgetItem(QStringList("offset_len_minus1 = " + QString::number(pSlice -> offset_len_minus1)))); + + QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_entry_point_offsets; i++ )")); + pitemThird -> addChild(pitemLoop); + + for(std::size_t i=0; i num_entry_point_offsets; i++) + pitemLoop -> addChild(new QTreeWidgetItem(QStringList("entry_point_offset_minus1[" + QString::number(i) + "] = " + QString::number(pSlice -> entry_point_offset_minus1[i])))); + } + } + + if(pPPS -> slice_segment_header_extension_present_flag) + { + pitem = new QTreeWidgetItem(QStringList("if (slice_segment_header_extension_present_flag)")); + psliceItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("slice_segment_header_extension_length = " + QString::number(pSlice -> slice_segment_header_extension_length)))); + + QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < slice_segment_header_extension_length; i++ )")); + pitem -> addChild(pitemLoop); + + for(std::size_t i=0; i slice_segment_header_extension_length; i++) + { + pitemLoop -> addChild(new QTreeWidgetItem(QStringList("slice_segment_header_extension_data_byte[" + QString::number(i) + "] = " + QString::number(pSlice -> slice_segment_header_extension_data_byte[i])))); + } + } +} + +void SyntaxViewer::createAUD(std::shared_ptr pAUD) +{ + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("AUD")); + addTopLevelItem(pitem); + pitem -> addChild(new QTreeWidgetItem(QStringList("pic_type = " + QString::number(pAUD -> pic_type)))); +} + + +void SyntaxViewer::createSEI(std::shared_ptr pSEI) +{ + QTreeWidgetItem *pitemSEI = new QTreeWidgetItem(QStringList("SEI")); + addTopLevelItem(pitemSEI); + + + + for(std::size_t i=0; i< pSEI -> sei_message.size(); i++) + { + std::size_t payloadType = 0; + std::size_t payloadSize = 0; + + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("sei_message(" + QString::number(i) + ")")); + pitemSEI -> addChild(pitem); + + if(pSEI -> sei_message[i].num_payload_type_ff_bytes) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("while( next_bits( 8 ) == 0xFF )")); + pitem -> addChild(pitemSecond); + for(std::size_t i=0; i sei_message[i].num_payload_type_ff_bytes; i++) + { + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("0xFF"))); + payloadType += 255; + } + } + + pitem -> addChild(new QTreeWidgetItem(QStringList("last_payload_type_byte = " + QString::number(pSEI -> sei_message[i].last_payload_type_byte)))); + payloadType += pSEI -> sei_message[i].last_payload_type_byte; + + + if(pSEI -> sei_message[i].num_payload_size_ff_bytes) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("while( next_bits( 8 ) == 0xFF )")); + pitem -> addChild(pitemSecond); + for(std::size_t j=0; j sei_message[i].num_payload_size_ff_bytes; j++) + { + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("0xFF"))); + payloadSize += 255; + } + } + + pitem -> addChild(new QTreeWidgetItem(QStringList("last_payload_size_byte = " + QString::number(pSEI -> sei_message[i].last_payload_size_byte)))); + + payloadSize += pSEI -> sei_message[i].last_payload_size_byte; + switch(payloadType) + { + case HEVC::SeiMessage::DECODED_PICTURE_HASH: + { + std::shared_ptr pdecPictHash = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemDecPictHash = new QTreeWidgetItem(QStringList("decoded_picture_hash(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemDecPictHash); + createDecodedPictureHash(pdecPictHash, pitemDecPictHash); + break; + } + + case HEVC::SeiMessage::USER_DATA_UNREGISTERED: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("user_data_unregistered(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createUserDataUnregistered(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::SCENE_INFO: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("scene_info(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createSceneInfo(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::FULL_FRAME_SNAPSHOT: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("picture_snapshot(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createFullFrameSnapshot(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::PROGRESSIVE_REFINEMENT_SEGMENT_START: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("progressive_refinement_segment_start(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createProgressiveRefinementSegmentStart(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::PROGRESSIVE_REFINEMENT_SEGMENT_END: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("progressive_refinement_segment_end(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createProgressiveRefinementSegmentEnd(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::BUFFERING_PERIOD: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("buffering_period(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createBufferingPeriod(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::FILLER_PAYLOAD: + { + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("filler_payload(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + break; + } + + case HEVC::SeiMessage::PICTURE_TIMING: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("pic_timing(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createPicTiming(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::RECOVERY_POINT: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("recovery_point(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createRecoveryPoint(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::TONE_MAPPING_INFO: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("tone_mapping_info(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createToneMapping(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::FRAME_PACKING: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("frame_packing_arrangement(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createFramePacking(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::DISPLAY_ORIENTATION: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("display_orientation(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createDisplayOrientation(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::SOP_DESCRIPTION: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("structure_of_pictures_info(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createSOPDescription(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::ACTIVE_PARAMETER_SETS: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("active_parameter_sets(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createActiveParameterSets(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::TEMPORAL_LEVEL0_INDEX: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("temporal_sub_layer_zero_index(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createTemporalLevel0Index(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::REGION_REFRESH_INFO: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("region_refresh_info(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createRegionRefreshInfo(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::TIME_CODE: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("time_code(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createTimeCode(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::MASTERING_DISPLAY_INFO: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("mastering_display_info(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createMasteringDisplayInfo(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::SEGM_RECT_FRAME_PACKING: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("segm_rect_frame_packing(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createSegmRectFramePacking(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::KNEE_FUNCTION_INFO: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("knee_function_info(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createKneeFunctionInfo(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::CHROMA_RESAMPLING_FILTER_HINT: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("chroma_resampling_filter_hint(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createChromaResamplingFilterHint(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::COLOUR_REMAPPING_INFO: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("colour_remapping_info(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createColourRemappingInfo(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::CONTENT_LIGHT_LEVEL_INFO: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("content_light_level_info(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createContentLightLevelInfo(pSeiMessage, pitemSei); + break; + } + + case HEVC::SeiMessage::ALTERNATIVE_TRANSFER_CHARACTERISTICS: + { + std::shared_ptr pSeiMessage = std::dynamic_pointer_cast(pSEI -> sei_message[i].sei_payload); + + QTreeWidgetItem *pitemSei = new QTreeWidgetItem(QStringList("alternative_transfer_characteristics(" + QString::number(payloadSize) + ")")); + pitem -> addChild(pitemSei); + createAlternativeTransferCharacteristics(pSeiMessage, pitemSei); + break; + } + + default: + pitem -> addChild(new QTreeWidgetItem(QStringList("sei_payload(" + QString::number(payloadType) + ", " + QString::number(payloadSize) + ")"))); + } + } +} + + +void SyntaxViewer::createProfileTierLevel(const HEVC::ProfileTierLevel &ptl, QTreeWidgetItem *pPtlItem) +{ + + pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_profile_space = " + QString::number(ptl.general_profile_space)))); + pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_tier_flag = " + QString::number(ptl.general_tier_flag)))); + pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_profile_idc = " + QString::number(ptl.general_profile_idc)))); + + QString str = "general_profile_compatibility_flag[i] = { \n\t"; + for(std::size_t i=0; i<31; i++) + { + str += QString::number(ptl.general_profile_compatibility_flag[i]) + ", "; + if((i+1) % 8 == 0) + str += "\n\t"; + } + str += QString::number(ptl.general_profile_compatibility_flag[31]) + "\n}"; + pPtlItem -> addChild(new QTreeWidgetItem(QStringList(str))); + + pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_progressive_source_flag = " + QString::number(ptl.general_progressive_source_flag)))); + pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_interlaced_source_flag = " + QString::number(ptl.general_interlaced_source_flag)))); + pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_non_packed_constraint_flag = " + QString::number(ptl.general_non_packed_constraint_flag)))); + pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_frame_only_constraint_flag = " + QString::number(ptl.general_frame_only_constraint_flag)))); + pPtlItem -> addChild(new QTreeWidgetItem(QStringList("general_level_idc = " + QString::number(ptl.general_level_idc)))); + + if(ptl.sub_layer_profile_present_flag.size() == 0) + { + pPtlItem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_profile_present_flag = {}"))); + pPtlItem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_level_present_flag = {}"))); + } + else + { + str = "sub_layer_profile_present_flag = {\n\t"; + for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList(str))); + + str = "sub_layer_level_present_flag = {\n\t"; + for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList(str))); + } + + std::size_t maxNumSubLayersMinus1 = ptl.sub_layer_profile_present_flag.size(); + bool needLoop = false; + + for(std::size_t i=0; i addChild(pitemLoop); + + for(std::size_t i=0; i addChild(pitem); + + + pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_profile_space[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_profile_space[i])))); + pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_tier_flag[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_tier_flag[i])))); + pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_profile_idc[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_profile_idc[i])))); + + QString str = "sub_layer_profile_compatibility_flag = { \n\t"; + for(std::size_t j=0; j<31; j++) + { + str += QString::number(ptl.sub_layer_profile_compatibility_flag[i][j]) + ", "; + if((j+1) % 8 == 0) + str += "\n\t"; + } + str += QString::number(ptl.sub_layer_profile_compatibility_flag[i][31]) + " \n}"; + pitem -> addChild(new QTreeWidgetItem(QStringList(str))); + + + pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_progressive_source_flag[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_progressive_source_flag[i])))); + pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_interlaced_source_flag[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_interlaced_source_flag[i])))); + pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_non_packed_constraint_flag[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_non_packed_constraint_flag[i])))); + pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_frame_only_constraint_flag[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_frame_only_constraint_flag[i])))); + } + + if(ptl.sub_layer_level_present_flag[i]) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( sub_layer_level_present_flag[" + QString::number(i) + "] )")); + pitemLoop -> addChild(pitem); + pitem -> addChild(new QTreeWidgetItem(QStringList("sub_layer_level_idc[" + QString::number(i) + "] = " + QString::number(ptl.sub_layer_level_idc[i])))); + } + } + } +} + + +void SyntaxViewer::createVuiParameters(const HEVC::VuiParameters &vui, std::size_t maxNumSubLayersMinus1, QTreeWidgetItem *pVuiItem) +{ + pVuiItem -> addChild(new QTreeWidgetItem(QStringList("aspect_ratio_info_present_flag = " + QString::number(vui.aspect_ratio_info_present_flag)))); + + if(vui.aspect_ratio_info_present_flag) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( aspect_ratio_info_present_flag )")); + pVuiItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("aspect_ratio_idc = " + QString::number(vui.aspect_ratio_idc)))); + + if(vui.aspect_ratio_idc == 255) //EXTENDED_SAR + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( aspect_ratio_idc == EXTENDED_SAR )")); + pitem -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("sar_width = " + QString::number(vui.sar_width)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("sar_height = " + QString::number(vui.sar_height)))); + } + } + + pVuiItem -> addChild(new QTreeWidgetItem(QStringList("overscan_info_present_flag = " + QString::number(vui.overscan_info_present_flag)))); + + if(vui.overscan_info_present_flag) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( overscan_info_present_flag )")); + pVuiItem -> addChild(pitem); + pitem -> addChild(new QTreeWidgetItem(QStringList("overscan_appropriate_flag = " + QString::number(vui.overscan_appropriate_flag)))); + } + + pVuiItem -> addChild(new QTreeWidgetItem(QStringList("video_signal_type_present_flag = " + QString::number(vui.video_signal_type_present_flag)))); + + if(vui.video_signal_type_present_flag) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( video_signal_type_present_flag )")); + pVuiItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("video_format = " + QString::number(vui.video_format)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("video_full_range_flag = " + QString::number(vui.video_full_range_flag)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("colour_description_present_flag = " + QString::number(vui.colour_description_present_flag)))); + + if(vui.colour_description_present_flag) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( colour_description_present_flag )")); + pitem -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("colour_primaries = " + QString::number(vui.colour_primaries)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("transfer_characteristics = " + QString::number(vui.transfer_characteristics)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("matrix_coeffs = " + QString::number(vui.matrix_coeffs)))); + } + } + + pVuiItem -> addChild(new QTreeWidgetItem(QStringList("chroma_loc_info_present_flag = " + QString::number(vui.chroma_loc_info_present_flag)))); + + if(vui.chroma_loc_info_present_flag) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( chroma_loc_info_present_flag )")); + pVuiItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("chroma_sample_loc_type_top_field = " + QString::number(vui.chroma_sample_loc_type_top_field)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("chroma_sample_loc_type_bottom_field = " + QString::number(vui.chroma_sample_loc_type_bottom_field)))); + } + + pVuiItem -> addChild(new QTreeWidgetItem(QStringList("neutral_chroma_indication_flag = " + QString::number(vui.neutral_chroma_indication_flag)))); + pVuiItem -> addChild(new QTreeWidgetItem(QStringList("field_seq_flag = " + QString::number(vui.field_seq_flag)))); + pVuiItem -> addChild(new QTreeWidgetItem(QStringList("frame_field_info_present_flag = " + QString::number(vui.frame_field_info_present_flag)))); + pVuiItem -> addChild(new QTreeWidgetItem(QStringList("default_display_window_flag = " + QString::number(vui.default_display_window_flag)))); + + + if(vui.default_display_window_flag) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( default_display_window_flag )")); + pVuiItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("def_disp_win_left_offset = " + QString::number(vui.def_disp_win_left_offset)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("def_disp_win_right_offset = " + QString::number(vui.def_disp_win_right_offset)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("def_disp_win_top_offset = " + QString::number(vui.def_disp_win_top_offset)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("def_disp_win_bottom_offset = " + QString::number(vui.def_disp_win_bottom_offset)))); + } + + pVuiItem -> addChild(new QTreeWidgetItem(QStringList("vui_timing_info_present_flag = " + QString::number(vui.vui_timing_info_present_flag)))); + + if(vui.vui_timing_info_present_flag) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( vui_timing_info_present_flag )")); + pVuiItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("vui_num_units_in_tick = " + QString::number(vui.vui_num_units_in_tick)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("vui_time_scale = " + QString::number(vui.vui_time_scale)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("vui_poc_proportional_to_timing_flag = " + QString::number(vui.vui_poc_proportional_to_timing_flag)))); + + if(vui.vui_poc_proportional_to_timing_flag) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( vui_poc_proportional_to_timing_flag )")); + pitem -> addChild(pitemSecond); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("vui_num_ticks_poc_diff_one_minus1 = " + QString::number(vui.vui_num_ticks_poc_diff_one_minus1)))); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("vui_hrd_parameters_present_flag = " + QString::number(vui.vui_hrd_parameters_present_flag)))); + } + + pitem -> addChild(new QTreeWidgetItem(QStringList("vui_hrd_parameters_present_flag = " + QString::number(vui.vui_hrd_parameters_present_flag)))); + + if(vui.vui_hrd_parameters_present_flag) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( vui_hrd_parameters_present_flag )")); + pitem -> addChild(pitemSecond); + + QTreeWidgetItem *pitemHrd = new QTreeWidgetItem(QStringList("hrd_parameters(1, " + QString::number(maxNumSubLayersMinus1) + ")")); + pitemSecond -> addChild(pitemHrd); + + createHrdParameters(vui.hrd_parameters, 1, pitemHrd); + } + } + + pVuiItem -> addChild(new QTreeWidgetItem(QStringList("bitstream_restriction_flag = " + QString::number(vui.bitstream_restriction_flag)))); + + if(vui.bitstream_restriction_flag) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( bitstream_restriction_flag )")); + pVuiItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("tiles_fixed_structure_flag = " + QString::number(vui.tiles_fixed_structure_flag)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("motion_vectors_over_pic_boundaries_flag = " + QString::number(vui.motion_vectors_over_pic_boundaries_flag)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("restricted_ref_pic_lists_flag = " + QString::number(vui.restricted_ref_pic_lists_flag)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("min_spatial_segmentation_idc = " + QString::number(vui.min_spatial_segmentation_idc)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("max_bytes_per_pic_denom = " + QString::number(vui.max_bytes_per_pic_denom)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("max_bits_per_min_cu_denom = " + QString::number(vui.max_bits_per_min_cu_denom)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("log2_max_mv_length_horizontal = " + QString::number(vui.log2_max_mv_length_horizontal)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("log2_max_mv_length_vertical = " + QString::number(vui.log2_max_mv_length_vertical)))); + } +} + + +void SyntaxViewer::createHrdParameters(const HEVC::HrdParameters &hrd, uint8_t commonInfPresentFlag, QTreeWidgetItem *pHrdItem) +{ + if(commonInfPresentFlag) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( commonInfPresentFlag )")); + pHrdItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("nal_hrd_parameters_present_flag = " + QString::number(hrd.nal_hrd_parameters_present_flag)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("vcl_hrd_parameters_present_flag = " + QString::number(hrd.vcl_hrd_parameters_present_flag)))); + + if(hrd.nal_hrd_parameters_present_flag || hrd.vcl_hrd_parameters_present_flag) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag )")); + pitem -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("sub_pic_hrd_params_present_flag = " + QString::number(hrd.sub_pic_hrd_params_present_flag)))); + if(hrd.sub_pic_hrd_params_present_flag) + { + QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("if (sub_pic_hrd_params_present_flag )")); + pitemSecond -> addChild(pitemThird); + + pitemThird -> addChild(new QTreeWidgetItem(QStringList("tick_divisor_minus2 = " + QString::number(hrd.tick_divisor_minus2)))); + pitemThird -> addChild(new QTreeWidgetItem(QStringList("du_cpb_removal_delay_increment_length_minus1 = " + QString::number(hrd.du_cpb_removal_delay_increment_length_minus1)))); + pitemThird -> addChild(new QTreeWidgetItem(QStringList("sub_pic_cpb_params_in_pic_timing_sei_flag = " + QString::number(hrd.sub_pic_cpb_params_in_pic_timing_sei_flag)))); + pitemThird -> addChild(new QTreeWidgetItem(QStringList("dpb_output_delay_du_length_minus1 = " + QString::number(hrd.dpb_output_delay_du_length_minus1)))); + } + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("bit_rate_scale = " + QString::number(hrd.bit_rate_scale)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("cpb_size_scale = " + QString::number(hrd.cpb_size_scale)))); + + if(hrd.sub_pic_hrd_params_present_flag) + { + QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("if (sub_pic_hrd_params_present_flag )")); + pitemSecond -> addChild(pitemThird); + + pitemThird -> addChild(new QTreeWidgetItem(QStringList("cpb_size_du_scale = " + QString::number(hrd.cpb_size_du_scale)))); + } + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("initial_cpb_removal_delay_length_minus1 = " + QString::number(hrd.initial_cpb_removal_delay_length_minus1)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("au_cpb_removal_delay_length_minus1 = " + QString::number(hrd.au_cpb_removal_delay_length_minus1)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("dpb_output_delay_length_minus1 = " + QString::number(hrd.dpb_output_delay_length_minus1)))); + } + } + + if(hrd.fixed_pic_rate_general_flag.size() > 0) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("for( i = 0; i <= maxNumSubLayersMinus1; i++ )")); + pHrdItem -> addChild(pitem); + + for(std::size_t i = 0; i < hrd.fixed_pic_rate_general_flag.size(); i++ ) + { + pitem -> addChild(new QTreeWidgetItem(QStringList("fixed_pic_rate_general_flag[" + QString::number(i) + "] = " + QString::number(hrd.fixed_pic_rate_general_flag[i])))); + + if(!hrd.fixed_pic_rate_general_flag[i]) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( !fixed_pic_rate_general_flag [" + QString::number(i) + "] )")); + pitem -> addChild(pitemSecond); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("fixed_pic_rate_within_cvs_flag[" + QString::number(i) + "] = " + QString::number(hrd.fixed_pic_rate_within_cvs_flag[i])))); + } + + if(hrd.fixed_pic_rate_within_cvs_flag[i]) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( fixed_pic_rate_within_cvs_flag[" + QString::number(i) + "] )")); + pitem -> addChild(pitemSecond); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("elemental_duration_in_tc_minus1[" + QString::number(i) + "] = " + QString::number(hrd.elemental_duration_in_tc_minus1[i])))); + } + else + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( !fixed_pic_rate_within_cvs_flag[" + QString::number(i) + "] )")); + pitem -> addChild(pitemSecond); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("low_delay_hrd_flag[" + QString::number(i) + "] = " + QString::number(hrd.low_delay_hrd_flag[i])))); + } + + if(!hrd.low_delay_hrd_flag[i]) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( !low_delay_hrd_flag[" + QString::number(i) + "] )")); + pitem -> addChild(pitemSecond); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("cpb_cnt_minus1[" + QString::number(i) + "] = " + QString::number(hrd.cpb_cnt_minus1[i])))); + } + + if(hrd.nal_hrd_parameters_present_flag) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( nal_hrd_parameters_present_flag )")); + pitem -> addChild(pitemSecond); + + QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("sub_layer_hrd_parameters(" + QString::number(i) + ")")); + pitemSecond -> addChild(pitemThird); + + createSubLayerHrdParameters(hrd.nal_sub_layer_hrd_parameters[i], hrd.sub_pic_hrd_params_present_flag, pitemThird); + } + if(hrd.vcl_hrd_parameters_present_flag) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( vcl_hrd_parameters_present_flag )")); + pitem -> addChild(pitemSecond); + + QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("sub_layer_hrd_parameters(" + QString::number(i) + ")")); + pitemSecond -> addChild(pitemThird); + + createSubLayerHrdParameters(hrd.vcl_sub_layer_hrd_parameters[i], hrd.sub_pic_hrd_params_present_flag, pitemThird); + } + } + } +} + + + +void SyntaxViewer::createSubLayerHrdParameters(const HEVC::SubLayerHrdParameters &slhrd, uint8_t sub_pic_hrd_params_present_flag, QTreeWidgetItem *pSlhrdItem) +{ + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("for( i = 0; i <= CpbCnt; i++ )")); + pSlhrdItem -> addChild(pitem); + + for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList("bit_rate_value_minus1[" + QString::number(i) + "] = " + QString::number(slhrd.bit_rate_value_minus1[i])))); + pitem -> addChild(new QTreeWidgetItem(QStringList("cpb_size_value_minus1[" + QString::number(i) + "] = " + QString::number(slhrd.cpb_size_value_minus1[i])))); + + if(sub_pic_hrd_params_present_flag) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( sub_pic_hrd_params_present_flag )")); + pitem -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("cpb_size_du_value_minus1[" + QString::number(i) + "] = " + QString::number(slhrd.cpb_size_du_value_minus1[i])))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("bit_rate_du_value_minus1[" + QString::number(i) + "] = " + QString::number(slhrd.bit_rate_du_value_minus1[i])))); + } + + pitem -> addChild(new QTreeWidgetItem(QStringList("cbr_flag[" + QString::number(i) + "] = " + QString::number(slhrd.cbr_flag[i])))); + } +} + + +void SyntaxViewer::createShortTermRefPicSet(std::size_t stRpsIdx, const HEVC::ShortTermRefPicSet &rpset, std::size_t num_short_term_ref_pic_sets, const std::vector &refPicSets, QTreeWidgetItem *pStrpsItem) +{ +// HEVC::ShortTermRefPicSet rpset = refPicSets[stRpsIdx]; + + if(stRpsIdx) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( stRpsIdx )")); + pStrpsItem -> addChild(pitem); + pitem -> addChild(new QTreeWidgetItem(QStringList("inter_ref_pic_set_prediction_flag = " + QString::number(rpset.inter_ref_pic_set_prediction_flag)))); + } + + if(rpset.inter_ref_pic_set_prediction_flag) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( inter_ref_pic_set_prediction_flag )")); + pStrpsItem -> addChild(pitem); + + if(stRpsIdx == num_short_term_ref_pic_sets) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( stRpsIdx == num_short_term_ref_pic_sets )")); + pitem -> addChild(pitemSecond); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("delta_idx_minus1 = " + QString::number(rpset.delta_idx_minus1)))); + } + + pitem -> addChild(new QTreeWidgetItem(QStringList("delta_rps_sign = " + QString::number(rpset.delta_rps_sign)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("abs_delta_rps_minus1 = " + QString::number(rpset.abs_delta_rps_minus1)))); + + std::size_t RefRpsIdx = stRpsIdx - (rpset.delta_idx_minus1 + 1); + + std::size_t NumDeltaPocs = 0; + + if(refPicSets[RefRpsIdx].inter_ref_pic_set_prediction_flag) + { + for(std::size_t i=0; i addChild(pitemLoop); + + for(std::size_t i=0; i<=NumDeltaPocs; i++ ) + { + pitemLoop -> addChild(new QTreeWidgetItem(QStringList("used_by_curr_pic_flag[" + QString::number(i) + "] = " + QString::number(rpset.used_by_curr_pic_flag[i])))); + + if(!rpset.used_by_curr_pic_flag[i]) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( !used_by_curr_pic_flag[j] )")); + pitemLoop -> addChild(pitem); + pitem -> addChild(new QTreeWidgetItem(QStringList("use_delta_flag[" + QString::number(i) + "] = " + QString::number(rpset.use_delta_flag[i])))); + + } + } + } + else + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if( !inter_ref_pic_set_prediction_flag )")); + pStrpsItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("num_negative_pics = " + QString::number(rpset.num_negative_pics)))); + pitem -> addChild(new QTreeWidgetItem(QStringList("num_positive_pics = " + QString::number(rpset.num_positive_pics)))); + + QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_negative_pics; i++ )")); + pitem -> addChild(pitemLoop); + + for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList("delta_poc_s0_minus1[" + QString::number(i) + "] = " + QString::number(rpset.delta_poc_s0_minus1[i])))); + pitemLoop -> addChild(new QTreeWidgetItem(QStringList("used_by_curr_pic_s0_flag[" + QString::number(i) + "] = " + QString::number(rpset.used_by_curr_pic_s0_flag[i])))); + } + + pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_positive_pics; i++ )")); + pitem -> addChild(pitemLoop); + + for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList("delta_poc_s1_minus1[" + QString::number(i) + "] = " + QString::number(rpset.delta_poc_s1_minus1[i])))); + pitemLoop -> addChild(new QTreeWidgetItem(QStringList("used_by_curr_pic_s1_flag[" + QString::number(i) + "] = " + QString::number(rpset.used_by_curr_pic_s1_flag[i])))); + } + } +} + + +void SyntaxViewer::createScalingListData(const HEVC::ScalingListData &scdata, QTreeWidgetItem *pScItem) +{ + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("for( sizeId = 0; sizeId < 4; sizeId++ )")); + pScItem -> addChild(pitem); + + + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("for( matrixId = 0; matrixId < ( ( sizeId == 3 ) ? 2 : 6 ); matrixId++ )")); + pitem -> addChild(pitemSecond); + + + for(std::size_t sizeId = 0; sizeId < 4; sizeId++) + { + for(std::size_t matrixId = 0; matrixId<((sizeId == 3)?2:6); matrixId++) + { + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("scaling_list_pred_mode_flag[" + QString::number(sizeId) + "][" + QString::number(matrixId) + "] = " + QString::number(scdata.scaling_list_pred_mode_flag[sizeId][matrixId])))); + + if(!scdata.scaling_list_pred_mode_flag[sizeId][matrixId]) + { + pitem = new QTreeWidgetItem(QStringList("if( !scaling_list_pred_mode_flag[ sizeId ][ matrixId ] )")); + pitemSecond -> addChild(pitem); + pitem -> addChild(new QTreeWidgetItem(QStringList("scaling_list_pred_matrix_id_delta[" + QString::number(sizeId) + "][" + QString::number(matrixId) + "] = " + QString::number(scdata.scaling_list_pred_matrix_id_delta[sizeId][matrixId])))); + } + else + { + std::size_t coefNum = std::min(64, (1 << (4 + (sizeId << 1)))); + if(sizeId > 1) + { + pitem = new QTreeWidgetItem(QStringList("if( sizeId > 1 )")); + pitemSecond -> addChild(pitem); + pitem -> addChild(new QTreeWidgetItem(QStringList("scaling_list_dc_coef_minus8[" + QString::number(sizeId) + "][" + QString::number(matrixId) + "] = " + QString::number(scdata.scaling_list_dc_coef_minus8[sizeId-2][matrixId])))); + } + + pitem = new QTreeWidgetItem(QStringList("for( i = 0; i < coefNum; i++ )")); + pitemSecond -> addChild(pitem); + + for(std::size_t i = 0; i < coefNum; i++) + { + pitem -> addChild(new QTreeWidgetItem(QStringList("scaling_list_delta_coef[" + QString::number(sizeId) + "][" + QString::number(matrixId) + "][" + QString::number(i) + "] = " + QString::number(scdata.scaling_list_delta_coef[sizeId][matrixId][i])))); + } + } + } + } +} + + +void SyntaxViewer::createRefPicListModification(const HEVC::RefPicListModification &rplModif, QTreeWidgetItem *pRplmItem) +{ + pRplmItem -> addChild(new QTreeWidgetItem(QStringList("ref_pic_list_modification_flag_l0 = " + QString::number(rplModif.ref_pic_list_modification_flag_l0)))); + + if(rplModif.ref_pic_list_modification_flag_l0) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("for( i = 0; i <= num_ref_idx_l0_active_minus1; i++ )")); + pRplmItem -> addChild(pitem); + + for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList("list_entry_l0[" + QString::number(i) + "] = " + QString::number(rplModif.list_entry_l0[i])))); + } + + pRplmItem -> addChild(new QTreeWidgetItem(QStringList("ref_pic_list_modification_flag_l1 = " + QString::number(rplModif.ref_pic_list_modification_flag_l1)))); + + if(rplModif.ref_pic_list_modification_flag_l1) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("for( i = 0; i <= num_ref_idx_l1_active_minus1; i++ )")); + pRplmItem -> addChild(pitem); + + for(std::size_t i=0; i addChild(new QTreeWidgetItem(QStringList("list_entry_l1[" + QString::number(i) + "] = " + QString::number(rplModif.list_entry_l1[i])))); + } +} + + +void SyntaxViewer::createPredWeightTable(const HEVC::PredWeightTable &pwt, std::shared_ptr pSlice, QTreeWidgetItem *ppwtItem) +{ + std::shared_ptr ppps = m_ppsMap[pSlice -> slice_pic_parameter_set_id]; + if(!ppps) + return ; + + std::shared_ptr psps = m_spsMap[ppps -> pps_seq_parameter_set_id]; + + if(!psps) + return ; + + ppwtItem -> addChild(new QTreeWidgetItem(QStringList("luma_log2_weight_denom = " + QString::number(pwt.luma_log2_weight_denom)))); + + if(psps -> chroma_format_idc != 0) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (psps -> chroma_format_idc)")); + ppwtItem -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("delta_chroma_log2_weight_denom = " + QString::number(pwt.delta_chroma_log2_weight_denom)))); + } + + QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for(i=0; i<=num_ref_idx_l0_active_minus1; i++)")); + ppwtItem -> addChild(pitemLoop); + + for(std::size_t i=0; i<=pSlice -> num_ref_idx_l0_active_minus1; i++) + pitemLoop -> addChild(new QTreeWidgetItem(QStringList("luma_weight_l0_flag[" + QString::number(i) + "] = " + QString::number(pwt.luma_weight_l0_flag[i])))); + + if(psps -> chroma_format_idc != 0) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (psps -> chroma_format_idc)")); + ppwtItem -> addChild(pitem); + + pitemLoop = new QTreeWidgetItem(QStringList("for(i=0; i<=num_ref_idx_l0_active_minus1; i++)")); + pitem -> addChild(pitemLoop); + + for(std::size_t i=0; i<=pSlice -> num_ref_idx_l0_active_minus1; i++) + pitemLoop -> addChild(new QTreeWidgetItem(QStringList("chroma_weight_l0_flag[" + QString::number(i) + "] = " + QString::number(pwt.chroma_weight_l0_flag[i])))); + } + + + for(std::size_t i=0; i<=pSlice -> num_ref_idx_l0_active_minus1; i++) + { + pitemLoop = new QTreeWidgetItem(QStringList("for(i=0; i<=num_ref_idx_l0_active_minus1; i++)")); + ppwtItem -> addChild(pitemLoop); + + if(pwt.luma_weight_l0_flag[i]) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (luma_weight_l0_flag[" + QString::number(i) +"])")); + pitemLoop -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("delta_luma_weight_l0[" + QString::number(i) + "] = " + QString::number(pwt.delta_luma_weight_l0[i])))); + pitem -> addChild(new QTreeWidgetItem(QStringList("luma_offset_l0[" + QString::number(i) + "] = " + QString::number(pwt.luma_offset_l0[i])))); + } + if(pwt.chroma_weight_l0_flag[i]) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (chroma_weight_l0_flag[" + QString::number(i) +"])")); + pitemLoop -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("delta_chroma_weight_l0[" + QString::number(i) + "] = { " + QString::number(pwt.delta_chroma_weight_l0[i][0]) + ", " + QString::number(pwt.delta_chroma_weight_l0[i][1]) + " } "))); + pitem -> addChild(new QTreeWidgetItem(QStringList("delta_chroma_offset_l0[" + QString::number(i) + "] = { " + QString::number(pwt.delta_chroma_offset_l0[i][0]) + ", " + QString::number(pwt.delta_chroma_offset_l0[i][1]) + " } "))); + } + } + + if(pSlice -> slice_type == SLICE_B) + { + QTreeWidgetItem *pitemBSlice = new QTreeWidgetItem(QStringList("slice_type == B")); + ppwtItem -> addChild(pitemBSlice); + + QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for(i=0; i<=num_ref_idx_l1_active_minus1; i++)")); + pitemBSlice -> addChild(pitemLoop); + + for(std::size_t i=0; i<=pSlice -> num_ref_idx_l1_active_minus1; i++) + pitemLoop -> addChild(new QTreeWidgetItem(QStringList("luma_weight_l1_flag[" + QString::number(i) + "] = " + QString::number(pwt.luma_weight_l1_flag[i])))); + + if(psps -> chroma_format_idc != 0) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (psps -> chroma_format_idc)")); + pitemBSlice -> addChild(pitem); + + pitemLoop = new QTreeWidgetItem(QStringList("for(i=0; i<=num_ref_idx_l1_active_minus1; i++)")); + pitem -> addChild(pitemLoop); + + for(std::size_t i=0; i<=pSlice -> num_ref_idx_l1_active_minus1; i++) + pitemLoop -> addChild(new QTreeWidgetItem(QStringList("chroma_weight_l1_flag[" + QString::number(i) + "] = " + QString::number(pwt.chroma_weight_l1_flag[i])))); + } + + + for(std::size_t i=0; i<=pSlice -> num_ref_idx_l1_active_minus1; i++) + { + pitemLoop = new QTreeWidgetItem(QStringList("for(i=0; i<=num_ref_idx_l1_active_minus1; i++)")); + pitemBSlice -> addChild(pitemLoop); + + if(pwt.luma_weight_l1_flag[i]) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (luma_weight_l1_flag[" + QString::number(i) +"])")); + pitemLoop -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("delta_luma_weight_l1[" + QString::number(i) + "] = " + QString::number(pwt.delta_luma_weight_l1[i])))); + pitem -> addChild(new QTreeWidgetItem(QStringList("luma_offset_l1[" + QString::number(i) + "] = " + QString::number(pwt.luma_offset_l1[i])))); + } + if(pwt.chroma_weight_l1_flag[i]) + { + QTreeWidgetItem *pitem = new QTreeWidgetItem(QStringList("if (chroma_weight_l1_flag[" + QString::number(i) +"])")); + pitemLoop -> addChild(pitem); + + pitem -> addChild(new QTreeWidgetItem(QStringList("delta_chroma_weight_l1[" + QString::number(i) + "] = { " + QString::number(pwt.delta_chroma_weight_l1[i][0]) + ", " + QString::number(pwt.delta_chroma_weight_l1[i][1]) + " } "))); + pitem -> addChild(new QTreeWidgetItem(QStringList("delta_chroma_offset_l1[" + QString::number(i) + "] = { " + QString::number(pwt.delta_chroma_offset_l1[i][0]) + ", " + QString::number(pwt.delta_chroma_offset_l1[i][1]) + " } "))); + } + } + } + +} + +void SyntaxViewer::createDecodedPictureHash(std::shared_ptr pDecPictHash, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("hash_type = " + QString::number(pDecPictHash->hash_type)))); + + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( cIdx = 0; cIdx < ( chroma_format_idc = = 0 ? 1 : 3 ); cIdx++ )")); + pItem -> addChild(ploop); + + QTreeWidgetItem *pif = new QTreeWidgetItem(QStringList("if(hash_type = " + QString::number(pDecPictHash->hash_type) + ") ")); + ploop -> addChild(pif); + + + if(pDecPictHash->hash_type == 0) + { + for(std::size_t i=0; ipicture_md5.size(); i++) + { + QString str; + for(std::size_t j=0; j<16; j++) + str += QString("%1").arg(pDecPictHash->picture_md5[i][j], 2, 16, QChar('0')).toUpper(); + pif -> addChild(new QTreeWidgetItem(QStringList("picture_md5[" + QString::number(i) + "] = " + str))); + } + } + if(pDecPictHash->hash_type == 1) + { + for(std::size_t i=0; ipicture_crc.size(); i++) + { + pif -> addChild(new QTreeWidgetItem(QStringList("picture_crc[" + QString::number(i) + "] = " + QString::number(pDecPictHash -> picture_crc[i])))); + } + } + else + { + for(std::size_t i=0; ipicture_crc.size(); i++) + { + pif -> addChild(new QTreeWidgetItem(QStringList("picture_checksum[" + QString::number(i) + "] = " + QString::number(pDecPictHash -> picture_checksum[i])))); + } + } +} + + +void SyntaxViewer::createMasteringDisplayInfo(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + QTreeWidgetItem *pitemLoop = new QTreeWidgetItem(QStringList("for( i = 0; i < 3 ; i++ )")); + pItem -> addChild(pitemLoop); + + + for (uint32_t i = 0; i < 3; i++) + { + pitemLoop -> addChild(new QTreeWidgetItem(QStringList("display_primary_x[" + QString::number(i) + "] = " + QString::number(pSei -> display_primary_x[i])))); + pitemLoop -> addChild(new QTreeWidgetItem(QStringList("display_primary_y[" + QString::number(i) + "] = " + QString::number(pSei -> display_primary_y[i])))); + } + + pItem -> addChild(new QTreeWidgetItem(QStringList("white_point_x = " + QString::number(pSei -> white_point_x)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("white_point_y = " + QString::number(pSei -> white_point_y)))); + + pItem -> addChild(new QTreeWidgetItem(QStringList("max_display_mastering_luminance = " + QString::number(pSei -> max_display_mastering_luminance)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("min_display_mastering_luminance = " + QString::number(pSei -> min_display_mastering_luminance)))); +} + + +void SyntaxViewer::createActiveParameterSets(std::shared_ptr pSeiPayload, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("active_video_parameter_set_id = " + QString::number(pSeiPayload -> active_video_parameter_set_id)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("self_contained_cvs_flag = " + QString::number(pSeiPayload -> self_contained_cvs_flag)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("no_parameter_set_update_flag = " + QString::number(pSeiPayload -> no_parameter_set_update_flag)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("num_sps_ids_minus1 = " + QString::number(pSeiPayload -> num_sps_ids_minus1)))); + + QString str = "active_seq_parameter_set_id = {\n\t"; + for (uint32_t i = 0; i < pSeiPayload -> num_sps_ids_minus1; i++) + { + str += QString::number(pSeiPayload -> active_seq_parameter_set_id[i]) + ", "; + if((i + 1) % 8) + str += "\n\t"; + } + + str += QString::number(pSeiPayload -> active_seq_parameter_set_id[pSeiPayload -> num_sps_ids_minus1]) + "\n}"; + pItem -> addChild(new QTreeWidgetItem(QStringList(str))); +} + + +void SyntaxViewer::createUserDataUnregistered(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + QString str = + QString("%1").arg(pSei -> uuid_iso_iec_11578[0], 2, 16, QChar('0')).toLower() + + QString("%1").arg(pSei -> uuid_iso_iec_11578[1], 2, 16, QChar('0')).toLower() + + QString("%1").arg(pSei -> uuid_iso_iec_11578[2], 2, 16, QChar('0')).toLower() + + QString("%1").arg(pSei -> uuid_iso_iec_11578[3], 2, 16, QChar('0')).toLower() + + "-" + + QString("%1").arg(pSei -> uuid_iso_iec_11578[4], 2, 16, QChar('0')).toLower() + + QString("%1").arg(pSei -> uuid_iso_iec_11578[5], 2, 16, QChar('0')).toLower() + + "-" + + QString("%1").arg(pSei -> uuid_iso_iec_11578[6], 2, 16, QChar('0')).toLower() + + QString("%1").arg(pSei -> uuid_iso_iec_11578[7], 2, 16, QChar('0')).toLower() + + "-" + + QString("%1").arg(pSei -> uuid_iso_iec_11578[8], 2, 16, QChar('0')).toLower() + + QString("%1").arg(pSei -> uuid_iso_iec_11578[9], 2, 16, QChar('0')).toLower() + + "-" + + QString("%1").arg(pSei -> uuid_iso_iec_11578[10], 2, 16, QChar('0')).toLower() + + QString("%1").arg(pSei -> uuid_iso_iec_11578[11], 2, 16, QChar('0')).toLower() + + QString("%1").arg(pSei -> uuid_iso_iec_11578[12], 2, 16, QChar('0')).toLower() + + QString("%1").arg(pSei -> uuid_iso_iec_11578[13], 2, 16, QChar('0')).toLower() + + QString("%1").arg(pSei -> uuid_iso_iec_11578[14], 2, 16, QChar('0')).toLower() + + QString("%1").arg(pSei -> uuid_iso_iec_11578[15], 2, 16, QChar('0')).toLower(); + + pItem -> addChild(new QTreeWidgetItem(QStringList("uuid_iso_iec_11578 = " + str))); + + + if(pSei -> user_data_payload_byte.empty()) + { + str = "user_data_payload_byte = { }"; + } + else + { + str = "user_data_payload_byte = {\n\t"; + for (int i = 0; i < pSei -> user_data_payload_byte.size() - 1; i++) + { + str += QString("%1").arg(pSei -> user_data_payload_byte[i], 2, 16, QChar('0')).toLower(); + if((i + 1) % 16 == 0) + str += "\n\t"; + } + str += QString::number(pSei -> user_data_payload_byte[pSei -> user_data_payload_byte.size() - 1], 16) + "\n}"; + } + + pItem -> addChild(new QTreeWidgetItem(QStringList(str))); +} + + +void SyntaxViewer::createBufferingPeriod(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("bp_seq_parameter_set_id = " + QString::number(pSei->bp_seq_parameter_set_id)))); + + std::shared_ptr psps = m_spsMap[pSei -> bp_seq_parameter_set_id]; + if(!psps) + return; + + if(!psps->vui_parameters.hrd_parameters.sub_pic_hrd_params_present_flag) + { + QTreeWidgetItem *pitemIrap = new QTreeWidgetItem(QStringList("if( !sub_pic_hrd_params_present_flag )")); + pItem -> addChild(pitemIrap); + pitemIrap -> addChild(new QTreeWidgetItem(QStringList("irap_cpb_params_present_flag = " + QString::number(pSei->irap_cpb_params_present_flag)))); + } + + if(pSei -> irap_cpb_params_present_flag) + { + QTreeWidgetItem *pitemIrap = new QTreeWidgetItem(QStringList("if( irap_cpb_params_present_flag )")); + pItem -> addChild(pitemIrap); + pitemIrap -> addChild(new QTreeWidgetItem(QStringList("cpb_delay_offset = " + QString::number(pSei->cpb_delay_offset)))); + pitemIrap -> addChild(new QTreeWidgetItem(QStringList("dpb_delay_offset = " + QString::number(pSei->dpb_delay_offset)))); + } + + pItem -> addChild(new QTreeWidgetItem(QStringList("concatenation_flag = " + QString::number(pSei->concatenation_flag)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("au_cpb_removal_delay_delta_minus1 = " + QString::number(pSei->au_cpb_removal_delay_delta_minus1)))); + + bool NalHrdBpPresentFlag = psps->vui_parameters.hrd_parameters.nal_hrd_parameters_present_flag; + if(NalHrdBpPresentFlag) + { + QTreeWidgetItem *pitemBpPresentFlag= new QTreeWidgetItem(QStringList("if( NalHrdBpPresentFlag )")); + pItem -> addChild(pitemBpPresentFlag); + + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i <= CpbCnt; i++ )")); + pitemBpPresentFlag -> addChild(ploop); + + for(std::size_t i=0; inal_initial_cpb_removal_delay.size(); i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("nal_initial_cpb_removal_delay[" + QString::number(i) + "] = " + QString::number(pSei -> nal_initial_cpb_removal_delay[i])))); + ploop -> addChild(new QTreeWidgetItem(QStringList("nal_initial_cpb_removal_offset[" + QString::number(i) + "] = " + QString::number(pSei -> nal_initial_cpb_removal_offset[i])))); + + if(psps->vui_parameters.hrd_parameters.sub_pic_hrd_params_present_flag || pSei->irap_cpb_params_present_flag) + { + QTreeWidgetItem *pitemAlt = new QTreeWidgetItem(QStringList("if( sub_pic_hrd_params_present_flag | | irap_cpb_params_present_flag )")); + ploop -> addChild(pitemAlt); + + pitemAlt -> addChild(new QTreeWidgetItem(QStringList("nal_initial_alt_cpb_removal_delay[" + QString::number(i) + "] = " + QString::number(pSei -> nal_initial_alt_cpb_removal_delay[i])))); + pitemAlt -> addChild(new QTreeWidgetItem(QStringList("nal_initial_alt_cpb_removal_offset[" + QString::number(i) + "] = " + QString::number(pSei -> nal_initial_alt_cpb_removal_offset[i])))); + } + + } + } + + bool VclHrdBpPresentFlag = psps->vui_parameters.hrd_parameters.vcl_hrd_parameters_present_flag; + if(VclHrdBpPresentFlag) + { + QTreeWidgetItem *pitemBpPresentFlag= new QTreeWidgetItem(QStringList("if( VclHrdBpPresentFlag )")); + pItem -> addChild(pitemBpPresentFlag); + + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i <= CpbCnt; i++ )")); + pitemBpPresentFlag -> addChild(ploop); + + for(std::size_t i=0; ivcl_initial_cpb_removal_delay.size(); i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("vcl_initial_cpb_removal_delay[" + QString::number(i) + "] = " + QString::number(pSei -> vcl_initial_cpb_removal_delay[i])))); + ploop -> addChild(new QTreeWidgetItem(QStringList("vcl_initial_cpb_removal_offset[" + QString::number(i) + "] = " + QString::number(pSei -> vcl_initial_cpb_removal_offset[i])))); + + if(psps->vui_parameters.hrd_parameters.sub_pic_hrd_params_present_flag || pSei->irap_cpb_params_present_flag) + { + QTreeWidgetItem *pitemAlt = new QTreeWidgetItem(QStringList("if( sub_pic_hrd_params_present_flag | | irap_cpb_params_present_flag )")); + ploop -> addChild(pitemAlt); + + pitemAlt -> addChild(new QTreeWidgetItem(QStringList("vcl_initial_alt_cpb_removal_delay[" + QString::number(i) + "] = " + QString::number(pSei -> vcl_initial_alt_cpb_removal_delay[i])))); + pitemAlt -> addChild(new QTreeWidgetItem(QStringList("vcl_initial_alt_cpb_removal_offset[" + QString::number(i) + "] = " + QString::number(pSei -> vcl_initial_alt_cpb_removal_offset[i])))); + } + } + } +} + + +void SyntaxViewer::createPicTiming(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + std::shared_ptr psps; + + if(m_spsMap.size()) + psps = m_spsMap.begin() -> second; + + if(!psps) + return; + + + if(psps->vui_parameters.frame_field_info_present_flag) + { + QTreeWidgetItem *pitemField = new QTreeWidgetItem(QStringList("if( frame_field_info_present_flag )")); + pItem -> addChild(pitemField); + + pitemField -> addChild(new QTreeWidgetItem(QStringList("pic_struct = " + QString::number(pSei->pic_struct)))); + pitemField -> addChild(new QTreeWidgetItem(QStringList("source_scan_type = " + QString::number(pSei->source_scan_type)))); + pitemField -> addChild(new QTreeWidgetItem(QStringList("duplicate_flag = " + QString::number(pSei->duplicate_flag)))); + } + + bool CpbDpbDelaysPresentFlag = psps->vui_parameters.hrd_parameters.nal_hrd_parameters_present_flag || + psps->vui_parameters.hrd_parameters.vcl_hrd_parameters_present_flag; + + if(CpbDpbDelaysPresentFlag) + { + QTreeWidgetItem *pitemDpbDelays = new QTreeWidgetItem(QStringList("if( CpbDpbDelaysPresentFlag )")); + pItem -> addChild(pitemDpbDelays); + + pitemDpbDelays -> addChild(new QTreeWidgetItem(QStringList("au_cpb_removal_delay_minus1 = " + QString::number(pSei->au_cpb_removal_delay_minus1)))); + pitemDpbDelays -> addChild(new QTreeWidgetItem(QStringList("pic_dpb_output_delay = " + QString::number(pSei->pic_dpb_output_delay)))); + + if(psps->vui_parameters.hrd_parameters.sub_pic_hrd_params_present_flag) + { + QTreeWidgetItem *pitemDuDelay = new QTreeWidgetItem(QStringList("if( CpbDpbDelaysPresentFlag )")); + pitemDpbDelays -> addChild(pitemDuDelay); + + pitemDuDelay -> addChild(new QTreeWidgetItem(QStringList("pic_dpb_output_du_delay = " + QString::number(pSei->pic_dpb_output_du_delay)))); + } + + if(psps->vui_parameters.hrd_parameters.sub_pic_hrd_params_present_flag && + psps->vui_parameters.hrd_parameters.sub_pic_cpb_params_in_pic_timing_sei_flag) + { + QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( CpbDpbDelaysPresentFlag )")); + pitemDpbDelays -> addChild(pitemIf); + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("num_decoding_units_minus1 = " + QString::number(pSei->num_decoding_units_minus1)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("du_common_cpb_removal_delay_flag = " + QString::number(pSei->du_common_cpb_removal_delay_flag)))); + + if(pSei -> du_common_cpb_removal_delay_flag) + { + QTreeWidgetItem *pitemDuCommCpb = new QTreeWidgetItem(QStringList("if( CpbDpbDelaysPresentFlag )")); + pitemIf -> addChild(pitemDuCommCpb); + + pitemDuCommCpb -> addChild(new QTreeWidgetItem(QStringList("du_common_cpb_removal_delay_increment_minus1 = " + QString::number(pSei->num_decoding_units_minus1)))); + } + + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i <= num_decoding_units_minus1; i++ )")); + pitemIf -> addChild(ploop); + + for(std::size_t i=0; i<=pSei -> num_decoding_units_minus1; i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("num_nalus_in_du_minus1[" + QString::number(i) + "] = " + QString::number(pSei -> num_nalus_in_du_minus1[i])))); + + if(!pSei -> du_common_cpb_removal_delay_flag && i num_decoding_units_minus1) + { + QTreeWidgetItem *pitemDuCommCpb = new QTreeWidgetItem(QStringList("if( !du_common_cpb_removal_delay_flag && i < num_decoding_units_minus1 )")); + ploop -> addChild(pitemDuCommCpb); + + pitemDuCommCpb -> addChild(new QTreeWidgetItem(QStringList("du_cpb_removal_delay_increment_minus1[" + QString::number(i) + "] = " + QString::number(pSei -> du_cpb_removal_delay_increment_minus1[i])))); + } + } + } + } +} + + +void SyntaxViewer::createRecoveryPoint(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("recovery_poc_cnt = " + QString::number(pSei->recovery_poc_cnt)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("exact_match_flag = " + QString::number(pSei->exact_match_flag)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("broken_link_flag = " + QString::number(pSei->broken_link_flag)))); +} + + +void SyntaxViewer::createContentLightLevelInfo(std::shared_ptr pSeiPayload, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("max_content_light_level = " + QString::number(pSeiPayload->max_content_light_level)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("max_pic_average_light_level = " + QString::number(pSeiPayload->max_pic_average_light_level)))); +} + +void SyntaxViewer::createAlternativeTransferCharacteristics(std::shared_ptr pSeiPayload, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("alternative_transfer_characteristics = " + QString::number(pSeiPayload->alternative_transfer_characteristics)))); +} + + +void SyntaxViewer::createFramePacking(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("frame_packing_arrangement_id = " + QString::number(pSei->frame_packing_arrangement_id)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("frame_packing_arrangement_cancel_flag = " + QString::number(pSei->frame_packing_arrangement_cancel_flag)))); + + if(!pSei -> frame_packing_arrangement_cancel_flag) + { + QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( !frame_packing_arrangement_cancel_flag )")); + pItem -> addChild(pitemIf); + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("frame_packing_arrangement_type = " + QString::number(pSei->frame_packing_arrangement_type)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("quincunx_sampling_flag = " + QString::number(pSei->quincunx_sampling_flag)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("content_interpretation_type = " + QString::number(pSei->content_interpretation_type)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("spatial_flipping_flag = " + QString::number(pSei->spatial_flipping_flag)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("frame0_flipped_flag = " + QString::number(pSei->frame0_flipped_flag)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("field_views_flag = " + QString::number(pSei->field_views_flag)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("current_frame_is_frame0_flag = " + QString::number(pSei->current_frame_is_frame0_flag)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("frame0_self_contained_flag = " + QString::number(pSei->frame0_self_contained_flag)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("frame1_self_contained_flag = " + QString::number(pSei->frame1_self_contained_flag)))); + + if(!pSei -> quincunx_sampling_flag && pSei -> frame_packing_arrangement_type != 5) + { + QTreeWidgetItem *pitemGridPos = new QTreeWidgetItem(QStringList("if( !quincunx_sampling_flag && frame_packing_arrangement_type != 5 )")); + pitemIf -> addChild(pitemGridPos); + + pitemGridPos -> addChild(new QTreeWidgetItem(QStringList("frame0_grid_position_x = " + QString::number(pSei->frame0_grid_position_x)))); + pitemGridPos -> addChild(new QTreeWidgetItem(QStringList("frame0_grid_position_y = " + QString::number(pSei->frame0_grid_position_y)))); + pitemGridPos -> addChild(new QTreeWidgetItem(QStringList("frame1_grid_position_x = " + QString::number(pSei->frame1_grid_position_x)))); + pitemGridPos -> addChild(new QTreeWidgetItem(QStringList("frame1_grid_position_y = " + QString::number(pSei->frame1_grid_position_y)))); + } + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("frame_packing_arrangement_reserved_byte = " + QString::number(pSei->frame_packing_arrangement_reserved_byte)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("frame_packing_arrangement_persistence_flag = " + QString::number(pSei->frame_packing_arrangement_persistence_flag)))); + + } + + pItem -> addChild(new QTreeWidgetItem(QStringList("upsampled_aspect_ratio_flag = " + QString::number(pSei->upsampled_aspect_ratio_flag)))); +} + + +void SyntaxViewer::createDisplayOrientation(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("display_orientation_cancel_flag = " + QString::number(pSei->display_orientation_cancel_flag)))); + if(!pSei -> display_orientation_cancel_flag) + { + QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( !display_orientation_cancel_flag )")); + pItem -> addChild(pitemIf); + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("hor_flip = " + QString::number(pSei->hor_flip)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("ver_flip = " + QString::number(pSei->ver_flip)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("anticlockwise_rotation = " + QString::number(pSei->anticlockwise_rotation)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("display_orientation_persistence_flag = " + QString::number(pSei->display_orientation_persistence_flag)))); + } +} + + +void SyntaxViewer::createToneMapping(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("tone_map_id = " + QString::number(pSei->tone_map_id)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("tone_map_cancel_flag = " + QString::number(pSei->tone_map_cancel_flag)))); + + if(!pSei -> tone_map_cancel_flag) + { + QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( !tone_map_cancel_flag )")); + pItem -> addChild(pitemIf); + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("tone_map_persistence_flag = " + QString::number(pSei->tone_map_persistence_flag)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("coded_data_bit_depth = " + QString::number(pSei->coded_data_bit_depth)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("target_bit_depth = " + QString::number(pSei->target_bit_depth)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("tone_map_model_id = " + QString::number(pSei->tone_map_model_id)))); + + if(pSei -> tone_map_model_id == 0) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( tone_map_model_id = = 0 )")); + pItem -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("min_value = " + QString::number(pSei->min_value)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("max_value = " + QString::number(pSei->max_value)))); + } + else if(pSei -> tone_map_model_id == 1) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( tone_map_model_id = = 1 )")); + pItem -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("sigmoid_midpoint = " + QString::number(pSei->sigmoid_midpoint)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("sigmoid_width = " + QString::number(pSei->sigmoid_width)))); + } + else if(pSei -> tone_map_model_id == 2) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( tone_map_model_id = = 2 )")); + pItem -> addChild(pitemSecond); + + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < ( 1 << target_bit_depth ); i++ )")); + pitemSecond -> addChild(ploop); + + for(std::size_t i = 0; i<(1 << pSei->target_bit_depth); i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("start_of_coded_interval[" + QString::number(i) + "] = " + QString::number(pSei -> start_of_coded_interval[i])))); + } + + } + else if(pSei -> tone_map_model_id == 3) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( tone_map_model_id = = 3 )")); + pItem -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("num_pivots = " + QString::number(pSei->num_pivots)))); + + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_pivots; i++ )")); + pitemSecond -> addChild(ploop); + + for(std::size_t i=0; i num_pivots; i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("coded_pivot_value[" + QString::number(i) + "] = " + QString::number(pSei -> coded_pivot_value[i])))); + ploop -> addChild(new QTreeWidgetItem(QStringList("target_pivot_value[" + QString::number(i) + "] = " + QString::number(pSei -> target_pivot_value[i])))); + } + } + else if(pSei -> tone_map_model_id == 4) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( tone_map_model_id = = 4 )")); + pItem -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("camera_iso_speed_idc = " + QString::number(pSei->camera_iso_speed_idc)))); + if(pSei -> camera_iso_speed_idc == 255) + { + QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("if( camera_iso_speed_idc = = EXTENDED_ISO )")); + pitemSecond -> addChild(pitemThird); + + pitemThird -> addChild(new QTreeWidgetItem(QStringList("camera_iso_speed_value = " + QString::number(pSei->camera_iso_speed_value)))); + } + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("exposure_index_idc = " + QString::number(pSei->exposure_index_idc)))); + if(pSei -> exposure_index_idc == 255) + { + QTreeWidgetItem *pitemThird = new QTreeWidgetItem(QStringList("if( exposure_index_idc = = EXTENDED_ISO )")); + pitemSecond -> addChild(pitemThird); + + pitemThird -> addChild(new QTreeWidgetItem(QStringList("exposure_index_value = " + QString::number(pSei->exposure_index_value)))); + } + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("exposure_compensation_value_sign_flag = " + QString::number(pSei->exposure_compensation_value_sign_flag)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("exposure_compensation_value_numerator = " + QString::number(pSei->exposure_compensation_value_numerator)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("exposure_compensation_value_denom_idc = " + QString::number(pSei->exposure_compensation_value_denom_idc)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("ref_screen_luminance_white = " + QString::number(pSei->ref_screen_luminance_white)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("extended_range_white_level = " + QString::number(pSei->extended_range_white_level)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("nominal_black_level_code_value = " + QString::number(pSei->nominal_black_level_code_value)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("nominal_white_level_code_value = " + QString::number(pSei->nominal_white_level_code_value)))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("extended_white_level_code_value = " + QString::number(pSei->extended_white_level_code_value)))); + } + } +} + + +void SyntaxViewer::createSOPDescription(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("sop_seq_parameter_set_id = " + QString::number(pSei->sop_seq_parameter_set_id)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("num_entries_in_sop_minus1 = " + QString::number(pSei->num_entries_in_sop_minus1)))); + + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i <= num_entries_in_sop_minus1; i++ )")); + pItem -> addChild(ploop); + + for(std::size_t i=0; i<=pSei -> num_entries_in_sop_minus1; i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("sop_vcl_nut[" + QString::number(i) + "] = " + QString::number(pSei -> sop_vcl_nut[i])))); + ploop -> addChild(new QTreeWidgetItem(QStringList("sop_temporal_id[" + QString::number(i) + "] = " + QString::number(pSei -> sop_temporal_id[i])))); + + if(pSei -> sop_vcl_nut[i] != 19 && pSei -> sop_vcl_nut[i] != 20) + { + QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( sop_vcl_nut[ i ] != IDR_W_RADL && sop_vcl_nut[ i ] != IDR_N_LP )")); + ploop -> addChild(pitemIf); + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("sop_short_term_rps_idx[" + QString::number(i) + "] = " + QString::number(pSei -> sop_short_term_rps_idx[i])))); + } + + if(i > 0) + { + QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( i > 0 )")); + ploop -> addChild(pitemIf); + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("sop_poc_delta[" + QString::number(i) + "] = " + QString::number(pSei -> sop_poc_delta[i])))); + } + } +} + + +void SyntaxViewer::createTemporalLevel0Index(std::shared_ptr pSeiPayload, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("temporal_sub_layer_zero_idx = " + QString::number(pSeiPayload->temporal_sub_layer_zero_idx)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("irap_pic_id = " + QString::number(pSeiPayload->irap_pic_id)))); +} + +void SyntaxViewer::createSegmRectFramePacking(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("segmented_rect_frame_packing_arrangement_cancel_flag = " + QString::number(pSei->segmented_rect_frame_packing_arrangement_cancel_flag)))); + + if(!pSei -> segmented_rect_frame_packing_arrangement_cancel_flag) + { + QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( !segmented_rect_frame_packing_arrangement_cancel_flag )")); + pItem -> addChild(pitemIf); + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("segmented_rect_content_interpretation_type = " + QString::number(pSei->segmented_rect_content_interpretation_type)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("segmented_rect_frame_packing_arrangement_persistence = " + QString::number(pSei->segmented_rect_frame_packing_arrangement_persistence)))); + } +} + + +void SyntaxViewer::createTimeCode(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("num_clock_ts = " + QString::number(pSei->num_clock_ts)))); + + if(pSei -> num_clock_ts > 0) + { + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_clock_ts; i++ )")); + pItem -> addChild(ploop); + + for(std::size_t i=0; i num_clock_ts; i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("clock_time_stamp_flag[" + QString::number(i) + "] = " + QString::number(pSei -> clock_time_stamp_flag[i])))); + + if(pSei -> clock_time_stamp_flag[i]) + { + QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( clock_time_stamp_flag[" + QString::number(i) + "] )")); + ploop -> addChild(pitemIf); + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("nuit_field_based_flag[" + QString::number(i) + "] = " + QString::number(pSei -> nuit_field_based_flag[i])))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("counting_type[" + QString::number(i) + "] = " + QString::number(pSei -> counting_type[i])))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("full_timestamp_flag[" + QString::number(i) + "] = " + QString::number(pSei -> full_timestamp_flag[i])))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("discontinuity_flag[" + QString::number(i) + "] = " + QString::number(pSei -> discontinuity_flag[i])))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("cnt_dropped_flag[" + QString::number(i) + "] = " + QString::number(pSei -> cnt_dropped_flag[i])))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("n_frames[" + QString::number(i) + "] = " + QString::number(pSei -> n_frames[i])))); + + + if(pSei -> full_timestamp_flag[i]) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( full_timestamp_flag[" + QString::number(i) + "] )")); + pitemIf -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("seconds_value[" + QString::number(i) + "] = " + QString::number(pSei -> seconds_value[i])))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("minutes_value[" + QString::number(i) + "] = " + QString::number(pSei -> minutes_value[i])))); + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("hours_value[" + QString::number(i) + "] = " + QString::number(pSei -> hours_value[i])))); + } + else + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( !full_timestamp_flag[" + QString::number(i) + "] )")); + pitemIf -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("seconds_flag[" + QString::number(i) + "] = " + QString::number(pSei -> seconds_flag[i])))); + + if(pSei -> seconds_flag[i]) + { + QTreeWidgetItem *pitemSeconds = new QTreeWidgetItem(QStringList("if( seconds_flag[" + QString::number(i) + "] )")); + pitemSecond -> addChild(pitemSeconds); + + pitemSeconds -> addChild(new QTreeWidgetItem(QStringList("seconds_value[" + QString::number(i) + "] = " + QString::number(pSei -> seconds_value[i])))); + pitemSeconds -> addChild(new QTreeWidgetItem(QStringList("minutes_flag[" + QString::number(i) + "] = " + QString::number(pSei -> minutes_flag[i])))); + + if(pSei -> minutes_flag[i]) + { + QTreeWidgetItem *pitemMinuts = new QTreeWidgetItem(QStringList("if( minutes_flag[" + QString::number(i) + "] )")); + pitemSeconds -> addChild(pitemMinuts); + + pitemMinuts -> addChild(new QTreeWidgetItem(QStringList("minutes_value[" + QString::number(i) + "] = " + QString::number(pSei -> minutes_value[i])))); + pitemMinuts -> addChild(new QTreeWidgetItem(QStringList("hours_flag[" + QString::number(i) + "] = " + QString::number(pSei -> hours_flag[i])))); + + if(pSei -> hours_flag[i]) + { + QTreeWidgetItem *pitemHours = new QTreeWidgetItem(QStringList("if( hours_flag[" + QString::number(i) + "] )")); + pitemMinuts -> addChild(pitemHours); + + pitemHours -> addChild(new QTreeWidgetItem(QStringList("hours_value[" + QString::number(i) + "] = " + QString::number(pSei -> hours_value[i])))); + } + } + } + } + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("time_offset_length[" + QString::number(i) + "] = " + QString::number(pSei -> time_offset_length[i])))); + if(pSei -> time_offset_length[i]) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( time_offset_length[" + QString::number(i) + "] )")); + pitemIf -> addChild(pitemSecond); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("time_offset_value[" + QString::number(i) + "] = " + QString::number(pSei -> time_offset_value[i])))); + } + } + } + } +} + + +void SyntaxViewer::createKneeFunctionInfo(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("knee_function_id = " + QString::number(pSei->knee_function_id)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("knee_function_cancel_flag = " + QString::number(pSei->knee_function_cancel_flag)))); + + if(!pSei -> knee_function_cancel_flag) + { + QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( !knee_function_cancel_flag )")); + pItem -> addChild(pitemIf); + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("knee_function_persistence_flag = " + QString::number(pSei -> knee_function_persistence_flag)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("input_d_range = " + QString::number(pSei -> input_d_range)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("input_disp_luminance = " + QString::number(pSei -> input_disp_luminance)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("output_d_range = " + QString::number(pSei -> output_d_range)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("output_disp_luminance = " + QString::number(pSei -> output_disp_luminance)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("num_knee_points_minus1 = " + QString::number(pSei -> num_knee_points_minus1)))); + + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i <= num_knee_points_minus1; i++ )")); + pitemIf -> addChild(ploop); + + for(std::size_t i=0; i<=pSei -> num_knee_points_minus1; i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("input_knee_point[" + QString::number(i) + "] = " + QString::number(pSei -> input_knee_point[i])))); + ploop -> addChild(new QTreeWidgetItem(QStringList("output_knee_point[" + QString::number(i) + "] = " + QString::number(pSei -> output_knee_point[i])))); + } + } +} + + +void SyntaxViewer::createChromaResamplingFilterHint(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("ver_chroma_filter_idc = " + QString::number(pSei->ver_chroma_filter_idc)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("hor_chroma_filter_idc = " + QString::number(pSei->hor_chroma_filter_idc)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("ver_filtering_field_processing_flag = " + QString::number(pSei->ver_filtering_field_processing_flag)))); + + if(pSei -> ver_chroma_filter_idc == 1 || pSei -> hor_chroma_filter_idc == 1) + { + QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( ver_chroma_filter_idc == 1 || hor_chroma_filter_idc == 1 )")); + pItem -> addChild(pitemIf); + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("target_format_idc = " + QString::number(pSei -> target_format_idc)))); + + if(pSei -> ver_chroma_filter_idc == 1) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( ver_chroma_filter_idc == 1 )")); + pitemIf -> addChild(pitemIf); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("num_vertical_filters = " + QString::number(pSei -> num_vertical_filters)))); + + if(pSei -> num_vertical_filters) + { + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_vertical_filters; i++ )")); + pitemSecond -> addChild(ploop); + + for(std::size_t i=0; i num_vertical_filters; i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("ver_tap_length_minus_1[" + QString::number(i) + "] = " + QString::number(pSei -> ver_tap_length_minus_1[i])))); + + QString str = "ver_filter_coeff[" + QString::number(i) + "] = {\n\t"; + for(std::size_t j=0; j ver_tap_length_minus_1[i]; j++) + { + str += QString::number(pSei -> ver_filter_coeff[i][j]) + ", "; + if((i+1) % 8 == 0) + str += "\n\t"; + } + str += QString::number(pSei -> ver_filter_coeff[i][pSei -> ver_tap_length_minus_1[i]]) + " \n}"; + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList(str))); + } + } + } + + if(pSei -> hor_chroma_filter_idc == 1) + { + QTreeWidgetItem *pitemSecond = new QTreeWidgetItem(QStringList("if( hor_chroma_filter_idc == 1 )")); + pitemIf -> addChild(pitemIf); + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList("num_horizontal_filters = " + QString::number(pSei -> num_horizontal_filters)))); + + if(pSei -> num_horizontal_filters) + { + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < num_horizontal_filters; i++ )")); + pitemSecond -> addChild(ploop); + + for(std::size_t i=0; i num_horizontal_filters; i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("hor_tap_length_minus_1[" + QString::number(i) + "] = " + QString::number(pSei -> hor_tap_length_minus_1[i])))); + + QString str = "hor_filter_coeff[" + QString::number(i) + "] = {\n\t"; + for(std::size_t j=0; j hor_tap_length_minus_1[i]; j++) + { + str += QString::number(pSei -> hor_filter_coeff[i][j]) + ", "; + if((i+1) % 8 == 0) + str += "\n\t"; + } + str += QString::number(pSei -> hor_filter_coeff[i][pSei -> hor_tap_length_minus_1[i]]) + " \n}"; + + pitemSecond -> addChild(new QTreeWidgetItem(QStringList(str))); + } + } + } + } +} + + +void SyntaxViewer::createColourRemappingInfo(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("colour_remap_id = " + QString::number(pSei->colour_remap_id)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("colour_remap_cancel_flag = " + QString::number(pSei->colour_remap_cancel_flag)))); + + if(!pSei -> colour_remap_cancel_flag) + { + QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( !colour_remap_cancel_flag )")); + pItem -> addChild(pitemIf); + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("colour_remap_persistence_flag = " + QString::number(pSei -> colour_remap_persistence_flag)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("colour_remap_video_signal_info_present_flag = " + QString::number(pSei -> colour_remap_video_signal_info_present_flag)))); + + if(pSei -> colour_remap_video_signal_info_present_flag) + { + QTreeWidgetItem *pitemIfSecond = new QTreeWidgetItem(QStringList("if( colour_remap_video_signal_info_present_flag )")); + pitemIf -> addChild(pitemIfSecond); + + pitemIfSecond -> addChild(new QTreeWidgetItem(QStringList("colour_remap_full_range_flag = " + QString::number(pSei -> colour_remap_full_range_flag)))); + pitemIfSecond -> addChild(new QTreeWidgetItem(QStringList("colour_remap_primaries = " + QString::number(pSei -> colour_remap_primaries)))); + pitemIfSecond -> addChild(new QTreeWidgetItem(QStringList("colour_remap_transfer_function = " + QString::number(pSei -> colour_remap_transfer_function)))); + pitemIfSecond -> addChild(new QTreeWidgetItem(QStringList("colour_remap_matrix_coefficients = " + QString::number(pSei -> colour_remap_matrix_coefficients)))); + } + pitemIf -> addChild(new QTreeWidgetItem(QStringList("colour_remap_input_bit_depth = " + QString::number(pSei -> colour_remap_input_bit_depth)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("colour_remap_bit_depth = " + QString::number(pSei -> colour_remap_bit_depth)))); + + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < 3; i++ )")); + pitemIf -> addChild(ploop); + + for(std::size_t i=0 ; i<3 ; i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("pre_lut_num_val_minus1[" + QString::number(i) + "] = " + QString::number(pSei -> pre_lut_num_val_minus1[i])))); + + if(pSei -> pre_lut_num_val_minus1[i] > 0) + { + QTreeWidgetItem *pitemIfSecond = new QTreeWidgetItem(QStringList("if( pre_lut_num_val_minus1[" + QString::number(i) + "] > 0 )")); + ploop -> addChild(pitemIfSecond); + + QTreeWidgetItem *ploopSecond = new QTreeWidgetItem(QStringList("for( j = 0; j <= pre_lut_num_val_minus1[" + QString::number(i) + "]; j++ )")); + pitemIfSecond -> addChild(ploopSecond); + + for (std::size_t j=0 ; j<=pSei -> pre_lut_num_val_minus1[i]; j++) + { + ploopSecond -> addChild(new QTreeWidgetItem(QStringList("pre_lut_coded_value[" + QString::number(i) + "][" + QString::number(j) + "] = " + QString::number(pSei -> pre_lut_coded_value[i][j])))); + ploopSecond -> addChild(new QTreeWidgetItem(QStringList("pre_lut_target_value[" + QString::number(i) + "][" + QString::number(j) + "] = " + QString::number(pSei -> pre_lut_target_value[i][j])))); + } + } + } + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("colour_remap_matrix_present_flag = " + QString::number(pSei -> colour_remap_matrix_present_flag)))); + + if(pSei -> colour_remap_matrix_present_flag) + { + QTreeWidgetItem *pitemIfSecond = new QTreeWidgetItem(QStringList("if( colour_remap_matrix_present_flag )")); + pitemIf -> addChild(pitemIfSecond); + + pitemIfSecond -> addChild(new QTreeWidgetItem(QStringList("log2_matrix_denom = " + QString::number(pSei -> log2_matrix_denom)))); + + QTreeWidgetItem *ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < 3; i++ )")); + pitemIfSecond -> addChild(ploop); + + for (std::size_t i=0 ; i<3 ; i++) + { + QString str = "colour_remap_coeffs[" + QString::number(i) + "] = { "; + for (std::size_t j=0 ; j<2 ; j++) + { + str += QString::number(pSei -> colour_remap_coeffs[i][j]) + ", "; + } + str += QString::number(pSei -> colour_remap_coeffs[i][2]) + " }"; + + ploop -> addChild(new QTreeWidgetItem(QStringList(str))); + } + } + + ploop = new QTreeWidgetItem(QStringList("for( i = 0; i < 3; i++ )")); + pitemIf -> addChild(ploop); + + for(std::size_t i=0 ; i<3 ; i++) + { + ploop -> addChild(new QTreeWidgetItem(QStringList("post_lut_num_val_minus1[" + QString::number(i) + "] = " + QString::number(pSei -> post_lut_num_val_minus1[i])))); + + if(pSei -> post_lut_num_val_minus1[i] > 0) + { + QTreeWidgetItem *pitemIfSecond = new QTreeWidgetItem(QStringList("if( post_lut_num_val_minus1[" + QString::number(i) + "] > 0 )")); + ploop -> addChild(pitemIfSecond); + + QTreeWidgetItem *ploopSecond = new QTreeWidgetItem(QStringList("for( j = 0; j <= post_lut_num_val_minus1[" + QString::number(i) + "]; j++ )")); + pitemIfSecond -> addChild(ploopSecond); + + for (std::size_t j=0 ; j<=pSei -> post_lut_num_val_minus1[i]; j++) + { + ploopSecond -> addChild(new QTreeWidgetItem(QStringList("post_lut_coded_value[" + QString::number(i) + "][" + QString::number(j) + "] = " + QString::number(pSei -> post_lut_coded_value[i][j])))); + ploopSecond -> addChild(new QTreeWidgetItem(QStringList("post_lut_target_value[" + QString::number(i) + "][" + QString::number(j) + "] = " + QString::number(pSei -> post_lut_target_value[i][j])))); + } + } + } + } +} + + +void SyntaxViewer::createSceneInfo(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("scene_info_present_flag = " + QString::number(pSei->scene_info_present_flag)))); + + if(pSei -> scene_info_present_flag) + { + QTreeWidgetItem *pitemIf = new QTreeWidgetItem(QStringList("if( scene_info_present_flag )")); + pItem -> addChild(pitemIf); + + pitemIf -> addChild(new QTreeWidgetItem(QStringList("prev_scene_id_valid_flag = " + QString::number(pSei -> prev_scene_id_valid_flag)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("scene_id = " + QString::number(pSei -> scene_id)))); + pitemIf -> addChild(new QTreeWidgetItem(QStringList("scene_transition_type = " + QString::number(pSei -> scene_transition_type)))); + + if(pSei -> scene_transition_type > 3) + { + QTreeWidgetItem *pitemIfSecond = new QTreeWidgetItem(QStringList("if( scene_transition_type > 3 )")); + pitemIf -> addChild(pitemIfSecond); + + pitemIfSecond -> addChild(new QTreeWidgetItem(QStringList("second_scene_id = " + QString::number(pSei -> second_scene_id)))); + } + } +} + +void SyntaxViewer::createProgressiveRefinementSegmentStart(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("progressive_refinement_id = " + QString::number(pSei->progressive_refinement_id)))); + pItem -> addChild(new QTreeWidgetItem(QStringList("pic_order_cnt_delta = " + QString::number(pSei->pic_order_cnt_delta)))); +} + + +void SyntaxViewer::createProgressiveRefinementSegmentEnd(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("progressive_refinement_id = " + QString::number(pSei->progressive_refinement_id)))); +} + + +void SyntaxViewer::createFullFrameSnapshot(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("snapshot_id = " + QString::number(pSei->snapshot_id)))); +} + + +void SyntaxViewer::createRegionRefreshInfo(std::shared_ptr pSei, QTreeWidgetItem *pItem) +{ + pItem -> addChild(new QTreeWidgetItem(QStringList("refreshed_region_flag = " + QString::number(pSei->refreshed_region_flag)))); +} + + +void SyntaxViewer::onItemCollapsed(QTreeWidgetItem * item) +{ + m_state.setActive(item, false); +} + + +void SyntaxViewer::onItemExpanded(QTreeWidgetItem * item) +{ + m_state.setActive(item, true); +} + + +void SyntaxViewer::updateItemsState() +{ + QTreeWidgetItemIterator itr(this); + + for(;*itr; itr++) + (*itr)-> setExpanded(m_state.isActive((*itr))); +} + + +bool SyntaxViewer::SyntaxViewerState::isActive(const QTreeWidgetItem *pitem) const +{ + std::map::const_iterator itr = m_state.find(name(pitem)); + if(itr != m_state.end()) + return itr -> second; + + return true; +} + + +void SyntaxViewer::SyntaxViewerState::setActive(const QTreeWidgetItem *pitem, bool isActive) +{ + m_state[name(pitem)] = isActive; +} + + +QString SyntaxViewer::SyntaxViewerState::name(const QTreeWidgetItem *pitem) const +{ + QString name; + while(pitem) + { + if(name.isEmpty()) + name = pitem -> text(0); + else + name = pitem -> text(0) + "::" + name; + + pitem = pitem -> parent(); + } + + return name; +} + +// H264 implementation methods +void SyntaxViewer::createH264SPS(std::shared_ptr pSPS) +{ + QTreeWidgetItem *pspsItem = new QTreeWidgetItem(QStringList("SPS (H.264)")); + addTopLevelItem(pspsItem); + + pspsItem->addChild(new QTreeWidgetItem(QStringList("profile_idc = " + QString::number(pSPS->profile_idc) + " (" + QString::fromStdString(H264::H264Utils::ProfileToString(pSPS->profile_idc)) + ")"))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("constraint_set0_flag = " + QString::number(pSPS->constraint_set0_flag)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("constraint_set1_flag = " + QString::number(pSPS->constraint_set1_flag)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("constraint_set2_flag = " + QString::number(pSPS->constraint_set2_flag)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("constraint_set3_flag = " + QString::number(pSPS->constraint_set3_flag)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("constraint_set4_flag = " + QString::number(pSPS->constraint_set4_flag)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("constraint_set5_flag = " + QString::number(pSPS->constraint_set5_flag)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("level_idc = " + QString::number(pSPS->level_idc) + " (" + QString::fromStdString(H264::H264Utils::LevelToString(pSPS->level_idc)) + ")"))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("seq_parameter_set_id = " + QString::number(pSPS->seq_parameter_set_id)))); + + if (pSPS->profile_idc == 100 || pSPS->profile_idc == 110 || pSPS->profile_idc == 122 || pSPS->profile_idc == 244 || pSPS->profile_idc == 44 || pSPS->profile_idc == 83 || pSPS->profile_idc == 86 || pSPS->profile_idc == 118 || pSPS->profile_idc == 128) + { + pspsItem->addChild(new QTreeWidgetItem(QStringList("chroma_format_idc = " + QString::number(pSPS->chroma_format_idc)))); + if (pSPS->chroma_format_idc == 3) + { + pspsItem->addChild(new QTreeWidgetItem(QStringList("separate_colour_plane_flag = " + QString::number(pSPS->separate_colour_plane_flag)))); + } + pspsItem->addChild(new QTreeWidgetItem(QStringList("bit_depth_luma_minus8 = " + QString::number(pSPS->bit_depth_luma_minus8)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("bit_depth_chroma_minus8 = " + QString::number(pSPS->bit_depth_chroma_minus8)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("qpprime_y_zero_transform_bypass_flag = " + QString::number(pSPS->qpprime_y_zero_transform_bypass_flag)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("seq_scaling_matrix_present_flag = " + QString::number(pSPS->seq_scaling_matrix_present_flag)))); + } + + pspsItem->addChild(new QTreeWidgetItem(QStringList("log2_max_frame_num_minus4 = " + QString::number(pSPS->log2_max_frame_num_minus4)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("pic_order_cnt_type = " + QString::number(pSPS->pic_order_cnt_type)))); + + if (pSPS->pic_order_cnt_type == 0) + { + pspsItem->addChild(new QTreeWidgetItem(QStringList("log2_max_pic_order_cnt_lsb_minus4 = " + QString::number(pSPS->log2_max_pic_order_cnt_lsb_minus4)))); + } + else if (pSPS->pic_order_cnt_type == 1) + { + pspsItem->addChild(new QTreeWidgetItem(QStringList("delta_pic_order_always_zero_flag = " + QString::number(pSPS->delta_pic_order_always_zero_flag)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("offset_for_non_ref_pic = " + QString::number(pSPS->offset_for_non_ref_pic)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("offset_for_top_to_bottom_field = " + QString::number(pSPS->offset_for_top_to_bottom_field)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("num_ref_frames_in_pic_order_cnt_cycle = " + QString::number(pSPS->num_ref_frames_in_pic_order_cnt_cycle)))); + for (size_t i = 0; i < pSPS->offset_for_ref_frame.size(); i++) + { + pspsItem->addChild(new QTreeWidgetItem(QStringList("offset_for_ref_frame[" + QString::number(i) + "] = " + QString::number(pSPS->offset_for_ref_frame[i])))); + } + } + + pspsItem->addChild(new QTreeWidgetItem(QStringList("max_num_ref_frames = " + QString::number(pSPS->max_num_ref_frames)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("gaps_in_frame_num_value_allowed_flag = " + QString::number(pSPS->gaps_in_frame_num_value_allowed_flag)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("pic_width_in_mbs_minus1 = " + QString::number(pSPS->pic_width_in_mbs_minus1) + " (" + QString::number((pSPS->pic_width_in_mbs_minus1 + 1) * 16) + ")"))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("pic_height_in_map_units_minus1 = " + QString::number(pSPS->pic_height_in_map_units_minus1) + " (" + QString::number((pSPS->pic_height_in_map_units_minus1 + 1) * 16) + ")"))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("frame_mbs_only_flag = " + QString::number(pSPS->frame_mbs_only_flag)))); + + if (!pSPS->frame_mbs_only_flag) + { + pspsItem->addChild(new QTreeWidgetItem(QStringList("mb_adaptive_frame_field_flag = " + QString::number(pSPS->mb_adaptive_frame_field_flag)))); + } + + pspsItem->addChild(new QTreeWidgetItem(QStringList("direct_8x8_inference_flag = " + QString::number(pSPS->direct_8x8_inference_flag)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("frame_cropping_flag = " + QString::number(pSPS->frame_cropping_flag)))); + + if (pSPS->frame_cropping_flag) + { + pspsItem->addChild(new QTreeWidgetItem(QStringList("frame_crop_left_offset = " + QString::number(pSPS->frame_crop_left_offset)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("frame_crop_right_offset = " + QString::number(pSPS->frame_crop_right_offset)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("frame_crop_top_offset = " + QString::number(pSPS->frame_crop_top_offset)))); + pspsItem->addChild(new QTreeWidgetItem(QStringList("frame_crop_bottom_offset = " + QString::number(pSPS->frame_crop_bottom_offset)))); + } + + pspsItem->addChild(new QTreeWidgetItem(QStringList("vui_parameters_present_flag = " + QString::number(pSPS->vui_parameters_present_flag)))); + + if (pSPS->vui_parameters_present_flag) + { + QTreeWidgetItem *vuiItem = new QTreeWidgetItem(QStringList("vui_parameters():")); + pspsItem->addChild(vuiItem); + + const H264::VuiParameters &vui = pSPS->vui_parameters; + + vuiItem->addChild(new QTreeWidgetItem(QStringList("aspect_ratio_info_present_flag = " + QString::number(vui.aspect_ratio_info_present_flag)))); + if (vui.aspect_ratio_info_present_flag) + { + vuiItem->addChild(new QTreeWidgetItem(QStringList("aspect_ratio_idc = " + QString::number(vui.aspect_ratio_idc)))); + if (vui.aspect_ratio_idc == 255) // Extended_SAR + { + vuiItem->addChild(new QTreeWidgetItem(QStringList("sar_width = " + QString::number(vui.sar_width)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("sar_height = " + QString::number(vui.sar_height)))); + } + } + + vuiItem->addChild(new QTreeWidgetItem(QStringList("overscan_info_present_flag = " + QString::number(vui.overscan_info_present_flag)))); + if (vui.overscan_info_present_flag) + { + vuiItem->addChild(new QTreeWidgetItem(QStringList("overscan_appropriate_flag = " + QString::number(vui.overscan_appropriate_flag)))); + } + + vuiItem->addChild(new QTreeWidgetItem(QStringList("video_signal_type_present_flag = " + QString::number(vui.video_signal_type_present_flag)))); + if (vui.video_signal_type_present_flag) + { + vuiItem->addChild(new QTreeWidgetItem(QStringList("video_format = " + QString::number(vui.video_format)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("video_full_range_flag = " + QString::number(vui.video_full_range_flag)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("colour_description_present_flag = " + QString::number(vui.colour_description_present_flag)))); + if (vui.colour_description_present_flag) + { + vuiItem->addChild(new QTreeWidgetItem(QStringList("colour_primaries = " + QString::number(vui.colour_primaries)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("transfer_characteristics = " + QString::number(vui.transfer_characteristics)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("matrix_coefficients = " + QString::number(vui.matrix_coefficients)))); + } + } + + vuiItem->addChild(new QTreeWidgetItem(QStringList("chroma_loc_info_present_flag = " + QString::number(vui.chroma_loc_info_present_flag)))); + if (vui.chroma_loc_info_present_flag) + { + vuiItem->addChild(new QTreeWidgetItem(QStringList("chroma_sample_loc_type_top_field = " + QString::number(vui.chroma_sample_loc_type_top_field)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("chroma_sample_loc_type_bottom_field = " + QString::number(vui.chroma_sample_loc_type_bottom_field)))); + } + + vuiItem->addChild(new QTreeWidgetItem(QStringList("timing_info_present_flag = " + QString::number(vui.timing_info_present_flag)))); + if (vui.timing_info_present_flag) + { + vuiItem->addChild(new QTreeWidgetItem(QStringList("num_units_in_tick = " + QString::number(vui.num_units_in_tick)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("time_scale = " + QString::number(vui.time_scale)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("fixed_frame_rate_flag = " + QString::number(vui.fixed_frame_rate_flag)))); + } + + vuiItem->addChild(new QTreeWidgetItem(QStringList("nal_hrd_parameters_present_flag = " + QString::number(vui.nal_hrd_parameters_present_flag)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("vcl_hrd_parameters_present_flag = " + QString::number(vui.vcl_hrd_parameters_present_flag)))); + + if (vui.nal_hrd_parameters_present_flag || vui.vcl_hrd_parameters_present_flag) + { + vuiItem->addChild(new QTreeWidgetItem(QStringList("low_delay_hrd_flag = " + QString::number(vui.low_delay_hrd_flag)))); + } + + vuiItem->addChild(new QTreeWidgetItem(QStringList("pic_struct_present_flag = " + QString::number(vui.pic_struct_present_flag)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("bitstream_restriction_flag = " + QString::number(vui.bitstream_restriction_flag)))); + + if (vui.bitstream_restriction_flag) + { + vuiItem->addChild(new QTreeWidgetItem(QStringList("motion_vectors_over_pic_boundaries_flag = " + QString::number(vui.motion_vectors_over_pic_boundaries_flag)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("max_bytes_per_pic_denom = " + QString::number(vui.max_bytes_per_pic_denom)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("max_bits_per_mb_denom = " + QString::number(vui.max_bits_per_mb_denom)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("log2_max_mv_length_horizontal = " + QString::number(vui.log2_max_mv_length_horizontal)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("log2_max_mv_length_vertical = " + QString::number(vui.log2_max_mv_length_vertical)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("num_reorder_frames = " + QString::number(vui.num_reorder_frames)))); + vuiItem->addChild(new QTreeWidgetItem(QStringList("max_dec_frame_buffering = " + QString::number(vui.max_dec_frame_buffering)))); + } + } + + // Calculate and display image dimensions + uint32_t width = (pSPS->pic_width_in_mbs_minus1 + 1) * 16; + uint32_t height = (pSPS->pic_height_in_map_units_minus1 + 1) * 16 * (2 - pSPS->frame_mbs_only_flag); + pspsItem->addChild(new QTreeWidgetItem(QStringList("Calculated image size: " + QString::number(width) + "x" + QString::number(height)))); +} + +void SyntaxViewer::createH264PPS(std::shared_ptr pPPS) +{ + QTreeWidgetItem *pppsItem = new QTreeWidgetItem(QStringList("PPS (H.264)")); + addTopLevelItem(pppsItem); + + pppsItem->addChild(new QTreeWidgetItem(QStringList("pic_parameter_set_id = " + QString::number(pPPS->pic_parameter_set_id)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("seq_parameter_set_id = " + QString::number(pPPS->seq_parameter_set_id)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("entropy_coding_mode_flag = " + QString::number(pPPS->entropy_coding_mode_flag) + " (" + (pPPS->entropy_coding_mode_flag ? "CABAC" : "CAVLC") + ")"))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("bottom_field_pic_order_in_frame_present_flag = " + QString::number(pPPS->bottom_field_pic_order_in_frame_present_flag)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("num_slice_groups_minus1 = " + QString::number(pPPS->num_slice_groups_minus1)))); + + if (pPPS->num_slice_groups_minus1 > 0) + { + pppsItem->addChild(new QTreeWidgetItem(QStringList("slice_group_map_type = " + QString::number(pPPS->slice_group_map_type)))); + + if (pPPS->slice_group_map_type == 0) + { + for (size_t i = 0; i <= pPPS->num_slice_groups_minus1; i++) + { + if (i < pPPS->run_length_minus1.size()) + { + pppsItem->addChild(new QTreeWidgetItem(QStringList("run_length_minus1[" + QString::number(i) + "] = " + QString::number(pPPS->run_length_minus1[i])))); + } + } + } + else if (pPPS->slice_group_map_type == 2) + { + for (size_t i = 0; i < pPPS->num_slice_groups_minus1; i++) + { + if (i < pPPS->top_left.size() && i < pPPS->bottom_right.size()) + { + pppsItem->addChild(new QTreeWidgetItem(QStringList("top_left[" + QString::number(i) + "] = " + QString::number(pPPS->top_left[i])))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("bottom_right[" + QString::number(i) + "] = " + QString::number(pPPS->bottom_right[i])))); + } + } + } + else if (pPPS->slice_group_map_type >= 3 && pPPS->slice_group_map_type <= 5) + { + pppsItem->addChild(new QTreeWidgetItem(QStringList("slice_group_change_direction_flag = " + QString::number(pPPS->slice_group_change_direction_flag)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("slice_group_change_rate_minus1 = " + QString::number(pPPS->slice_group_change_rate_minus1)))); + } + else if (pPPS->slice_group_map_type == 6) + { + pppsItem->addChild(new QTreeWidgetItem(QStringList("pic_size_in_map_units_minus1 = " + QString::number(pPPS->pic_size_in_map_units_minus1)))); + // Display first few slice_group_id values + size_t displayCount = std::min((size_t)10, pPPS->slice_group_id.size()); + for (size_t i = 0; i < displayCount; i++) + { + pppsItem->addChild(new QTreeWidgetItem(QStringList("slice_group_id[" + QString::number(i) + "] = " + QString::number(pPPS->slice_group_id[i])))); + } + if (pPPS->slice_group_id.size() > displayCount) + { + pppsItem->addChild(new QTreeWidgetItem(QStringList("... (" + QString::number(pPPS->slice_group_id.size() - displayCount) + " more entries)"))); + } + } + } + + pppsItem->addChild(new QTreeWidgetItem(QStringList("num_ref_idx_l0_default_active_minus1 = " + QString::number(pPPS->num_ref_idx_l0_default_active_minus1)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("num_ref_idx_l1_default_active_minus1 = " + QString::number(pPPS->num_ref_idx_l1_default_active_minus1)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("weighted_pred_flag = " + QString::number(pPPS->weighted_pred_flag)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("weighted_bipred_idc = " + QString::number(pPPS->weighted_bipred_idc)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("pic_init_qp_minus26 = " + QString::number(pPPS->pic_init_qp_minus26) + " (QP=" + QString::number(26 + pPPS->pic_init_qp_minus26) + ")"))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("pic_init_qs_minus26 = " + QString::number(pPPS->pic_init_qs_minus26)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("chroma_qp_index_offset = " + QString::number(pPPS->chroma_qp_index_offset)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("deblocking_filter_control_present_flag = " + QString::number(pPPS->deblocking_filter_control_present_flag)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("constrained_intra_pred_flag = " + QString::number(pPPS->constrained_intra_pred_flag)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("redundant_pic_cnt_present_flag = " + QString::number(pPPS->redundant_pic_cnt_present_flag)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("transform_8x8_mode_flag = " + QString::number(pPPS->transform_8x8_mode_flag)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("pic_scaling_matrix_present_flag = " + QString::number(pPPS->pic_scaling_matrix_present_flag)))); + pppsItem->addChild(new QTreeWidgetItem(QStringList("second_chroma_qp_index_offset = " + QString::number(pPPS->second_chroma_qp_index_offset)))); +} + +void SyntaxViewer::createH264Slice(std::shared_ptr pSlice) +{ + QString sliceTypeStr = QString::fromStdString(H264::H264Utils::SliceTypeToString((H264::Slice::SliceType)pSlice->slice_type)); + QTreeWidgetItem *psliceItem = new QTreeWidgetItem(QStringList("Slice (H.264) - " + sliceTypeStr)); + addTopLevelItem(psliceItem); + + psliceItem->addChild(new QTreeWidgetItem(QStringList("first_mb_in_slice = " + QString::number(pSlice->first_mb_in_slice)))); + psliceItem->addChild(new QTreeWidgetItem(QStringList("slice_type = " + QString::number(pSlice->slice_type) + " (" + sliceTypeStr + ")"))); + psliceItem->addChild(new QTreeWidgetItem(QStringList("pic_parameter_set_id = " + QString::number(pSlice->pic_parameter_set_id)))); + psliceItem->addChild(new QTreeWidgetItem(QStringList("colour_plane_id = " + QString::number(pSlice->colour_plane_id)))); + psliceItem->addChild(new QTreeWidgetItem(QStringList("frame_num = " + QString::number(pSlice->frame_num)))); + psliceItem->addChild(new QTreeWidgetItem(QStringList("field_pic_flag = " + QString::number(pSlice->field_pic_flag)))); + + if (pSlice->field_pic_flag) + { + psliceItem->addChild(new QTreeWidgetItem(QStringList("bottom_field_flag = " + QString::number(pSlice->bottom_field_flag)))); + } + + if (pSlice->m_nalHeader.nal_unit_type == H264::NAL_IDR_SLICE) + { + psliceItem->addChild(new QTreeWidgetItem(QStringList("idr_pic_id = " + QString::number(pSlice->idr_pic_id)))); + } + + psliceItem->addChild(new QTreeWidgetItem(QStringList("pic_order_cnt_lsb = " + QString::number(pSlice->pic_order_cnt_lsb)))); + psliceItem->addChild(new QTreeWidgetItem(QStringList("delta_pic_order_cnt_bottom = " + QString::number(pSlice->delta_pic_order_cnt_bottom)))); + + for (size_t i = 0; i < pSlice->delta_pic_order_cnt.size(); i++) + { + psliceItem->addChild(new QTreeWidgetItem(QStringList("delta_pic_order_cnt[" + QString::number(i) + "] = " + QString::number(pSlice->delta_pic_order_cnt[i])))); + } + + psliceItem->addChild(new QTreeWidgetItem(QStringList("redundant_pic_cnt = " + QString::number(pSlice->redundant_pic_cnt)))); + + if (pSlice->slice_type == H264::Slice::B_SLICE || pSlice->slice_type == H264::Slice::B_SLICE_A) + { + psliceItem->addChild(new QTreeWidgetItem(QStringList("direct_spatial_mv_pred_flag = " + QString::number(pSlice->direct_spatial_mv_pred_flag)))); + } + + if (pSlice->slice_type == H264::Slice::P_SLICE || pSlice->slice_type == H264::Slice::P_SLICE_A || + pSlice->slice_type == H264::Slice::SP_SLICE || pSlice->slice_type == H264::Slice::SP_SLICE_A || + pSlice->slice_type == H264::Slice::B_SLICE || pSlice->slice_type == H264::Slice::B_SLICE_A) + { + psliceItem->addChild(new QTreeWidgetItem(QStringList("num_ref_idx_active_override_flag = " + QString::number(pSlice->num_ref_idx_active_override_flag)))); + + if (pSlice->num_ref_idx_active_override_flag) + { + psliceItem->addChild(new QTreeWidgetItem(QStringList("num_ref_idx_l0_active_minus1 = " + QString::number(pSlice->num_ref_idx_l0_active_minus1)))); + + if (pSlice->slice_type == H264::Slice::B_SLICE || pSlice->slice_type == H264::Slice::B_SLICE_A) + { + psliceItem->addChild(new QTreeWidgetItem(QStringList("num_ref_idx_l1_active_minus1 = " + QString::number(pSlice->num_ref_idx_l1_active_minus1)))); + } + } + } + + psliceItem->addChild(new QTreeWidgetItem(QStringList("ref_pic_list_modification_flag_l0 = " + QString::number(pSlice->ref_pic_list_modification_flag_l0)))); + psliceItem->addChild(new QTreeWidgetItem(QStringList("ref_pic_list_modification_flag_l1 = " + QString::number(pSlice->ref_pic_list_modification_flag_l1)))); + + if (pSlice->m_nalHeader.nal_unit_type == H264::NAL_IDR_SLICE) + { + psliceItem->addChild(new QTreeWidgetItem(QStringList("no_output_of_prior_pics_flag = " + QString::number(pSlice->no_output_of_prior_pics_flag)))); + psliceItem->addChild(new QTreeWidgetItem(QStringList("long_term_reference_flag = " + QString::number(pSlice->long_term_reference_flag)))); + } + else + { + psliceItem->addChild(new QTreeWidgetItem(QStringList("adaptive_ref_pic_marking_mode_flag = " + QString::number(pSlice->adaptive_ref_pic_marking_mode_flag)))); + } + + psliceItem->addChild(new QTreeWidgetItem(QStringList("cabac_init_idc = " + QString::number(pSlice->cabac_init_idc)))); + psliceItem->addChild(new QTreeWidgetItem(QStringList("slice_qp_delta = " + QString::number(pSlice->slice_qp_delta)))); + + if (pSlice->slice_type == H264::Slice::SP_SLICE || pSlice->slice_type == H264::Slice::SP_SLICE_A || + pSlice->slice_type == H264::Slice::SI_SLICE || pSlice->slice_type == H264::Slice::SI_SLICE_A) + { + if (pSlice->slice_type == H264::Slice::SP_SLICE || pSlice->slice_type == H264::Slice::SP_SLICE_A) + { + psliceItem->addChild(new QTreeWidgetItem(QStringList("sp_for_switch_flag = " + QString::number(pSlice->sp_for_switch_flag)))); + } + psliceItem->addChild(new QTreeWidgetItem(QStringList("slice_qs_delta = " + QString::number(pSlice->slice_qs_delta)))); + } + + psliceItem->addChild(new QTreeWidgetItem(QStringList("disable_deblocking_filter_idc = " + QString::number(pSlice->disable_deblocking_filter_idc)))); + + if (pSlice->disable_deblocking_filter_idc != 1) + { + psliceItem->addChild(new QTreeWidgetItem(QStringList("slice_alpha_c0_offset_div2 = " + QString::number(pSlice->slice_alpha_c0_offset_div2)))); + psliceItem->addChild(new QTreeWidgetItem(QStringList("slice_beta_offset_div2 = " + QString::number(pSlice->slice_beta_offset_div2)))); + } + + psliceItem->addChild(new QTreeWidgetItem(QStringList("slice_group_change_cycle = " + QString::number(pSlice->slice_group_change_cycle)))); +} + +void SyntaxViewer::createH264AUD(std::shared_ptr pAUD) +{ + QTreeWidgetItem *paudItem = new QTreeWidgetItem(QStringList("AUD (H.264)")); + addTopLevelItem(paudItem); + + QString picTypeDesc; + switch (pAUD->primary_pic_type) + { + case 0: picTypeDesc = "I"; break; + case 1: picTypeDesc = "I, P"; break; + case 2: picTypeDesc = "I, P, B"; break; + case 3: picTypeDesc = "SI"; break; + case 4: picTypeDesc = "SI, SP"; break; + case 5: picTypeDesc = "I, SI"; break; + case 6: picTypeDesc = "I, SI, P, SP"; break; + case 7: picTypeDesc = "I, SI, P, SP, B"; break; + default: picTypeDesc = "Unknown"; break; + } + + paudItem->addChild(new QTreeWidgetItem(QStringList("primary_pic_type = " + QString::number(pAUD->primary_pic_type) + " (" + picTypeDesc + ")"))); +} + +void SyntaxViewer::createH264SEI(std::shared_ptr pSEI) +{ + QTreeWidgetItem *pseiItem = new QTreeWidgetItem(QStringList("SEI (H.264)")); + addTopLevelItem(pseiItem); + + pseiItem->addChild(new QTreeWidgetItem(QStringList("SEI payload size = " + QString::number(pSEI->sei_payload.size())))); + + // Display first few bytes of payload as hex + QString payloadHex = ""; + size_t displayBytes = std::min((size_t)16, pSEI->sei_payload.size()); + for (size_t i = 0; i < displayBytes; ++i) + { + payloadHex += QString("%1 ").arg(pSEI->sei_payload[i], 2, 16, QChar('0')).toUpper(); + } + if (pSEI->sei_payload.size() > displayBytes) + { + payloadHex += "..."; + } + pseiItem->addChild(new QTreeWidgetItem(QStringList("Payload (hex): " + payloadHex))); +} diff --git a/utils/hevc_es_browser_gui/SyntaxViewer.h b/utils/hevc_es_browser_gui/SyntaxViewer.h index 52e72ae..733cf5d 100644 --- a/utils/hevc_es_browser_gui/SyntaxViewer.h +++ b/utils/hevc_es_browser_gui/SyntaxViewer.h @@ -7,11 +7,14 @@ #include #include +#include +#include #include #include #include "types.h" +#include "VideoParser.h" class SyntaxViewer: public QTreeWidget { @@ -24,22 +27,34 @@ class SyntaxViewer: public QTreeWidget public slots: void onNalUChanged(std::shared_ptr, ParserInfo info); + void onH264NalUChanged(std::shared_ptr, H264::Parser::Info info); + void onVideoNalUChanged(std::shared_ptr, VideoParserInfo info); void setParameretsSets(const VPSMap &vpsMap, const SPSMap &spsMap, const PPSMap &ppsMap); + void setH264ParameterSets(const std::map> &spsMap, + const std::map> &ppsMap); private slots: void onItemCollapsed(QTreeWidgetItem * item); void onItemExpanded(QTreeWidgetItem * item); private: + // HEVC methods void createVPS(std::shared_ptr pVPS); void createSPS(std::shared_ptr pSPS); void createPPS(std::shared_ptr pPPS); void createSlice(std::shared_ptr pSlice); void createAUD(std::shared_ptr pAUD); void createSEI(std::shared_ptr pSEI); + + // H264 methods + void createH264SPS(std::shared_ptr pSPS); + void createH264PPS(std::shared_ptr pPPS); + void createH264Slice(std::shared_ptr pSlice); + void createH264AUD(std::shared_ptr pAUD); + void createH264SEI(std::shared_ptr pSEI); void createProfileTierLevel(const HEVC::ProfileTierLevel &ptl, QTreeWidgetItem *pItem); void createVuiParameters(const HEVC::VuiParameters &vui, std::size_t maxNumSubLayersMinus1, QTreeWidgetItem *pItem); @@ -75,9 +90,14 @@ class SyntaxViewer: public QTreeWidget void createContentLightLevelInfo(std::shared_ptr pSeiPayload, QTreeWidgetItem *pItem); void createAlternativeTransferCharacteristics(std::shared_ptr pSeiPayload, QTreeWidgetItem *pItem); + // HEVC parameter sets std::map > m_vpsMap; std::map > m_spsMap; std::map > m_ppsMap; + + // H264 parameter sets + std::map > m_h264SpsMap; + std::map > m_h264PpsMap; class SyntaxViewerState { diff --git a/utils/hevc_es_browser_gui/UnifiedCommonInfoViewer.cpp b/utils/hevc_es_browser_gui/UnifiedCommonInfoViewer.cpp new file mode 100644 index 0000000..69bb5be --- /dev/null +++ b/utils/hevc_es_browser_gui/UnifiedCommonInfoViewer.cpp @@ -0,0 +1,313 @@ +#include "UnifiedCommonInfoViewer.h" + +#include +#include +#include +#include + +#include +#include + +UnifiedCommonInfoViewer::UnifiedCommonInfoViewer(QWidget *pwgt): + QTableWidget(pwgt) +{ + setColumnCount(4); + QStringList labels; + labels << "Offset" << "Length" << "Nal Unit Type" << "Info"; + setHorizontalHeaderLabels(labels); + + horizontalHeader() -> setStretchLastSection(true); + setSelectionBehavior(QAbstractItemView::SelectRows); + setAlternatingRowColors(true); + + connect(selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + SLOT(onSelectionChanged(const QItemSelection &, const QItemSelection &))); + + readCustomData(); +} + +void UnifiedCommonInfoViewer::saveCustomData() +{ + QSettings settings; + settings.beginGroup("UnifiedCommonInfoViewer"); + settings.setValue("HeaderState", horizontalHeader() -> saveState()); + settings.endGroup(); +} + +void UnifiedCommonInfoViewer::readCustomData() +{ + QSettings settings; + settings.beginGroup("UnifiedCommonInfoViewer"); + QByteArray headerState = settings.value("HeaderState").toByteArray(); + if(!headerState.isEmpty()) + { + horizontalHeader() -> restoreState(headerState); + } + settings.endGroup(); +} + +void UnifiedCommonInfoViewer::clear() +{ + m_nalus.clear(); + m_hevcVpsMap.clear(); + m_hevcSpsMap.clear(); + m_hevcPpsMap.clear(); + m_h264SpsMap.clear(); + m_h264PpsMap.clear(); + + setRowCount(0); +} + +void UnifiedCommonInfoViewer::onVideoNALUnit(std::shared_ptr pNALUnit, const VideoParserInfo& info) +{ + VideoNALUInfo naluInfo; + naluInfo.m_pNALUnit = pNALUnit; + naluInfo.m_info = info; + m_nalus.push_back(naluInfo); + + int row = rowCount(); + insertRow(row); + + // Offset Column: Display hexadecimal and decimal positions + QString offset = "0x" + QString::number(info.m_position, 16) + " (" + QString::number(info.m_position) + ")"; + setItem(row, 0, new QTableWidgetItem(offset)); + + // Length Column: Set to empty first, then calculate later + setItem(row, 1, new QTableWidgetItem(QString())); + + // If not the first row, calculate the length of the previous NAL unit + if(row > 0) + { + std::size_t prevPosition = m_nalus[m_nalus.size() - 2].m_info.m_position; + std::size_t length = info.m_position - prevPosition; + item(row - 1, 1)->setText(QString::number(length)); + } + + // Nal Unit Type Column: Display NAL unit type + setItem(row, 2, new QTableWidgetItem(QString::fromStdString(pNALUnit->getTypeName()))); + + // Info Column: Display detailed information based on NAL unit type + QString infoStr = "Unknown"; + + if (pNALUnit->getCodec() == VideoCodec::HEVC) + { + auto hevcWrapper = std::dynamic_pointer_cast(pNALUnit); + if (hevcWrapper) + { + auto hevcNALU = hevcWrapper->getHEVCNALUnit(); + switch(hevcNALU->m_nalHeader.type) + { + case HEVC::NAL_VPS: + infoStr = "Video parameter set"; + break; + case HEVC::NAL_SPS: + infoStr = "Sequence parameter set"; + break; + case HEVC::NAL_PPS: + infoStr = "Picture parameter set"; + break; + case HEVC::NAL_IDR_W_RADL: + case HEVC::NAL_IDR_N_LP: + infoStr = "IDR Slice"; + break; + case HEVC::NAL_TRAIL_R: + case HEVC::NAL_TSA_R: + case HEVC::NAL_STSA_R: + case HEVC::NAL_RADL_R: + case HEVC::NAL_RASL_R: + case HEVC::NAL_TRAIL_N: + case HEVC::NAL_TSA_N: + case HEVC::NAL_STSA_N: + case HEVC::NAL_RADL_N: + case HEVC::NAL_RASL_N: + case HEVC::NAL_BLA_W_LP: + case HEVC::NAL_BLA_W_RADL: + case HEVC::NAL_BLA_N_LP: + case HEVC::NAL_CRA_NUT: + { + auto slice = std::dynamic_pointer_cast(hevcNALU); + if (slice) + { + if (slice->dependent_slice_segment_flag) + infoStr = "Dependent Slice"; + else + { + switch(slice->slice_type) + { + case HEVC::Slice::B_SLICE: + infoStr = "B Slice"; + break; + case HEVC::Slice::P_SLICE: + infoStr = "P Slice"; + break; + case HEVC::Slice::I_SLICE: + infoStr = "I Slice"; + break; + } + } + } + else + { + infoStr = "P Slice"; // Default value + } + break; + } + case HEVC::NAL_AUD: + infoStr = "Access unit delimiter"; + break; + case HEVC::NAL_SEI_PREFIX: + case HEVC::NAL_SEI_SUFFIX: + infoStr = "SEI"; + break; + default: + infoStr = "Unknown HEVC NAL"; + break; + } + } + } + else if (pNALUnit->getCodec() == VideoCodec::H264) + { + auto h264Wrapper = std::dynamic_pointer_cast(pNALUnit); + if (h264Wrapper) + { + auto h264NALU = h264Wrapper->getH264NALUnit(); + switch(h264NALU->m_nalHeader.nal_unit_type) + { + case 7: // SPS + infoStr = "Sequence parameter set"; + break; + case 8: // PPS + infoStr = "Picture parameter set"; + break; + case 5: // IDR slice + infoStr = "IDR Slice"; + break; + case 1: // Non-IDR slice + case 2: + case 3: + case 4: + { + auto slice = std::dynamic_pointer_cast(h264NALU); + if (slice) + { + // H.264 Slice Type: slice_type % 5 to get the basic type + uint32_t baseSliceType = slice->slice_type % 5; + switch(baseSliceType) + { + case H264::Slice::P_SLICE: + infoStr = "P Slice"; + break; + case H264::Slice::B_SLICE: + infoStr = "B Slice"; + break; + case H264::Slice::I_SLICE: + infoStr = "I Slice"; + break; + case H264::Slice::SP_SLICE: + infoStr = "SP Slice"; + break; + case H264::Slice::SI_SLICE: + infoStr = "SI Slice"; + break; + default: + infoStr = "Unknown Slice"; + break; + } + } + else + { + infoStr = "P Slice"; // Default value + } + break; + } + case 6: // SEI + infoStr = "SEI"; + break; + case 9: // AUD + infoStr = "Access unit delimiter"; + break; + default: + infoStr = "Unknown H.264 NAL"; + break; + } + } + } + + setItem(row, 3, new QTableWidgetItem(infoStr)); + + // Update parameter sets + if (pNALUnit->getCodec() == VideoCodec::HEVC) + { + auto hevcWrapper = std::dynamic_pointer_cast(pNALUnit); + if (hevcWrapper) + { + auto hevcNALU = hevcWrapper->getHEVCNALUnit(); + + if (std::shared_ptr vps = std::dynamic_pointer_cast(hevcNALU)) + { + m_hevcVpsMap[vps->vps_video_parameter_set_id] = vps; + updateParameterSets(); + } + else if (std::shared_ptr sps = std::dynamic_pointer_cast(hevcNALU)) + { + m_hevcSpsMap[sps->sps_seq_parameter_set_id] = sps; + updateParameterSets(); + } + else if (std::shared_ptr pps = std::dynamic_pointer_cast(hevcNALU)) + { + m_hevcPpsMap[pps->pps_pic_parameter_set_id] = pps; + updateParameterSets(); + } + } + } + else if (pNALUnit->getCodec() == VideoCodec::H264) + { + auto h264Wrapper = std::dynamic_pointer_cast(pNALUnit); + if (h264Wrapper) + { + auto h264NALU = h264Wrapper->getH264NALUnit(); + + if (std::shared_ptr sps = std::dynamic_pointer_cast(h264NALU)) + { + m_h264SpsMap[sps->seq_parameter_set_id] = sps; + updateParameterSets(); + } + else if (std::shared_ptr pps = std::dynamic_pointer_cast(h264NALU)) + { + m_h264PpsMap[pps->pic_parameter_set_id] = pps; + updateParameterSets(); + } + } + } + + scrollToBottom(); +} + +void UnifiedCommonInfoViewer::updateParameterSets() +{ + // Emit HEVC parameter set change signal + if (!m_hevcVpsMap.empty() || !m_hevcSpsMap.empty() || !m_hevcPpsMap.empty()) + { + emit hevcParameterSetsChanged(m_hevcVpsMap, m_hevcSpsMap, m_hevcPpsMap); + } + + // Emit H.264 parameter set change signal + if (!m_h264SpsMap.empty() || !m_h264PpsMap.empty()) + { + emit h264ParameterSetsChanged(m_h264SpsMap, m_h264PpsMap); + } +} + +void UnifiedCommonInfoViewer::onSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected) +{ + Q_UNUSED(deselected); + + if(selected.indexes().size() > 0) + { + int row = selected.indexes().first().row(); + if(row >= 0 && row < (int)m_nalus.size()) + { + emit naluSelected(m_nalus[row].m_pNALUnit, m_nalus[row].m_info); + } + } +} \ No newline at end of file diff --git a/utils/hevc_es_browser_gui/UnifiedCommonInfoViewer.h b/utils/hevc_es_browser_gui/UnifiedCommonInfoViewer.h new file mode 100644 index 0000000..9d8a408 --- /dev/null +++ b/utils/hevc_es_browser_gui/UnifiedCommonInfoViewer.h @@ -0,0 +1,69 @@ +#ifndef UNIFIED_COMMON_INFO_VIEWER_H_ +#define UNIFIED_COMMON_INFO_VIEWER_H_ + +#include +#include + +#include +#include + +#include "VideoParser.h" +#include "types.h" + +class UnifiedCommonInfoViewer: + public QTableWidget, + public VideoParserConsumer +{ + Q_OBJECT + + signals: + void naluSelected(std::shared_ptr pNALUnit, VideoParserInfo info); + void hevcParameterSetsChanged(const VPSMap &vpsMap, + const SPSMap &spsMap, + const PPSMap &ppsMap); + void h264ParameterSetsChanged(const std::map>& spsMap, + const std::map>& ppsMap); + + public: + UnifiedCommonInfoViewer(QWidget *pwgt = NULL); + + void saveCustomData(); + void clear(); + + // VideoParserConsumer interface + virtual void onVideoNALUnit(std::shared_ptr pNALUnit, const VideoParserInfo& info) override; + virtual void onVideoWarning(const std::string& warning, const VideoParserInfo& info) override { + (void)warning; + (void)info; + }; + + private slots: + void onSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected); + + private: + void readCustomData(); + void updateParameterSets(); + + struct VideoNALUInfo + { + std::shared_ptr m_pNALUnit; + VideoParserInfo m_info; + }; + + std::vector m_nalus; + + // HEVC parameter set + std::map> m_hevcVpsMap; + std::map> m_hevcSpsMap; + std::map> m_hevcPpsMap; + + // H.264 parameter set + std::map> m_h264SpsMap; + std::map> m_h264PpsMap; +}; + +// Register meta type +Q_DECLARE_METATYPE(std::shared_ptr) +Q_DECLARE_METATYPE(VideoParserInfo) + +#endif // UNIFIED_COMMON_INFO_VIEWER_H_ \ No newline at end of file diff --git a/utils/hevc_es_browser_gui/UnifiedWarningsViewer.cpp b/utils/hevc_es_browser_gui/UnifiedWarningsViewer.cpp new file mode 100644 index 0000000..8c623c3 --- /dev/null +++ b/utils/hevc_es_browser_gui/UnifiedWarningsViewer.cpp @@ -0,0 +1,111 @@ +#include "UnifiedWarningsViewer.h" + +#include +#include +#include + +UnifiedWarningsViewer::UnifiedWarningsViewer(QWidget *pwgt): + QTableWidget(pwgt) +{ + setColumnCount(4); + QStringList labels; + labels << "#" << "Codec" << "Position" << "Warning"; + setHorizontalHeaderLabels(labels); + + horizontalHeader() -> setStretchLastSection(true); + setSelectionBehavior(QAbstractItemView::SelectRows); + setAlternatingRowColors(true); + + readCustomData(); +} + +void UnifiedWarningsViewer::saveCustomData() +{ + QSettings settings; + settings.beginGroup("UnifiedWarningsViewer"); + settings.setValue("HeaderState", horizontalHeader() -> saveState()); + settings.endGroup(); +} + +void UnifiedWarningsViewer::readCustomData() +{ + QSettings settings; + settings.beginGroup("UnifiedWarningsViewer"); + QByteArray headerState = settings.value("HeaderState").toByteArray(); + if(!headerState.isEmpty()) + { + horizontalHeader() -> restoreState(headerState); + } + settings.endGroup(); +} + +void UnifiedWarningsViewer::clear() +{ + setRowCount(0); +} + +void UnifiedWarningsViewer::onVideoWarning(const std::string& warning, const VideoParserInfo& info) +{ + int row = rowCount(); + insertRow(row); + + // Sequence Number + setItem(row, 0, new QTableWidgetItem(QString::number(row + 1))); + + // Codec Type + QString codecStr; + switch(info.m_codec) + { + case VideoCodec::H264: + codecStr = "H.264"; + break; + case VideoCodec::HEVC: + codecStr = "HEVC"; + break; + default: + codecStr = "Unknown"; + break; + } + setItem(row, 1, new QTableWidgetItem(codecStr)); + + // Position + setItem(row, 2, new QTableWidgetItem(QString::number(info.m_position))); + + // Warning Message + setItem(row, 3, new QTableWidgetItem(QString::fromStdString(warning))); + + scrollToBottom(); +} + +void UnifiedWarningsViewer::addWarning(const std::string& warning, VideoCodec codec) +{ + int row = rowCount(); + insertRow(row); + + // Sequence Number + setItem(row, 0, new QTableWidgetItem(QString::number(row + 1))); + + // Codec Type + QString codecStr; + switch(codec) + { + case VideoCodec::H264: + codecStr = "H.264"; + break; + case VideoCodec::HEVC: + codecStr = "HEVC"; + break; + default: + codecStr = "General"; + break; + } + setItem(row, 1, new QTableWidgetItem(codecStr)); + + // Position + setItem(row, 2, new QTableWidgetItem("-")); + + // Warning Message + setItem(row, 3, new QTableWidgetItem(QString::fromStdString(warning))); + + scrollToBottom(); +} \ No newline at end of file diff --git a/utils/hevc_es_browser_gui/UnifiedWarningsViewer.h b/utils/hevc_es_browser_gui/UnifiedWarningsViewer.h new file mode 100644 index 0000000..49eba32 --- /dev/null +++ b/utils/hevc_es_browser_gui/UnifiedWarningsViewer.h @@ -0,0 +1,30 @@ +#ifndef UNIFIED_WARNINGS_VIEWER_H_ +#define UNIFIED_WARNINGS_VIEWER_H_ + +#include +#include "VideoParser.h" + +class UnifiedWarningsViewer: + public QTableWidget, + public VideoParserConsumer +{ + Q_OBJECT + + public: + UnifiedWarningsViewer(QWidget *pwgt = NULL); + + void saveCustomData(); + void clear(); + + // VideoParserConsumer interface + virtual void onVideoNALUnit(std::shared_ptr pNALUnit, const VideoParserInfo& info) override {}; + virtual void onVideoWarning(const std::string& warning, const VideoParserInfo& info) override; + + // Compatibility method for ProfileConformanceAnalyzer + void addWarning(const std::string& warning, VideoCodec codec = VideoCodec::UNKNOWN); + + private: + void readCustomData(); +}; + +#endif // UNIFIED_WARNINGS_VIEWER_H_ \ No newline at end of file diff --git a/utils/hevc_es_browser_gui/VideoParser.cpp b/utils/hevc_es_browser_gui/VideoParser.cpp new file mode 100644 index 0000000..5eebd54 --- /dev/null +++ b/utils/hevc_es_browser_gui/VideoParser.cpp @@ -0,0 +1,334 @@ +#include "VideoParser.h" +#include +#include +#include +#include +#include + +// HEVC NAL Unit Type to String Function +std::string hevcNALUnitTypeToString(HEVC::NALUnitType type) +{ + switch(type) + { + case HEVC::NAL_TRAIL_N: return "TRAIL_N"; + case HEVC::NAL_TRAIL_R: return "TRAIL_R"; + case HEVC::NAL_TSA_N: return "TSA_N"; + case HEVC::NAL_TSA_R: return "TSA_R"; + case HEVC::NAL_STSA_N: return "STSA_N"; + case HEVC::NAL_STSA_R: return "STSA_R"; + case HEVC::NAL_RADL_N: return "RADL_N"; + case HEVC::NAL_RADL_R: return "RADL_R"; + case HEVC::NAL_RASL_N: return "RASL_N"; + case HEVC::NAL_RASL_R: return "RASL_R"; + case HEVC::NAL_BLA_W_LP: return "BLA_W_LP"; + case HEVC::NAL_BLA_W_RADL: return "BLA_W_RADL"; + case HEVC::NAL_BLA_N_LP: return "BLA_N_LP"; + case HEVC::NAL_IDR_W_RADL: return "IDR_W_RADL"; + case HEVC::NAL_IDR_N_LP: return "IDR_N_LP"; + case HEVC::NAL_CRA_NUT: return "CRA_NUT"; + case HEVC::NAL_IRAP_VCL23: return "IRAP_VCL23"; + case HEVC::NAL_VPS: return "VPS"; + case HEVC::NAL_SPS: return "SPS"; + case HEVC::NAL_PPS: return "PPS"; + case HEVC::NAL_AUD: return "AUD"; + case HEVC::NAL_EOS_NUT: return "EOS_NUT"; + case HEVC::NAL_EOB_NUT: return "EOB_NUT"; + case HEVC::NAL_FD_NUT: return "FD_NUT"; + case HEVC::NAL_SEI_PREFIX: return "SEI_PREFIX"; + case HEVC::NAL_SEI_SUFFIX: return "SEI_SUFFIX"; + default: return "UNKNOWN"; + } +} + +// HEVCNALUnitWrapper implementation +std::string HEVCNALUnitWrapper::getTypeName() const +{ + return hevcNALUnitTypeToString(m_pNALUnit->m_nalHeader.type); +} + +// H264NALUnitWrapper implementation +std::string H264NALUnitWrapper::getTypeName() const +{ + return H264::H264Utils::NALUnitTypeToString(m_pNALUnit->m_nalHeader.nal_unit_type); +} + +// HEVC Consumer Adapter +class HEVCConsumerAdapter : public HEVC::Parser::Consumer +{ +public: + HEVCConsumerAdapter(VideoParserConsumer* consumer) : m_consumer(consumer) {} + + void onNALUnit(std::shared_ptr pNALUnit, const HEVC::Parser::Info* pInfo) override + { + if (m_consumer && pInfo) + { + auto wrapper = std::make_shared(pNALUnit); + VideoParserInfo info(*pInfo); + m_consumer->onVideoNALUnit(wrapper, info); + } + } + + void onWarning(const std::string& warning, const HEVC::Parser::Info* pInfo, HEVC::Parser::WarningType) override + { + if (m_consumer && pInfo) + { + VideoParserInfo info(*pInfo); + m_consumer->onVideoWarning(warning, info); + } + } + +private: + VideoParserConsumer* m_consumer; +}; + +// H.264 Consumer Adapter +class H264ConsumerAdapter : public H264::Parser::Consumer +{ +public: + H264ConsumerAdapter(VideoParserConsumer* consumer) : m_consumer(consumer) {} + + void onNALUnit(std::shared_ptr pNALUnit, const H264::Parser::Info* pInfo) override + { + if (m_consumer && pInfo) + { + auto wrapper = std::make_shared(pNALUnit); + VideoParserInfo info(*pInfo); + m_consumer->onVideoNALUnit(wrapper, info); + } + } + + void onWarning(const std::string& warning, const H264::Parser::Info* pInfo, H264::Parser::WarningType) override + { + if (m_consumer && pInfo) + { + VideoParserInfo info(*pInfo); + m_consumer->onVideoWarning(warning, info); + } + } + +private: + VideoParserConsumer* m_consumer; +}; + +// VideoParser implementation +class VideoParser::Impl +{ +public: + VideoCodec m_currentCodec = VideoCodec::UNKNOWN; + HEVC::Parser* m_pHEVCParser = nullptr; + H264::Parser* m_pH264Parser = nullptr; + + std::vector m_consumers; + std::vector m_hevcAdapters; + std::vector m_h264Adapters; + + ~Impl() + { + // Clean up adapters + for (auto adapter : m_hevcAdapters) + { + delete adapter; + } + for (auto adapter : m_h264Adapters) + { + delete adapter; + } + + // Release parsers + if (m_pHEVCParser) + { + HEVC::Parser::release(m_pHEVCParser); + } + if (m_pH264Parser) + { + H264::Parser::release(m_pH264Parser); + } + } +}; + +VideoParser::VideoParser() : m_pImpl(new Impl()) +{ +} + +VideoParser::~VideoParser() +{ + delete m_pImpl; +} + +VideoCodec VideoParser::detectCodec(const uint8_t* data, std::size_t size) +{ + if (size < 6) return VideoCodec::UNKNOWN; + + // Limit search range to improve performance + std::size_t searchLimit = std::min(size, static_cast(4096)); + + // Search for NAL unit start code + for (std::size_t i = 0; i <= searchLimit - 5; ++i) + { + if (data[i] == 0x00 && data[i+1] == 0x00 && data[i+2] == 0x00 && data[i+3] == 0x01) + { + if (i + 5 < searchLimit) + { + uint8_t nalHeader1 = data[i + 4]; + + // HEVC detection: NAL unit type in bits 1-6 + uint8_t hevcType = (nalHeader1 >> 1) & 0x3F; + + // Prioritize HEVC-specific parameter set NAL unit types (most reliable identification method) + if (hevcType == 32 || hevcType == 33 || hevcType == 34) // VPS, SPS, PPS + { + return VideoCodec::HEVC; + } + + // H.264 detection: NAL unit type in low 5 bits + uint8_t h264Type = nalHeader1 & 0x1F; + + // Prioritize H.264-specific parameter set NAL unit types (most reliable identification method) + if (h264Type == 7 || h264Type == 8) // SPS, PPS + { + return VideoCodec::H264; + } + + // Secondary check: other HEVC NAL unit types + if (hevcType == 39 || hevcType == 40 || // SEI + (hevcType >= 16 && hevcType <= 21)) // IDR/CRA slices + { + return VideoCodec::HEVC; + } + + // Secondary check: other H.264 NAL unit types + if (h264Type == 5 || h264Type == 6 || h264Type == 9) // IDR slice, SEI, AUD + { + return VideoCodec::H264; + } + } + } + } + + return VideoCodec::UNKNOWN; +} + +bool VideoParser::setCodec(VideoCodec codec) +{ + if (m_pImpl->m_currentCodec == codec) return true; + + // Clean up existing parsers + if (m_pImpl->m_pHEVCParser) + { + HEVC::Parser::release(m_pImpl->m_pHEVCParser); + m_pImpl->m_pHEVCParser = nullptr; + } + if (m_pImpl->m_pH264Parser) + { + H264::Parser::release(m_pImpl->m_pH264Parser); + m_pImpl->m_pH264Parser = nullptr; + } + + m_pImpl->m_hevcAdapters.clear(); + m_pImpl->m_h264Adapters.clear(); + + // Create new parsers + if (codec == VideoCodec::HEVC) + { + m_pImpl->m_pHEVCParser = HEVC::Parser::create(); + if (!m_pImpl->m_pHEVCParser) return false; + + // Create adapters for each consumer + for (auto consumer : m_pImpl->m_consumers) + { + HEVCConsumerAdapter* adapter = new HEVCConsumerAdapter(consumer); + m_pImpl->m_pHEVCParser->addConsumer(adapter); + m_pImpl->m_hevcAdapters.push_back(adapter); + } + } + else if (codec == VideoCodec::H264) + { + m_pImpl->m_pH264Parser = H264::Parser::create(); + if (!m_pImpl->m_pH264Parser) return false; + + // Create adapters for each consumer + for (auto consumer : m_pImpl->m_consumers) + { + H264ConsumerAdapter* adapter = new H264ConsumerAdapter(consumer); + m_pImpl->m_pH264Parser->addConsumer(adapter); + m_pImpl->m_h264Adapters.push_back(adapter); + } + } + else + { + return false; + } + + m_pImpl->m_currentCodec = codec; + return true; +} + +void VideoParser::addConsumer(VideoParserConsumer* consumer) +{ + if (std::find(m_pImpl->m_consumers.begin(), m_pImpl->m_consumers.end(), consumer) != m_pImpl->m_consumers.end()) + return; // Consumer already exists + + m_pImpl->m_consumers.push_back(consumer); + + // If a parser already exists, add the adapter + if (m_pImpl->m_pHEVCParser) + { + HEVCConsumerAdapter* adapter = new HEVCConsumerAdapter(consumer); + m_pImpl->m_pHEVCParser->addConsumer(adapter); + m_pImpl->m_hevcAdapters.push_back(adapter); + } + if (m_pImpl->m_pH264Parser) + { + H264ConsumerAdapter* adapter = new H264ConsumerAdapter(consumer); + m_pImpl->m_pH264Parser->addConsumer(adapter); + m_pImpl->m_h264Adapters.push_back(adapter); + } +} + +void VideoParser::removeConsumer(VideoParserConsumer* consumer) +{ + auto it = std::find(m_pImpl->m_consumers.begin(), m_pImpl->m_consumers.end(), consumer); + if (it != m_pImpl->m_consumers.end()) + { + m_pImpl->m_consumers.erase(it); + + // Remove the corresponding adapter + // Note: This simplification assumes that the adapter list is in the same order as the consumer list + m_pImpl->m_hevcAdapters.clear(); + m_pImpl->m_h264Adapters.clear(); + + // Recreate adapters + if (m_pImpl->m_pHEVCParser) + { + for (auto cons : m_pImpl->m_consumers) + { + auto adapter = new HEVCConsumerAdapter(cons); + m_pImpl->m_pHEVCParser->addConsumer(adapter); + m_pImpl->m_hevcAdapters.push_back(adapter); + } + } + if (m_pImpl->m_pH264Parser) + { + for (auto cons : m_pImpl->m_consumers) + { + auto adapter = new H264ConsumerAdapter(cons); + m_pImpl->m_pH264Parser->addConsumer(adapter); + m_pImpl->m_h264Adapters.push_back(adapter); + } + } + } +} + +std::size_t VideoParser::process(const uint8_t* data, std::size_t size, std::size_t position) +{ + if (m_pImpl->m_currentCodec == VideoCodec::HEVC && m_pImpl->m_pHEVCParser) + { + return m_pImpl->m_pHEVCParser->process(data, size, position); + } + else if (m_pImpl->m_currentCodec == VideoCodec::H264 && m_pImpl->m_pH264Parser) + { + return m_pImpl->m_pH264Parser->process(data, size, position); + } + + return 0; +} \ No newline at end of file diff --git a/utils/hevc_es_browser_gui/VideoParser.h b/utils/hevc_es_browser_gui/VideoParser.h new file mode 100644 index 0000000..23e1a2f --- /dev/null +++ b/utils/hevc_es_browser_gui/VideoParser.h @@ -0,0 +1,112 @@ +#ifndef VIDEO_PARSER_H_ +#define VIDEO_PARSER_H_ + +#include +#include +#include +#include + +#include +#include + +enum class VideoCodec +{ + UNKNOWN, + H264, + HEVC +}; + +// Unified NAL Unit Base Class +class VideoNALUnit +{ +public: + virtual ~VideoNALUnit() = default; + virtual VideoCodec getCodec() const = 0; + virtual std::string getTypeName() const = 0; + virtual uint32_t getSize() const = 0; +}; + +// HEVC NAL Unit Wrapper +class HEVCNALUnitWrapper : public VideoNALUnit +{ +public: + HEVCNALUnitWrapper(std::shared_ptr pNALUnit) : m_pNALUnit(pNALUnit) {} + + VideoCodec getCodec() const override { return VideoCodec::HEVC; } + std::string getTypeName() const override; + uint32_t getSize() const override { return 0; } // Size not available in NAL header + + std::shared_ptr getHEVCNALUnit() const { return m_pNALUnit; } + +private: + std::shared_ptr m_pNALUnit; +}; + +// H.264 NAL Unit Wrapper +class H264NALUnitWrapper : public VideoNALUnit +{ +public: + H264NALUnitWrapper(std::shared_ptr pNALUnit) : m_pNALUnit(pNALUnit) {} + + VideoCodec getCodec() const override { return VideoCodec::H264; } + std::string getTypeName() const override; + uint32_t getSize() const override { return 0; } // Size not available in NAL header + + std::shared_ptr getH264NALUnit() const { return m_pNALUnit; } + +private: + std::shared_ptr m_pNALUnit; +}; + +// Unified Parser Info +struct VideoParserInfo +{ + std::size_t m_position; + VideoCodec m_codec; + + // Default constructor (required for Qt metatype system) + VideoParserInfo() + : m_position(0) + , m_codec(VideoCodec::UNKNOWN) {} + + // Convert from HEVC::Parser::Info + VideoParserInfo(const HEVC::Parser::Info& info) + : m_position(info.m_position) + , m_codec(VideoCodec::HEVC) {} + + // Convert from H264::Parser::Info + VideoParserInfo(const H264::Parser::Info& info) + : m_position(info.m_position) + , m_codec(VideoCodec::H264) {} +}; + +// Unified Consumer Interface +class VideoParserConsumer +{ +public: + virtual ~VideoParserConsumer() = default; + virtual void onVideoNALUnit(std::shared_ptr pNALUnit, const VideoParserInfo& info) = 0; + virtual void onVideoWarning(const std::string& warning, const VideoParserInfo& info) = 0; +}; + +// Unified Video Parser +class VideoParser +{ +public: + VideoParser(); + ~VideoParser(); + + VideoCodec detectCodec(const uint8_t* data, std::size_t size); + bool setCodec(VideoCodec codec); + + void addConsumer(VideoParserConsumer* consumer); + void removeConsumer(VideoParserConsumer* consumer); + + std::size_t process(const uint8_t* data, std::size_t size, std::size_t position); + +private: + class Impl; + Impl* m_pImpl; +}; + +#endif // VIDEO_PARSER_H_ \ No newline at end of file diff --git a/utils/hevc_es_browser_gui/WarningsViewer.cpp b/utils/hevc_es_browser_gui/WarningsViewer.cpp index 412eae7..c2c1039 100644 --- a/utils/hevc_es_browser_gui/WarningsViewer.cpp +++ b/utils/hevc_es_browser_gui/WarningsViewer.cpp @@ -9,6 +9,7 @@ WarningsViewer::WarningsViewer(QWidget *pwgt) { + (void)pwgt; m_ptable = new QTableWidget(0, 2); QStringList labels; @@ -39,6 +40,8 @@ WarningsViewer::WarningsViewer(QWidget *pwgt) void WarningsViewer::onNALUnit(std::shared_ptr pNALUnit, const HEVC::Parser::Info *pInfo) { + (void)pNALUnit; + (void)pInfo; } diff --git a/utils/hevc_es_browser_gui/hevc_es_browser_gui.pro b/utils/hevc_es_browser_gui/hevc_es_browser_gui.pro index aa816fe..ddce57a 100644 --- a/utils/hevc_es_browser_gui/hevc_es_browser_gui.pro +++ b/utils/hevc_es_browser_gui/hevc_es_browser_gui.pro @@ -12,7 +12,7 @@ CONFIG += c++11 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -INCLUDEPATH += . ../../hevcparser/include/ ../common/ ../../external/QHexView/include/ +INCLUDEPATH += . ../../hevcparser/include/ ../../h264parser/include/ ../common/ ../../external/QHexView/include/ gitinfo.commands = verinfo/verinfo.sh version version_info.h @@ -29,6 +29,9 @@ HEADERS += CommonInfoViewer.h \ StreamInfoViewer.h \ HDRInfoViewer.h \ ProfileConformanceAnalyzer.h \ + VideoParser.h \ + UnifiedCommonInfoViewer.h \ + UnifiedWarningsViewer.h \ ../common/ConvToString.h \ ../../external/QHexView/include/QHexView.h @@ -41,10 +44,13 @@ SOURCES += CommonInfoViewer.cpp \ StreamInfoViewer.cpp \ HDRInfoViewer.cpp \ ProfileConformanceAnalyzer.cpp \ + VideoParser.cpp \ + UnifiedCommonInfoViewer.cpp \ + UnifiedWarningsViewer.cpp \ ../common/ConvToString.cpp \ ../../external/QHexView/src/QHexView.cpp -LIBS += -lhevcparser +LIBS += -lhevcparser -lh264parser QMAKE_LIBDIR += ../../build diff --git a/utils/hevc_es_browser_gui/hevc_es_browser_gui.pro.user b/utils/hevc_es_browser_gui/hevc_es_browser_gui.pro.user new file mode 100644 index 0000000..943e413 --- /dev/null +++ b/utils/hevc_es_browser_gui/hevc_es_browser_gui.pro.user @@ -0,0 +1,226 @@ + + + + + + EnvironmentId + {209abd5b-fe0c-4aee-a967-9dea9fa52ed4} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + true + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 0 + 80 + true + true + 1 + 0 + false + true + false + 2 + true + true + 0 + 8 + true + false + 1 + true + true + true + *.md, *.MD, Makefile + false + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + false + + + 0 + true + + true + true + Builtin.DefaultTidyAndClazy + 6 + true + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + true + Qt 5.15.17 (mingw64) + Qt 5.15.17 (mingw64) + {7d8c090f-b0db-47ab-85bd-32d28381c02d} + 0 + 0 + 0 + + D:\my_project\code\hevcesbrowser\utils\hevc_es_browser_gui + D:/my_project/code/hevcesbrowser/utils/hevc_es_browser_gui + + + true + QtProjectManager.QMakeBuildStep + true + + + + true + Qt4ProjectManager.MakeStep + D:\msys64\mingw64\bin\mingw32-make.exe + + 2 + 构建 + 构建 + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + D:\msys64\mingw64\bin\mingw32-make.exe + + 1 + 清除 + 清除 + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release (imported) + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + + 0 + 部署 + 部署 + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph "dwarf,4096" -F 250 + + Qt4ProjectManager.Qt4RunConfiguration: + D:/my_project/code/hevcesbrowser/utils/hevc_es_browser_gui/hevc_es_browser_gui.pro + false + true + true + true + D:/my_project/code/hevcesbrowser/utils/hevc_es_browser_gui/../../build + + 1 + 0 + + 1 + + + 0 + 部署 + 部署 + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + 0 + true + + 2 + + false + -e cpu-cycles --call-graph "dwarf,4096" -F 250 + + Qt4ProjectManager.Qt4RunConfiguration: + D:/my_project/code/hevcesbrowser/utils/hevc_es_browser_gui/hevc_es_browser_gui.pro + false + true + true + true + D:/my_project/code/hevcesbrowser/utils/hevc_es_browser_gui/../../build + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/utils/hevc_es_browser_gui/test_include.cpp b/utils/hevc_es_browser_gui/test_include.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d419480bdf43c745e9b2656b8fbebe3d14da387 GIT binary patch literal 54 zcmezWPnjW;A&()MA%~%qA%!88L4iSuAq*%6V&^jiFeEY*F%$#YMGSfj89+H+1}+8w DUtbD( literal 0 HcmV?d00001 diff --git a/utils/video_es_browser_console/CMakeLists.txt b/utils/video_es_browser_console/CMakeLists.txt new file mode 100644 index 0000000..a04845e --- /dev/null +++ b/utils/video_es_browser_console/CMakeLists.txt @@ -0,0 +1,29 @@ +project(videoesbrowser_console) + +set(SOURCES + src/main.cpp + src/VideoInfoWriter.cpp + src/H264InfoWriter.cpp + ../hevc_es_browser_console/src/HEVCInfoWriter.cpp + ../common/ConvToString.cpp +) + +find_package(Boost COMPONENTS program_options system REQUIRED) + +include_directories( + ${Boost_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR}/../../hevcparser/include/ + ${CMAKE_CURRENT_SOURCE_DIR}/../../h264parser/include/ + ${CMAKE_CURRENT_SOURCE_DIR}/../common/ + ${CMAKE_CURRENT_SOURCE_DIR}/../hevc_es_browser_console/src/ +) + +set(LIBS + hevcparser + h264parser + ${Boost_LIBRARIES} +) + +add_executable(videoesbrowser_console ${SOURCES}) +target_link_libraries(videoesbrowser_console ${LIBS}) +add_dependencies(videoesbrowser_console hevcparser h264parser) \ No newline at end of file diff --git a/utils/video_es_browser_console/src/H264InfoWriter.cpp b/utils/video_es_browser_console/src/H264InfoWriter.cpp new file mode 100644 index 0000000..06c4870 --- /dev/null +++ b/utils/video_es_browser_console/src/H264InfoWriter.cpp @@ -0,0 +1,220 @@ +#include "H264InfoWriter.h" + +#include +#include + +#include + +using namespace H264; + +void H264InfoWriter::onNALUnit(std::shared_ptr pNALUnit, const H264::Parser::Info *pInfo) +{ + NALUInfo nalUInfo; + + nalUInfo.m_pNALUnit = pNALUnit; + nalUInfo.m_info = *pInfo; + m_nalus.push_back(nalUInfo); +} + +void H264InfoWriter::write(std::ostream &out) +{ + out << "H.264 Syntax elements (count = " << m_nalus.size() << "):" << std::endl; + for(std::size_t i=0; i m_nalHeader.nal_unit_type) + { + case NAL_SPS: + { + std::shared_ptr pSPS = std::dynamic_pointer_cast(m_nalus[i].m_pNALUnit); + writeSPS(pSPS, out); + m_spsMap[pSPS -> seq_parameter_set_id] = pSPS; + break; + } + + case NAL_PPS: + { + std::shared_ptr pPPS = std::dynamic_pointer_cast(m_nalus[i].m_pNALUnit); + writePPS(pPPS, out); + m_ppsMap[pPPS -> pic_parameter_set_id] = pPPS; + break; + } + + case NAL_SLICE: + case NAL_IDR_SLICE: + { + writeSlice(std::dynamic_pointer_cast(m_nalus[i].m_pNALUnit), out); + break; + } + + case NAL_AUD: + { + std::shared_ptr pAUD = std::dynamic_pointer_cast(m_nalus[i].m_pNALUnit); + writeAUD(pAUD, out); + break; + } + + case NAL_SEI: + { + writeSEI(std::dynamic_pointer_cast(m_nalus[i].m_pNALUnit), out); + break; + } + }; + out << std::endl; + } +} + +void H264InfoWriter::writeNALHeader(const NALUInfo& naluInfo, std::ostream &out) +{ + out << std::hex << "0x" << naluInfo.m_info.m_position << std::dec << ": "; + out << H264Utils::NALUnitTypeToString(naluInfo.m_pNALUnit -> m_nalHeader.nal_unit_type) << std::endl; +} + +void H264InfoWriter::writeSPS(std::shared_ptr pSPS, std::ostream &out) +{ + out << "\t" << "profile_idc = " << (int) pSPS -> profile_idc << " (" << H264Utils::ProfileToString(pSPS -> profile_idc) << ")" << std::endl; + out << "\t" << "constraint_set0_flag = " << (int) pSPS -> constraint_set0_flag << std::endl; + out << "\t" << "constraint_set1_flag = " << (int) pSPS -> constraint_set1_flag << std::endl; + out << "\t" << "constraint_set2_flag = " << (int) pSPS -> constraint_set2_flag << std::endl; + out << "\t" << "constraint_set3_flag = " << (int) pSPS -> constraint_set3_flag << std::endl; + out << "\t" << "constraint_set4_flag = " << (int) pSPS -> constraint_set4_flag << std::endl; + out << "\t" << "constraint_set5_flag = " << (int) pSPS -> constraint_set5_flag << std::endl; + out << "\t" << "level_idc = " << (int) pSPS -> level_idc << " (" << H264Utils::LevelToString(pSPS -> level_idc) << ")" << std::endl; + out << "\t" << "seq_parameter_set_id = " << (int) pSPS -> seq_parameter_set_id << std::endl; + out << "\t" << "chroma_format_idc = " << (int) pSPS -> chroma_format_idc << std::endl; + + if(pSPS -> chroma_format_idc == 3) + out << "\t" << "separate_colour_plane_flag = " << (int) pSPS -> separate_colour_plane_flag << std::endl; + + out << "\t" << "bit_depth_luma_minus8 = " << (int) pSPS -> bit_depth_luma_minus8 << std::endl; + out << "\t" << "bit_depth_chroma_minus8 = " << (int) pSPS -> bit_depth_chroma_minus8 << std::endl; + out << "\t" << "log2_max_frame_num_minus4 = " << (int) pSPS -> log2_max_frame_num_minus4 << std::endl; + out << "\t" << "pic_order_cnt_type = " << (int) pSPS -> pic_order_cnt_type << std::endl; + + if(pSPS -> pic_order_cnt_type == 0) + out << "\t" << "log2_max_pic_order_cnt_lsb_minus4 = " << (int) pSPS -> log2_max_pic_order_cnt_lsb_minus4 << std::endl; + else if(pSPS -> pic_order_cnt_type == 1) + { + out << "\t" << "delta_pic_order_always_zero_flag = " << (int) pSPS -> delta_pic_order_always_zero_flag << std::endl; + out << "\t" << "offset_for_non_ref_pic = " << (int) pSPS -> offset_for_non_ref_pic << std::endl; + out << "\t" << "offset_for_top_to_bottom_field = " << (int) pSPS -> offset_for_top_to_bottom_field << std::endl; + out << "\t" << "num_ref_frames_in_pic_order_cnt_cycle = " << (int) pSPS -> num_ref_frames_in_pic_order_cnt_cycle << std::endl; + } + + out << "\t" << "max_num_ref_frames = " << (int) pSPS -> max_num_ref_frames << std::endl; + out << "\t" << "gaps_in_frame_num_value_allowed_flag = " << (int) pSPS -> gaps_in_frame_num_value_allowed_flag << std::endl; + out << "\t" << "pic_width_in_mbs_minus1 = " << (int) pSPS -> pic_width_in_mbs_minus1 << std::endl; + out << "\t" << "pic_height_in_map_units_minus1 = " << (int) pSPS -> pic_height_in_map_units_minus1 << std::endl; + out << "\t" << "frame_mbs_only_flag = " << (int) pSPS -> frame_mbs_only_flag << std::endl; + + if(!pSPS -> frame_mbs_only_flag) + out << "\t" << "mb_adaptive_frame_field_flag = " << (int) pSPS -> mb_adaptive_frame_field_flag << std::endl; + + out << "\t" << "direct_8x8_inference_flag = " << (int) pSPS -> direct_8x8_inference_flag << std::endl; + out << "\t" << "frame_cropping_flag = " << (int) pSPS -> frame_cropping_flag << std::endl; + + if(pSPS -> frame_cropping_flag) + { + out << "\t" << "frame_crop_left_offset = " << (int) pSPS -> frame_crop_left_offset << std::endl; + out << "\t" << "frame_crop_right_offset = " << (int) pSPS -> frame_crop_right_offset << std::endl; + out << "\t" << "frame_crop_top_offset = " << (int) pSPS -> frame_crop_top_offset << std::endl; + out << "\t" << "frame_crop_bottom_offset = " << (int) pSPS -> frame_crop_bottom_offset << std::endl; + } + + out << "\t" << "vui_parameters_present_flag = " << (int) pSPS -> vui_parameters_present_flag << std::endl; + + if(pSPS -> vui_parameters_present_flag) + writeVuiParameters(pSPS -> vui_parameters, out, "\t"); +} + +void H264InfoWriter::writePPS(std::shared_ptr pPPS, std::ostream &out) +{ + out << "\t" << "pic_parameter_set_id = " << (int) pPPS -> pic_parameter_set_id << std::endl; + out << "\t" << "seq_parameter_set_id = " << (int) pPPS -> seq_parameter_set_id << std::endl; + out << "\t" << "entropy_coding_mode_flag = " << (int) pPPS -> entropy_coding_mode_flag << std::endl; + out << "\t" << "bottom_field_pic_order_in_frame_present_flag = " << (int) pPPS -> bottom_field_pic_order_in_frame_present_flag << std::endl; + out << "\t" << "num_slice_groups_minus1 = " << (int) pPPS -> num_slice_groups_minus1 << std::endl; + out << "\t" << "num_ref_idx_l0_default_active_minus1 = " << (int) pPPS -> num_ref_idx_l0_default_active_minus1 << std::endl; + out << "\t" << "num_ref_idx_l1_default_active_minus1 = " << (int) pPPS -> num_ref_idx_l1_default_active_minus1 << std::endl; + out << "\t" << "weighted_pred_flag = " << (int) pPPS -> weighted_pred_flag << std::endl; + out << "\t" << "weighted_bipred_idc = " << (int) pPPS -> weighted_bipred_idc << std::endl; + out << "\t" << "pic_init_qp_minus26 = " << (int) pPPS -> pic_init_qp_minus26 << std::endl; + out << "\t" << "pic_init_qs_minus26 = " << (int) pPPS -> pic_init_qs_minus26 << std::endl; + out << "\t" << "chroma_qp_index_offset = " << (int) pPPS -> chroma_qp_index_offset << std::endl; + out << "\t" << "deblocking_filter_control_present_flag = " << (int) pPPS -> deblocking_filter_control_present_flag << std::endl; + out << "\t" << "constrained_intra_pred_flag = " << (int) pPPS -> constrained_intra_pred_flag << std::endl; + out << "\t" << "redundant_pic_cnt_present_flag = " << (int) pPPS -> redundant_pic_cnt_present_flag << std::endl; +} + +void H264InfoWriter::writeSlice(std::shared_ptr pSlice, std::ostream &out) +{ + out << "\t" << "first_mb_in_slice = " << (int) pSlice -> first_mb_in_slice << std::endl; + out << "\t" << "slice_type = " << (int) pSlice -> slice_type << " (" << H264Utils::SliceTypeToString((Slice::SliceType)(pSlice -> slice_type % 5)) << ")" << std::endl; + out << "\t" << "pic_parameter_set_id = " << (int) pSlice -> pic_parameter_set_id << std::endl; + out << "\t" << "frame_num = " << (int) pSlice -> frame_num << std::endl; + + if(pSlice -> m_nalHeader.nal_unit_type == NAL_IDR_SLICE) + out << "\t" << "idr_pic_id = " << (int) pSlice -> idr_pic_id << std::endl; +} + +void H264InfoWriter::writeAUD(std::shared_ptr pAUD, std::ostream &out) +{ + out << "\t" << "primary_pic_type = " << (int) pAUD -> primary_pic_type << std::endl; +} + +void H264InfoWriter::writeSEI(std::shared_ptr pSEI, std::ostream &out) +{ + out << "\t" << "SEI payload size = " << pSEI -> sei_payload.size() << " bytes" << std::endl; +} + +void H264InfoWriter::writeVuiParameters(const H264::VuiParameters &vui, std::ostream &out, const std::string &prefix) +{ + out << prefix << "aspect_ratio_info_present_flag = " << (int) vui.aspect_ratio_info_present_flag << std::endl; + if(vui.aspect_ratio_info_present_flag) + { + out << prefix << "aspect_ratio_idc = " << (int) vui.aspect_ratio_idc << std::endl; + if(vui.aspect_ratio_idc == 255) + { + out << prefix << "sar_width = " << (int) vui.sar_width << std::endl; + out << prefix << "sar_height = " << (int) vui.sar_height << std::endl; + } + } + + out << prefix << "overscan_info_present_flag = " << (int) vui.overscan_info_present_flag << std::endl; + if(vui.overscan_info_present_flag) + out << prefix << "overscan_appropriate_flag = " << (int) vui.overscan_appropriate_flag << std::endl; + + out << prefix << "video_signal_type_present_flag = " << (int) vui.video_signal_type_present_flag << std::endl; + if(vui.video_signal_type_present_flag) + { + out << prefix << "video_format = " << (int) vui.video_format << std::endl; + out << prefix << "video_full_range_flag = " << (int) vui.video_full_range_flag << std::endl; + out << prefix << "colour_description_present_flag = " << (int) vui.colour_description_present_flag << std::endl; + if(vui.colour_description_present_flag) + { + out << prefix << "colour_primaries = " << (int) vui.colour_primaries << std::endl; + out << prefix << "transfer_characteristics = " << (int) vui.transfer_characteristics << std::endl; + out << prefix << "matrix_coefficients = " << (int) vui.matrix_coefficients << std::endl; + } + } + + out << prefix << "timing_info_present_flag = " << (int) vui.timing_info_present_flag << std::endl; + if(vui.timing_info_present_flag) + { + out << prefix << "num_units_in_tick = " << (int) vui.num_units_in_tick << std::endl; + out << prefix << "time_scale = " << (int) vui.time_scale << std::endl; + out << prefix << "fixed_frame_rate_flag = " << (int) vui.fixed_frame_rate_flag << std::endl; + } +} + +void H264InfoWriter::writeHrdParameters(const H264::HrdParameters &hrd, std::ostream &out, const std::string &prefix) +{ + out << prefix << "cpb_cnt_minus1 = " << (int) hrd.cpb_cnt_minus1 << std::endl; + out << prefix << "bit_rate_scale = " << (int) hrd.bit_rate_scale << std::endl; + out << prefix << "cpb_size_scale = " << (int) hrd.cpb_size_scale << std::endl; + out << prefix << "initial_cpb_removal_delay_length_minus1 = " << (int) hrd.initial_cpb_removal_delay_length_minus1 << std::endl; + out << prefix << "cpb_removal_delay_length_minus1 = " << (int) hrd.cpb_removal_delay_length_minus1 << std::endl; + out << prefix << "dpb_output_delay_length_minus1 = " << (int) hrd.dpb_output_delay_length_minus1 << std::endl; + out << prefix << "time_offset_length = " << (int) hrd.time_offset_length << std::endl; +} \ No newline at end of file diff --git a/utils/video_es_browser_console/src/H264InfoWriter.h b/utils/video_es_browser_console/src/H264InfoWriter.h new file mode 100644 index 0000000..600f3b6 --- /dev/null +++ b/utils/video_es_browser_console/src/H264InfoWriter.h @@ -0,0 +1,44 @@ +#ifndef H264_INFO_WRITER_H_ +#define H264_INFO_WRITER_H_ + +#include + +#include +#include +#include + +class H264InfoWriter: public H264::Parser::Consumer +{ + public: + virtual void onNALUnit(std::shared_ptr pNALUnit, const H264::Parser::Info *pInfo); + virtual void onWarning(const std::string &warning, const H264::Parser::Info *pInfo, H264::Parser::WarningType) {}; + + void write(std::ostream &out); + + protected: + + struct NALUInfo + { + std::shared_ptr m_pNALUnit; + H264::Parser::Info m_info; + }; + + virtual void writeNALHeader(const NALUInfo& naluInfo, std::ostream &out); + virtual void writeSPS(std::shared_ptr pSPS, std::ostream &out); + virtual void writePPS(std::shared_ptr pPPS, std::ostream &out); + virtual void writeSlice(std::shared_ptr pSlice, std::ostream &out); + virtual void writeAUD(std::shared_ptr pAUD, std::ostream &out); + virtual void writeSEI(std::shared_ptr pSEI, std::ostream &out); + + virtual void writeVuiParameters(const H264::VuiParameters &vui, std::ostream &out, const std::string &prefix); + virtual void writeHrdParameters(const H264::HrdParameters &hrd, std::ostream &out, const std::string &prefix); + + std::vector m_nalus; + + std::map > m_spsMap; + std::map > m_ppsMap; + +}; + + +#endif \ No newline at end of file diff --git a/utils/video_es_browser_console/src/VideoInfoWriter.cpp b/utils/video_es_browser_console/src/VideoInfoWriter.cpp new file mode 100644 index 0000000..0389ab1 --- /dev/null +++ b/utils/video_es_browser_console/src/VideoInfoWriter.cpp @@ -0,0 +1,208 @@ +#include "VideoInfoWriter.h" +#include "H264InfoWriter.h" +#include "../../hevc_es_browser_console/src/HEVCInfoWriter.h" + +#include +#include + +#include +#include + +VideoInfoWriter::VideoInfoWriter() + : m_detectedCodec(CODEC_UNKNOWN) + , m_h264Writer(nullptr) + , m_hevcWriter(nullptr) +{ +} + +VideoInfoWriter::~VideoInfoWriter() +{ + if(m_h264Writer) + delete static_cast(m_h264Writer); + if(m_hevcWriter) + delete static_cast(m_hevcWriter); +} + +bool VideoInfoWriter::analyzeFile(const std::string &filename) +{ + std::ifstream in(filename.c_str(), std::ios_base::binary); + if(!in.good()) + { + std::cerr << "Cannot open file: " << filename << std::endl; + return false; + } + + in.seekg(0, std::ios::end); + std::size_t size = in.tellg(); + in.seekg(0, std::ios::beg); + + if(size == 0) + { + std::cerr << "File is empty: " << filename << std::endl; + return false; + } + + char *pdata = new char[size]; + if(!pdata) + { + std::cerr << "Memory allocation failed" << std::endl; + return false; + } + + in.read(pdata, size); + std::size_t actualSize = in.gcount(); + + // Detect codec + m_detectedCodec = detectCodec((const uint8_t*)pdata, actualSize); + + bool success = false; + switch(m_detectedCodec) + { + case CODEC_H264: + success = analyzeH264((const uint8_t*)pdata, actualSize); + break; + case CODEC_HEVC: + success = analyzeHEVC((const uint8_t*)pdata, actualSize); + break; + default: + std::cerr << "Unknown or unsupported codec" << std::endl; + break; + } + + delete[] pdata; + return success; +} + +VideoCodec VideoInfoWriter::detectCodec(const uint8_t *data, std::size_t size) +{ + // Look for NAL unit start codes and analyze the first few NAL units + for(std::size_t pos = 0; pos + 4 < size; pos++) + { + bool naluFound = false; + std::size_t startOffset = 0; + + if(data[pos] == 0 && data[pos+1] == 0 && data[pos+2] == 1) + { + naluFound = true; + startOffset = 3; + } + else if(data[pos] == 0 && data[pos+1] == 0 && data[pos+2] == 0 && data[pos+3] == 1) + { + naluFound = true; + startOffset = 4; + } + + if(naluFound && pos + startOffset < size) + { + uint8_t nalHeader = data[pos + startOffset]; + + // H.264 NAL unit type is in bits 0-4 + uint8_t h264NalType = nalHeader & 0x1F; + + // HEVC NAL unit type is in bits 1-6 (shifted right by 1) + uint8_t hevcNalType = (nalHeader >> 1) & 0x3F; + + // Check for H.264 specific NAL types + if(h264NalType == 7 || h264NalType == 8 || h264NalType == 5 || h264NalType == 1) + { + return CODEC_H264; + } + + // Check for HEVC specific NAL types + if(hevcNalType == 32 || hevcNalType == 33 || hevcNalType == 34 || + hevcNalType == 19 || hevcNalType == 20 || hevcNalType == 21) + { + return CODEC_HEVC; + } + } + } + + return CODEC_UNKNOWN; +} + +bool VideoInfoWriter::analyzeH264(const uint8_t *data, std::size_t size) +{ + H264::Parser *pparser = H264::Parser::create(); + if(!pparser) + return false; + + m_h264Writer = new H264InfoWriter(); + H264InfoWriter* writer = static_cast(m_h264Writer); + + pparser->addConsumer(writer); + + try + { + pparser->process(data, size); + } + catch(const std::exception& e) + { + std::cerr << "H.264 parsing error: " << e.what() << std::endl; + pparser->releaseConsumer(writer); + H264::Parser::release(pparser); + return false; + } + + pparser->releaseConsumer(writer); + H264::Parser::release(pparser); + return true; +} + +bool VideoInfoWriter::analyzeHEVC(const uint8_t *data, std::size_t size) +{ + HEVC::Parser *pparser = HEVC::Parser::create(); + if(!pparser) + return false; + + m_hevcWriter = new HEVCInfoWriter(); + HEVCInfoWriter* writer = static_cast(m_hevcWriter); + + pparser->addConsumer(writer); + + try + { + pparser->process(data, size); + } + catch(const std::exception& e) + { + std::cerr << "HEVC parsing error: " << e.what() << std::endl; + pparser->releaseConsumer(writer); + HEVC::Parser::release(pparser); + return false; + } + + pparser->releaseConsumer(writer); + HEVC::Parser::release(pparser); + return true; +} + +void VideoInfoWriter::writeAnalysis(std::ostream &out, const std::string &filename) +{ + out << filename << std::endl; + out << "=======================" << std::endl; + + switch(m_detectedCodec) + { + case CODEC_H264: + out << "Detected codec: H.264/AVC" << std::endl; + if(m_h264Writer) + { + H264InfoWriter* writer = static_cast(m_h264Writer); + writer->write(out); + } + break; + + case CODEC_HEVC: + out << "Detected codec: H.265/HEVC" << std::endl; + if(m_hevcWriter) + { + HEVCInfoWriter* writer = static_cast(m_hevcWriter); + writer->write(out); + } + break; + + default: + out << "Unknown or unsupported codec" << std::endl; + break; + } +} \ No newline at end of file diff --git a/utils/video_es_browser_console/src/VideoInfoWriter.h b/utils/video_es_browser_console/src/VideoInfoWriter.h new file mode 100644 index 0000000..c8bb3b4 --- /dev/null +++ b/utils/video_es_browser_console/src/VideoInfoWriter.h @@ -0,0 +1,34 @@ +#ifndef VIDEO_INFO_WRITER_H_ +#define VIDEO_INFO_WRITER_H_ + +#include +#include +#include + +enum VideoCodec +{ + CODEC_UNKNOWN, + CODEC_H264, + CODEC_HEVC +}; + +class VideoInfoWriter +{ +public: + VideoInfoWriter(); + ~VideoInfoWriter(); + + bool analyzeFile(const std::string &filename); + void writeAnalysis(std::ostream &out, const std::string &filename); + +private: + VideoCodec detectCodec(const uint8_t *data, std::size_t size); + bool analyzeH264(const uint8_t *data, std::size_t size); + bool analyzeHEVC(const uint8_t *data, std::size_t size); + + VideoCodec m_detectedCodec; + void* m_h264Writer; + void* m_hevcWriter; +}; + +#endif \ No newline at end of file diff --git a/utils/video_es_browser_console/src/main.cpp b/utils/video_es_browser_console/src/main.cpp new file mode 100644 index 0000000..40b86c6 --- /dev/null +++ b/utils/video_es_browser_console/src/main.cpp @@ -0,0 +1,91 @@ +#include +#include + +#include + +#include "VideoInfoWriter.h" + +int main(int argc, char **argv) +{ + namespace po = boost::program_options; + try + { + po::options_description desc("Video Elementary Stream Browser - Supports both H.264 and H.265/HEVC"); + desc.add_options() + ("help,h", "produce help message") + ("input,i", po::value(), "path to input video elementary stream file") + ("output,o", po::value(), "path to output analysis file (optional, defaults to stdout)") + ; + + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.count("help")) + { + std::cout << desc << "\n"; + std::cout << "\nSupported formats:\n"; + std::cout << " - H.264/AVC elementary streams (.h264, .264)\n"; + std::cout << " - H.265/HEVC elementary streams (.h265, .hevc)\n"; + std::cout << "\nExample usage:\n"; + std::cout << " " << argv[0] << " -i video.h264\n"; + std::cout << " " << argv[0] << " -i video.hevc -o analysis.txt\n"; + return 0; + } + + if(!vm.count("input")) + { + std::cerr << "Error: Input file is required.\n\n"; + std::cout << desc << "\n"; + return 1; + } + + std::string inputFile = vm["input"].as(); + + std::ostream *pout = &std::cout; + std::ofstream fileOut; + + if(vm.count("output")) + { + std::string outputFile = vm["output"].as(); + fileOut.open(outputFile.c_str()); + if(!fileOut.good()) + { + std::cerr << "Error: Cannot open output file '" << outputFile << "' for writing" << std::endl; + return 2; + } + pout = &fileOut; + } + + VideoInfoWriter analyzer; + + std::cout << "Analyzing file: " << inputFile << std::endl; + std::cout << "Detecting codec..." << std::endl; + + if(!analyzer.analyzeFile(inputFile)) + { + std::cerr << "Error: Failed to analyze file '" << inputFile << "'" << std::endl; + return 3; + } + + std::cout << "Analysis complete. Writing results..." << std::endl; + analyzer.writeAnalysis(*pout, inputFile); + + if(vm.count("output")) + { + std::cout << "Results written to: " << vm["output"].as() << std::endl; + } + } + catch(std::exception& e) + { + std::cerr << "Error: " << e.what() << "\n"; + return 1; + } + catch(...) + { + std::cerr << "Unknown error occurred!\n"; + return 1; + } + + return 0; +} \ No newline at end of file