summaryrefslogtreecommitdiff
path: root/libavcodec/dnxhddec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/dnxhddec.c')
-rw-r--r--libavcodec/dnxhddec.c61
1 files changed, 41 insertions, 20 deletions
diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c
index 956196ce64..2548614e90 100644
--- a/libavcodec/dnxhddec.c
+++ b/libavcodec/dnxhddec.c
@@ -5,20 +5,20 @@
*
* 10 bit support added by MirriAd Ltd, Joseph Artsimovich <joseph@mirriad.com>
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -49,6 +49,9 @@ typedef struct DNXHDContext {
int bit_depth; // 8, 10 or 0 if not initialized at all.
void (*decode_dct_block)(struct DNXHDContext *ctx, DCTELEM *block,
int n, int qscale);
+ int last_qscale;
+ int luma_scale[64];
+ int chroma_scale[64];
} DNXHDContext;
#define DNXHD_VLC_BITS 9
@@ -63,6 +66,7 @@ static av_cold int dnxhd_decode_init(AVCodecContext *avctx)
ctx->avctx = avctx;
avctx->coded_frame = &ctx->picture;
+ avcodec_get_frame_defaults(&ctx->picture);
ctx->picture.type = AV_PICTURE_TYPE_I;
ctx->picture.key_frame = 1;
return 0;
@@ -185,16 +189,22 @@ static av_always_inline void dnxhd_decode_dct_block(DNXHDContext *ctx,
int level_bias,
int level_shift)
{
- int i, j, index1, index2, len;
+ int i, j, index1, index2, len, flags;
int level, component, sign;
+ const int *scale;
const uint8_t *weight_matrix;
+ const uint8_t *ac_level = ctx->cid_table->ac_level;
+ const uint8_t *ac_flags = ctx->cid_table->ac_flags;
+ const int eob_index = ctx->cid_table->eob_index;
OPEN_READER(bs, &ctx->gb);
if (n&2) {
component = 1 + (n&1);
+ scale = ctx->chroma_scale;
weight_matrix = ctx->cid_table->chroma_weight;
} else {
component = 0;
+ scale = ctx->luma_scale;
weight_matrix = ctx->cid_table->luma_weight;
}
@@ -210,33 +220,32 @@ static av_always_inline void dnxhd_decode_dct_block(DNXHDContext *ctx,
block[0] = ctx->last_dc[component];
//av_log(ctx->avctx, AV_LOG_DEBUG, "dc %d\n", block[0]);
- for (i = 1; ; i++) {
- UPDATE_CACHE(bs, &ctx->gb);
- GET_VLC(index1, bs, &ctx->gb, ctx->ac_vlc.table,
- DNXHD_VLC_BITS, 2);
- //av_log(ctx->avctx, AV_LOG_DEBUG, "index %d\n", index1);
- level = ctx->cid_table->ac_level[index1];
- if (!level) { /* EOB */
- //av_log(ctx->avctx, AV_LOG_DEBUG, "EOB\n");
- break;
- }
+ i = 0;
+
+ UPDATE_CACHE(bs, &ctx->gb);
+ GET_VLC(index1, bs, &ctx->gb, ctx->ac_vlc.table,
+ DNXHD_VLC_BITS, 2);
+
+ while (index1 != eob_index) {
+ level = ac_level[index1];
+ flags = ac_flags[index1];
sign = SHOW_SBITS(bs, &ctx->gb, 1);
SKIP_BITS(bs, &ctx->gb, 1);
- if (ctx->cid_table->ac_index_flag[index1]) {
- level += SHOW_UBITS(bs, &ctx->gb, index_bits) << 6;
+ if (flags & 1) {
+ level += SHOW_UBITS(bs, &ctx->gb, index_bits) << 7;
SKIP_BITS(bs, &ctx->gb, index_bits);
}
- if (ctx->cid_table->ac_run_flag[index1]) {
+ if (flags & 2) {
UPDATE_CACHE(bs, &ctx->gb);
GET_VLC(index2, bs, &ctx->gb, ctx->run_vlc.table,
DNXHD_VLC_BITS, 2);
i += ctx->cid_table->run[index2];
}
- if (i > 63) {
+ if (++i > 63) {
av_log(ctx->avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", n, i);
break;
}
@@ -244,13 +253,17 @@ static av_always_inline void dnxhd_decode_dct_block(DNXHDContext *ctx,
j = ctx->scantable.permutated[i];
//av_log(ctx->avctx, AV_LOG_DEBUG, "j %d\n", j);
//av_log(ctx->avctx, AV_LOG_DEBUG, "level %d, weight %d\n", level, weight_matrix[i]);
- level = (2*level+1) * qscale * weight_matrix[i];
+ level *= scale[i];
if (level_bias < 32 || weight_matrix[i] != level_bias)
level += level_bias;
level >>= level_shift;
//av_log(NULL, AV_LOG_DEBUG, "i %d, j %d, end level %d\n", i, j, level);
block[j] = (level^sign) - sign;
+
+ UPDATE_CACHE(bs, &ctx->gb);
+ GET_VLC(index1, bs, &ctx->gb, ctx->ac_vlc.table,
+ DNXHD_VLC_BITS, 2);
}
CLOSE_READER(bs, &ctx->gb);
@@ -281,6 +294,14 @@ static int dnxhd_decode_macroblock(DNXHDContext *ctx, int x, int y)
skip_bits1(&ctx->gb);
//av_log(ctx->avctx, AV_LOG_DEBUG, "qscale %d\n", qscale);
+ if (qscale != ctx->last_qscale) {
+ for (i = 0; i < 64; i++) {
+ ctx->luma_scale[i] = qscale * ctx->cid_table->luma_weight[i];
+ ctx->chroma_scale[i] = qscale * ctx->cid_table->chroma_weight[i];
+ }
+ ctx->last_qscale = qscale;
+ }
+
for (i = 0; i < 8; i++) {
ctx->dsp.clear_block(ctx->blocks[i]);
ctx->decode_dct_block(ctx, ctx->blocks[i], i, qscale);