@@ -160,11 +160,6 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
const uint8_t *end;
size_t unit_size;
- // Reset start_code to ensure that avpriv_find_start_code()
- // really reads a new start code and does not reuse the old
- // start code in any way (as e.g. happens when there is a
- // Sequence End unit at the very end of a packet).
- start_code = UINT32_MAX;
end = avpriv_find_start_code(start--, frag->data + frag->data_size,
&start_code);
@@ -69,7 +69,7 @@ typedef struct H264ParseContext {
static int find_start_code(const uint8_t *buf, int buf_size,
int buf_index, int next_avc)
{
- uint32_t state = -1;
+ uint32_t state;
buf_index = avpriv_find_start_code(buf + buf_index, buf + next_avc + 1, &state) - buf - 1;
@@ -165,6 +165,45 @@ av_cold void ff_mpeg12_init_vlcs(void)
}
#if FF_API_FLAG_TRUNCATED
+/**
+ * By preserving the <b>@p start_code</b> value between subsequent calls, the caller can
+ * detect start codes across buffer boundaries.
+ *
+ * @param[in,out] start_code A pointer to a mutable @c uint32_t.<br>
+ * As input: For no history preset to <b>@c ~0 </b>, otherwise preset to the last
+ * returned start code to enable detecting start codes across
+ * buffer boundaries.<br>
+ * On output: Set to the found start code if it exists or an invalid
+ * start code (the 4 bytes prior to the returned value,
+ * using the input history if @f$ end - p < 4 @f$).
+ *
+ * @sa avpriv_find_start_code()
+ */
+static const uint8_t *find_start_code_truncated(const uint8_t *av_restrict p,
+ const uint8_t * const end,
+ uint32_t * const av_restrict start_code)
+{
+ av_assert0(p <= end);
+ if (p >= end)
+ return end;
+
+ if (*start_code == 0x100)
+ *start_code = ~0;
+ // invalidate byte 0 so overlapping start codes are not erroneously detected
+
+ // read up to the first three bytes in p to enable reading a start code across
+ // two (to four) buffers
+ for (int i = 0; i < 3; i++) {
+ *start_code <<= 8;
+ *start_code += *p;
+ p++;
+ if (start_code_is_valid(*start_code) || p == end)
+ return p;
+ }
+ // buffer length is at least 4
+ return avpriv_find_start_code(p - 3, end, start_code);
+}
+
/**
* Find the end of the current frame in the bitstream.
* @return the position of the first byte of the next frame, or -1
@@ -199,7 +238,7 @@ int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size,
}
state++;
} else {
- i = avpriv_find_start_code(buf + i, buf + buf_size, &state) - buf - 1;
+ i = find_start_code_truncated(buf + i, buf + buf_size, &state) - buf - 1;
if (pc->frame_start_found == 0 && state >= SLICE_MIN_START_CODE && state <= SLICE_MAX_START_CODE) {
i++;
pc->frame_start_found = 4;
@@ -36,7 +36,6 @@ static void scan_buffer(const uint8_t *buf, int buf_size,
const uint8_t *end = buf + buf_size, *pos = buf;
while (pos < end) {
- startcode = -1;
pos = avpriv_find_start_code(pos, end, &startcode);
if (startcode == USER_DATA_STARTCODE && pos_p) {
@@ -33,6 +33,45 @@ struct MpvParseContext {
};
#if !FF_API_FLAG_TRUNCATED
+/**
+ * By preserving the <b>@p start_code</b> value between subsequent calls, the caller can
+ * detect start codes across buffer boundaries.
+ *
+ * @param[in,out] start_code A pointer to a mutable @c uint32_t.<br>
+ * As input: For no history preset to <b>@c ~0 </b>, otherwise preset to the last
+ * returned start code to enable detecting start codes across
+ * buffer boundaries.<br>
+ * On output: Set to the found start code if it exists or an invalid
+ * start code (the 4 bytes prior to the returned value,
+ * using the input history if @f$ end - p < 4 @f$).
+ *
+ * @sa avpriv_find_start_code()
+ */
+static const uint8_t *find_start_code_truncated(const uint8_t *av_restrict p,
+ const uint8_t * const end,
+ uint32_t * const av_restrict start_code)
+{
+ av_assert0(p <= end);
+ if (p >= end)
+ return end;
+
+ if (*start_code == 0x100)
+ *start_code = ~0;
+ // invalidate byte 0 so overlapping start codes are not erroneously detected
+
+ // read up to the first three bytes in p to enable reading a start code across
+ // two (to four) buffers
+ for (int i = 0; i < 3; i++) {
+ *start_code <<= 8;
+ *start_code += *p;
+ p++;
+ if (start_code_is_valid(*start_code) || p == end)
+ return p;
+ }
+ // buffer length is at least 4
+ return avpriv_find_start_code(p - 3, end, start_code);
+}
+
/**
* Find the end of the current frame in the bitstream.
* @return the position of the first byte of the next frame, or -1
@@ -68,7 +107,7 @@ static int mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf,
}
state++;
} else {
- i = avpriv_find_start_code(buf + i, buf + buf_size, &state) - buf - 1;
+ i = find_start_code_truncated(buf + i, buf + buf_size, &state) - buf - 1;
if (pc->frame_start_found == 0 && state >= SLICE_MIN_START_CODE && state <= SLICE_MAX_START_CODE) {
i++;
pc->frame_start_found = 4;
@@ -120,7 +159,6 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s,
s->repeat_pict = 0;
while (buf < buf_end) {
- start_code= -1;
buf= avpriv_find_start_code(buf, buf_end, &start_code);
bytes_left = buf_end - buf;
switch(start_code) {
@@ -50,20 +50,14 @@ static av_always_inline int start_code_is_valid(uint32_t start_code) {
* A start code is a sequence of 4 bytes with the hexadecimal value <b><tt> 00 00 01 XX </tt></b>,
* where <b><tt> XX </tt></b> represents any value and memory address increases left to right.
*
- * By preserving the <b>@p start_code</b> value between subsequent calls, the caller can
- * detect start codes across buffer boundaries.
- *
* @param[in] p A pointer to the start of the memory buffer to scan.
* @param[in] end A pointer to the past-the-end memory address for the buffer
* given by @p p. <b>@p p</b> must be ≤ <b>@p end</b>.
*
- * @param[in,out] start_code A pointer to a mutable @c uint32_t.<br>
- * As input: For no history preset to <b>@c ~0 </b>, otherwise preset to the last
- * returned start code to enable detecting start codes across
- * buffer boundaries.<br>
- * On output: Set to the found start code if it exists or an invalid
- * start code (the 4 bytes prior to the returned value,
- * using the input history if @f$ end - p < 4 @f$).
+ * @param[out] start_code A pointer to a mutable @c uint32_t.<br>
+ * Set to the found start code if it exists or an invalid start code
+ * (the 4 bytes prior to the returned value or <b>@c ~0 </b> if
+ * @f$ end - p < 4 @f$).
*
* @return A pointer to the memory address following the found start code, or <b>@p end</b>
* if no start code was found.
@@ -941,19 +941,13 @@ const uint8_t *avpriv_find_start_code(const uint8_t *av_restrict p,
uint32_t * const av_restrict start_code)
{
av_assert0(p <= end);
- if (p >= end)
+ // minimum length for a start code
+ if (p + 4 > end) {
+ *start_code = ~0; // set to an invalid start code
return end;
-
- // read up to the first three bytes in p to enable reading a start code across
- // two (to four) buffers
- for (int i = 0; i < 3; i++) {
- *start_code <<= 8;
- *start_code += *p;
- p++;
- if (start_code_is_valid(*start_code) || p == end)
- return p;
}
- // p is now properly incremented for the negative indices in the while loop
+
+ p += 3; // offset for negative indices in while loop
/* with memory address increasing left to right, we are looking for (in hexadecimal):
* 00 00 01 XX
@@ -57,7 +57,7 @@ enum Profile {
static av_always_inline const uint8_t* find_next_marker(const uint8_t *src, const uint8_t *end)
{
if (end - src >= 4) {
- uint32_t mrk = 0xFFFFFFFF;
+ uint32_t mrk;
src = avpriv_find_start_code(src, end, &mrk);
if (start_code_is_valid(mrk))
return src - 4;
@@ -54,7 +54,7 @@ void ff_rtp_send_mpegvideo(AVFormatContext *s1, const uint8_t *buf1, int size)
r1 = buf1;
while (1) {
- uint32_t start_code = ~0;
+ uint32_t start_code;
r = avpriv_find_start_code(r1, end, &start_code);
if (start_code_is_valid(start_code)) {
/* New start code found */