int bits_per_mb;
int force_quant;
int alpha_bits;
+ int warn;
char *vendor;
int quant_sel;
get_alpha_data(ctx, src, linesize, xp, yp,
pwidth, avctx->height / ctx->pictures_per_frame,
ctx->blocks[0], mbs_per_slice, ctx->alpha_bits);
- sizes[i] = encode_alpha_plane(ctx, pb,
- mbs_per_slice, ctx->blocks[0],
- quant);
+ sizes[i] = encode_alpha_plane(ctx, pb, mbs_per_slice,
+ ctx->blocks[0], quant);
}
total_size += sizes[i];
if (put_bits_left(pb) < 0) {
- av_log(avctx, AV_LOG_ERROR, "Serious underevaluation of"
- "required buffer size");
- return AVERROR_BUFFER_TOO_SMALL;
+ av_log(avctx, AV_LOG_ERROR,
+ "Underestimated required buffer size.\n");
+ return AVERROR_BUG;
}
}
return total_size;
int slice_hdr_size = 2 + 2 * (ctx->num_planes - 1);
int frame_size, picture_size, slice_size;
int pkt_size, ret;
+ int max_slice_size = (ctx->frame_size_upper_bound - 200) / (ctx->pictures_per_frame * ctx->slices_per_picture + 1);
uint8_t frame_flags;
*avctx->coded_frame = *pic;
bytestream_put_byte(&buf, slice_hdr_size << 3);
slice_hdr = buf;
buf += slice_hdr_size - 1;
+ if (pkt_size <= buf - orig_buf + 2 * max_slice_size) {
+ uint8_t *start = pkt->data;
+ // Recompute new size according to max_slice_size
+ // and deduce delta
+ int delta = 200 + (ctx->pictures_per_frame *
+ ctx->slices_per_picture + 1) *
+ max_slice_size - pkt_size;
+
+ delta = FFMAX(delta, 2 * max_slice_size);
+ ctx->frame_size_upper_bound += delta;
+
+ if (!ctx->warn) {
+ avpriv_request_sample(avctx,
+ "Packet too small: is %i,"
+ " needs %i (slice: %i). "
+ "Correct allocation",
+ pkt_size, delta, max_slice_size);
+ ctx->warn = 1;
+ }
+
+ ret = av_grow_packet(pkt, delta);
+ if (ret < 0)
+ return ret;
+
+ pkt_size += delta;
+ // restore pointers
+ orig_buf = pkt->data + (orig_buf - start);
+ buf = pkt->data + (buf - start);
+ picture_size_pos = pkt->data + (picture_size_pos - start);
+ slice_sizes = pkt->data + (slice_sizes - start);
+ slice_hdr = pkt->data + (slice_hdr - start);
+ tmp = pkt->data + (tmp - start);
+ }
init_put_bits(&pb, buf, (pkt_size - (buf - orig_buf)) * 8);
- ret = encode_slice(avctx, pic, &pb, sizes, x, y, q, mbs_per_slice);
+ ret = encode_slice(avctx, pic, &pb, sizes, x, y, q,
+ mbs_per_slice);
if (ret < 0)
return ret;
}
bytestream_put_be16(&slice_sizes, slice_size);
buf += slice_size - slice_hdr_size;
+ if (max_slice_size < slice_size)
+ max_slice_size = slice_size;
}
}
ctx->bits_per_mb = ls * 8;
if (ctx->chroma_factor == CFACTOR_Y444)
ctx->bits_per_mb += ls * 4;
- if (ctx->num_planes == 4)
- ctx->bits_per_mb += ls * 4;
}
- ctx->frame_size_upper_bound = ctx->pictures_per_frame *
- ctx->slices_per_picture *
+ ctx->frame_size_upper_bound = (ctx->pictures_per_frame *
+ ctx->slices_per_picture + 1) *
(2 + 2 * ctx->num_planes +
(mps * ctx->bits_per_mb) / 8)
+ 200;
+ if (ctx->alpha_bits) {
+ // The alpha plane is run-coded and might exceed the bit budget.
+ ctx->frame_size_upper_bound += (ctx->pictures_per_frame *
+ ctx->slices_per_picture + 1) *
+ /* num pixels per slice */ (ctx->mbs_per_slice * 256 *
+ /* bits per pixel */ (1 + ctx->alpha_bits + 1) + 7 >> 3);
+ }
+
avctx->codec_tag = ctx->profile_info->tag;
av_log(avctx, AV_LOG_DEBUG,