|
|
|
/*
|
|
|
|
* This file is part of FFmpeg.
|
|
|
|
*
|
|
|
|
* FFmpeg is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* FFmpeg is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with FFmpeg; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "libavutil/avassert.h"
|
|
|
|
|
|
|
|
#include "cbs.h"
|
|
|
|
#include "cbs_internal.h"
|
|
|
|
#include "cbs_mpeg2.h"
|
|
|
|
#include "startcode.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define HEADER(name) do { \
|
|
|
|
ff_cbs_trace_header(ctx, name); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define CHECK(call) do { \
|
|
|
|
err = (call); \
|
|
|
|
if (err < 0) \
|
|
|
|
return err; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
|
|
|
|
#define FUNC_MPEG2(rw, name) FUNC_NAME(rw, mpeg2, name)
|
|
|
|
#define FUNC(name) FUNC_MPEG2(READWRITE, name)
|
|
|
|
|
|
|
|
#define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
|
|
|
|
|
|
|
|
#define ui(width, name) \
|
|
|
|
xui(width, name, current->name, 0, MAX_UINT_BITS(width), 0, )
|
|
|
|
#define uir(width, name) \
|
|
|
|
xui(width, name, current->name, 1, MAX_UINT_BITS(width), 0, )
|
|
|
|
#define uis(width, name, subs, ...) \
|
|
|
|
xui(width, name, current->name, 0, MAX_UINT_BITS(width), subs, __VA_ARGS__)
|
|
|
|
#define uirs(width, name, subs, ...) \
|
|
|
|
xui(width, name, current->name, 1, MAX_UINT_BITS(width), subs, __VA_ARGS__)
|
cbs_mpeg2: Fix parsing of picture and slice headers
1. The extra information in slice headers was parsed incorrectly:
In the first reading pass to derive the length of the extra information,
one should look at bits n, n + 9, n + 18, ... and check whether they
equal one (further extra information) or zero (end of extra information),
but instead bits n, n + 8, n + 16, ... were inspected. The second pass
of reading (where the length is already known and the bytes between the
length-determining bits are copied into a buffer) did not record what
was in bits n, n + 9, n + 18, ..., presuming they equal one. And during
writing, the bytes in the buffer are interleaved with set bits and
written. This means that if the detected length of the extra information
was greater than the real length, the output was corrupted. Fortunately
no sample is known that made use of this mechanism: The extra information
in slices is still marked as reserved in the specifications. cbs_mpeg2
is now ready in case this changes.
2. Furthermore, the buffer is now padded and slightly different, but
very similar code for reading resp. writing has been replaced by code
used for both. This was made possible by a new macro, the equivalent
to cbs_h2645's fixed().
3. These changes also made it possible to remove the extra_bit_slice
element from the MPEG2RawSliceHeader structure. Said element was always
zero except when the detected length of the extra information was less
than the real length.
4. The extra information in picture headers (which uses essentially the
same syntax as the extra information in slice headers) has simply been
forgotten. This meant that if this extra information was present, it was
discarded during reading; and unfortunately writing created invalid
bitstreams in this case (an extra_bit_picture - the last set bit of the
whole unit - indicated that there would be a further byte of data,
although the output didn't contain said data).
This has been fixed; both types of extra information are now parsed via
the same code and essentially passed through.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
6 years ago
|
|
|
#define xui(width, name, var, range_min, range_max, subs, ...) \
|
|
|
|
xuia(width, #name, var, range_min, range_max, subs, __VA_ARGS__)
|
|
|
|
#define sis(width, name, subs, ...) \
|
|
|
|
xsi(width, name, current->name, subs, __VA_ARGS__)
|
|
|
|
|
cbs_mpeg2: Fix parsing of picture and slice headers
1. The extra information in slice headers was parsed incorrectly:
In the first reading pass to derive the length of the extra information,
one should look at bits n, n + 9, n + 18, ... and check whether they
equal one (further extra information) or zero (end of extra information),
but instead bits n, n + 8, n + 16, ... were inspected. The second pass
of reading (where the length is already known and the bytes between the
length-determining bits are copied into a buffer) did not record what
was in bits n, n + 9, n + 18, ..., presuming they equal one. And during
writing, the bytes in the buffer are interleaved with set bits and
written. This means that if the detected length of the extra information
was greater than the real length, the output was corrupted. Fortunately
no sample is known that made use of this mechanism: The extra information
in slices is still marked as reserved in the specifications. cbs_mpeg2
is now ready in case this changes.
2. Furthermore, the buffer is now padded and slightly different, but
very similar code for reading resp. writing has been replaced by code
used for both. This was made possible by a new macro, the equivalent
to cbs_h2645's fixed().
3. These changes also made it possible to remove the extra_bit_slice
element from the MPEG2RawSliceHeader structure. Said element was always
zero except when the detected length of the extra information was less
than the real length.
4. The extra information in picture headers (which uses essentially the
same syntax as the extra information in slice headers) has simply been
forgotten. This meant that if this extra information was present, it was
discarded during reading; and unfortunately writing created invalid
bitstreams in this case (an extra_bit_picture - the last set bit of the
whole unit - indicated that there would be a further byte of data,
although the output didn't contain said data).
This has been fixed; both types of extra information are now parsed via
the same code and essentially passed through.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
6 years ago
|
|
|
#define marker_bit() \
|
|
|
|
bit("marker_bit", 1)
|
|
|
|
#define bit(string, value) do { \
|
|
|
|
av_unused uint32_t bit = value; \
|
|
|
|
xuia(1, string, bit, value, value, 0, ); \
|
cbs_mpeg2: Fix parsing of picture and slice headers
1. The extra information in slice headers was parsed incorrectly:
In the first reading pass to derive the length of the extra information,
one should look at bits n, n + 9, n + 18, ... and check whether they
equal one (further extra information) or zero (end of extra information),
but instead bits n, n + 8, n + 16, ... were inspected. The second pass
of reading (where the length is already known and the bytes between the
length-determining bits are copied into a buffer) did not record what
was in bits n, n + 9, n + 18, ..., presuming they equal one. And during
writing, the bytes in the buffer are interleaved with set bits and
written. This means that if the detected length of the extra information
was greater than the real length, the output was corrupted. Fortunately
no sample is known that made use of this mechanism: The extra information
in slices is still marked as reserved in the specifications. cbs_mpeg2
is now ready in case this changes.
2. Furthermore, the buffer is now padded and slightly different, but
very similar code for reading resp. writing has been replaced by code
used for both. This was made possible by a new macro, the equivalent
to cbs_h2645's fixed().
3. These changes also made it possible to remove the extra_bit_slice
element from the MPEG2RawSliceHeader structure. Said element was always
zero except when the detected length of the extra information was less
than the real length.
4. The extra information in picture headers (which uses essentially the
same syntax as the extra information in slice headers) has simply been
forgotten. This meant that if this extra information was present, it was
discarded during reading; and unfortunately writing created invalid
bitstreams in this case (an extra_bit_picture - the last set bit of the
whole unit - indicated that there would be a further byte of data,
although the output didn't contain said data).
This has been fixed; both types of extra information are now parsed via
the same code and essentially passed through.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
6 years ago
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
|
|
#define READ
|
|
|
|
#define READWRITE read
|
|
|
|
#define RWContext GetBitContext
|
|
|
|
|
cbs_mpeg2: Fix parsing of picture and slice headers
1. The extra information in slice headers was parsed incorrectly:
In the first reading pass to derive the length of the extra information,
one should look at bits n, n + 9, n + 18, ... and check whether they
equal one (further extra information) or zero (end of extra information),
but instead bits n, n + 8, n + 16, ... were inspected. The second pass
of reading (where the length is already known and the bytes between the
length-determining bits are copied into a buffer) did not record what
was in bits n, n + 9, n + 18, ..., presuming they equal one. And during
writing, the bytes in the buffer are interleaved with set bits and
written. This means that if the detected length of the extra information
was greater than the real length, the output was corrupted. Fortunately
no sample is known that made use of this mechanism: The extra information
in slices is still marked as reserved in the specifications. cbs_mpeg2
is now ready in case this changes.
2. Furthermore, the buffer is now padded and slightly different, but
very similar code for reading resp. writing has been replaced by code
used for both. This was made possible by a new macro, the equivalent
to cbs_h2645's fixed().
3. These changes also made it possible to remove the extra_bit_slice
element from the MPEG2RawSliceHeader structure. Said element was always
zero except when the detected length of the extra information was less
than the real length.
4. The extra information in picture headers (which uses essentially the
same syntax as the extra information in slice headers) has simply been
forgotten. This meant that if this extra information was present, it was
discarded during reading; and unfortunately writing created invalid
bitstreams in this case (an extra_bit_picture - the last set bit of the
whole unit - indicated that there would be a further byte of data,
although the output didn't contain said data).
This has been fixed; both types of extra information are now parsed via
the same code and essentially passed through.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
6 years ago
|
|
|
#define xuia(width, string, var, range_min, range_max, subs, ...) do { \
|
|
|
|
uint32_t value; \
|
cbs_mpeg2: Fix parsing of picture and slice headers
1. The extra information in slice headers was parsed incorrectly:
In the first reading pass to derive the length of the extra information,
one should look at bits n, n + 9, n + 18, ... and check whether they
equal one (further extra information) or zero (end of extra information),
but instead bits n, n + 8, n + 16, ... were inspected. The second pass
of reading (where the length is already known and the bytes between the
length-determining bits are copied into a buffer) did not record what
was in bits n, n + 9, n + 18, ..., presuming they equal one. And during
writing, the bytes in the buffer are interleaved with set bits and
written. This means that if the detected length of the extra information
was greater than the real length, the output was corrupted. Fortunately
no sample is known that made use of this mechanism: The extra information
in slices is still marked as reserved in the specifications. cbs_mpeg2
is now ready in case this changes.
2. Furthermore, the buffer is now padded and slightly different, but
very similar code for reading resp. writing has been replaced by code
used for both. This was made possible by a new macro, the equivalent
to cbs_h2645's fixed().
3. These changes also made it possible to remove the extra_bit_slice
element from the MPEG2RawSliceHeader structure. Said element was always
zero except when the detected length of the extra information was less
than the real length.
4. The extra information in picture headers (which uses essentially the
same syntax as the extra information in slice headers) has simply been
forgotten. This meant that if this extra information was present, it was
discarded during reading; and unfortunately writing created invalid
bitstreams in this case (an extra_bit_picture - the last set bit of the
whole unit - indicated that there would be a further byte of data,
although the output didn't contain said data).
This has been fixed; both types of extra information are now parsed via
the same code and essentially passed through.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
6 years ago
|
|
|
CHECK(ff_cbs_read_unsigned(ctx, rw, width, string, \
|
|
|
|
SUBSCRIPTS(subs, __VA_ARGS__), \
|
|
|
|
&value, range_min, range_max)); \
|
|
|
|
var = value; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define xsi(width, name, var, subs, ...) do { \
|
|
|
|
int32_t value; \
|
|
|
|
CHECK(ff_cbs_read_signed(ctx, rw, width, #name, \
|
|
|
|
SUBSCRIPTS(subs, __VA_ARGS__), &value, \
|
|
|
|
MIN_INT_BITS(width), \
|
|
|
|
MAX_INT_BITS(width))); \
|
|
|
|
var = value; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define nextbits(width, compare, var) \
|
|
|
|
(get_bits_left(rw) >= width && \
|
|
|
|
(var = show_bits(rw, width)) == (compare))
|
|
|
|
|
|
|
|
#define infer(name, value) do { \
|
|
|
|
current->name = value; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#include "cbs_mpeg2_syntax_template.c"
|
|
|
|
|
|
|
|
#undef READ
|
|
|
|
#undef READWRITE
|
|
|
|
#undef RWContext
|
cbs_mpeg2: Fix parsing of picture and slice headers
1. The extra information in slice headers was parsed incorrectly:
In the first reading pass to derive the length of the extra information,
one should look at bits n, n + 9, n + 18, ... and check whether they
equal one (further extra information) or zero (end of extra information),
but instead bits n, n + 8, n + 16, ... were inspected. The second pass
of reading (where the length is already known and the bytes between the
length-determining bits are copied into a buffer) did not record what
was in bits n, n + 9, n + 18, ..., presuming they equal one. And during
writing, the bytes in the buffer are interleaved with set bits and
written. This means that if the detected length of the extra information
was greater than the real length, the output was corrupted. Fortunately
no sample is known that made use of this mechanism: The extra information
in slices is still marked as reserved in the specifications. cbs_mpeg2
is now ready in case this changes.
2. Furthermore, the buffer is now padded and slightly different, but
very similar code for reading resp. writing has been replaced by code
used for both. This was made possible by a new macro, the equivalent
to cbs_h2645's fixed().
3. These changes also made it possible to remove the extra_bit_slice
element from the MPEG2RawSliceHeader structure. Said element was always
zero except when the detected length of the extra information was less
than the real length.
4. The extra information in picture headers (which uses essentially the
same syntax as the extra information in slice headers) has simply been
forgotten. This meant that if this extra information was present, it was
discarded during reading; and unfortunately writing created invalid
bitstreams in this case (an extra_bit_picture - the last set bit of the
whole unit - indicated that there would be a further byte of data,
although the output didn't contain said data).
This has been fixed; both types of extra information are now parsed via
the same code and essentially passed through.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
6 years ago
|
|
|
#undef xuia
|
|
|
|
#undef xsi
|
|
|
|
#undef nextbits
|
|
|
|
#undef infer
|
|
|
|
|
|
|
|
|
|
|
|
#define WRITE
|
|
|
|
#define READWRITE write
|
|
|
|
#define RWContext PutBitContext
|
|
|
|
|
cbs_mpeg2: Fix parsing of picture and slice headers
1. The extra information in slice headers was parsed incorrectly:
In the first reading pass to derive the length of the extra information,
one should look at bits n, n + 9, n + 18, ... and check whether they
equal one (further extra information) or zero (end of extra information),
but instead bits n, n + 8, n + 16, ... were inspected. The second pass
of reading (where the length is already known and the bytes between the
length-determining bits are copied into a buffer) did not record what
was in bits n, n + 9, n + 18, ..., presuming they equal one. And during
writing, the bytes in the buffer are interleaved with set bits and
written. This means that if the detected length of the extra information
was greater than the real length, the output was corrupted. Fortunately
no sample is known that made use of this mechanism: The extra information
in slices is still marked as reserved in the specifications. cbs_mpeg2
is now ready in case this changes.
2. Furthermore, the buffer is now padded and slightly different, but
very similar code for reading resp. writing has been replaced by code
used for both. This was made possible by a new macro, the equivalent
to cbs_h2645's fixed().
3. These changes also made it possible to remove the extra_bit_slice
element from the MPEG2RawSliceHeader structure. Said element was always
zero except when the detected length of the extra information was less
than the real length.
4. The extra information in picture headers (which uses essentially the
same syntax as the extra information in slice headers) has simply been
forgotten. This meant that if this extra information was present, it was
discarded during reading; and unfortunately writing created invalid
bitstreams in this case (an extra_bit_picture - the last set bit of the
whole unit - indicated that there would be a further byte of data,
although the output didn't contain said data).
This has been fixed; both types of extra information are now parsed via
the same code and essentially passed through.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
6 years ago
|
|
|
#define xuia(width, string, var, range_min, range_max, subs, ...) do { \
|
|
|
|
CHECK(ff_cbs_write_unsigned(ctx, rw, width, string, \
|
|
|
|
SUBSCRIPTS(subs, __VA_ARGS__), \
|
|
|
|
var, range_min, range_max)); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define xsi(width, name, var, subs, ...) do { \
|
|
|
|
CHECK(ff_cbs_write_signed(ctx, rw, width, #name, \
|
|
|
|
SUBSCRIPTS(subs, __VA_ARGS__), var, \
|
|
|
|
MIN_INT_BITS(width), \
|
|
|
|
MAX_INT_BITS(width))); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define nextbits(width, compare, var) (var)
|
|
|
|
|
|
|
|
#define infer(name, value) do { \
|
|
|
|
if (current->name != (value)) { \
|
|
|
|
av_log(ctx->log_ctx, AV_LOG_WARNING, "Warning: " \
|
|
|
|
"%s does not match inferred value: " \
|
|
|
|
"%"PRId64", but should be %"PRId64".\n", \
|
|
|
|
#name, (int64_t)current->name, (int64_t)(value)); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#include "cbs_mpeg2_syntax_template.c"
|
|
|
|
|
|
|
|
#undef WRITE
|
|
|
|
#undef READWRITE
|
|
|
|
#undef RWContext
|
cbs_mpeg2: Fix parsing of picture and slice headers
1. The extra information in slice headers was parsed incorrectly:
In the first reading pass to derive the length of the extra information,
one should look at bits n, n + 9, n + 18, ... and check whether they
equal one (further extra information) or zero (end of extra information),
but instead bits n, n + 8, n + 16, ... were inspected. The second pass
of reading (where the length is already known and the bytes between the
length-determining bits are copied into a buffer) did not record what
was in bits n, n + 9, n + 18, ..., presuming they equal one. And during
writing, the bytes in the buffer are interleaved with set bits and
written. This means that if the detected length of the extra information
was greater than the real length, the output was corrupted. Fortunately
no sample is known that made use of this mechanism: The extra information
in slices is still marked as reserved in the specifications. cbs_mpeg2
is now ready in case this changes.
2. Furthermore, the buffer is now padded and slightly different, but
very similar code for reading resp. writing has been replaced by code
used for both. This was made possible by a new macro, the equivalent
to cbs_h2645's fixed().
3. These changes also made it possible to remove the extra_bit_slice
element from the MPEG2RawSliceHeader structure. Said element was always
zero except when the detected length of the extra information was less
than the real length.
4. The extra information in picture headers (which uses essentially the
same syntax as the extra information in slice headers) has simply been
forgotten. This meant that if this extra information was present, it was
discarded during reading; and unfortunately writing created invalid
bitstreams in this case (an extra_bit_picture - the last set bit of the
whole unit - indicated that there would be a further byte of data,
although the output didn't contain said data).
This has been fixed; both types of extra information are now parsed via
the same code and essentially passed through.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
6 years ago
|
|
|
#undef xuia
|
|
|
|
#undef xsi
|
|
|
|
#undef nextbits
|
|
|
|
#undef infer
|
|
|
|
|
|
|
|
|
|
|
|
static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
|
|
|
|
CodedBitstreamFragment *frag,
|
|
|
|
int header)
|
|
|
|
{
|
|
|
|
const uint8_t *start;
|
|
|
|
uint32_t start_code = -1;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
CodedBitstreamUnitType unit_type = start_code & 0xff;
|
|
|
|
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);
|
|
|
|
|
|
|
|
// start points to the byte containing the start_code_identifier
|
|
|
|
// (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 (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;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = ff_cbs_append_unit_data(frag, unit_type, (uint8_t*)start,
|
|
|
|
unit_size, frag->data_ref);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
start = end;
|
|
|
|
|
|
|
|
// Do we have a further unit to add to the fragment?
|
|
|
|
} while ((start_code >> 8) == 0x000001);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx,
|
|
|
|
CodedBitstreamUnit *unit)
|
|
|
|
{
|
|
|
|
GetBitContext gbc;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = init_get_bits(&gbc, unit->data, 8 * unit->data_size);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
err = ff_cbs_alloc_unit_content2(ctx, unit);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (MPEG2_START_IS_SLICE(unit->type)) {
|
|
|
|
MPEG2RawSlice *slice = unit->content;
|
|
|
|
int pos, len;
|
|
|
|
|
|
|
|
err = cbs_mpeg2_read_slice_header(ctx, &gbc, &slice->header);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (!get_bits_left(&gbc))
|
|
|
|
return AVERROR_INVALIDDATA;
|
|
|
|
|
|
|
|
pos = get_bits_count(&gbc);
|
|
|
|
len = unit->data_size;
|
|
|
|
|
|
|
|
slice->data_size = len - pos / 8;
|
|
|
|
slice->data_ref = av_buffer_ref(unit->data_ref);
|
|
|
|
if (!slice->data_ref)
|
|
|
|
return AVERROR(ENOMEM);
|
|
|
|
slice->data = unit->data + pos / 8;
|
|
|
|
|
|
|
|
slice->data_bit_start = pos % 8;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
switch (unit->type) {
|
|
|
|
#define START(start_code, type, read_func, free_func) \
|
|
|
|
case start_code: \
|
|
|
|
{ \
|
|
|
|
type *header = unit->content; \
|
|
|
|
err = cbs_mpeg2_read_ ## read_func(ctx, &gbc, header); \
|
|
|
|
if (err < 0) \
|
|
|
|
return err; \
|
|
|
|
} \
|
|
|
|
break;
|
|
|
|
START(MPEG2_START_PICTURE, MPEG2RawPictureHeader,
|
cbs_mpeg2: Fix parsing of picture and slice headers
1. The extra information in slice headers was parsed incorrectly:
In the first reading pass to derive the length of the extra information,
one should look at bits n, n + 9, n + 18, ... and check whether they
equal one (further extra information) or zero (end of extra information),
but instead bits n, n + 8, n + 16, ... were inspected. The second pass
of reading (where the length is already known and the bytes between the
length-determining bits are copied into a buffer) did not record what
was in bits n, n + 9, n + 18, ..., presuming they equal one. And during
writing, the bytes in the buffer are interleaved with set bits and
written. This means that if the detected length of the extra information
was greater than the real length, the output was corrupted. Fortunately
no sample is known that made use of this mechanism: The extra information
in slices is still marked as reserved in the specifications. cbs_mpeg2
is now ready in case this changes.
2. Furthermore, the buffer is now padded and slightly different, but
very similar code for reading resp. writing has been replaced by code
used for both. This was made possible by a new macro, the equivalent
to cbs_h2645's fixed().
3. These changes also made it possible to remove the extra_bit_slice
element from the MPEG2RawSliceHeader structure. Said element was always
zero except when the detected length of the extra information was less
than the real length.
4. The extra information in picture headers (which uses essentially the
same syntax as the extra information in slice headers) has simply been
forgotten. This meant that if this extra information was present, it was
discarded during reading; and unfortunately writing created invalid
bitstreams in this case (an extra_bit_picture - the last set bit of the
whole unit - indicated that there would be a further byte of data,
although the output didn't contain said data).
This has been fixed; both types of extra information are now parsed via
the same code and essentially passed through.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
6 years ago
|
|
|
picture_header, &cbs_mpeg2_free_picture_header);
|
|
|
|
START(MPEG2_START_USER_DATA, MPEG2RawUserData,
|
|
|
|
user_data, &cbs_mpeg2_free_user_data);
|
|
|
|
START(MPEG2_START_SEQUENCE_HEADER, MPEG2RawSequenceHeader,
|
|
|
|
sequence_header, NULL);
|
|
|
|
START(MPEG2_START_EXTENSION, MPEG2RawExtensionData,
|
|
|
|
extension_data, NULL);
|
|
|
|
START(MPEG2_START_GROUP, MPEG2RawGroupOfPicturesHeader,
|
|
|
|
group_of_pictures_header, NULL);
|
|
|
|
START(MPEG2_START_SEQUENCE_END, MPEG2RawSequenceEnd,
|
|
|
|
sequence_end, NULL);
|
|
|
|
#undef START
|
|
|
|
default:
|
|
|
|
return AVERROR(ENOSYS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cbs_mpeg2_write_header(CodedBitstreamContext *ctx,
|
|
|
|
CodedBitstreamUnit *unit,
|
|
|
|
PutBitContext *pbc)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
switch (unit->type) {
|
|
|
|
#define START(start_code, type, func) \
|
|
|
|
case start_code: \
|
|
|
|
err = cbs_mpeg2_write_ ## func(ctx, pbc, unit->content); \
|
|
|
|
break;
|
|
|
|
START(MPEG2_START_PICTURE, MPEG2RawPictureHeader, picture_header);
|
|
|
|
START(MPEG2_START_USER_DATA, MPEG2RawUserData, user_data);
|
|
|
|
START(MPEG2_START_SEQUENCE_HEADER, MPEG2RawSequenceHeader, sequence_header);
|
|
|
|
START(MPEG2_START_EXTENSION, MPEG2RawExtensionData, extension_data);
|
|
|
|
START(MPEG2_START_GROUP, MPEG2RawGroupOfPicturesHeader,
|
|
|
|
group_of_pictures_header);
|
|
|
|
START(MPEG2_START_SEQUENCE_END, MPEG2RawSequenceEnd, sequence_end);
|
|
|
|
#undef START
|
|
|
|
default:
|
|
|
|
av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for start "
|
|
|
|
"code %02"PRIx32".\n", unit->type);
|
|
|
|
return AVERROR_PATCHWELCOME;
|
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cbs_mpeg2_write_slice(CodedBitstreamContext *ctx,
|
|
|
|
CodedBitstreamUnit *unit,
|
|
|
|
PutBitContext *pbc)
|
|
|
|
{
|
|
|
|
MPEG2RawSlice *slice = unit->content;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = cbs_mpeg2_write_slice_header(ctx, pbc, &slice->header);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (slice->data) {
|
|
|
|
size_t rest = slice->data_size - (slice->data_bit_start + 7) / 8;
|
|
|
|
uint8_t *pos = slice->data + slice->data_bit_start / 8;
|
|
|
|
|
|
|
|
av_assert0(slice->data_bit_start >= 0 &&
|
|
|
|
slice->data_size > slice->data_bit_start / 8);
|
|
|
|
|
|
|
|
if (slice->data_size * 8 + 8 > put_bits_left(pbc))
|
|
|
|
return AVERROR(ENOSPC);
|
|
|
|
|
|
|
|
// First copy the remaining bits of the first byte
|
|
|
|
if (slice->data_bit_start % 8)
|
|
|
|
put_bits(pbc, 8 - slice->data_bit_start % 8,
|
|
|
|
*pos++ & MAX_UINT_BITS(8 - slice->data_bit_start % 8));
|
|
|
|
|
|
|
|
if (put_bits_count(pbc) % 8 == 0) {
|
|
|
|
// If the writer is aligned at this point,
|
|
|
|
// memcpy can be used to improve performance.
|
|
|
|
// This is the normal case.
|
|
|
|
flush_put_bits(pbc);
|
|
|
|
memcpy(put_bits_ptr(pbc), pos, rest);
|
|
|
|
skip_put_bytes(pbc, rest);
|
|
|
|
} else {
|
|
|
|
// If not, we have to copy manually:
|
|
|
|
for (; rest > 3; rest -= 4, pos += 4)
|
|
|
|
put_bits32(pbc, AV_RB32(pos));
|
|
|
|
|
|
|
|
for (; rest; rest--, pos++)
|
|
|
|
put_bits(pbc, 8, *pos);
|
|
|
|
|
|
|
|
// Align with zeros
|
|
|
|
put_bits(pbc, 8 - put_bits_count(pbc) % 8, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cbs_mpeg2_write_unit(CodedBitstreamContext *ctx,
|
|
|
|
CodedBitstreamUnit *unit,
|
|
|
|
PutBitContext *pbc)
|
|
|
|
{
|
|
|
|
if (MPEG2_START_IS_SLICE(unit->type))
|
|
|
|
return cbs_mpeg2_write_slice (ctx, unit, pbc);
|
|
|
|
else
|
|
|
|
return cbs_mpeg2_write_header(ctx, unit, pbc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx,
|
|
|
|
CodedBitstreamFragment *frag)
|
|
|
|
{
|
|
|
|
uint8_t *data;
|
|
|
|
size_t size, dp;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
size = 0;
|
|
|
|
for (i = 0; i < frag->nb_units; i++)
|
|
|
|
size += 3 + frag->units[i].data_size;
|
|
|
|
|
|
|
|
frag->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
|
|
|
|
if (!frag->data_ref)
|
|
|
|
return AVERROR(ENOMEM);
|
|
|
|
data = frag->data_ref->data;
|
|
|
|
|
|
|
|
dp = 0;
|
|
|
|
for (i = 0; i < frag->nb_units; i++) {
|
|
|
|
CodedBitstreamUnit *unit = &frag->units[i];
|
|
|
|
|
|
|
|
data[dp++] = 0;
|
|
|
|
data[dp++] = 0;
|
|
|
|
data[dp++] = 1;
|
|
|
|
|
|
|
|
memcpy(data + dp, unit->data, unit->data_size);
|
|
|
|
dp += unit->data_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
av_assert0(dp == size);
|
|
|
|
|
|
|
|
memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
|
|
|
|
frag->data = data;
|
|
|
|
frag->data_size = size;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const CodedBitstreamUnitTypeDescriptor cbs_mpeg2_unit_types[] = {
|
|
|
|
CBS_UNIT_TYPE_INTERNAL_REF(MPEG2_START_PICTURE, MPEG2RawPictureHeader,
|
|
|
|
extra_information_picture.extra_information),
|
|
|
|
|
|
|
|
{
|
|
|
|
.nb_unit_types = CBS_UNIT_TYPE_RANGE,
|
|
|
|
.unit_type_range_start = 0x01,
|
|
|
|
.unit_type_range_end = 0xaf,
|
|
|
|
|
|
|
|
.content_type = CBS_CONTENT_TYPE_INTERNAL_REFS,
|
|
|
|
.content_size = sizeof(MPEG2RawSlice),
|
|
|
|
.nb_ref_offsets = 2,
|
|
|
|
.ref_offsets = { offsetof(MPEG2RawSlice, header.extra_information_slice.extra_information),
|
|
|
|
offsetof(MPEG2RawSlice, data) },
|
|
|
|
},
|
|
|
|
|
|
|
|
CBS_UNIT_TYPE_INTERNAL_REF(MPEG2_START_USER_DATA, MPEG2RawUserData,
|
|
|
|
user_data),
|
|
|
|
|
|
|
|
CBS_UNIT_TYPE_POD(MPEG2_START_SEQUENCE_HEADER, MPEG2RawSequenceHeader),
|
|
|
|
CBS_UNIT_TYPE_POD(MPEG2_START_EXTENSION, MPEG2RawExtensionData),
|
|
|
|
CBS_UNIT_TYPE_POD(MPEG2_START_SEQUENCE_END, MPEG2RawSequenceEnd),
|
|
|
|
CBS_UNIT_TYPE_POD(MPEG2_START_GROUP, MPEG2RawGroupOfPicturesHeader),
|
|
|
|
|
|
|
|
CBS_UNIT_TYPE_END_OF_LIST
|
|
|
|
};
|
|
|
|
|
|
|
|
const CodedBitstreamType ff_cbs_type_mpeg2 = {
|
|
|
|
.codec_id = AV_CODEC_ID_MPEG2VIDEO,
|
|
|
|
|
|
|
|
.priv_data_size = sizeof(CodedBitstreamMPEG2Context),
|
|
|
|
|
|
|
|
.unit_types = cbs_mpeg2_unit_types,
|
|
|
|
|
|
|
|
.split_fragment = &cbs_mpeg2_split_fragment,
|
|
|
|
.read_unit = &cbs_mpeg2_read_unit,
|
|
|
|
.write_unit = &cbs_mpeg2_write_unit,
|
|
|
|
.assemble_fragment = &cbs_mpeg2_assemble_fragment,
|
|
|
|
};
|