Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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()
35 changes: 33 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -36,6 +50,7 @@ Building requirements:
Building:
-----

```bash
cd hevcesbrowser

git submodule init && git submodule update
Expand All @@ -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

35 changes: 35 additions & 0 deletions h264parser/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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()
268 changes: 268 additions & 0 deletions h264parser/include/H264.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
#ifndef H264_H_
#define H264_H_

#include <memory>
#include <vector>
#include <array>
#include <cstdint>
#include <cstddef>

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<uint32_t> bit_rate_value_minus1;
std::vector<uint32_t> cpb_size_value_minus1;
std::vector<uint8_t> 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<NALUnit> 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<int32_t> 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<uint32_t> run_length_minus1;
std::vector<uint32_t> top_left;
std::vector<uint32_t> 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<uint32_t> 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<int32_t> 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<uint8_t> sei_payload;
void toDefault();
};

}

#endif
Loading