summaryrefslogtreecommitdiffstats
path: root/libavcodec/huffyuvdec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/huffyuvdec.c')
-rw-r--r--libavcodec/huffyuvdec.c118
1 files changed, 97 insertions, 21 deletions
diff --git a/libavcodec/huffyuvdec.c b/libavcodec/huffyuvdec.c
index 15fce93..d08aa5c 100644
--- a/libavcodec/huffyuvdec.c
+++ b/libavcodec/huffyuvdec.c
@@ -21,6 +21,8 @@
* 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
+ *
+ * yuva, gray, 4:4:4, 4:1:1, 4:1:0 and >8 bit per sample support sponsored by NOA
*/
/**
@@ -88,16 +90,16 @@ static const unsigned char classic_add_chroma[256] = {
6, 12, 8, 10, 7, 9, 6, 4, 6, 2, 2, 3, 3, 3, 3, 2,
};
-static int read_len_table(uint8_t *dst, GetBitContext *gb)
+static int read_len_table(uint8_t *dst, GetBitContext *gb, int n)
{
int i, val, repeat;
- for (i = 0; i < 256;) {
+ for (i = 0; i < n;) {
repeat = get_bits(gb, 3);
val = get_bits(gb, 5);
if (repeat == 0)
repeat = get_bits(gb, 8);
- if (i + repeat > 256 || get_bits_left(gb) < 0) {
+ if (i + repeat > n || get_bits_left(gb) < 0) {
av_log(NULL, AV_LOG_ERROR, "Error reading huffman table\n");
return -1;
}
@@ -118,19 +120,19 @@ static int generate_joint_tables(HYuvContext *s)
int p, i, y, u;
for (p = 0; p < 4; p++) {
int p0 = s->version > 2 ? p : 0;
- for (i = y = 0; y < 256; y++) {
+ for (i = y = 0; y < s->n; y++) {
int len0 = s->len[p0][y];
int limit = VLC_BITS - len0;
if(limit <= 0 || !len0)
continue;
- for (u = 0; u < 256; u++) {
+ for (u = 0; u < s->n; u++) {
int len1 = s->len[p][u];
if (len1 > limit || !len1)
continue;
av_assert0(i < (1 << VLC_BITS));
len[i] = len0 + len1;
bits[i] = (s->bits[p0][y] << len1) + s->bits[p][u];
- symbols[i] = (y << 8) + u;
+ symbols[i] = (y << 8) + u; //FIXME
if(symbols[i] != 0xffff) // reserved to mean "invalid"
i++;
}
@@ -199,13 +201,13 @@ static int read_huffman_tables(HYuvContext *s, const uint8_t *src, int length)
count = 1 + s->alpha + 2*s->chroma;
for (i = 0; i < count; i++) {
- if (read_len_table(s->len[i], &gb) < 0)
+ if (read_len_table(s->len[i], &gb, s->n) < 0)
return -1;
- if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i]) < 0) {
+ if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i], s->n) < 0) {
return -1;
}
ff_free_vlc(&s->vlc[i]);
- if ((ret = init_vlc(&s->vlc[i], VLC_BITS, 256, s->len[i], 1, 1,
+ if ((ret = init_vlc(&s->vlc[i], VLC_BITS, s->n, s->len[i], 1, 1,
s->bits[i], 4, 4, 0)) < 0)
return ret;
}
@@ -224,12 +226,12 @@ static int read_old_huffman_tables(HYuvContext *s)
init_get_bits(&gb, classic_shift_luma,
classic_shift_luma_table_size * 8);
- if (read_len_table(s->len[0], &gb) < 0)
+ if (read_len_table(s->len[0], &gb, 256) < 0)
return -1;
init_get_bits(&gb, classic_shift_chroma,
classic_shift_chroma_table_size * 8);
- if (read_len_table(s->len[1], &gb) < 0)
+ if (read_len_table(s->len[1], &gb, 256) < 0)
return -1;
for(i=0; i<256; i++) s->bits[0][i] = classic_add_luma [i];
@@ -397,6 +399,9 @@ static av_cold int decode_init(AVCodecContext *avctx)
case 0x675:
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
break;
+ case 0x695:
+ avctx->pix_fmt = AV_PIX_FMT_YUV420P10;
+ break;
case 0x67A:
avctx->pix_fmt = AV_PIX_FMT_YUV410P;
break;
@@ -409,6 +414,11 @@ static av_cold int decode_init(AVCodecContext *avctx)
case 0x775:
avctx->pix_fmt = AV_PIX_FMT_YUVA420P;
break;
+ case 0x795:
+ avctx->pix_fmt = AV_PIX_FMT_YUVA420P10;
+ break;
+ default:
+ return AVERROR_INVALIDDATA;
}
}
@@ -499,19 +509,35 @@ static void decode_422_bitstream(HYuvContext *s, int count)
dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\
}\
}
+#define READ_2PIX_PLANE16(dst0, dst1, plane){\
+ dst0 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\
+ dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\
+}
static void decode_plane_bitstream(HYuvContext *s, int count, int plane)
{
int i;
count/=2;
- if (count >= (get_bits_left(&s->gb)) / (31 * 2)) {
- for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) {
- READ_2PIX_PLANE(s->temp[0][2 * i], s->temp[0][2 * i + 1], plane);
+ if (s->bps <= 8) {
+ if (count >= (get_bits_left(&s->gb)) / (31 * 2)) {
+ for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) {
+ READ_2PIX_PLANE(s->temp[0][2 * i], s->temp[0][2 * i + 1], plane);
+ }
+ } else {
+ for(i=0; i<count; i++){
+ READ_2PIX_PLANE(s->temp[0][2 * i], s->temp[0][2 * i + 1], plane);
+ }
}
} else {
- for(i=0; i<count; i++){
- READ_2PIX_PLANE(s->temp[0][2 * i], s->temp[0][2 * i + 1], plane);
+ if (count >= (get_bits_left(&s->gb)) / (31 * 2)) {
+ for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) {
+ READ_2PIX_PLANE16(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane);
+ }
+ } else {
+ for(i=0; i<count; i++){
+ READ_2PIX_PLANE16(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane);
+ }
}
}
}
@@ -601,6 +627,56 @@ static void draw_slice(HYuvContext *s, AVFrame *frame, int y)
s->last_slice_end = y + h;
}
+static int left_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *src, int w, int acc)
+{
+ if (s->bps <= 8) {
+ return s->dsp.add_hfyu_left_prediction(dst, src, w, acc);
+ } else {
+ //FIXME optimize
+ unsigned mask = s->n-1;
+ int i;
+ const uint16_t *src16 = (const uint16_t *)src;
+ uint16_t *dst16 = ( uint16_t *)dst;
+
+ for(i=0; i<w-1; i++){
+ acc+= src16[i];
+ dst16[i]= acc & mask;
+ i++;
+ acc+= src16[i];
+ dst16[i]= acc & mask;
+ }
+
+ for(; i<w; i++){
+ acc+= src16[i];
+ dst16[i]= acc & mask;
+ }
+
+ return acc;
+ }
+}
+
+static void add_bytes(HYuvContext *s, uint8_t *dst, uint8_t *src, int w)
+{
+ if (s->bps <= 8) {
+ s->dsp.add_bytes(dst, src, w);
+ } else {
+ //FIXME optimize
+ const uint16_t *src16 = (const uint16_t *)src;
+ uint16_t *dst16 = ( uint16_t *)dst;
+ long i;
+ unsigned long msb = 0x1000100010001ULL << (s->bps-1);
+ unsigned long lsb = msb - 0x1000100010001ULL;
+ unsigned long mask = lsb + msb;
+ for (i = 0; i <= w - (int)sizeof(long)/2; i += sizeof(long)/2) {
+ long a = *(long*)(src16+i);
+ long b = *(long*)(dst16+i);
+ *(long*)(dst16+i) = ((a&lsb) + (b&lsb)) ^ ((a^b)&msb);
+ }
+ for(; i<w; i++)
+ dst16[i] = (dst16[i] + src16[i]) & mask;
+ }
+}
+
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
AVPacket *avpkt)
{
@@ -663,16 +739,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
case LEFT:
case PLANE:
decode_plane_bitstream(s, w, plane);
- left = s->dsp.add_hfyu_left_prediction(p->data[plane], s->temp[0], w, 0);
+ left = left_prediction(s, p->data[plane], s->temp[0], w, 0);
for (y = 1; y < h; y++) {
uint8_t *dst = p->data[plane] + p->linesize[plane]*y;
decode_plane_bitstream(s, w, plane);
- left = s->dsp.add_hfyu_left_prediction(dst, s->temp[0], w, left);
+ left = left_prediction(s, dst, s->temp[0], w, left);
if (s->predictor == PLANE) {
if (y > s->interlaced) {
- s->dsp.add_bytes(dst, dst - fake_stride, w);
+ add_bytes(s, dst, dst - fake_stride, w);
}
}
}
@@ -680,14 +756,14 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
break;
case MEDIAN:
decode_plane_bitstream(s, w, plane);
- left= s->dsp.add_hfyu_left_prediction(p->data[plane], s->temp[0], w, 0);
+ left= left_prediction(s, p->data[plane], s->temp[0], w, 0);
y = 1;
/* second line is left predicted for interlaced case */
if (s->interlaced) {
decode_plane_bitstream(s, w, plane);
- left = s->dsp.add_hfyu_left_prediction(p->data[plane] + p->linesize[plane], s->temp[0], w, left);
+ left = left_prediction(s, p->data[plane] + p->linesize[plane], s->temp[0], w, left);
y++;
}
OpenPOWER on IntegriCloud