#include "mpeg-types.h" #include "mpeg-util.h" #include #include #define H265_NAL_AUD 35 /// @param[out] leading optional leading zero bytes /// @return -1-not found, other-AUD position(include start code) static int mpeg_h265_find_access_unit_delimiter(const uint8_t* p, size_t bytes, size_t* leading) { size_t i, zeros; for (zeros = i = 0; i + 1 < bytes; i++) { if (0x01 == p[i] && zeros >= 2 && H265_NAL_AUD == ((p[i + 1] >> 1) & 0x3f)) { assert(i >= zeros); if (leading) *leading = (zeros > 2 ? 3 : 2) + 1; // zeros - (zeros > 2 ? 3 : 2); return (int)(i - (zeros > 2 ? 3 : 2)); } zeros = 0x00 != p[i] ? 0 : (zeros + 1); } return -1; } // Rec. ITU-T H.265 v4 (12/2016) (p26) // intra random access point (IRAP) picture: // A coded picture for which each VCL NAL unit has nal_unit_type // in the range of BLA_W_LP to RSV_IRAP_VCL23, inclusive. static int mpeg_h265_find_keyframe(const uint8_t* p, size_t bytes) { size_t i; uint8_t type; for (i = 2; i + 1 < bytes; i++) { if (0x01 == p[i] && 0x00 == p[i - 1] && 0x00 == p[i - 2]) { type = (p[i + 1] >> 1) & 0x3f; if (type < 32) return (16 <= type && type <= 23) ? 1 : 0; } } return 0; } static int mpeg_h265_is_new_access_unit(const uint8_t* nalu, size_t bytes) { enum { NAL_VPS = 32, NAL_SPS = 33, NAL_PPS = 34, NAL_AUD = 35, NAL_PREFIX_SEI = 39, }; uint8_t nal_type; uint8_t nuh_layer_id; if(bytes < 3) return 0; nal_type = (nalu[0] >> 1) & 0x3f; nuh_layer_id = ((nalu[0] & 0x01) << 5) | ((nalu[1] >> 3) &0x1F); // 7.4.2.4.4 Order of NAL units and coded pictures and their association to access units if(NAL_VPS == nal_type || NAL_SPS == nal_type || NAL_PPS == nal_type || (nuh_layer_id == 0 && (NAL_AUD == nal_type || NAL_PREFIX_SEI == nal_type || (41 <= nal_type && nal_type <= 44) || (48 <= nal_type && nal_type <= 55)))) return 1; // 7.4.2.4.5 Order of VCL NAL units and association to coded pictures if (nal_type <= 31) { //first_slice_segment_in_pic_flag 0x80 return (nalu[2] & 0x80) ? 1 : 0; } return 0; } int mpeg_h265_find_new_access_unit(const uint8_t* data, size_t bytes, int* vcl) { int n; size_t leading; uint8_t nal_type; const uint8_t* p, *end; end = data + bytes; for (p = data; p && p < end; p += n) { n = mpeg_h264_find_nalu(p, end - p, &leading); if (n < 0) return -1; nal_type = (p[n] >> 1) & 0x3f; if (*vcl > 0 && mpeg_h265_is_new_access_unit(p+n, end - p - n)) { return (int)(p - data + n - leading); } else if (nal_type <= 31) { *vcl = (16 <= nal_type && nal_type <= 23) ? 1 : 2; } else { // nothing to do } } return -1; }