MythTV master
bytereader.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Unlicense
2// Created by Scott Theisen, 2022-2025
3/* The Unlicense
4This is free and unencumbered software released into the public domain.
5
6Anyone is free to copy, modify, publish, use, compile, sell, or
7distribute this software, either in source code form or as a compiled
8binary, for any purpose, commercial or non-commercial, and by any
9means.
10
11In jurisdictions that recognize copyright laws, the author or authors
12of this software dedicate any and all copyright interest in the
13software to the public domain. We make this dedication for the benefit
14of the public at large and to the detriment of our heirs and
15successors. We intend this dedication to be an overt act of
16relinquishment in perpetuity of all present and future rights to this
17software under copyright law.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25OTHER DEALINGS IN THE SOFTWARE.
26
27For more information, please refer to <https://unlicense.org>
28*/
29
30#include "bytereader.h"
31
32#include <algorithm>
33
34const uint8_t* ByteReader::find_start_code(const uint8_t * p,
35 const uint8_t * const end,
36 uint32_t * const start_code)
37{
38 // minimum length for a start code
39 if (p + 4 > end)
40 {
41 *start_code = ~0; // set to an invalid start code
42 return end;
43 }
44
45 p += 3; // offset for negative indices in while loop
46
47 /* with memory address increasing left to right, we are looking for (in hexadecimal):
48 * 00 00 01 XX
49 * p points at the address which should have the value of XX
50 */
51 while (p < end)
52 {
53 if (/* UU UU UU */ p[-1] < 1) // equivalently p[-1] == 0
54 {
55 p++;
56 // could be in a start code, so check next byte
57 }
58 else if (/* UU UU UN */ p[-1] > 1 ||
59 /* UU UU 01 */ p[-2] != 0 ||
60 /* UU 00 01 */ p[-3] != 0)
61 {
62 // start check over with 3 new bytes
63 p += 3;
64 }
65 else /* 00 00 01 */
66 {
67 p++;
68 // p now points at the address following the start code value XX
69 break;
70 }
71 }
72
73 p = std::min(p, end);
74 // read the previous 4 bytes, i.e. bytes {p - 4, p - 3, p - 2, p - 1}
75 *start_code = readBigEndianU32(p - 4);
76 return p;
77}
78
79const uint8_t* ByteReader::find_start_code_truncated(const uint8_t * p,
80 const uint8_t * const end,
81 uint32_t * const start_code)
82{
83 if (p >= end)
84 {
85 return end;
86 }
87
88 if (*start_code == 0x100)
89 {
90 *start_code = ~0;
91 // invalidate byte 0 so overlapping start codes are not erroneously detected
92 }
93
94 // read up to the first three bytes in p to enable reading a start code across
95 // two (to four) buffers
96 for (int i = 0; i < 3; i++)
97 {
98 *start_code <<= 8;
99 *start_code += *p;
100 p++;
101 if (start_code_is_valid(*start_code) || p == end)
102 {
103 return p;
104 }
105 }
106 // buffer length is at least 4
107 return find_start_code(p - 3, end, start_code);
108}
This is in libmythtv because that is where the parsers, which are its main users, are.
bool start_code_is_valid(uint32_t start_code)
Test whether a start code found by find_start_code() is valid.
Definition: bytereader.h:62
MTV_PUBLIC const uint8_t * find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *start_code)
Find the first start code in the buffer p.
Definition: bytereader.cpp:34
uint32_t readBigEndianU32(const uint8_t *x)
Definition: bytereader.h:109
MTV_PUBLIC const uint8_t * find_start_code_truncated(const uint8_t *p, const uint8_t *end, uint32_t *start_code)
By preserving the start_code value between subsequent calls, the caller can detect start codes across...
Definition: bytereader.cpp:79