MythTV master
bytereader.cpp
Go to the documentation of this file.
1/*
2 * find_start_code from libavcodec/FFmpeg
3 * Copyright (c) 2022 Scott Theisen
4 *
5 * This file is part of MythTV. The functions have been adapted to use C++.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "bytereader.h"
23
24#include <algorithm>
25
26const uint8_t* ByteReader::find_start_code(const uint8_t * p,
27 const uint8_t * const end,
28 uint32_t * const start_code)
29{
30 // minimum length for a start code
31 if (p + 4 > end)
32 {
33 *start_code = ~0; // set to an invalid start code
34 return end;
35 }
36
37 p += 3; // offset for negative indices in while loop
38
39 /* with memory address increasing left to right, we are looking for (in hexadecimal):
40 * 00 00 01 XX
41 * p points at the address which should have the value of XX
42 */
43 while (p < end)
44 {
45 if (/* UU UU UU */ p[-1] < 1) // equivalently p[-1] == 0
46 {
47 p++;
48 // could be in a start code, so check next byte
49 }
50 else if (/* UU UU UN */ p[-1] > 1 ||
51 /* UU UU 01 */ p[-2] != 0 ||
52 /* UU 00 01 */ p[-3] != 0)
53 {
54 // start check over with 3 new bytes
55 p += 3;
56 }
57 else /* 00 00 01 */
58 {
59 p++;
60 // p now points at the address following the start code value XX
61 break;
62 }
63 }
64
65 p = std::min(p, end);
66 // read the previous 4 bytes, i.e. bytes {p - 4, p - 3, p - 2, p - 1}
67 *start_code = static_cast<uint32_t>(p[-4]) << 24 |
68 static_cast<uint32_t>(p[-3]) << 16 |
69 static_cast<uint32_t>(p[-2]) << 8 |
70 static_cast<uint32_t>(p[-1]);
71 return p;
72}
73
74const uint8_t* ByteReader::find_start_code_truncated(const uint8_t * p,
75 const uint8_t * const end,
76 uint32_t * const start_code)
77{
78 if (p >= end)
79 {
80 return end;
81 }
82
83 if (*start_code == 0x100)
84 {
85 *start_code = ~0;
86 // invalidate byte 0 so overlapping start codes are not erroneously detected
87 }
88
89 // read up to the first three bytes in p to enable reading a start code across
90 // two (to four) buffers
91 for (int i = 0; i < 3; i++)
92 {
93 *start_code <<= 8;
94 *start_code += *p;
95 p++;
96 if (start_code_is_valid(*start_code) || p == end)
97 {
98 return p;
99 }
100 }
101 // buffer length is at least 4
102 return find_start_code(p - 3, end, start_code);
103}
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:54
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:26
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:74