Files
libstb-hal/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.c
2017-12-28 19:53:18 +01:00

183 lines
4.8 KiB
C

/*
* DC prediction
*
* Copyright (c) 2006 vixy project
*
* This file contains the code that based on FFmpeg (http://ffmpeg.mplayerhq.hu/)
* See original copyright notice in /FFMPEG_CREDITS and /FFMPEG_IMPORTS
*
* This file is part of VIXY FLV Converter.
*
* 'VIXY FLV Converter' 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.
*
* 'VIXY FLV Converter' 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 "dcprediction.h"
// M4V ADDED
static const uint8 mpeg4_y_dc_scale_table[32] =
{
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
0, 8, 8, 8, 8, 10, 12, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 36, 38, 40, 42, 44, 46
};
// M4V ADDED
static const uint8 mpeg4_c_dc_scale_table[32] =
{
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
0, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25
};
static int __inline get_pred(int *dc_cur, int stride, int scale)
{
/* B C
A X */
int A = dc_cur[-1];
int B = dc_cur[-1 - stride];
int C = dc_cur[-stride];
int pred;
if (abs(A - B) < abs(B - C))
{
pred = C;
}
else
{
pred = A;
}
return (pred + (scale >> 1)) / scale;
}
static void __inline set_dc_to_dc_cur(int *dc_cur, int level, int scale)
{
level *= scale;
if (level & (~2047))
{
if (level < 0)
level = 0;
else
level = 2047;
}
dc_cur[0] = level;
}
static int *get_dc_cur(M4V_DCPRED *pred, int mb_x, int mb_y, int n)
{
if (n < 4)
{
return pred->dc[n] + mb_x * 2 + mb_y * 2 * pred->stride[n] + pred->block_offset[n];
}
else
{
return pred->dc[n] + mb_x * 1 + mb_y * pred->stride[n];
}
}
static int __inline get_scale(M4V_DCPRED *pred, int n)
{
if (n < 4)
{
return pred->y_dc_scale;
}
else
{
return pred->c_dc_scale;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void dcpred_set_qscale(M4V_DCPRED *pred, int qscale)
{
if (qscale < 0) qscale = 0;
if (qscale > 31) qscale = 31;
pred->y_dc_scale = mpeg4_y_dc_scale_table[qscale];
pred->c_dc_scale = mpeg4_c_dc_scale_table[qscale];
}
void dcpred_set_pos(M4V_DCPRED *pred, int mb_x, int mb_y)
{
int n;
for (n = 0; n < 6; n++)
{
pred->dc_cur[n] = get_dc_cur(pred, mb_x, mb_y, n);
}
}
int dcpred_for_enc(M4V_DCPRED *p, int n, int level)
{
int *dc_cur = p->dc_cur[n];
int scale = get_scale(p, n);
int pred = get_pred(dc_cur, p->stride[n], scale);
set_dc_to_dc_cur(dc_cur, level, scale);
return level - pred;
}
int dcpred_for_dec(M4V_DCPRED *p, int n, int level)
{
int *dc_cur = p->dc_cur[n];
int scale = get_scale(p, n);
int pred = get_pred(dc_cur, p->stride[n], scale);
level += pred;
set_dc_to_dc_cur(dc_cur, level, scale);
return level;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void init_plane(M4V_DCPRED *pred, int n)
{
int x, len = pred->stride[n] * pred->height[n];
int *p = pred->_dc[n];
for (x = 0; x < len; x++)
{
p[x] = 1024;
}
}
void init_dcpred(M4V_DCPRED *pred)
{
init_plane(pred, 0);
init_plane(pred, 4);
init_plane(pred, 5);
}
void alloc_dcpred(M4V_DCPRED *pred, int mb_width, int mb_height)
{
const int w2 = mb_width * 2 + 1;
const int h2 = mb_height * 2 + 1;
const int w = mb_width + 1;
const int h = mb_height + 1;
pred->_dc[0] = pred->_dc[1] = pred->_dc[2] = pred->_dc[3] = (int *)malloc(sizeof(int) * w2 * h2);
pred->_dc[4] = (int *)malloc(sizeof(int) * w * h);
pred->_dc[5] = (int *)malloc(sizeof(int) * w * h);
pred->dc[0] = pred->dc[1] = pred->dc[2] = pred->dc[3] = pred->_dc[0] + w2 + 1;
pred->dc[4] = pred->_dc[4] + w + 1;
pred->dc[5] = pred->_dc[5] + w + 1;
pred->stride[0] = pred->stride[1] = pred->stride[2] = pred->stride[3] = w2;
pred->height[0] = pred->height[1] = pred->height[2] = pred->height[3] = h2;
pred->stride[4] = pred->stride[5] = w;
pred->height[4] = pred->height[5] = h;
pred->block_offset[0] = 0;
pred->block_offset[1] = 1;
pred->block_offset[2] = w2;
pred->block_offset[3] = w2 + 1;
pred->block_offset[4] = 0;
pred->block_offset[5] = 0;
}
void free_dcpred(M4V_DCPRED *pred)
{
free(pred->_dc[0]);
free(pred->_dc[4]);
free(pred->_dc[5]);
}