├── .gitignore ├── CMakeLists.txt ├── EyerH264Decoder ├── AnnexBReader.cpp ├── AnnexBReader.hpp ├── BitStream.cpp ├── BitStream.hpp ├── CMakeLists.txt ├── EBSP.cpp ├── EBSP.hpp ├── Main.cpp ├── Nalu.cpp ├── Nalu.hpp ├── NaluPPS.cpp ├── NaluPPS.hpp ├── NaluSPS.cpp ├── NaluSPS.hpp ├── RBSP.cpp └── RBSP.hpp ├── LICENSE ├── README.md ├── REAddTag.sh └── demo_video_176x144_baseline.h264 /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeLists.txt.user 2 | CMakeCache.txt 3 | CMakeFiles 4 | CMakeScripts 5 | Testing 6 | Makefile 7 | cmake_install.cmake 8 | install_manifest.txt 9 | compile_commands.json 10 | CTestTestfile.cmake 11 | _deps 12 | 13 | .DS_Store 14 | .idea/ 15 | cmake-build-debug/ -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.0) 2 | 3 | PROJECT(EyerH264Deocder 4 | VERSION 1.0.0.0 5 | ) 6 | 7 | message( STATUS "CMAKE_PROJECT_NAME = ${CMAKE_PROJECT_NAME}" ) 8 | message( STATUS "PROJECT_VERSION_MAJOR = ${PROJECT_VERSION_MAJOR}" ) 9 | message( STATUS "PROJECT_VERSION_MINOR = ${PROJECT_VERSION_MINOR}" ) 10 | message( STATUS "PROJECT_VERSION_PATCH = ${PROJECT_VERSION_PATCH}" ) 11 | message( STATUS "PROJECT_VERSION_TWEAK = ${PROJECT_VERSION_TWEAK}" ) 12 | message( STATUS "PROJECT_HOMEPAGE_URL = ${PROJECT_HOMEPAGE_URL}") 13 | message( STATUS "CMAKE_PROJECT_DESCRIPTION = ${CMAKE_PROJECT_DESCRIPTION}" ) 14 | 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 16 | 17 | MESSAGE(STATUS "operation system is ${CMAKE_SYSTEM}") 18 | 19 | SET(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install/) 20 | 21 | IF (CMAKE_SYSTEM_NAME MATCHES "Linux") 22 | MESSAGE(STATUS "current platform: Linux ") 23 | ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Windows") 24 | MESSAGE(STATUS "current platform: Windows") 25 | ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Android") 26 | MESSAGE(STATUS "current platform: Android") 27 | ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Darwin") 28 | MESSAGE(STATUS "current platform: Darwin") 29 | ELSEIF (CMAKE_SYSTEM_NAME MATCHES "Emscripten") 30 | MESSAGE(STATUS "current platform: Emscripten") 31 | ELSE () 32 | MESSAGE(STATUS "other platform: ${CMAKE_SYSTEM_NAME}") 33 | ENDIF (CMAKE_SYSTEM_NAME MATCHES "Linux") 34 | 35 | ADD_SUBDIRECTORY(EyerH264Decoder) -------------------------------------------------------------------------------- /EyerH264Decoder/AnnexBReader.cpp: -------------------------------------------------------------------------------- 1 | #include "AnnexBReader.hpp" 2 | 3 | AnnexBReader::AnnexBReader(const std::string & _filePath) 4 | { 5 | filePath = _filePath; 6 | } 7 | 8 | AnnexBReader::~AnnexBReader() 9 | { 10 | Close(); 11 | } 12 | 13 | // 用来打开文件 14 | int AnnexBReader::Open() 15 | { 16 | f = fopen(filePath.c_str(), "rb"); 17 | if(f == nullptr){ 18 | return -1; 19 | } 20 | return 0; 21 | } 22 | 23 | // 用来关闭文件 24 | int AnnexBReader::Close() 25 | { 26 | if(f != nullptr){ 27 | fclose(f); 28 | f = nullptr; 29 | } 30 | if(buffer != nullptr){ 31 | free(buffer); 32 | buffer = nullptr; 33 | } 34 | return 0; 35 | } 36 | 37 | // 用来读取一个 Nalu 文件 38 | int AnnexBReader::ReadNalu(Nalu & nalu) 39 | { 40 | while(1){ 41 | if(bufferLen <= 0){ 42 | int readedLen = ReadFromFile(); 43 | if(readedLen <= 0){ 44 | isEnd = true; 45 | } 46 | } 47 | 48 | uint8_t * buf = buffer; 49 | 50 | int startCodeLen = 0; 51 | // Find Start Code 52 | bool isStartCode = CheckStartCode(startCodeLen, buf, bufferLen); 53 | if(!isStartCode){ 54 | break; 55 | } 56 | 57 | nalu.startCodeLen = startCodeLen; 58 | 59 | // Find End Code 60 | int endPos = -1; 61 | for(int i=2;i 0){ 71 | nalu.SetBuf(buffer, endPos); 72 | uint8_t * _buffer = (uint8_t*)malloc(bufferLen - endPos); 73 | 74 | memcpy(_buffer, buffer + endPos, bufferLen - endPos); 75 | 76 | if(buffer != nullptr){ 77 | free(buffer); 78 | buffer = nullptr; 79 | } 80 | buffer = _buffer; 81 | bufferLen = bufferLen - endPos; 82 | 83 | return 0; 84 | } 85 | else{ 86 | if(isEnd == true){ 87 | // 到达文件末尾,取所有 buffer 出来 88 | nalu.SetBuf(buffer, bufferLen); 89 | if(buffer != nullptr){ 90 | free(buffer); 91 | buffer = nullptr; 92 | } 93 | buffer = nullptr; 94 | bufferLen = 0; 95 | 96 | return 0; 97 | } 98 | int readedLen = ReadFromFile(); 99 | if(readedLen <= 0){ 100 | isEnd = true; 101 | } 102 | } 103 | } 104 | 105 | return -1; 106 | } 107 | 108 | int AnnexBReader::ReadFromFile() 109 | { 110 | int tempBufferLen = 1024; 111 | uint8_t * buf = (uint8_t *) malloc (tempBufferLen); 112 | int readedLen = fread(buf, 1, tempBufferLen, f); 113 | 114 | if(readedLen > 0){ 115 | // 将新读取的 buf 添加到旧的 buffer 之后 116 | uint8_t * _buffer = (uint8_t *) malloc (bufferLen + readedLen); 117 | memcpy(_buffer, buffer, bufferLen); 118 | memcpy(_buffer + bufferLen, buf, readedLen); 119 | bufferLen = bufferLen + readedLen; 120 | 121 | if(buffer != nullptr){ 122 | free(buffer); 123 | buffer = nullptr; 124 | } 125 | 126 | buffer = _buffer; 127 | } 128 | 129 | free(buf); 130 | 131 | return readedLen; 132 | } 133 | 134 | bool AnnexBReader::CheckStartCode(int & startCodeLen, uint8_t * bufPtr, int bufLen) 135 | { 136 | if(bufLen <= 2){ 137 | startCodeLen = 0; 138 | return false; 139 | } 140 | if(bufLen >= 4){ 141 | if(bufPtr[0] == 0) { 142 | if (bufPtr[1] == 0) { 143 | if (bufPtr[2] == 0) { 144 | if (bufPtr[3] == 1) { 145 | startCodeLen = 4; 146 | return true; 147 | } 148 | } 149 | if(bufPtr[2] == 1){ 150 | startCodeLen = 3; 151 | return true; 152 | } 153 | } 154 | } 155 | } 156 | if(bufLen <= 3){ 157 | if(bufPtr[0] == 0) { 158 | if (bufPtr[1] == 0) { 159 | if(bufPtr[2] == 1){ 160 | startCodeLen = 3; 161 | return true; 162 | } 163 | } 164 | } 165 | } 166 | 167 | startCodeLen = 0; 168 | return false; 169 | } -------------------------------------------------------------------------------- /EyerH264Decoder/AnnexBReader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EYERLIB_EYER_AVC_BLOG_ANNEXBREADER_HPP 2 | #define EYERLIB_EYER_AVC_BLOG_ANNEXBREADER_HPP 3 | 4 | #include 5 | #include 6 | 7 | #include "Nalu.hpp" 8 | 9 | class AnnexBReader 10 | { 11 | public: 12 | AnnexBReader(const std::string & _filePath); 13 | ~AnnexBReader(); 14 | 15 | // 用来打开文件 16 | int Open(); 17 | 18 | // 用来关闭文件 19 | int Close(); 20 | 21 | // 用来读取一个 Nalu 22 | int ReadNalu(Nalu & nalu); 23 | 24 | private: 25 | bool CheckStartCode(int & startCodeLen, uint8_t * bufPtr, int bufLen); 26 | int ReadFromFile(); 27 | 28 | std::string filePath; 29 | FILE * f = nullptr; 30 | 31 | bool isEnd = false; 32 | uint8_t * buffer = nullptr; 33 | int bufferLen = 0; 34 | }; 35 | 36 | #endif //EYERLIB_EYER_AVC_BLOG_ANNEXBREADER_HPP -------------------------------------------------------------------------------- /EyerH264Decoder/BitStream.cpp: -------------------------------------------------------------------------------- 1 | #include "BitStream.hpp" 2 | 3 | BitStream::BitStream(uint8_t * _buf, int _size) 4 | { 5 | start = _buf; 6 | p = _buf; 7 | size = _size; 8 | bits_left = 8; 9 | } 10 | 11 | BitStream::~BitStream() 12 | { 13 | 14 | } 15 | 16 | int BitStream::ReadU1() 17 | { 18 | int r = 0; 19 | bits_left--; 20 | r = ((*(p)) >> bits_left) & 0x01; 21 | if (bits_left == 0) { 22 | p++; 23 | bits_left = 8; 24 | } 25 | return r; 26 | } 27 | 28 | int BitStream::ReadU(int n) 29 | { 30 | int r = 0; 31 | int i; 32 | for (i = 0; i < n; i++) { 33 | r |= ( ReadU1() << ( n - i - 1 ) ); 34 | } 35 | return r; 36 | } 37 | 38 | int BitStream::ReadUE() 39 | { 40 | int r = 0; 41 | int i = 0; 42 | while((ReadU1() == 0) && (i < 32)){ 43 | i++; 44 | } 45 | r = ReadU(i); 46 | r += (1 << i) - 1; 47 | return r; 48 | } 49 | 50 | int BitStream::ReadSE() 51 | { 52 | int r = ReadUE(); 53 | if (r & 0x01) { 54 | r = (r+1)/2; 55 | } 56 | else { 57 | r = -(r/2); 58 | } 59 | return r; 60 | } -------------------------------------------------------------------------------- /EyerH264Decoder/BitStream.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EYERH264DEOCDER_BITSTREAM_HPP 2 | #define EYERH264DEOCDER_BITSTREAM_HPP 3 | 4 | #include 5 | #include 6 | 7 | class BitStream { 8 | public: 9 | /** 10 | * 构造函数可以传入一个 buffer,这里可以直接把 nalu 的 buffer 传入 11 | */ 12 | BitStream(uint8_t * buf, int size); 13 | ~BitStream(); 14 | 15 | int ReadU1(); 16 | int ReadU(int n); 17 | int ReadUE(); 18 | int ReadSE(); 19 | 20 | private: 21 | // 指向 buffer 开始的位置 22 | uint8_t * start = nullptr; 23 | 24 | // buffer 的长度(单位 Byte) 25 | int size = 0; 26 | 27 | // 当前读取到了哪个字节 28 | uint8_t * p = nullptr; 29 | 30 | // 当前读取到了字节中的第几位 31 | int bits_left = 8; 32 | }; 33 | 34 | #endif //EYERH264DEOCDER_BITSTREAM_HPP 35 | -------------------------------------------------------------------------------- /EyerH264Decoder/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | INCLUDE_DIRECTORIES (../) 2 | 3 | ADD_EXECUTABLE( 4 | EyerH264Decoder 5 | 6 | Main.cpp 7 | 8 | AnnexBReader.cpp 9 | AnnexBReader.hpp 10 | 11 | Nalu.hpp 12 | Nalu.cpp 13 | 14 | EBSP.hpp 15 | EBSP.cpp 16 | 17 | RBSP.hpp 18 | RBSP.cpp 19 | 20 | BitStream.hpp 21 | BitStream.cpp 22 | 23 | NaluSPS.hpp 24 | NaluSPS.cpp 25 | 26 | NaluPPS.hpp 27 | NaluPPS.cpp 28 | ) 29 | 30 | FILE(COPY 31 | ${CMAKE_CURRENT_SOURCE_DIR}/../demo_video_176x144_baseline.h264 32 | DESTINATION 33 | ${CMAKE_CURRENT_BINARY_DIR}/ 34 | ) 35 | 36 | INSTALL( 37 | TARGETS EyerH264Decoder 38 | RUNTIME DESTINATION bin 39 | LIBRARY DESTINATION lib 40 | ARCHIVE DESTINATION lib 41 | ) -------------------------------------------------------------------------------- /EyerH264Decoder/EBSP.cpp: -------------------------------------------------------------------------------- 1 | #include "EBSP.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | EBSP::EBSP() 8 | { 9 | 10 | } 11 | 12 | EBSP::~EBSP() 13 | { 14 | if(buf != nullptr){ 15 | free(buf); 16 | buf = nullptr; 17 | } 18 | } 19 | 20 | EBSP::EBSP(const EBSP & ebsp) 21 | { 22 | *this = ebsp; 23 | } 24 | 25 | EBSP & EBSP::operator = (const EBSP & ebsp) 26 | { 27 | if(buf != nullptr){ 28 | free(buf); 29 | buf = nullptr; 30 | } 31 | len = ebsp.len; 32 | buf = (uint8_t *)malloc(len); 33 | memcpy(buf, ebsp.buf, len); 34 | return *this; 35 | } 36 | 37 | int EBSP::GetRBSP(RBSP & rbsp) 38 | { 39 | rbsp.len = len; 40 | rbsp.buf = (uint8_t *)malloc(rbsp.len); 41 | 42 | int targetIndex = 0; 43 | for(int i=0; i 2){ 47 | if(buf[i - 1] == 0x00 && buf[i - 2] == 0x00){ 48 | // 判断 后一个是不是 0 1 2 3 49 | if(i < len - 1){ 50 | if(buf[i + 1] == 0x00 || buf[i + 1] == 0x01 || buf[i + 1] == 0x02 || buf[i + 1] == 0x03){ 51 | // 满足条件,该位置不进行拷贝 52 | rbsp.len--; 53 | continue; 54 | } 55 | } 56 | } 57 | } 58 | } 59 | rbsp.buf[targetIndex] = buf[i]; 60 | targetIndex++; 61 | } 62 | return 0; 63 | } -------------------------------------------------------------------------------- /EyerH264Decoder/EBSP.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EYERH264DEOCDER_EBSP_HPP 2 | #define EYERH264DEOCDER_EBSP_HPP 3 | 4 | #include 5 | 6 | #include "RBSP.hpp" 7 | 8 | class EBSP { 9 | public: 10 | EBSP(); 11 | ~EBSP(); 12 | 13 | EBSP(const EBSP & ebsp); 14 | EBSP & operator = (const EBSP & ebsp); 15 | 16 | int GetRBSP(RBSP & rbsp); 17 | 18 | public: 19 | uint8_t * buf = nullptr; 20 | int len = 0; 21 | }; 22 | 23 | #endif //EYERH264DEOCDER_EBSP_HPP 24 | -------------------------------------------------------------------------------- /EyerH264Decoder/Main.cpp: -------------------------------------------------------------------------------- 1 | #include "AnnexBReader.hpp" 2 | #include "EBSP.hpp" 3 | #include "RBSP.hpp" 4 | #include "BitStream.hpp" 5 | 6 | #include "NaluSPS.hpp" 7 | #include "NaluPPS.hpp" 8 | 9 | int main(int argc, char const *argv[]) 10 | { 11 | std::string filePath = "./demo_video_176x144_baseline.h264"; 12 | AnnexBReader reader(filePath); 13 | int ret = reader.Open(); 14 | if(ret){ 15 | printf("Read Fail"); 16 | return -1; 17 | } 18 | 19 | while(1){ 20 | Nalu nalu; 21 | ret = reader.ReadNalu(nalu); 22 | if(ret){ 23 | break; 24 | } 25 | 26 | nalu.ParseRBSP(); 27 | nalu.ParseHeader(); 28 | 29 | printf("Nalu Type: %d\n", nalu.GetNaluType()); 30 | 31 | if(nalu.GetNaluType() == 7){ 32 | NaluSPS sps = nalu; 33 | sps.Parse(); 34 | } 35 | if(nalu.GetNaluType() == 8){ 36 | NaluPPS pps = nalu; 37 | pps.Parse(); 38 | } 39 | } 40 | 41 | reader.Close(); 42 | 43 | return 0; 44 | } -------------------------------------------------------------------------------- /EyerH264Decoder/Nalu.cpp: -------------------------------------------------------------------------------- 1 | #include "Nalu.hpp" 2 | 3 | Nalu::Nalu() 4 | { 5 | 6 | } 7 | 8 | Nalu::Nalu(const Nalu & nalu) 9 | { 10 | *this = nalu; 11 | } 12 | 13 | Nalu & Nalu::operator = (const Nalu & nalu) 14 | { 15 | if(buf != nullptr){ 16 | free(buf); 17 | buf = nullptr; 18 | } 19 | 20 | startCodeLen = nalu.startCodeLen; 21 | len = nalu.len; 22 | buf = (uint8_t *)malloc(len); 23 | memcpy(buf, nalu.buf, len); 24 | 25 | forbidden_bit = nalu.forbidden_bit; 26 | nal_ref_idc = nalu.nal_ref_idc; 27 | nal_unit_type = nalu.nal_unit_type; 28 | 29 | rbsp = nalu.rbsp; 30 | 31 | return *this; 32 | } 33 | 34 | Nalu::~Nalu() 35 | { 36 | if(buf != nullptr){ 37 | free(buf); 38 | buf = nullptr; 39 | } 40 | } 41 | 42 | int Nalu::SetBuf(uint8_t * _buf, int _len) 43 | { 44 | if(buf != nullptr){ 45 | free(buf); 46 | buf = nullptr; 47 | } 48 | len = _len; 49 | 50 | buf = (uint8_t *)malloc(len); 51 | memcpy(buf, _buf, len); 52 | 53 | return 0; 54 | } 55 | 56 | int Nalu::GetEBSP(EBSP & ebsp) 57 | { 58 | ebsp.len = len - startCodeLen; 59 | ebsp.buf = (uint8_t *)malloc(ebsp.len); 60 | 61 | memcpy(ebsp.buf, buf + startCodeLen, ebsp.len); 62 | 63 | return 0; 64 | } 65 | 66 | int Nalu::ParseRBSP() 67 | { 68 | EBSP ebsp; 69 | int ret = GetEBSP(ebsp); 70 | if(ret){ 71 | return -1; 72 | } 73 | 74 | // 此处的 rbsp 是成员变量 75 | return ebsp.GetRBSP(rbsp); 76 | } 77 | 78 | int Nalu::ParseHeader() 79 | { 80 | uint8_t naluHead = rbsp.buf[0]; 81 | forbidden_bit = (naluHead >> 7) & 1; 82 | nal_ref_idc = (naluHead >> 5) & 3; 83 | nal_unit_type = (naluHead >> 0) & 0x1f; 84 | return 0; 85 | } 86 | 87 | int Nalu::GetNaluType() 88 | { 89 | return nal_unit_type; 90 | } 91 | 92 | int Nalu::Parse() 93 | { 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /EyerH264Decoder/Nalu.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EYERH264DEOCDER_NALU_HPP 2 | #define EYERH264DEOCDER_NALU_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "EBSP.hpp" 10 | 11 | class Nalu { 12 | public: 13 | Nalu(); 14 | Nalu(const Nalu & nalu); 15 | ~Nalu(); 16 | 17 | Nalu & operator = (const Nalu & nalu); 18 | 19 | int SetBuf(uint8_t * _buf, int _len); 20 | 21 | int GetEBSP(EBSP & ebsp); 22 | 23 | int ParseRBSP(); 24 | int ParseHeader(); 25 | 26 | int GetNaluType(); 27 | 28 | virtual int Parse(); 29 | 30 | public: 31 | uint8_t * buf = nullptr; 32 | int len = 0; 33 | int startCodeLen = 0; 34 | 35 | RBSP rbsp; 36 | 37 | int forbidden_bit = 0; 38 | int nal_ref_idc = 0; 39 | int nal_unit_type = 0; 40 | }; 41 | 42 | #endif //EYERH264DEOCDER_NALU_HPP 43 | -------------------------------------------------------------------------------- /EyerH264Decoder/NaluPPS.cpp: -------------------------------------------------------------------------------- 1 | #include "NaluPPS.hpp" 2 | 3 | #include "BitStream.hpp" 4 | 5 | NaluPPS::NaluPPS(const Nalu & nalu) 6 | : Nalu(nalu) 7 | { 8 | 9 | } 10 | 11 | int NaluPPS::Parse() 12 | { 13 | BitStream bs(rbsp.buf, rbsp.len); 14 | 15 | bs.ReadU(8); 16 | 17 | 18 | pic_parameter_set_id = bs.ReadUE(); 19 | seq_parameter_set_id = bs.ReadUE(); 20 | entropy_coding_mode_flag = bs.ReadU1(); 21 | pic_order_present_flag = bs.ReadU1(); 22 | num_slice_groups_minus1 = bs.ReadUE(); 23 | 24 | if(num_slice_groups_minus1 > 0) { 25 | slice_group_map_type = bs.ReadUE(); 26 | if(slice_group_map_type == 0) { 27 | for(int i_group = 0; i_group <= num_slice_groups_minus1; i_group++){ 28 | run_length_minus1[i_group] = bs.ReadUE(); 29 | } 30 | } 31 | else if(slice_group_map_type == 2) { 32 | for(int i_group = 0; i_group < num_slice_groups_minus1; i_group++) { 33 | top_left[ i_group ] = bs.ReadUE(); 34 | bottom_right[ i_group ] = bs.ReadUE(); 35 | } 36 | } 37 | else if( slice_group_map_type == 3 || 38 | slice_group_map_type == 4 || 39 | slice_group_map_type == 5 ) 40 | { 41 | slice_group_change_direction_flag = bs.ReadU1(); 42 | slice_group_change_rate_minus1 = bs.ReadUE(); 43 | } 44 | else if(slice_group_map_type == 6) { 45 | pic_size_in_map_units_minus1 = bs.ReadUE(); 46 | for( int i = 0; i <= pic_size_in_map_units_minus1; i++ ) { 47 | int v = intlog2( num_slice_groups_minus1 + 1 ); 48 | slice_group_id[i] = bs.ReadU(v); 49 | } 50 | } 51 | } 52 | 53 | num_ref_idx_l0_active_minus1 = bs.ReadUE(); 54 | num_ref_idx_l1_active_minus1 = bs.ReadUE(); 55 | weighted_pred_flag = bs.ReadU1(); 56 | weighted_bipred_idc = bs.ReadU(2); 57 | pic_init_qp_minus26 = bs.ReadSE(); 58 | pic_init_qs_minus26 = bs.ReadSE(); 59 | chroma_qp_index_offset = bs.ReadSE(); 60 | deblocking_filter_control_present_flag = bs.ReadU1(); 61 | constrained_intra_pred_flag = bs.ReadU1(); 62 | redundant_pic_cnt_present_flag = bs.ReadU1(); 63 | 64 | // TODO more_rbsp_data 65 | /* 66 | if(bs.more_data()) { 67 | transform_8x8_mode_flag = bs.bs_read_u1(); 68 | pic_scaling_matrix_present_flag = bs.bs_read_u1(); 69 | if(pic_scaling_matrix_present_flag) { 70 | // TODO 71 | } 72 | } 73 | */ 74 | 75 | return 0; 76 | } 77 | 78 | int NaluPPS::intlog2(int x) 79 | { 80 | int log = 0; 81 | if (x < 0) { x = 0; } 82 | while ((x >> log) > 0) { 83 | log++; 84 | } 85 | if (log > 0 && x == 1 << (log-1)) { 86 | log--; 87 | } 88 | return log; 89 | } -------------------------------------------------------------------------------- /EyerH264Decoder/NaluPPS.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EYERH264DEOCDER_NALUPPS_HPP 2 | #define EYERH264DEOCDER_NALUPPS_HPP 3 | 4 | #include "Nalu.hpp" 5 | 6 | class NaluPPS : public Nalu 7 | { 8 | public: 9 | NaluPPS(const Nalu & nalu); 10 | virtual int Parse() override; 11 | 12 | int intlog2(int x); 13 | 14 | public: 15 | int pic_parameter_set_id = 0; 16 | int seq_parameter_set_id = 0; 17 | int entropy_coding_mode_flag = 0; 18 | int pic_order_present_flag = 0; 19 | int num_slice_groups_minus1 = 0; 20 | int slice_group_map_type = 0; 21 | int run_length_minus1[8]; // up to num_slice_groups_minus1, which is <= 7 in Baseline and Extended, 0 otheriwse 22 | int top_left[8]; 23 | int bottom_right[8]; 24 | int slice_group_change_direction_flag = 0; 25 | int slice_group_change_rate_minus1 = 0; 26 | int pic_size_in_map_units_minus1 = 0; 27 | int slice_group_id[256]; // FIXME what size? 28 | 29 | int num_ref_idx_l0_active_minus1 = 0; 30 | int num_ref_idx_l1_active_minus1 = 0; 31 | int weighted_pred_flag = 0; 32 | int weighted_bipred_idc = 0; 33 | int pic_init_qp_minus26 = 0; 34 | int pic_init_qs_minus26 = 0; 35 | int chroma_qp_index_offset = 0; 36 | int deblocking_filter_control_present_flag = 0; 37 | int constrained_intra_pred_flag = 0; 38 | int redundant_pic_cnt_present_flag = 0; 39 | 40 | 41 | //Fidelity Range Extensions Stuff 42 | int transform_8x8_mode_flag = 0; 43 | int pic_scaling_matrix_present_flag = 0; 44 | }; 45 | 46 | #endif //EYERH264DEOCDER_NALUPPS_HPP 47 | -------------------------------------------------------------------------------- /EyerH264Decoder/NaluSPS.cpp: -------------------------------------------------------------------------------- 1 | #include "NaluSPS.hpp" 2 | 3 | #include "BitStream.hpp" 4 | 5 | NaluSPS::NaluSPS(const Nalu & nalu) 6 | : Nalu(nalu) 7 | { 8 | 9 | } 10 | 11 | int NaluSPS::Parse() 12 | { 13 | BitStream bs(rbsp.buf, rbsp.len); 14 | 15 | bs.ReadU(8); 16 | 17 | profile_idc = bs.ReadU(8); 18 | constraint_set0_flag = bs.ReadU1(); 19 | constraint_set1_flag = bs.ReadU1(); 20 | constraint_set2_flag = bs.ReadU1(); 21 | constraint_set3_flag = bs.ReadU1(); 22 | constraint_set4_flag = bs.ReadU1(); 23 | constraint_set5_flag = bs.ReadU1(); 24 | bs.ReadU(2); 25 | level_idc = bs.ReadU(8); 26 | seq_parameter_set_id = bs.ReadUE(); 27 | 28 | bool isHigh = (profile_idc == 100 || profile_idc == 110 || 29 | profile_idc == 122 || profile_idc == 244 || profile_idc == 44 || 30 | profile_idc == 83 || profile_idc == 86 || profile_idc == 118 || 31 | profile_idc == 128 || profile_idc == 138 || profile_idc == 139 || 32 | profile_idc == 134 || profile_idc == 135); 33 | if(isHigh) 34 | { 35 | chroma_format_idc = bs.ReadUE(); 36 | 37 | if(chroma_format_idc == 3) { 38 | separate_colour_plance_flag = bs.ReadU1(); 39 | } 40 | bit_depth_luma_minus8 = bs.ReadUE(); 41 | bit_depth_chroma_minus8 = bs.ReadUE(); 42 | qpprime_y_zero_transform_bypass_flag = bs.ReadU1(); 43 | seq_scaling_matrix_present_flag = bs.ReadU1(); 44 | 45 | if(seq_scaling_matrix_present_flag) { 46 | for(int i=0; i<((chroma_format_idc != 3) ? 8 : 12); i++ ){ 47 | seq_scaling_list_present_flag[i] = bs.ReadU1(); 48 | if(seq_scaling_list_present_flag[i]){ 49 | if(i<6) { 50 | ReadScalingList(bs, ScalingList4x4[i], 16, &(UseDefaultScalingMatrix4x4Flag[i])); 51 | } 52 | else { 53 | ReadScalingList(bs, ScalingList8x8[i-6], 64, &(UseDefaultScalingMatrix8x8Flag[i-6])); 54 | } 55 | } 56 | } 57 | } 58 | } 59 | 60 | 61 | if (separate_colour_plance_flag == 0){ 62 | ChromaArrayType = chroma_format_idc; 63 | } 64 | else{ 65 | ChromaArrayType = 0; 66 | } 67 | 68 | if (chroma_format_idc == 1) { 69 | SubWidthC = 2; 70 | SubHeightC = 2; 71 | } 72 | if (chroma_format_idc == 2) { 73 | SubWidthC = 2; 74 | SubHeightC = 1; 75 | } 76 | if (chroma_format_idc == 3) { 77 | SubWidthC = 1; 78 | SubHeightC = 1; 79 | } 80 | 81 | 82 | 83 | 84 | log2_max_frame_num_minus4 = bs.ReadUE(); 85 | pic_order_cnt_type = bs.ReadUE(); 86 | 87 | 88 | if(pic_order_cnt_type == 0) { 89 | log2_max_pic_order_cnt_lsb_minus4 = bs.ReadUE(); 90 | } 91 | else if(pic_order_cnt_type == 1){ 92 | delta_pic_order_always_zero_flag = bs.ReadU1(); 93 | offset_for_non_ref_pic = bs.ReadSE(); 94 | offset_for_top_to_bottom_field = bs.ReadSE(); 95 | num_ref_frames_in_pic_order_cnt_cycle = bs.ReadUE(); 96 | 97 | for(int i=0; i 4 | #include 5 | 6 | RBSP::RBSP() 7 | { 8 | 9 | } 10 | 11 | RBSP::~RBSP() 12 | { 13 | if(buf != nullptr){ 14 | free(buf); 15 | buf = nullptr; 16 | } 17 | } 18 | 19 | RBSP::RBSP(const RBSP & rbsp) 20 | { 21 | *this = rbsp; 22 | } 23 | 24 | RBSP & RBSP::operator = (const RBSP & rbsp) 25 | { 26 | if(buf != nullptr){ 27 | free(buf); 28 | buf = nullptr; 29 | } 30 | 31 | len = rbsp.len; 32 | buf = (uint8_t *)malloc(len); 33 | memcpy(buf, rbsp.buf, len); 34 | 35 | return *this; 36 | } -------------------------------------------------------------------------------- /EyerH264Decoder/RBSP.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EYERH264DEOCDER_RBSP_HPP 2 | #define EYERH264DEOCDER_RBSP_HPP 3 | 4 | #include 5 | 6 | class RBSP { 7 | public: 8 | RBSP(); 9 | ~RBSP(); 10 | 11 | RBSP(const RBSP & rbsp); 12 | RBSP & operator = (const RBSP & rbsp); 13 | 14 | public: 15 | uint8_t * buf = nullptr; 16 | int len = 0; 17 | }; 18 | 19 | #endif //EYERH264DEOCDER_RBSP_HPP 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Redknot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EyerH264Decoder -------------------------------------------------------------------------------- /REAddTag.sh: -------------------------------------------------------------------------------- 1 | commit_list=$(git log --pretty=format:"%H,") 2 | echo ${commit_list} 3 | 4 | array=(${commit_list//,/ }) 5 | 6 | for var in ${array[@]} 7 | do 8 | echo $var 9 | echo ".............................." 10 | echo "" 11 | 12 | git show $var 13 | done -------------------------------------------------------------------------------- /demo_video_176x144_baseline.h264: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redknotmiaoyuqiao/EyerH264Decoder/59e0a396f0b9c0a4a2c034ba6d44fae22297e979/demo_video_176x144_baseline.h264 --------------------------------------------------------------------------------