#include #include #include #include #include #include #include #include #include #include "bitstream.h" #define START_CODE 0x000001 static uint32_t read24be(const uint8_t* ptr) { return (ptr[0] << 16) | (ptr[1] << 8) | ptr[2]; } static void write32le(FILE *of, uint32_t v) { uint8_t va[4] = { v & 0xff, (v >> 8) & 0xff, (v >> 16) & 0xff, (v >> 24) & 0xff }; fwrite(va, 1, sizeof(va), of); } // Table 7-1 enum hevc_nal_type { HEVC_NAL_TYPE_TRAIL_N = 0, HEVC_NAL_TYPE_TRAIL_R = 1, HEVC_NAL_TYPE_TSA_N = 2, HEVC_NAL_TYPE_TSA_R = 3, HEVC_NAL_TYPE_STSA_N = 4, HEVC_NAL_TYPE_STSA_R = 5, HEVC_NAL_TYPE_RADL_N = 6, HEVC_NAL_TYPE_RADL_R = 7, HEVC_NAL_TYPE_RASL_N = 8, HEVC_NAL_TYPE_RASL_R = 9, HEVC_NAL_TYPE_BLA_W_LP = 16, HEVC_NAL_TYPE_BLA_W_RADL = 17, HEVC_NAL_TYPE_BLA_N_LP = 18, HEVC_NAL_TYPE_IDR_W_RADL = 19, HEVC_NAL_TYPE_IDR_N_LP = 20, HEVC_NAL_TYPE_CRA_NUT = 21, HEVC_NAL_TYPE_RSV_IRAP_VCL23 = 23, HEVC_NAL_TYPE_VPS_NUT = 32, HEVC_NAL_TYPE_SPS_NUT = 33, HEVC_NAL_TYPE_PPS_NUT = 34, HEVC_NAL_TYPE_AUD_NUT = 35, HEVC_NAL_TYPE_EOS_NUT = 36, HEVC_NAL_TYPE_EOB_NUT = 37, HEVC_NAL_TYPE_FD_NUT = 38, HEVC_NAL_TYPE_PREFIX_SEI_NUT = 39, HEVC_NAL_TYPE_SUFFIX_SEI_NUT = 40, }; // Table 7-7 enum hevc_slice_type { HEVC_SLICE_B = 0, HEVC_SLICE_P = 1, HEVC_SLICE_I = 2, }; static void hevc_index(const uint8_t *data, size_t file_size, FILE *of_prefix, FILE *of_index) { const uint8_t* ptr = data; const uint8_t* ptr_end = data + file_size; assert(ptr[0] == 0); ptr++; assert(read24be(ptr) == START_CODE); // pps. ignore for now uint32_t num_extra_slice_header_bits = 0; uint32_t dependent_slice_segments_enabled_flag = 0; while (ptr < ptr_end) { const uint8_t* next = ptr+1; for (; next < ptr_end-4; next++) { if (read24be(next) == START_CODE) break; } size_t nal_size = next - ptr; if (nal_size < 6) { break; } { struct bitstream bs = {0}; bs_init(&bs, ptr, nal_size); uint32_t start_code = bs_get(&bs, 24); assert(start_code == 0x000001); // nal_unit_header uint32_t forbidden_zero_bit = bs_get(&bs, 1); uint32_t nal_unit_type = bs_get(&bs, 6); uint32_t nuh_layer_id = bs_get(&bs, 6); uint32_t nuh_temporal_id_plus1 = bs_get(&bs, 3); // if (nal_unit_type != 1) printf("%3d -- %3d %10d %lu\n", nal_unit_type, frame_num, (uint32_t)(ptr-data), nal_size); switch (nal_unit_type) { case HEVC_NAL_TYPE_VPS_NUT: case HEVC_NAL_TYPE_SPS_NUT: case HEVC_NAL_TYPE_PPS_NUT: fwrite(ptr, 1, nal_size, of_prefix); break; case HEVC_NAL_TYPE_TRAIL_N: case HEVC_NAL_TYPE_TRAIL_R: case HEVC_NAL_TYPE_TSA_N: case HEVC_NAL_TYPE_TSA_R: case HEVC_NAL_TYPE_STSA_N: case HEVC_NAL_TYPE_STSA_R: case HEVC_NAL_TYPE_RADL_N: case HEVC_NAL_TYPE_RADL_R: case HEVC_NAL_TYPE_RASL_N: case HEVC_NAL_TYPE_RASL_R: case HEVC_NAL_TYPE_BLA_W_LP: case HEVC_NAL_TYPE_BLA_W_RADL: case HEVC_NAL_TYPE_BLA_N_LP: case HEVC_NAL_TYPE_IDR_W_RADL: case HEVC_NAL_TYPE_IDR_N_LP: case HEVC_NAL_TYPE_CRA_NUT: { // slice_segment_header uint32_t first_slice_segment_in_pic_flag = bs_get(&bs, 1); if (nal_unit_type >= HEVC_NAL_TYPE_BLA_W_LP && nal_unit_type <= HEVC_NAL_TYPE_RSV_IRAP_VCL23) { uint32_t no_output_of_prior_pics_flag = bs_get(&bs, 1); } uint32_t slice_pic_parameter_set_id = bs_get(&bs, 1); if (!first_slice_segment_in_pic_flag) { // ... break; } if (!dependent_slice_segments_enabled_flag) { for (int i=0; i 4); const uint8_t* data = (const uint8_t*)mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0); assert(data != MAP_FAILED); if (strcmp(file_type, "hevc") == 0) { hevc_index(data, file_size, of_prefix, of_index); } else if (strcmp(file_type, "h264") == 0) { h264_index(data, file_size, of_prefix, of_index); } else { assert(false); } munmap((void*)data, file_size); close(fd); return 0; }