aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Rheinhardt <andreas.rheinhardt@gmail.com>2019-07-29 21:56:56 +0200
committerJames Almer <jamrial@gmail.com>2019-12-31 16:57:37 -0300
commit14644e33226bf7f280da2bffd387b9fe26572d22 (patch)
tree640bdb5d5272645ba5eaf7a70646f3dfad43a3fb
parentc1fb94fcacf3208ea8396953351a00af56e3f336 (diff)
downloadffmpeg-14644e33226bf7f280da2bffd387b9fe26572d22.tar.gz
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> (cherry picked from commit fd93d5efe64206d5f1bce8c702602353444c0c1a)
-rw-r--r--libavcodec/cbs_mpeg2.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c
index 464bd7add7..c6d0db819e 100644
--- a/libavcodec/cbs_mpeg2.c
+++ b/libavcodec/cbs_mpeg2.c
@@ -170,27 +170,41 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
CodedBitstreamUnitType unit_type;
uint32_t start_code = -1;
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_code);
+ if (start_code >> 8 != 0x000001) {
+ // No start code found.
+ return AVERROR_INVALIDDATA;
+ }
+
for (i = 0;; i++) {
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,
&start_code);
// 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
// the end of fragment->data).
- if (end == frag->data + frag->data_size) {
- // We didn't find a start code, so this is the final unit.
- unit_size = end - start;
- } else {
+ if (start_code >> 8 == 0x000001) {
// Unit runs from start to the beginning of the start code
// pointed to by end (including any padding zeroes).
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,
@@ -198,7 +212,7 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
if (err < 0)
return err;
- if (end == frag->data + frag->data_size)
+ if (final)
break;
start = end;