AV1 keyframe oracle. The wire form is a Low-Overhead-Bitstream-Format temporal unit (OBU stream, no Annex-B start codes). A random-access point carries a Sequence-Header OBU (type 1), so its presence marks a decodable GOP start. OBU header byte: obu_type = (b >> 3) & 0x0F; obu_extension_flag = (b >> 2) & 1; obu_has_size_field = (b >> 1) & 1. A LEB128 obu_size follows the (optional 1-byte extension
| 67 | // obu_has_size_field = (b >> 1) & 1. A LEB128 obu_size follows the (optional |
| 68 | // 1-byte extension) header when has_size_field is set. |
| 69 | bool isAv1Keyframe(const uint8_t* data, size_t size) { |
| 70 | if (data == nullptr || size == 0) { |
| 71 | return false; |
| 72 | } |
| 73 | constexpr int kObuSequenceHeader = 1; |
| 74 | size_t pos = 0; |
| 75 | while (pos < size) { |
| 76 | const uint8_t header = data[pos]; |
| 77 | const int obu_type = (header >> 3) & 0x0F; |
| 78 | if (obu_type == kObuSequenceHeader) { |
| 79 | return true; |
| 80 | } |
| 81 | const bool extension_flag = ((header >> 2) & 0x01) != 0; |
| 82 | const bool has_size_field = ((header >> 1) & 0x01) != 0; |
| 83 | size_t cursor = pos + 1 + (extension_flag ? 1 : 0); |
| 84 | if (cursor > size) { |
| 85 | break; |
| 86 | } |
| 87 | size_t payload_size = 0; |
| 88 | if (has_size_field) { |
| 89 | // LEB128 obu_size (AV1 spec 4.10.5: at most 8 bytes). |
| 90 | uint64_t value = 0; |
| 91 | bool terminated = false; |
| 92 | for (int byte_index = 0; byte_index < 8 && cursor < size; ++byte_index) { |
| 93 | const uint8_t byte = data[cursor++]; |
| 94 | value |= static_cast<uint64_t>(byte & 0x7F) << (byte_index * 7); |
| 95 | if ((byte & 0x80) == 0) { |
| 96 | terminated = true; |
| 97 | break; |
| 98 | } |
| 99 | } |
| 100 | if (!terminated) { |
| 101 | break; |
| 102 | } |
| 103 | payload_size = static_cast<size_t>(value); |
| 104 | } else { |
| 105 | // No size field: the OBU runs to the end of the temporal unit. |
| 106 | payload_size = size - cursor; |
| 107 | } |
| 108 | const size_t next = cursor + payload_size; |
| 109 | if (next <= pos) { // malformed / non-progressing — stop scanning. |
| 110 | break; |
| 111 | } |
| 112 | pos = next; |
| 113 | } |
| 114 | return false; |
| 115 | } |
| 116 | |
| 117 | } // namespace |
| 118 |