prores: allow user to set fixed quantiser

This commit is contained in:
Kostya Shishkov 2012-03-17 15:14:00 +01:00
parent 8bc5d90a7e
commit 6acac061ab
1 changed files with 70 additions and 44 deletions

View File

@ -184,6 +184,7 @@ typedef struct ProresContext {
int num_slices;
int num_planes;
int bits_per_mb;
int force_quant;
char *vendor;
int quant_sel;
@ -397,7 +398,9 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic,
int plane_factor, is_chroma;
uint16_t *qmat;
if (quant < MAX_STORED_Q) {
if (ctx->force_quant) {
qmat = ctx->quants[0];
} else if (quant < MAX_STORED_Q) {
qmat = ctx->quants[quant];
} else {
qmat = ctx->custom_q;
@ -750,6 +753,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
// slices
for (y = 0; y < ctx->mb_height; y++) {
mbs_per_slice = ctx->mbs_per_slice;
if (!ctx->force_quant) {
for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) {
while (ctx->mb_width - x < mbs_per_slice)
mbs_per_slice >>= 1;
@ -761,10 +765,11 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
ctx->slice_q[x] = ctx->nodes[q].quant;
q = ctx->nodes[q].prev_node;
}
}
mbs_per_slice = ctx->mbs_per_slice;
for (x = mb = 0; x < ctx->mb_width; x += mbs_per_slice, mb++) {
q = ctx->slice_q[mb];
q = ctx->force_quant ? ctx->force_quant : ctx->slice_q[mb];
while (ctx->mb_width - x < mbs_per_slice)
mbs_per_slice >>= 1;
@ -859,6 +864,8 @@ static av_cold int encode_init(AVCodecContext *avctx)
return AVERROR_INVALIDDATA;
}
ctx->force_quant = avctx->global_quality / FF_QP2LAMBDA;
if (!ctx->force_quant) {
if (!ctx->bits_per_mb) {
for (i = 0; i < NUM_MB_LIMITS - 1; i++)
if (prores_mb_limits[i] >= ctx->mb_width * ctx->mb_height)
@ -869,10 +876,6 @@ static av_cold int encode_init(AVCodecContext *avctx)
return AVERROR_INVALIDDATA;
}
ctx->frame_size = ctx->num_slices * (2 + 2 * ctx->num_planes
+ (2 * mps * ctx->bits_per_mb) / 8)
+ 200;
min_quant = ctx->profile_info->min_quant;
max_quant = ctx->profile_info->max_quant;
for (i = min_quant; i < MAX_STORED_Q; i++) {
@ -880,13 +883,6 @@ static av_cold int encode_init(AVCodecContext *avctx)
ctx->quants[i][j] = ctx->quant_mat[j] * i;
}
avctx->codec_tag = ctx->profile_info->tag;
av_log(avctx, AV_LOG_DEBUG, "profile %d, %d slices, %d bits per MB\n",
ctx->profile, ctx->num_slices, ctx->bits_per_mb);
av_log(avctx, AV_LOG_DEBUG, "estimated frame size %d\n",
ctx->frame_size);
ctx->nodes = av_malloc((ctx->slices_width + 1) * TRELLIS_WIDTH
* sizeof(*ctx->nodes));
if (!ctx->nodes) {
@ -904,6 +900,36 @@ static av_cold int encode_init(AVCodecContext *avctx)
encode_close(avctx);
return AVERROR(ENOMEM);
}
} else {
int ls = 0;
if (ctx->force_quant > 64) {
av_log(avctx, AV_LOG_ERROR, "too large quantiser, maximum is 64\n");
return AVERROR_INVALIDDATA;
}
for (j = 0; j < 64; j++) {
ctx->quants[0][j] = ctx->quant_mat[j] * ctx->force_quant;
ls += av_log2((1 << 11) / ctx->quants[0][j]) * 2 + 1;
}
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 = ctx->num_slices * (2 + 2 * ctx->num_planes
+ (2 * mps * ctx->bits_per_mb) / 8)
+ 200;
avctx->codec_tag = ctx->profile_info->tag;
av_log(avctx, AV_LOG_DEBUG, "profile %d, %d slices, %d bits per MB\n",
ctx->profile, ctx->num_slices, ctx->bits_per_mb);
av_log(avctx, AV_LOG_DEBUG, "estimated frame size %d\n",
ctx->frame_size);
return 0;
}