#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) \
#undef READWRITE
#undef RWContext
#undef xui
-#undef ui
#undef marker_bit
#undef nextbits
#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)
#undef READWRITE
#undef RWContext
#undef xui
-#undef ui
#undef marker_bit
#undef nextbits
+static void cbs_mpeg2_free_user_data(void *unit, uint8_t *content)
+{
+ MPEG2RawUserData *user = (MPEG2RawUserData*)content;
+ av_buffer_unref(&user->user_data_ref);
+ av_freep(&content);
+}
+
+static void cbs_mpeg2_free_slice(void *unit, uint8_t *content)
+{
+ MPEG2RawSlice *slice = (MPEG2RawSlice*)content;
+ av_buffer_unref(&slice->header.extra_information_ref);
+ av_buffer_unref(&slice->data_ref);
+ av_freep(&content);
+}
+
static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
CodedBitstreamFragment *frag,
int header)
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);
- 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;
MPEG2RawSlice *slice;
int pos, len;
- slice = av_mallocz(sizeof(*slice));
- if (!slice)
- return AVERROR(ENOMEM);
+ err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*slice),
+ &cbs_mpeg2_free_slice);
+ if (err < 0)
+ return err;
+ slice = unit->content;
+
err = cbs_mpeg2_read_slice_header(ctx, &gbc, &slice->header);
- if (err < 0) {
- av_free(slice);
+ if (err < 0)
return err;
- }
pos = get_bits_count(&gbc);
len = unit->data_size;
slice->data_size = len - pos / 8;
- slice->data = av_malloc(slice->data_size +
- AV_INPUT_BUFFER_PADDING_SIZE);
- if (!slice->data) {
- av_free(slice);
+ slice->data_ref = av_buffer_ref(unit->data_ref);
+ if (!slice->data_ref)
return AVERROR(ENOMEM);
- }
+ 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;
- unit->content = slice;
-
} else {
switch (unit->type) {
-#define START(start_code, type, func) \
+#define START(start_code, type, read_func, free_func) \
case start_code: \
{ \
type *header; \
- header = av_mallocz(sizeof(*header)); \
- if (!header) \
- return AVERROR(ENOMEM); \
- err = cbs_mpeg2_read_ ## func(ctx, &gbc, header); \
- if (err < 0) { \
- av_free(header); \
+ err = ff_cbs_alloc_unit_content(ctx, unit, \
+ sizeof(*header), free_func); \
+ if (err < 0) \
+ return err; \
+ header = unit->content; \
+ err = cbs_mpeg2_read_ ## read_func(ctx, &gbc, header); \
+ if (err < 0) \
return err; \
- } \
- unit->content = header; \
} \
break;
- START(0x00, MPEG2RawPictureHeader, picture_header);
- START(0xb2, MPEG2RawUserData, user_data);
- START(0xb3, MPEG2RawSequenceHeader, sequence_header);
- START(0xb5, MPEG2RawExtensionData, extension_data);
- START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header);
+ START(0x00, MPEG2RawPictureHeader, picture_header, NULL);
+ START(0xb2, MPEG2RawUserData, user_data,
+ &cbs_mpeg2_free_user_data);
+ START(0xb3, MPEG2RawSequenceHeader, sequence_header, NULL);
+ START(0xb5, MPEG2RawExtensionData, extension_data, NULL);
+ START(0xb8, MPEG2RawGroupOfPicturesHeader,
+ group_of_pictures_header, NULL);
#undef START
default:
av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown start code %02"PRIx32".\n",
unit->data_size = (put_bits_count(&pbc) + 7) / 8;
flush_put_bits(&pbc);
- err = av_reallocp(&unit->data, unit->data_size);
+ err = ff_cbs_alloc_unit_data(ctx, unit, unit->data_size);
if (err < 0)
return err;
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;
- data = av_malloc(size);
- if (!data)
+ 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++) {
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;
return 0;
}
-static void cbs_mpeg2_free_unit(CodedBitstreamUnit *unit)
-{
- if (MPEG2_START_IS_SLICE(unit->type)) {
- MPEG2RawSlice *slice = unit->content;
- av_freep(&slice->data);
- av_freep(&slice->header.extra_information);
- } else if (unit->type == MPEG2_START_USER_DATA) {
- MPEG2RawUserData *user = unit->content;
- av_freep(&user->user_data);
- }
- av_freep(&unit->content);
-}
-
static void cbs_mpeg2_close(CodedBitstreamContext *ctx)
{
CodedBitstreamMPEG2Context *priv = ctx->priv_data;
.write_unit = &cbs_mpeg2_write_unit,
.assemble_fragment = &cbs_mpeg2_assemble_fragment,
- .free_unit = &cbs_mpeg2_free_unit,
.close = &cbs_mpeg2_close,
};