X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fcbs_mpeg2.c;h=8b8b2665631edbeaa2c5f81cc9fefab1db49749e;hb=d6fc5dc24aa09e026c6271a7565e63798dfe46f3;hp=bfb64a0851192d555768cba9dfcafe3f6c3cdd0d;hpb=a123e576a485931013c9fae85025d0e78ff3102d;p=ffmpeg diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index bfb64a08511..8b8b2665631 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -38,24 +38,29 @@ #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 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) \ @@ -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; @@ -197,16 +192,11 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx, 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 { @@ -274,8 +264,6 @@ static int cbs_mpeg2_write_slice(CodedBitstreamContext *ctx, PutBitContext *pbc) { MPEG2RawSlice *slice = unit->content; - GetBitContext gbc; - 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); - init_get_bits(&gbc, slice->data, slice->data_size * 8); - skip_bits_long(&gbc, slice->data_bit_start); - - while (get_bits_left(&gbc) > 15) - put_bits(pbc, 16, get_bits(&gbc, 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 = get_bits_left(&gbc); - put_bits(pbc, bits_left, get_bits(&gbc, 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; @@ -362,7 +367,7 @@ 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; @@ -382,8 +387,8 @@ 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);