mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-12-28 18:41:14 +00:00
encoders/codecs/h264: Basic support for parsing NALs
This commit is contained in:
parent
afa47646f5
commit
bc5de8061f
2 changed files with 101 additions and 0 deletions
|
@ -20,3 +20,68 @@
|
|||
// SOFTWARE.
|
||||
|
||||
#include "h264.hpp"
|
||||
|
||||
uint8_t* is_nal_start(uint8_t* ptr, uint8_t* end_ptr, size_t& size)
|
||||
{
|
||||
// Ensure that the remaining space actually can contain a prefix and NAL header.
|
||||
if ((ptr + (3 + 1)) >= end_ptr)
|
||||
return nullptr;
|
||||
|
||||
if (*ptr != 0x0)
|
||||
return nullptr;
|
||||
if (*(ptr + 1) != 0x0)
|
||||
return nullptr;
|
||||
|
||||
// 3-Byte NAL prefix.
|
||||
if (*(ptr + 2) == 0x1) {
|
||||
size = 3;
|
||||
return ptr + 3;
|
||||
}
|
||||
|
||||
// 4-Byte NAL Prefix
|
||||
if ((ptr + (4 + 1)) >= end_ptr)
|
||||
return nullptr;
|
||||
if (*(ptr + 2) != 0x0)
|
||||
return nullptr;
|
||||
if (*(ptr + 3) != 0x01)
|
||||
return nullptr;
|
||||
|
||||
size = 4;
|
||||
return ptr + 4;
|
||||
}
|
||||
|
||||
uint8_t* streamfx::encoder::codec::h264::find_closest_nal(uint8_t* ptr, uint8_t* end_ptr, size_t& size)
|
||||
{
|
||||
for (uint8_t* seek_ptr = ptr; seek_ptr < end_ptr; seek_ptr++) {
|
||||
if (auto nal_ptr = is_nal_start(seek_ptr, end_ptr, size); nal_ptr != nullptr)
|
||||
return nal_ptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t streamfx::encoder::codec::h264::get_packet_reference_count(uint8_t* ptr, uint8_t* end_ptr)
|
||||
{
|
||||
size_t nal_ptr_prefix = 0;
|
||||
uint8_t* nal_ptr = find_closest_nal(ptr, end_ptr, nal_ptr_prefix);
|
||||
while ((nal_ptr != nullptr) && (nal_ptr < end_ptr)) {
|
||||
// Try and figure out the actual size of the NAL.
|
||||
size_t nal_end_ptr_prefix = 0;
|
||||
uint8_t* nal_end_ptr = find_closest_nal(nal_ptr, end_ptr, nal_end_ptr_prefix);
|
||||
size_t nal_size = (nal_end_ptr ? nal_end_ptr : end_ptr) - nal_ptr - nal_end_ptr_prefix;
|
||||
|
||||
// Try and figure out the ideal priority.
|
||||
switch (static_cast<nal_unit_type>((*nal_ptr) & 0x5)) {
|
||||
case nal_unit_type::CODED_SLICE_NONIDR:
|
||||
return (*nal_ptr >> 5) & 0x2;
|
||||
case nal_unit_type::CODED_SLICE_IDR:
|
||||
return (*nal_ptr >> 5) & 0x2;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Update our NAL pointer.
|
||||
nal_ptr = nal_end_ptr;
|
||||
}
|
||||
|
||||
return std::numeric_limits<uint32_t>::max();
|
||||
}
|
||||
|
|
|
@ -60,4 +60,40 @@ namespace streamfx::encoder::codec::h264 {
|
|||
L6_2,
|
||||
UNKNOWN = -1,
|
||||
};
|
||||
|
||||
// See ITU-T H.264
|
||||
enum class nal_unit_type : uint8_t {
|
||||
UNSPECIFIED = 0,
|
||||
CODED_SLICE_NONIDR = 1,
|
||||
CODED_SLICE_DATA_PARTITION_A = 2,
|
||||
CODED_SLICE_DATA_PARTITION_B = 3,
|
||||
CODED_SLICE_DATA_PARTITION_C = 4,
|
||||
CODED_SLICE_IDR = 5,
|
||||
SUPPLEMENTAL_ENHANCEMENT_INFORMATION = 6,
|
||||
SEQUENCE_PARAMETER_SET = 7,
|
||||
PICTURE_PARAMETER_SET = 8,
|
||||
ACCESS_UNIT_DELIMITER = 9,
|
||||
END_OF_SEQUENCE = 10,
|
||||
END_OF_STREAM = 11,
|
||||
FILLER_DATA = 12,
|
||||
SEQUENCE_PARAMETER_SET_EXTENSION = 13,
|
||||
PREFIX_NAL_UNIT = 14,
|
||||
SUBSET_SEQUENCE_PARAMETER_SET = 15,
|
||||
DEPTH_PARAMETER_SET = 16,
|
||||
CODED_SLICE_AUXILIARY_PICTURE = 19,
|
||||
CODED_SLICE_EXTENSION = 20,
|
||||
CODED_SLICE_EXTENSION_DEPTH_VIEW = 21,
|
||||
};
|
||||
|
||||
/** Search for the closest NAL unit.
|
||||
*
|
||||
* \param ptr Beginning of the search range.
|
||||
* \param endptr End of the search range (exclusive).
|
||||
*
|
||||
* \return A valid pointer if a NAL was found, otherwise \ref nullptr.
|
||||
*/
|
||||
uint8_t* find_closest_nal(uint8_t* ptr, uint8_t* endptr, size_t& size);
|
||||
|
||||
uint32_t get_packet_reference_count(uint8_t* ptr, uint8_t* endptr);
|
||||
|
||||
} // namespace streamfx::encoder::codec::h264
|
||||
|
|
Loading…
Reference in a new issue