diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-02-19 01:36:23 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-02-19 01:47:10 +0100 |
commit | 4a519b6e036bb593d868c2a424da43512215c571 (patch) | |
tree | bbbd734383e7b2bfd005a1c19fe64d36d493b576 /libavcodec/proresenc_kostya.c | |
parent | 57182b9f0fa15ebedbf5229e17bc77a70cc68d9d (diff) | |
parent | 5be805d38cb43e6f0b85941f75946d09bc8cc13f (diff) | |
download | ffmpeg-streaming-4a519b6e036bb593d868c2a424da43512215c571.zip ffmpeg-streaming-4a519b6e036bb593d868c2a424da43512215c571.tar.gz |
Merge remote-tracking branch 'qatar/master'
* qatar/master:
mov: Use defines for sample flags in fragments
mov: Use defines for trun flags
mov: Use defines for tfhd flags
proresenc: force bitrate not to exceed given limit
vc1parse: call vc1_init_common().
wma: don't return 0 on invalid packets.
asf: prevent packet_size_left from going negative if hdrlen > pktlen.
mjpegb: don't return 0 at the end of frame decoding.
rtpdec: Identify incorrectly signalled H263
vp8dsp: split long line.
aiff: don't skip block_align==0 check on COMM-after-SSND files.
dpcm: ignore extra unpaired bytes in stereo streams.
mp3on4: require a minimum framesize.
mpc7: assign an error level + context to av_log() msg.
huffyuv: error out on bit overrun.
dct-test: Add the missing ff_ prefix to the altivec functions
dct-test: Remove a stray declaration of a nonexistent function
movenc: Write the unknown duration as 64 bit fields in ismv
movenc: Write track durations with all bits set if duration is unknown
Conflicts:
libavcodec/dct-test.c
libavcodec/wmadec.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/proresenc_kostya.c')
-rw-r--r-- | libavcodec/proresenc_kostya.c | 72 |
1 files changed, 62 insertions, 10 deletions
diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c index 242537b..8259b2a 100644 --- a/libavcodec/proresenc_kostya.c +++ b/libavcodec/proresenc_kostya.c @@ -139,11 +139,14 @@ struct TrellisNode { int score; }; +#define MAX_STORED_Q 16 + typedef struct ProresContext { AVClass *class; DECLARE_ALIGNED(16, DCTELEM, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE]; DECLARE_ALIGNED(16, uint16_t, emu_buf)[16*16]; - int16_t quants[16][64]; + int16_t quants[MAX_STORED_Q][64]; + int16_t custom_q[64]; ProresDSPContext dsp; ScanTable scantable; @@ -156,6 +159,8 @@ typedef struct ProresContext { int num_planes; int bits_per_mb; + int frame_size; + int profile; const struct prores_profile *profile_info; @@ -348,6 +353,15 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, int slice_width_factor = av_log2(mbs_per_slice); int num_cblocks, pwidth; int plane_factor, is_chroma; + uint16_t *qmat; + + if (quant < MAX_STORED_Q) { + qmat = ctx->quants[quant]; + } else { + qmat = ctx->custom_q; + for (i = 0; i < 64; i++) + qmat[i] = ctx->profile_info->quant[i] * quant; + } for (i = 0; i < ctx->num_planes; i++) { is_chroma = (i == 1 || i == 2); @@ -373,7 +387,7 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, sizes[i] = encode_slice_plane(ctx, pb, src, pic->linesize[i], mbs_per_slice, ctx->blocks[0], num_cblocks, plane_factor, - ctx->quants[quant]); + qmat); total_size += sizes[i]; } return total_size; @@ -500,6 +514,8 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, int error, bits, bits_limit; int mbs, prev, cur, new_score; int slice_bits[TRELLIS_WIDTH], slice_score[TRELLIS_WIDTH]; + int overquant; + uint16_t *qmat; mbs = x + mbs_per_slice; @@ -526,7 +542,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, mbs_per_slice, num_cblocks[i]); } - for (q = min_quant; q <= max_quant; q++) { + for (q = min_quant; q < max_quant + 2; q++) { ctx->nodes[trellis_node + q].prev_node = -1; ctx->nodes[trellis_node + q].quant = q; } @@ -549,12 +565,43 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, slice_bits[q] = bits; slice_score[q] = error; } + if (slice_bits[max_quant] <= ctx->bits_per_mb * mbs_per_slice) { + slice_bits[max_quant + 1] = slice_bits[max_quant]; + slice_score[max_quant + 1] = slice_score[max_quant] + 1; + overquant = max_quant; + } else { + for (q = max_quant + 1; q < 128; q++) { + bits = 0; + error = 0; + if (q < MAX_STORED_Q) { + qmat = ctx->quants[q]; + } else { + qmat = ctx->custom_q; + for (i = 0; i < 64; i++) + qmat[i] = ctx->profile_info->quant[i] * q; + } + for (i = 0; i < ctx->num_planes; i++) { + bits += estimate_slice_plane(ctx, &error, i, + src, pic->linesize[i], + mbs_per_slice, + num_cblocks[i], plane_factor[i], + qmat); + } + if (bits <= ctx->bits_per_mb * mbs_per_slice) + break; + } + + slice_bits[max_quant + 1] = bits; + slice_score[max_quant + 1] = error; + overquant = q; + } + ctx->nodes[trellis_node + max_quant + 1].quant = overquant; bits_limit = mbs * ctx->bits_per_mb; - for (pq = min_quant; pq <= max_quant; pq++) { + for (pq = min_quant; pq < max_quant + 2; pq++) { prev = trellis_node - TRELLIS_WIDTH + pq; - for (q = min_quant; q <= max_quant; q++) { + for (q = min_quant; q < max_quant + 2; q++) { cur = trellis_node + q; bits = ctx->nodes[prev].bits + slice_bits[q]; @@ -578,7 +625,7 @@ static int find_slice_quant(AVCodecContext *avctx, const AVFrame *pic, error = ctx->nodes[trellis_node + min_quant].score; pq = trellis_node + min_quant; - for (q = min_quant + 1; q <= max_quant; q++) { + for (q = min_quant + 1; q < max_quant + 2; q++) { if (ctx->nodes[trellis_node + q].score <= error) { error = ctx->nodes[trellis_node + q].score; pq = trellis_node + q; @@ -606,8 +653,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame->key_frame = 1; - pkt_size = ctx->mb_width * ctx->mb_height * 64 * 3 * 12 - + ctx->num_slices * 2 + 200 + FF_MIN_BUFFER_SIZE; + pkt_size = ctx->frame_size + FF_MIN_BUFFER_SIZE; if ((ret = ff_alloc_packet(pkt, pkt_size)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); @@ -762,9 +808,13 @@ static av_cold int encode_init(AVCodecContext *avctx) break; ctx->bits_per_mb = ctx->profile_info->br_tab[i]; + 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_quant; i++) { + for (i = min_quant; i < MAX_STORED_Q; i++) { for (j = 0; j < 64; j++) ctx->quants[i][j] = ctx->profile_info->quant[j] * i; } @@ -773,6 +823,8 @@ static av_cold int encode_init(AVCodecContext *avctx) 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)); @@ -780,7 +832,7 @@ static av_cold int encode_init(AVCodecContext *avctx) encode_close(avctx); return AVERROR(ENOMEM); } - for (i = min_quant; i <= max_quant; i++) { + for (i = min_quant; i < max_quant + 2; i++) { ctx->nodes[i].prev_node = -1; ctx->nodes[i].bits = 0; ctx->nodes[i].score = 0; |