2 * Copyright (c) 2012 Konstantin Shishkov
4 * This file is part of Libav.
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * Common functions for Microsoft Screen 1 and 2
26 #include "libavutil/intfloat.h"
27 #include "libavutil/intreadwrite.h"
37 static const int sec_order_sizes
[4] = { 1, 7, 6, 1 };
39 enum ContextDirection
{
46 static int model_calc_threshold(Model
*m
)
50 thr
= 2 * m
->weights
[m
->num_syms
] - 1;
51 thr
= ((thr
>> 1) + 4 * m
->cum_prob
[0]) / thr
;
53 return FFMIN(thr
, 0x3FFF);
56 static void model_reset(Model
*m
)
60 for (i
= 0; i
<= m
->num_syms
; i
++) {
62 m
->cum_prob
[i
] = m
->num_syms
- i
;
65 for (i
= 0; i
< m
->num_syms
; i
++)
66 m
->idx2sym
[i
+ 1] = i
;
69 static av_cold
void model_init(Model
*m
, int num_syms
, int thr_weight
)
71 m
->num_syms
= num_syms
;
72 m
->thr_weight
= thr_weight
;
73 m
->threshold
= num_syms
* thr_weight
;
76 static void model_rescale_weights(Model
*m
)
81 if (m
->thr_weight
== THRESH_ADAPTIVE
)
82 m
->threshold
= model_calc_threshold(m
);
83 while (m
->cum_prob
[0] > m
->threshold
) {
85 for (i
= m
->num_syms
; i
>= 0; i
--) {
86 m
->cum_prob
[i
] = cum_prob
;
87 m
->weights
[i
] = (m
->weights
[i
] + 1) >> 1;
88 cum_prob
+= m
->weights
[i
];
93 void ff_mss12_model_update(Model
*m
, int val
)
97 if (m
->weights
[val
] == m
->weights
[val
- 1]) {
98 for (i
= val
; m
->weights
[i
- 1] == m
->weights
[val
]; i
--);
102 sym1
= m
->idx2sym
[val
];
103 sym2
= m
->idx2sym
[i
];
105 m
->idx2sym
[val
] = sym2
;
106 m
->idx2sym
[i
] = sym1
;
112 for (i
= val
- 1; i
>= 0; i
--)
114 model_rescale_weights(m
);
117 static void pixctx_reset(PixContext
*ctx
)
121 if (!ctx
->special_initial_cache
)
122 for (i
= 0; i
< ctx
->cache_size
; i
++)
130 model_reset(&ctx
->cache_model
);
131 model_reset(&ctx
->full_model
);
133 for (i
= 0; i
< 15; i
++)
134 for (j
= 0; j
< 4; j
++)
135 model_reset(&ctx
->sec_models
[i
][j
]);
138 static av_cold
void pixctx_init(PixContext
*ctx
, int cache_size
,
139 int full_model_syms
, int special_initial_cache
)
143 ctx
->cache_size
= cache_size
+ 4;
144 ctx
->num_syms
= cache_size
;
145 ctx
->special_initial_cache
= special_initial_cache
;
147 model_init(&ctx
->cache_model
, ctx
->num_syms
+ 1, THRESH_LOW
);
148 model_init(&ctx
->full_model
, full_model_syms
, THRESH_HIGH
);
150 for (i
= 0, idx
= 0; i
< 4; i
++)
151 for (j
= 0; j
< sec_order_sizes
[i
]; j
++, idx
++)
152 for (k
= 0; k
< 4; k
++)
153 model_init(&ctx
->sec_models
[idx
][k
], 2 + i
,
154 i
? THRESH_LOW
: THRESH_ADAPTIVE
);
157 static av_always_inline
int decode_pixel(ArithCoder
*acoder
, PixContext
*pctx
,
158 uint8_t *ngb
, int num_ngb
, int any_ngb
)
162 val
= acoder
->get_model_sym(acoder
, &pctx
->cache_model
);
163 if (val
< pctx
->num_syms
) {
168 for (i
= 0; i
< pctx
->cache_size
; i
++) {
169 for (j
= 0; j
< num_ngb
; j
++)
170 if (pctx
->cache
[i
] == ngb
[j
])
178 val
= FFMIN(i
, pctx
->cache_size
- 1);
180 pix
= pctx
->cache
[val
];
182 pix
= acoder
->get_model_sym(acoder
, &pctx
->full_model
);
183 for (i
= 0; i
< pctx
->cache_size
- 1; i
++)
184 if (pctx
->cache
[i
] == pix
)
189 for (i
= val
; i
> 0; i
--)
190 pctx
->cache
[i
] = pctx
->cache
[i
- 1];
191 pctx
->cache
[0] = pix
;
197 static int decode_pixel_in_context(ArithCoder
*acoder
, PixContext
*pctx
,
198 uint8_t *src
, int stride
, int x
, int y
,
201 uint8_t neighbours
[4];
209 memset(neighbours
, src
[-1], 4);
211 neighbours
[TOP
] = src
[-stride
];
213 neighbours
[TOP_LEFT
] = neighbours
[LEFT
] = neighbours
[TOP
];
215 neighbours
[TOP_LEFT
] = src
[-stride
- 1];
216 neighbours
[ LEFT
] = src
[-1];
219 neighbours
[TOP_RIGHT
] = src
[-stride
+ 1];
221 neighbours
[TOP_RIGHT
] = neighbours
[TOP
];
225 if (x
>= 2 && src
[-2] == neighbours
[LEFT
])
227 if (y
>= 2 && src
[-2 * stride
] == neighbours
[TOP
])
231 ref_pix
[0] = neighbours
[0];
232 for (i
= 1; i
< 4; i
++) {
233 for (j
= 0; j
< nlen
; j
++)
234 if (ref_pix
[j
] == neighbours
[i
])
237 ref_pix
[nlen
++] = neighbours
[i
];
245 if (neighbours
[TOP
] == neighbours
[TOP_LEFT
]) {
246 if (neighbours
[TOP_RIGHT
] == neighbours
[TOP_LEFT
])
248 else if (neighbours
[LEFT
] == neighbours
[TOP_LEFT
])
252 } else if (neighbours
[TOP_RIGHT
] == neighbours
[TOP_LEFT
]) {
253 if (neighbours
[LEFT
] == neighbours
[TOP_LEFT
])
257 } else if (neighbours
[LEFT
] == neighbours
[TOP_LEFT
]) {
264 if (neighbours
[TOP
] == neighbours
[TOP_LEFT
])
266 else if (neighbours
[TOP_RIGHT
] == neighbours
[TOP_LEFT
])
268 else if (neighbours
[LEFT
] == neighbours
[TOP_LEFT
])
270 else if (neighbours
[TOP_RIGHT
] == neighbours
[TOP
])
272 else if (neighbours
[TOP
] == neighbours
[LEFT
])
282 pix
= acoder
->get_model_sym(acoder
,
283 &pctx
->sec_models
[layer
][sub
]);
287 return decode_pixel(acoder
, pctx
, ref_pix
, nlen
, 1);
290 static int decode_region(ArithCoder
*acoder
, uint8_t *dst
, uint8_t *rgb_pic
,
291 int x
, int y
, int width
, int height
, int stride
,
292 int rgb_stride
, PixContext
*pctx
, const uint32_t *pal
)
295 uint8_t *rgb_dst
= rgb_pic
+ x
* 3 + y
* rgb_stride
;
297 dst
+= x
+ y
* stride
;
299 for (j
= 0; j
< height
; j
++) {
300 for (i
= 0; i
< width
; i
++) {
302 p
= decode_pixel(acoder
, pctx
, NULL
, 0, 0);
304 p
= decode_pixel_in_context(acoder
, pctx
, dst
+ i
, stride
,
305 i
, j
, width
- i
- 1);
309 AV_WB24(rgb_dst
+ i
* 3, pal
[p
]);
312 rgb_dst
+= rgb_stride
;
318 static void copy_rectangles(MSS12Context
const *c
,
319 int x
, int y
, int width
, int height
)
324 for (j
= y
; j
< y
+ height
; j
++) {
325 memcpy(c
->rgb_pic
+ j
* c
->rgb_stride
+ x
* 3,
326 c
->last_rgb_pic
+ j
* c
->rgb_stride
+ x
* 3,
328 memcpy(c
->pal_pic
+ j
* c
->pal_stride
+ x
,
329 c
->last_pal_pic
+ j
* c
->pal_stride
+ x
,
334 static int motion_compensation(MSS12Context
const *c
,
335 int x
, int y
, int width
, int height
)
337 if (x
+ c
->mvX
< 0 || x
+ c
->mvX
+ width
> c
->avctx
->width
||
338 y
+ c
->mvY
< 0 || y
+ c
->mvY
+ height
> c
->avctx
->height
||
342 uint8_t *dst
= c
->pal_pic
+ x
+ y
* c
->pal_stride
;
343 uint8_t *rgb_dst
= c
->rgb_pic
+ x
* 3 + y
* c
->rgb_stride
;
349 if (c
->last_rgb_pic
) {
350 src
= c
->last_pal_pic
+ x
+ y
* c
->pal_stride
;
351 rgb_src
= c
->last_rgb_pic
+ x
* 3 + y
* c
->rgb_stride
;
353 src
= c
->pal_pic
+ x
+ y
* c
->pal_stride
;
354 rgb_src
= c
->rgb_pic
+ x
* 3 + y
* c
->rgb_stride
;
356 for (j
= 0; j
< height
; j
++) {
357 memmove(dst
, src
, width
);
358 memmove(rgb_dst
, rgb_src
, width
* 3);
359 dst
+= c
->pal_stride
;
360 src
+= c
->pal_stride
;
361 rgb_dst
+= c
->rgb_stride
;
362 rgb_src
+= c
->rgb_stride
;
368 static int decode_region_masked(MSS12Context
const *c
, ArithCoder
*acoder
,
369 uint8_t *dst
, int stride
, uint8_t *mask
,
370 int mask_stride
, int x
, int y
,
371 int width
, int height
,
375 uint8_t *rgb_dst
= c
->rgb_pic
+ x
* 3 + y
* c
->rgb_stride
;
377 dst
+= x
+ y
* stride
;
378 mask
+= x
+ y
* mask_stride
;
380 for (j
= 0; j
< height
; j
++) {
381 for (i
= 0; i
< width
; i
++) {
382 if (c
->avctx
->err_recognition
& AV_EF_EXPLODE
&&
383 ( c
->rgb_pic
&& mask
[i
] != 0x01 && mask
[i
] != 0x02 && mask
[i
] != 0x04 ||
384 !c
->rgb_pic
&& mask
[i
] != 0x80 && mask
[i
] != 0xFF))
387 if (mask
[i
] == 0x02) {
388 copy_rectangles(c
, x
+ i
, y
+ j
, 1, 1);
389 } else if (mask
[i
] == 0x04) {
390 if (motion_compensation(c
, x
+ i
, y
+ j
, 1, 1))
392 } else if (mask
[i
] != 0x80) {
394 p
= decode_pixel(acoder
, pctx
, NULL
, 0, 0);
396 p
= decode_pixel_in_context(acoder
, pctx
, dst
+ i
, stride
,
397 i
, j
, width
- i
- 1);
400 AV_WB24(rgb_dst
+ i
* 3, c
->pal
[p
]);
405 rgb_dst
+= c
->rgb_stride
;
411 static av_cold
void slicecontext_init(SliceContext
*sc
,
412 int version
, int full_model_syms
)
414 model_init(&sc
->intra_region
, 2, THRESH_ADAPTIVE
);
415 model_init(&sc
->inter_region
, 2, THRESH_ADAPTIVE
);
416 model_init(&sc
->split_mode
, 3, THRESH_HIGH
);
417 model_init(&sc
->edge_mode
, 2, THRESH_HIGH
);
418 model_init(&sc
->pivot
, 3, THRESH_LOW
);
420 pixctx_init(&sc
->intra_pix_ctx
, 8, full_model_syms
, 0);
422 pixctx_init(&sc
->inter_pix_ctx
, version
? 3 : 2,
423 full_model_syms
, version
? 1 : 0);
426 void ff_mss12_slicecontext_reset(SliceContext
*sc
)
428 model_reset(&sc
->intra_region
);
429 model_reset(&sc
->inter_region
);
430 model_reset(&sc
->split_mode
);
431 model_reset(&sc
->edge_mode
);
432 model_reset(&sc
->pivot
);
433 pixctx_reset(&sc
->intra_pix_ctx
);
434 pixctx_reset(&sc
->inter_pix_ctx
);
437 static int decode_pivot(SliceContext
*sc
, ArithCoder
*acoder
, int base
)
441 inv
= acoder
->get_model_sym(acoder
, &sc
->edge_mode
);
442 val
= acoder
->get_model_sym(acoder
, &sc
->pivot
) + 1;
445 if ((base
+ 1) / 2 - 2 <= 0)
448 val
= acoder
->get_number(acoder
, (base
+ 1) / 2 - 2) + 3;
454 return inv
? base
- val
: val
;
457 static int decode_region_intra(SliceContext
*sc
, ArithCoder
*acoder
,
458 int x
, int y
, int width
, int height
)
460 MSS12Context
const *c
= sc
->c
;
463 mode
= acoder
->get_model_sym(acoder
, &sc
->intra_region
);
466 int i
, j
, pix
, rgb_pix
;
467 int stride
= c
->pal_stride
;
468 int rgb_stride
= c
->rgb_stride
;
469 uint8_t *dst
= c
->pal_pic
+ x
+ y
* stride
;
470 uint8_t *rgb_dst
= c
->rgb_pic
+ x
* 3 + y
* rgb_stride
;
472 pix
= decode_pixel(acoder
, &sc
->intra_pix_ctx
, NULL
, 0, 0);
473 rgb_pix
= c
->pal
[pix
];
474 for (i
= 0; i
< height
; i
++, dst
+= stride
, rgb_dst
+= rgb_stride
) {
475 memset(dst
, pix
, width
);
477 for (j
= 0; j
< width
* 3; j
+= 3)
478 AV_WB24(rgb_dst
+ j
, rgb_pix
);
481 return decode_region(acoder
, c
->pal_pic
, c
->rgb_pic
,
482 x
, y
, width
, height
, c
->pal_stride
, c
->rgb_stride
,
483 &sc
->intra_pix_ctx
, &c
->pal
[0]);
489 static int decode_region_inter(SliceContext
*sc
, ArithCoder
*acoder
,
490 int x
, int y
, int width
, int height
)
492 MSS12Context
const *c
= sc
->c
;
495 mode
= acoder
->get_model_sym(acoder
, &sc
->inter_region
);
498 mode
= decode_pixel(acoder
, &sc
->inter_pix_ctx
, NULL
, 0, 0);
500 if (c
->avctx
->err_recognition
& AV_EF_EXPLODE
&&
501 ( c
->rgb_pic
&& mode
!= 0x01 && mode
!= 0x02 && mode
!= 0x04 ||
502 !c
->rgb_pic
&& mode
!= 0x80 && mode
!= 0xFF))
506 copy_rectangles(c
, x
, y
, width
, height
);
507 else if (mode
== 0x04)
508 return motion_compensation(c
, x
, y
, width
, height
);
509 else if (mode
!= 0x80)
510 return decode_region_intra(sc
, acoder
, x
, y
, width
, height
);
512 if (decode_region(acoder
, c
->mask
, NULL
,
513 x
, y
, width
, height
, c
->mask_stride
, 0,
514 &sc
->inter_pix_ctx
, &c
->pal
[0]) < 0)
516 return decode_region_masked(c
, acoder
, c
->pal_pic
,
517 c
->pal_stride
, c
->mask
,
526 int ff_mss12_decode_rect(SliceContext
*sc
, ArithCoder
*acoder
,
527 int x
, int y
, int width
, int height
)
531 mode
= acoder
->get_model_sym(acoder
, &sc
->split_mode
);
535 if ((pivot
= decode_pivot(sc
, acoder
, height
)) < 1)
537 if (ff_mss12_decode_rect(sc
, acoder
, x
, y
, width
, pivot
))
539 if (ff_mss12_decode_rect(sc
, acoder
, x
, y
+ pivot
, width
, height
- pivot
))
543 if ((pivot
= decode_pivot(sc
, acoder
, width
)) < 1)
545 if (ff_mss12_decode_rect(sc
, acoder
, x
, y
, pivot
, height
))
547 if (ff_mss12_decode_rect(sc
, acoder
, x
+ pivot
, y
, width
- pivot
, height
))
552 return decode_region_intra(sc
, acoder
, x
, y
, width
, height
);
554 return decode_region_inter(sc
, acoder
, x
, y
, width
, height
);
562 av_cold
int ff_mss12_decode_init(MSS12Context
*c
, int version
,
563 SliceContext
* sc1
, SliceContext
*sc2
)
565 AVCodecContext
*avctx
= c
->avctx
;
568 if (avctx
->extradata_size
< 52 + 256 * 3) {
569 av_log(avctx
, AV_LOG_ERROR
, "Insufficient extradata size %d\n",
570 avctx
->extradata_size
);
571 return AVERROR_INVALIDDATA
;
574 if (AV_RB32(avctx
->extradata
) < avctx
->extradata_size
) {
575 av_log(avctx
, AV_LOG_ERROR
,
576 "Insufficient extradata size: expected %d got %d\n",
577 AV_RB32(avctx
->extradata
),
578 avctx
->extradata_size
);
579 return AVERROR_INVALIDDATA
;
582 avctx
->coded_width
= AV_RB32(avctx
->extradata
+ 20);
583 avctx
->coded_height
= AV_RB32(avctx
->extradata
+ 24);
584 if (avctx
->coded_width
> 4096 || avctx
->coded_height
> 4096) {
585 av_log(avctx
, AV_LOG_ERROR
, "Frame dimensions %dx%d too large",
586 avctx
->coded_width
, avctx
->coded_height
);
587 return AVERROR_INVALIDDATA
;
590 av_log(avctx
, AV_LOG_DEBUG
, "Encoder version %d.%d\n",
591 AV_RB32(avctx
->extradata
+ 4), AV_RB32(avctx
->extradata
+ 8));
592 if (version
!= AV_RB32(avctx
->extradata
+ 4) > 1) {
593 av_log(avctx
, AV_LOG_ERROR
,
594 "Header version doesn't match codec tag\n");
598 c
->free_colours
= AV_RB32(avctx
->extradata
+ 48);
599 if ((unsigned)c
->free_colours
> 256) {
600 av_log(avctx
, AV_LOG_ERROR
,
601 "Incorrect number of changeable palette entries: %d\n",
603 return AVERROR_INVALIDDATA
;
605 av_log(avctx
, AV_LOG_DEBUG
, "%d free colour(s)\n", c
->free_colours
);
607 av_log(avctx
, AV_LOG_DEBUG
, "Display dimensions %dx%d\n",
608 AV_RB32(avctx
->extradata
+ 12), AV_RB32(avctx
->extradata
+ 16));
609 av_log(avctx
, AV_LOG_DEBUG
, "Coded dimensions %dx%d\n",
610 avctx
->coded_width
, avctx
->coded_height
);
611 av_log(avctx
, AV_LOG_DEBUG
, "%g frames per second\n",
612 av_int2float(AV_RB32(avctx
->extradata
+ 28)));
613 av_log(avctx
, AV_LOG_DEBUG
, "Bitrate %d bps\n",
614 AV_RB32(avctx
->extradata
+ 32));
615 av_log(avctx
, AV_LOG_DEBUG
, "Max. lead time %g ms\n",
616 av_int2float(AV_RB32(avctx
->extradata
+ 36)));
617 av_log(avctx
, AV_LOG_DEBUG
, "Max. lag time %g ms\n",
618 av_int2float(AV_RB32(avctx
->extradata
+ 40)));
619 av_log(avctx
, AV_LOG_DEBUG
, "Max. seek time %g ms\n",
620 av_int2float(AV_RB32(avctx
->extradata
+ 44)));
623 if (avctx
->extradata_size
< 60 + 256 * 3) {
624 av_log(avctx
, AV_LOG_ERROR
,
625 "Insufficient extradata size %d for v2\n",
626 avctx
->extradata_size
);
627 return AVERROR_INVALIDDATA
;
630 c
->slice_split
= AV_RB32(avctx
->extradata
+ 52);
631 av_log(avctx
, AV_LOG_DEBUG
, "Slice split %d\n", c
->slice_split
);
633 c
->full_model_syms
= AV_RB32(avctx
->extradata
+ 56);
634 if (c
->full_model_syms
< 2 || c
->full_model_syms
> 256) {
635 av_log(avctx
, AV_LOG_ERROR
,
636 "Incorrect number of used colours %d\n",
638 return AVERROR_INVALIDDATA
;
640 av_log(avctx
, AV_LOG_DEBUG
, "Used colours %d\n",
644 c
->full_model_syms
= 256;
647 for (i
= 0; i
< 256; i
++)
648 c
->pal
[i
] = AV_RB24(avctx
->extradata
+ 52 +
649 (version
? 8 : 0) + i
* 3);
651 c
->mask_stride
= FFALIGN(avctx
->width
, 16);
652 c
->mask
= av_malloc(c
->mask_stride
* avctx
->height
);
654 av_log(avctx
, AV_LOG_ERROR
, "Cannot allocate mask plane\n");
655 return AVERROR(ENOMEM
);
659 slicecontext_init(sc1
, version
, c
->full_model_syms
);
660 if (c
->slice_split
) {
662 slicecontext_init(sc2
, version
, c
->full_model_syms
);
669 av_cold
int ff_mss12_decode_end(MSS12Context
*c
)