/* * Unquantize functions for mpegvideo * Copyright (c) 2000,2001 Fabrice Bellard * Copyright (c) 2002-2004 Michael Niedermayer * * 4MV & hq & B-frame encoding stuff by Michael Niedermayer * * This file is part of FFmpeg. * * 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. * * 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 FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "config.h" #include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "avcodec.h" #include "mpegvideo.h" #include "mpegvideodata.h" #include "mpegvideo_unquantize.h" static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s, int16_t *block, int n, int qscale) { int i, level, nCoeffs; const uint16_t *quant_matrix; nCoeffs= s->block_last_index[n]; block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale; /* XXX: only MPEG-1 */ quant_matrix = s->intra_matrix; for(i=1;i<=nCoeffs;i++) { int j= s->intra_scantable.permutated[i]; level = block[j]; if (level) { if (level < 0) { level = -level; level = (int)(level * qscale * quant_matrix[j]) >> 3; level = (level - 1) | 1; level = -level; } else { level = (int)(level * qscale * quant_matrix[j]) >> 3; level = (level - 1) | 1; } block[j] = level; } } } static void dct_unquantize_mpeg1_inter_c(MpegEncContext *s, int16_t *block, int n, int qscale) { int i, level, nCoeffs; const uint16_t *quant_matrix; nCoeffs= s->block_last_index[n]; quant_matrix = s->inter_matrix; for(i=0; i<=nCoeffs; i++) { int j= s->intra_scantable.permutated[i]; level = block[j]; if (level) { if (level < 0) { level = -level; level = (((level << 1) + 1) * qscale * ((int) (quant_matrix[j]))) >> 4; level = (level - 1) | 1; level = -level; } else { level = (((level << 1) + 1) * qscale * ((int) (quant_matrix[j]))) >> 4; level = (level - 1) | 1; } block[j] = level; } } } static void dct_unquantize_mpeg2_intra_c(MpegEncContext *s, int16_t *block, int n, int qscale) { int i, level, nCoeffs; const uint16_t *quant_matrix; if (s->q_scale_type) qscale = ff_mpeg2_non_linear_qscale[qscale]; else qscale <<= 1; nCoeffs= s->block_last_index[n]; block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale; quant_matrix = s->intra_matrix; for(i=1;i<=nCoeffs;i++) { int j= s->intra_scantable.permutated[i]; level = block[j]; if (level) { if (level < 0) { level = -level; level = (int)(level * qscale * quant_matrix[j]) >> 4; level = -level; } else { level = (int)(level * qscale * quant_matrix[j]) >> 4; } block[j] = level; } } } static void dct_unquantize_mpeg2_intra_bitexact(MpegEncContext *s, int16_t *block, int n, int qscale) { int i, level, nCoeffs; const uint16_t *quant_matrix; int sum=-1; if (s->q_scale_type) qscale = ff_mpeg2_non_linear_qscale[qscale]; else qscale <<= 1; nCoeffs= s->block_last_index[n]; block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale; sum += block[0]; quant_matrix = s->intra_matrix; for(i=1;i<=nCoeffs;i++) { int j= s->intra_scantable.permutated[i]; level = block[j]; if (level) { if (level < 0) { level = -level; level = (int)(level * qscale * quant_matrix[j]) >> 4; level = -level; } else { level = (int)(level * qscale * quant_matrix[j]) >> 4; } block[j] = level; sum+=level; } } block[63]^=sum&1; } static void dct_unquantize_mpeg2_inter_c(MpegEncContext *s, int16_t *block, int n, int qscale) { int i, level, nCoeffs; const uint16_t *quant_matrix; int sum=-1; if (s->q_scale_type) qscale = ff_mpeg2_non_linear_qscale[qscale]; else qscale <<= 1; nCoeffs= s->block_last_index[n]; quant_matrix = s->inter_matrix; for(i=0; i<=nCoeffs; i++) { int j= s->intra_scantable.permutated[i]; level = block[j]; if (level) { if (level < 0) { level = -level; level = (((level << 1) + 1) * qscale * ((int) (quant_matrix[j]))) >> 5; level = -level; } else { level = (((level << 1) + 1) * qscale * ((int) (quant_matrix[j]))) >> 5; } block[j] = level; sum+=level; } } block[63]^=sum&1; } static void dct_unquantize_h263_intra_c(MpegEncContext *s, int16_t *block, int n, int qscale) { int i, level, qmul, qadd; int nCoeffs; av_assert2(s->block_last_index[n]>=0 || s->h263_aic); qmul = qscale << 1; if (!s->h263_aic) { block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale; qadd = (qscale - 1) | 1; }else{ qadd = 0; } if(s->ac_pred) nCoeffs=63; else nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ]; for(i=1; i<=nCoeffs; i++) { level = block[i]; if (level) { if (level < 0) { level = level * qmul - qadd; } else { level = level * qmul + qadd; } block[i] = level; } } } static void dct_unquantize_h263_inter_c(MpegEncContext *s, int16_t *block, int n, int qscale) { int i, level, qmul, qadd; int nCoeffs; av_assert2(s->block_last_index[n]>=0); qadd = (qscale - 1) | 1; qmul = qscale << 1; nCoeffs= s->inter_scantable.raster_end[ s->block_last_index[n] ]; for(i=0; i<=nCoeffs; i++) { level = block[i]; if (level) { if (level < 0) { level = level * qmul - qadd; } else { level = level * qmul + qadd; } block[i] = level; } } } av_cold void ff_mpv_unquantize_init(MPVUnquantDSPContext *s, int bitexact, int q_scale_type) { s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_c; s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_c; s->dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_c; s->dct_unquantize_mpeg1_inter = dct_unquantize_mpeg1_inter_c; s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_c; if (bitexact) s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_bitexact; s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_c; #if HAVE_INTRINSICS_NEON ff_mpv_unquantize_init_neon(s, bitexact); #endif #if ARCH_ARM ff_mpv_unquantize_init_arm(s, bitexact); #elif ARCH_PPC ff_mpv_unquantize_init_ppc(s, bitexact); #elif ARCH_X86 ff_mpv_unquantize_init_x86(s, bitexact); #elif ARCH_MIPS ff_mpv_unquantize_init_mips(s, bitexact, q_scale_type); #endif }