cbs_mpeg2: Fix parsing the last unit

There is one way to find out if avpriv_find_start_code has found a start
code or not: One has to check whether the state variable contains a
start code, i.e. whether the three most significant bytes are 0x00 00 01.
Checking for whether the return value is the end of the designated
buffer is not enough: If the last four bytes constitute a start code,
the return value is also the end of the buffer. This happens with
sequence_end_codes which have been ignored for exactly this reason,
although e.g. all three files used for fate tests of cbs_mpeg2 contain
sequence_end_codes.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
This commit is contained in:
Andreas Rheinhardt 2019-07-29 21:56:56 +02:00 committed by Mark Thompson
parent 276b21a586
commit fd93d5efe6

View File

@ -170,27 +170,41 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
CodedBitstreamUnitType unit_type; CodedBitstreamUnitType unit_type;
uint32_t start_code = -1; uint32_t start_code = -1;
size_t unit_size; size_t unit_size;
int err, i; int err, i, final = 0;
start = avpriv_find_start_code(frag->data, frag->data + frag->data_size, start = avpriv_find_start_code(frag->data, frag->data + frag->data_size,
&start_code); &start_code);
if (start_code >> 8 != 0x000001) {
// No start code found.
return AVERROR_INVALIDDATA;
}
for (i = 0;; i++) { for (i = 0;; i++) {
unit_type = start_code & 0xff; unit_type = start_code & 0xff;
if (start == frag->data + frag->data_size) {
// The last four bytes form a start code which constitutes
// a unit of its own. In this situation avpriv_find_start_code
// won't modify start_code at all so modify start_code so that
// the next unit will be treated as the last unit.
start_code = 0;
}
end = avpriv_find_start_code(start--, frag->data + frag->data_size, end = avpriv_find_start_code(start--, frag->data + frag->data_size,
&start_code); &start_code);
// start points to the byte containing the start_code_identifier // start points to the byte containing the start_code_identifier
// (or to the last byte of fragment->data); end points to the byte // (may be the last byte of fragment->data); end points to the byte
// following the byte containing the start code identifier (or to // following the byte containing the start code identifier (or to
// the end of fragment->data). // the end of fragment->data).
if (end == frag->data + frag->data_size) { if (start_code >> 8 == 0x000001) {
// We didn't find a start code, so this is the final unit.
unit_size = end - start;
} else {
// Unit runs from start to the beginning of the start code // Unit runs from start to the beginning of the start code
// pointed to by end (including any padding zeroes). // pointed to by end (including any padding zeroes).
unit_size = (end - 4) - start; unit_size = (end - 4) - start;
} else {
// We didn't find a start code, so this is the final unit.
unit_size = end - start;
final = 1;
} }
err = ff_cbs_insert_unit_data(ctx, frag, i, unit_type, (uint8_t*)start, err = ff_cbs_insert_unit_data(ctx, frag, i, unit_type, (uint8_t*)start,
@ -198,7 +212,7 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
if (err < 0) if (err < 0)
return err; return err;
if (end == frag->data + frag->data_size) if (final)
break; break;
start = end; start = end;