📄 h264.cpp
字号:
/* * h264 stamdard */#include <mp4creator.h>#define NALU_TYPE_SLICE 1#define NALU_TYPE_IDR 5#define NALU_TYPE_PPS 8#define NALU_TYPE_SPS 7#define P_SLICE 0#define B_SLICE 1#define I_SLICE 2#define SP_SLICE 3#define SI_SLICE 4/* * Load the next NAL unit from the file into the supplied buffer, which * better be large enough! * NAL unit: A syntax structure containing an indication of the type of data * to follow and bytes containing that data in the form of an RBSP interspersed * as necessary with emulation prevention bytes. */static int LoadNextNALU(FILE* inFile, u_int8_t* pBuf, u_int32_t* pBufSize){ static u_int8_t state = 0; static u_int8_t nextstartzeros = 0; *pBufSize = 0; /* initial state, never read from file before */ if (state == 0) { /* * go looking for first sync word * we discard anything before this */ state = 1; while (state < 5) { /* read a byte */ u_char b; if (fread(&b, 1, 1, inFile) == 0) { // EOF or IO error return 0; } switch (state) { case 1: if (b == 0) { state = 2; } else { state = 1; } break; case 2: if (b == 0) { state = 3; } else { state = 1; } break; case 3: if (b == 0){ state = 4; } else if (b == 1) { state = 5; pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = 1; } else { state = 1; } break; case 4: if (b == 1) { state = 5; pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = 1; } else if (b == 0) { state = 4; } else { state = 1; } break; } } /* we're primed now */ state = 1; } else if (state == 5) { state = 0; return 0; } else { pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = 0; if (nextstartzeros == 3) { pBuf[(*pBufSize)++] = 0; } pBuf[(*pBufSize)++] = 1; } /* read bytes, execute state machine */ while (1) { /* read a byte */ u_char b; if (fread(&b, 1, 1, inFile) == 0) { /* handle EOF */ if (feof(inFile)) { switch (state) { case 4: pBuf[(*pBufSize)++] = 0; case 3: pBuf[(*pBufSize)++] = 0; case 2: pBuf[(*pBufSize)++] = 0; break; } state = 5; return 1; } /* else error */ *pBufSize = 0; return 0; } switch (state) { case 1: if (b == 0) { state = 2; } else { pBuf[(*pBufSize)++] = b; } break; case 2: if (b == 0) { state = 3; } else { pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = b; state = 1; } break; case 3: if (b == 0) { state = 4; } else if (b == 1){ state = 1; nextstartzeros = 2; return 1; } else { pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = b; state = 1; } break; case 4: if (b == 1) { state = 1; nextstartzeros = 3; return 1; } else if (b == 0) { pBuf[(*pBufSize)++] = 0; state = 4; } else { pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = 0; pBuf[(*pBufSize)++] = b; state = 1; } break; default: ASSERT(false); } }}/* * Parse NALU according to the annex B in h264 standard JVT-G050 * and return the RBSP * NALU: * forbidden_bit : f(1) * nal_ref_idc : u(2) * nal_unit_type : u(5) * EBSP : Encapsulation of RBSP(Raw Byte Sequence Payload) * 0x000003xx = 0x0000xx */static void parseAnnexbNALU(u_int8_t* pBuf, u_int32_t* pBufSize, u_int32_t* forbidden_bit, u_int32_t* nal_reference_idc, u_int32_t* nal_unit_type){ u_int32_t count=0,i,j=0; if (pBuf[2] == 0) { i = 4; } else { i = 3; } // parse the NAL unit header information *forbidden_bit = (pBuf[i]>>7) & 1; *nal_reference_idc = (pBuf[i]>>5) & 3; *nal_unit_type = (pBuf[i]) & 0x1f; // Convert EBSP to RBSP for (i = i+1; i < *pBufSize; i++) { if (count == 2 && pBuf[i] == 0x03) { i++; count = 0; } pBuf[j] = pBuf[i]; if (pBuf[i] == 0) { count++; } else { count = 0; } j++; } *pBufSize = j;}/* * u(1) : unsigned integer using 1 bit. */static u_int32_t u_1(u_int8_t* pBuf, u_int32_t* pi, u_int32_t* pj){ u_int32_t tmp; tmp = (pBuf[*pi] >> (7-*pj)) & 1; *pi += (*pj+1)/8; *pj = (*pj+1)%8; return tmp;}/* * u(v) : unsigned integer Exp-Golomb-coded syntax element with the left bit * first. The parsing process for this descriptor is specified in subclause * 9.1 in JVT-G050 */static u_int32_t ue_v(u_int8_t* pBuf, u_int32_t* pi, u_int32_t* pj){ u_int32_t count = 0, i, codeNum = 0, rangeBaseNum = 1; while (u_1(pBuf, pi, pj) == 0) { count++; } for (i = 0; i < count; i++) { rangeBaseNum = rangeBaseNum*2; } for (i = 0; i < count; i++) { codeNum = codeNum*2 + u_1(pBuf, pi, pj); } codeNum += rangeBaseNum - 1; return codeNum;}/* * se(v) : signed integer Exp-Golomb-coded syntax element with the left bit * first. The parsing process for this descriptor is specified in subclause * 9.1 in JVT-G050 */static u_int32_t se_v(u_int8_t* pBuf, u_int32_t* pi, u_int32_t* pj){ u_int32_t tmp = ue_v(pBuf, pi, pj); if (tmp%2 == 0) { return -(tmp+1)/2; } else { return (tmp+1)/2; }}/* * Parse the RBSP with NAL unit type of SPS(Sequence Parameter Set) and * get the width and the height of this image sequence */static int parseNALU_SPS(u_int8_t* pBuf, u_int32_t* pBufSize, u_int16_t* img_width, u_int16_t* img_height){ u_int32_t i = 0, j = 0, k; u_int32_t pic_order_cnt_type, num_ref_frames_in_pic_order_cnt_cycle; u_int32_t pic_width_in_mbs_minus1, pic_height_in_map_units_minus1; // profile_idc : u(8) i++; // level_idc : u(8) i++; // more_than_one_slice_group_allowed_flag : u(1) // arbitrary_slice_order_allowed_flag : u(1) // redundant_slices_allowed_flag ; u(1) j += 3; // seq_parameter_set_id : ue(v) ue_v(pBuf, &i, &j); // log2_max_frame_num_minus4 : ue(v) ue_v(pBuf, &i, &j); // pic_order_cnt_type pic_order_cnt_type = ue_v(pBuf, &i, &j); if (pic_order_cnt_type == 0) { // log2_max_pic_order_cnt_lsb_minus4 : ue(v) ue_v(pBuf, &i, &j); } else if (pic_order_cnt_type == 1) { // delta_pic_order_always_zero_flag1 : u(1) u_1(pBuf, &i, &j); // offset_for_non_ref_pic : se(v) se_v(pBuf, &i, &j); // offset_for_top_to_bottom_field : se(v) se_v(pBuf, &i, &j); // num_ref_frames_in_pic_order_cnt_cycle : ue(v) num_ref_frames_in_pic_order_cnt_cycle = ue_v(pBuf, &i, &j); for (k=0; k<num_ref_frames_in_pic_order_cnt_cycle; k++) { // offset_for_ref_frame[k] : se(v) se_v(pBuf, &i, &j); } } // num_ref_frames : ue(v) ue_v(pBuf, &i, &j); // required_frame_num_update_behaviour_flag : u(1) u_1(pBuf, &i, &j); // pic_width_in_mbs_minus1 : ue(v) pic_width_in_mbs_minus1 = ue_v(pBuf, &i, &j); // pic_height_in_map_units_minus1 : ue(v) pic_height_in_map_units_minus1 = ue_v(pBuf, &i, &j); // ... ... ... // ... ... ... *img_width = (pic_width_in_mbs_minus1 + 1)*16; *img_height = (pic_height_in_map_units_minus1+1)*16;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -