diff options
Diffstat (limited to 'libavcodec/cbs_mpeg2.c')
-rw-r--r-- | libavcodec/cbs_mpeg2.c | 120 |
1 files changed, 63 insertions, 57 deletions
diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index 3db10c5152..8b8b266563 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -1,18 +1,18 @@ /* - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -38,29 +38,34 @@ #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) +#define uis(width, name, subs, ...) \ + xui(width, name, current->name, subs, __VA_ARGS__) + #define READ #define READWRITE read -#define RWContext BitstreamContext +#define RWContext GetBitContext -#define xui(width, name, var) do { \ +#define xui(width, name, var, subs, ...) do { \ uint32_t value = 0; \ CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \ + SUBSCRIPTS(subs, __VA_ARGS__), \ &value, 0, (1 << width) - 1)); \ var = value; \ } while (0) -#define ui(width, name) \ - xui(width, name, current->name) - #define marker_bit() do { \ av_unused uint32_t one; \ - CHECK(ff_cbs_read_unsigned(ctx, rw, 1, "marker_bit", &one, 1, 1)); \ + CHECK(ff_cbs_read_unsigned(ctx, rw, 1, "marker_bit", NULL, &one, 1, 1)); \ } while (0) #define nextbits(width, compare, var) \ - (bitstream_bits_left(rw) >= width && \ - (var = bitstream_peek(rw, width)) == (compare)) + (get_bits_left(rw) >= width && \ + (var = show_bits(rw, width)) == (compare)) #include "cbs_mpeg2_syntax_template.c" @@ -68,7 +73,6 @@ #undef READWRITE #undef RWContext #undef xui -#undef ui #undef marker_bit #undef nextbits @@ -77,16 +81,14 @@ #define READWRITE write #define RWContext PutBitContext -#define xui(width, name, var) do { \ +#define xui(width, name, var, subs, ...) do { \ CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \ + SUBSCRIPTS(subs, __VA_ARGS__), \ var, 0, (1 << width) - 1)); \ } while (0) -#define ui(width, name) \ - xui(width, name, current->name) - #define marker_bit() do { \ - CHECK(ff_cbs_write_unsigned(ctx, rw, 1, "marker_bit", 1, 1, 1)); \ + CHECK(ff_cbs_write_unsigned(ctx, rw, 1, "marker_bit", NULL, 1, 1, 1)); \ } while (0) #define nextbits(width, compare, var) (var) @@ -97,7 +99,6 @@ #undef READWRITE #undef RWContext #undef xui -#undef ui #undef marker_bit #undef nextbits @@ -146,18 +147,12 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, unit_size = (end - 4) - (start - 1); } - unit_data = av_malloc(unit_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!unit_data) - return AVERROR(ENOMEM); - memcpy(unit_data, start - 1, unit_size); - memset(unit_data + unit_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + unit_data = (uint8_t *)start - 1; err = ff_cbs_insert_unit_data(ctx, frag, i, unit_type, - unit_data, unit_size, NULL); - if (err < 0) { - av_freep(&unit_data); + unit_data, unit_size, frag->data_ref); + if (err < 0) return err; - } if (end == frag->data + frag->data_size) break; @@ -172,10 +167,10 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, CodedBitstreamUnit *unit) { - BitstreamContext bc; + GetBitContext gbc; int err; - err = bitstream_init(&bc, unit->data, 8 * unit->data_size); + err = init_get_bits(&gbc, unit->data, 8 * unit->data_size); if (err < 0) return err; @@ -189,24 +184,19 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, return err; slice = unit->content; - err = cbs_mpeg2_read_slice_header(ctx, &bc, &slice->header); + err = cbs_mpeg2_read_slice_header(ctx, &gbc, &slice->header); if (err < 0) return err; - pos = bitstream_tell(&bc); + pos = get_bits_count(&gbc); len = unit->data_size; slice->data_size = len - pos / 8; - slice->data_ref = av_buffer_alloc(slice->data_size + - AV_INPUT_BUFFER_PADDING_SIZE); + slice->data_ref = av_buffer_ref(unit->data_ref); if (!slice->data_ref) return AVERROR(ENOMEM); - slice->data = slice->data_ref->data; + slice->data = unit->data + pos / 8; - memcpy(slice->data, - unit->data + pos / 8, slice->data_size); - memset(slice->data + slice->data_size, 0, - AV_INPUT_BUFFER_PADDING_SIZE); slice->data_bit_start = pos % 8; } else { @@ -220,7 +210,7 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, if (err < 0) \ return err; \ header = unit->content; \ - err = cbs_mpeg2_read_ ## read_func(ctx, &bc, header); \ + err = cbs_mpeg2_read_ ## read_func(ctx, &gbc, header); \ if (err < 0) \ return err; \ } \ @@ -274,8 +264,6 @@ static int cbs_mpeg2_write_slice(CodedBitstreamContext *ctx, PutBitContext *pbc) { MPEG2RawSlice *slice = unit->content; - BitstreamContext bc; - size_t bits_left; int err; err = cbs_mpeg2_write_slice_header(ctx, pbc, &slice->header); @@ -283,21 +271,38 @@ static int cbs_mpeg2_write_slice(CodedBitstreamContext *ctx, 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 && + 8 * slice->data_size > slice->data_bit_start); + if (slice->data_size * 8 + 8 > put_bits_left(pbc)) return AVERROR(ENOSPC); - bitstream_init(&bc, slice->data, slice->data_size * 8); - bitstream_skip(&bc, slice->data_bit_start); - - while (bitstream_bits_left(&bc) > 15) - put_bits(pbc, 16, bitstream_read(&bc, 16)); + // 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)); - bits_left = bitstream_bits_left(&bc); - put_bits(pbc, bits_left, bitstream_read(&bc, bits_left)); + for (; rest; rest--, pos++) + put_bits(pbc, 8, *pos); - // Align with zeroes. - while (put_bits_count(pbc) % 8 != 0) - put_bits(pbc, 1, 0); + // Align with zeros + put_bits(pbc, 8 - put_bits_count(pbc) % 8, 0); + } } return 0; @@ -319,7 +324,7 @@ static int cbs_mpeg2_write_unit(CodedBitstreamContext *ctx, if (err < 0) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a " "sufficiently large write buffer (last attempt " - "%zu bytes).\n", priv->write_buffer_size); + "%"SIZE_SPECIFIER" bytes).\n", priv->write_buffer_size); return err; } } @@ -362,14 +367,14 @@ static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag) { uint8_t *data; - size_t size, dp, sp; + 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); + frag->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!frag->data_ref) return AVERROR(ENOMEM); data = frag->data_ref->data; @@ -382,12 +387,13 @@ static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx, data[dp++] = 0; data[dp++] = 1; - for (sp = 0; sp < unit->data_size; sp++) - data[dp++] = unit->data[sp]; + 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; |